#!/usr/bin/env bash
set -euo pipefail

fail() { printf 'seat-grant: %s\n' "$*" >&2; exit 1; }
[[ $# -ge 1 ]] || fail 'usage: seat-grant create|revoke ...'
ACTION=$1; shift

STATE_DIR=${OVERDECK_SUBROUTER_STATE_DIR:-/var/lib/overdeck/subrouter/state}
BIN=${OVERDECK_SUBROUTER_BIN:-/var/lib/overdeck/subrouter/current/bin/subrouter}
SERVICE_USER=${OVERDECK_SUBROUTER_SERVICE_USER:-overdeck-subrouter}
TEST_ROOT=${OVERDECK_SUBROUTER_SEAT_TEST_ROOT:-}
if [[ -n "$TEST_ROOT" ]]; then
  [[ "$TEST_ROOT" = /* && -d "$TEST_ROOT" ]] || fail 'test root must be an existing absolute directory'
  STAGE_ROOT="$TEST_ROOT/run/overdeck-subrouter-seat"
  OWNER_UID=$(id -u)
  OWNER_GID=$(id -g)
  RUNNER=()
else
  [[ ${EUID:-$(id -u)} -eq 0 ]] || fail 'root required (invoke through deck-sudo)'
  [[ ${SUDO_UID:-} =~ ^[0-9]+$ && ${SUDO_GID:-} =~ ^[0-9]+$ ]] || fail 'sudo owner identity missing'
  OWNER_UID=$SUDO_UID
  OWNER_GID=$SUDO_GID
  STAGE_ROOT=/run/overdeck-subrouter-seat
  [[ -x "$BIN" ]] || fail 'installed subrouter binary missing'
  RUNNER=(/usr/sbin/runuser --user "$SERVICE_USER" --)
fi

safe_run_id() { [[ "$1" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$ ]]; }
safe_route_id() { [[ "$1" =~ ^[A-Za-z0-9_-]{12,96}$ ]]; }
run_dir_for() { printf '%s/%s/%s\n' "$STAGE_ROOT" "$OWNER_UID" "$1"; }

service_exec() {
  if [[ -n "$TEST_ROOT" ]]; then
    "$BIN" "$@"
  else
    "${RUNNER[@]}" /usr/bin/env -i \
      HOME="$STATE_DIR/home" XDG_CONFIG_HOME="$STATE_DIR/config" XDG_CACHE_HOME="$STATE_DIR/cache" \
      XDG_STATE_HOME="$STATE_DIR/state" SUBROUTER_STATE_DIR="$STATE_DIR" \
      "$BIN" "$@"
  fi
}

case "$ACTION" in
  create)
    RUN_ID='' ROUTE_REF='' TTL=900
    while (($#)); do
      case "$1" in
        --run-id) [[ $# -ge 2 ]] || fail '--run-id requires a value'; RUN_ID=$2; shift 2 ;;
        --route-ref) [[ $# -ge 2 ]] || fail '--route-ref requires a value'; ROUTE_REF=$2; shift 2 ;;
        --ttl-seconds) [[ $# -ge 2 && $2 =~ ^[0-9]+$ ]] || fail '--ttl-seconds requires an integer'; TTL=$2; shift 2 ;;
        *) fail "unknown create argument: $1" ;;
      esac
    done
    safe_run_id "$RUN_ID" || fail 'run id invalid'
    [[ "$ROUTE_REF" = /* && -f "$ROUTE_REF" && ! -L "$ROUTE_REF" ]] || fail 'route ref must be an absolute regular file'
    [[ "$(stat -c '%a' "$ROUTE_REF" 2>/dev/null || true)" == 600 ]] || fail 'route ref mode must be 0600'
    ROUTE_ID=$(<"$ROUTE_REF")
    safe_route_id "$ROUTE_ID" || fail 'route id invalid'
    [[ $TTL -ge 60 && $TTL -le 3600 ]] || fail 'ttl must be 60..3600 seconds'
    RUN_DIR=$(run_dir_for "$RUN_ID")
    [[ ! -e "$RUN_DIR" ]] || fail 'run staging already exists'
    install -d -m 0711 "$STAGE_ROOT"
    install -d -m 0711 "$STAGE_ROOT/$OWNER_UID"
    # Subrouter's protected-output contract requires the immediate parent to be
    # owned by the service euid with exact mode 0700 at key creation time.
    install -d -o "$SERVICE_USER" -g "$SERVICE_USER" -m 0700 "$RUN_DIR" 2>/dev/null \
      || install -d -m 0700 "$RUN_DIR"
    EXP=$(date -u -d "+$TTL seconds" +%Y-%m-%dT%H:%M:%SZ)
    if ! service_exec authority-grant create --state-dir "$STATE_DIR" --route-id "$ROUTE_ID" \
      --audience buildbox-run --expires-at "$EXP" --proxy-key-file "$RUN_DIR/proxy.key" \
      --grant-id-file "$RUN_DIR/grant.id" >/dev/null; then
      rm -rf -- "$RUN_DIR"
      fail 'authority grant creation failed'
    fi
    chown "$OWNER_UID:$OWNER_GID" "$RUN_DIR" "$RUN_DIR/proxy.key" "$RUN_DIR/grant.id" 2>/dev/null || true
    chmod 0700 "$RUN_DIR"; chmod 0600 "$RUN_DIR/proxy.key" "$RUN_DIR/grant.id"
    printf '%s\n' "$EXP" > "$RUN_DIR/expires-at"
    chown "$OWNER_UID:$OWNER_GID" "$RUN_DIR/expires-at" 2>/dev/null || true
    chmod 0600 "$RUN_DIR/expires-at"
    printf '{"status":"created","grant_expires_at":"%s"}\n' "$EXP"
    ;;
  revoke)
    RUN_ID=''
    while (($#)); do
      case "$1" in
        --run-id) [[ $# -ge 2 ]] || fail '--run-id requires a value'; RUN_ID=$2; shift 2 ;;
        *) fail "unknown revoke argument: $1" ;;
      esac
    done
    safe_run_id "$RUN_ID" || fail 'run id invalid'
    RUN_DIR=$(run_dir_for "$RUN_ID")
    [[ -d "$RUN_DIR" && ! -L "$RUN_DIR" ]] || fail 'run staging missing'
    [[ -f "$RUN_DIR/grant.id" && ! -L "$RUN_DIR/grant.id" ]] || fail 'grant identifier missing'
    GRANT_ID=$(<"$RUN_DIR/grant.id")
    safe_route_id "$GRANT_ID" || fail 'grant identifier invalid'
    service_exec authority-grant revoke --state-dir "$STATE_DIR" --grant-id "$GRANT_ID" >/dev/null \
      || fail 'authority grant revoke failed'
    service_exec authority-grant remove --state-dir "$STATE_DIR" --grant-id "$GRANT_ID" >/dev/null \
      || fail 'authority grant removal failed'
    REVOKED=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    rm -rf -- "$RUN_DIR"
    printf '{"status":"revoked","grant_revoked_at":"%s"}\n' "$REVOKED"
    ;;
  *) fail 'usage: seat-grant create|revoke ...' ;;
esac
