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

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

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_MIGRATION_TEST_ROOT:-}
SERVICE_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
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-migration"
  OWNER_UID=$(id -u); OWNER_GID=$(id -g)
  STAGE_USER=$(id -un)
  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_USER=$SERVICE_USER
  STAGE_ROOT=/run/overdeck-subrouter-migration
  [[ -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_account_id() { [[ "$1" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ]]; }
service_exec() {
  if [[ -n "$TEST_ROOT" ]]; then
    "$BIN" "$@"
  else
    "${RUNNER[@]}" /usr/bin/env -i \
      PATH="$SERVICE_PATH" 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
}

RUN_ID='' PROVIDER='' ACCOUNT_ID='' OUTPUT_DIR='' TTL=3600
while (($#)); do
  case "$1" in
    --run-id) [[ $# -ge 2 ]] || fail '--run-id requires a value'; RUN_ID=$2; shift 2 ;;
    --provider) [[ $# -ge 2 ]] || fail '--provider requires a value'; PROVIDER=$2; shift 2 ;;
    --account-id) [[ $# -ge 2 ]] || fail '--account-id requires a value'; ACCOUNT_ID=$2; shift 2 ;;
    --output-dir) [[ $# -ge 2 ]] || fail '--output-dir requires a value'; OUTPUT_DIR=$2; shift 2 ;;
    --ttl-seconds) [[ $# -ge 2 && $2 =~ ^[0-9]+$ ]] || fail '--ttl-seconds requires an integer'; TTL=$2; shift 2 ;;
    *) fail "unknown provision argument: $1" ;;
  esac
done
safe_run_id "$RUN_ID" || fail 'run id invalid'
[[ "$PROVIDER" == codex || "$PROVIDER" == claude ]] || fail 'provider invalid'
safe_account_id "$ACCOUNT_ID" || fail 'account id invalid'
[[ $TTL -ge 300 && $TTL -le 3600 ]] || fail 'ttl must be 300..3600 seconds'
[[ "$OUTPUT_DIR" = /* && -d "$OUTPUT_DIR" && ! -L "$OUTPUT_DIR" ]] || fail 'output dir must be an absolute regular directory'
[[ "$(stat -c '%a' "$OUTPUT_DIR" 2>/dev/null || true)" == 700 ]] || fail 'output dir mode must be 0700'
[[ "$(stat -c '%u:%g' "$OUTPUT_DIR" 2>/dev/null || true)" == "$OWNER_UID:$OWNER_GID" ]] || fail 'output dir owner mismatch'
[[ ! -e "$OUTPUT_DIR/route.id" && ! -e "$OUTPUT_DIR/proxy.key" ]] || fail 'output material already exists'

RUN_DIR="$STAGE_ROOT/$OWNER_UID/$RUN_ID"
[[ ! -e "$RUN_DIR" ]] || fail 'run staging already exists'
install -d -m 0711 "$STAGE_ROOT" "$STAGE_ROOT/$OWNER_UID"
install -d -o "$STAGE_USER" -g "$STAGE_USER" -m 0700 "$RUN_DIR" 2>/dev/null || install -d -m 0700 "$RUN_DIR"
ACCOUNT_CREATED=0 ROUTE_CREATED=0
cleanup_failed() {
  set +e
  if (( ROUTE_CREATED )); then
    route=$(cat -- "$RUN_DIR/route.id" 2>/dev/null || true)
    [[ -n "$route" ]] && service_exec authority-route remove --state-dir "$STATE_DIR" --route-id "$route" >/dev/null 2>&1 || true
  fi
  if (( ACCOUNT_CREATED )); then
    service_exec authority-account remove --state-dir "$STATE_DIR" --provider "$PROVIDER" --account-id "$ACCOUNT_ID" >/dev/null 2>&1 || true
  fi
  rm -rf -- "$RUN_DIR"
}
trap 'cleanup_failed; exit 130' INT TERM

LOGIN=(authority-account login --state-dir "$STATE_DIR" --provider "$PROVIDER" --account-id "$ACCOUNT_ID")
[[ "$PROVIDER" == codex ]] && LOGIN+=(--device-auth)
if ! service_exec "${LOGIN[@]}"; then
  rm -rf -- "$RUN_DIR"
  fail 'authority account login failed'
fi
ACCOUNT_CREATED=1
TENANT_ID="migration-$RUN_ID"
if ! service_exec authority-route create --state-dir "$STATE_DIR" --tenant-id "$TENANT_ID" --provider "$PROVIDER" \
  --account-id "$ACCOUNT_ID" --enabled --route-id-file "$RUN_DIR/route.id" >/dev/null; then
  cleanup_failed
  fail 'authority route creation failed'
fi
ROUTE_CREATED=1
ROUTE_ID=$(<"$RUN_DIR/route.id")
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 workstation \
  --expires-at "$EXP" --proxy-key-file "$RUN_DIR/proxy.key" >/dev/null; then
  cleanup_failed
  fail 'authority grant creation failed'
fi
install -o "$OWNER_UID" -g "$OWNER_GID" -m 0600 "$RUN_DIR/route.id" "$OUTPUT_DIR/route.id"
install -o "$OWNER_UID" -g "$OWNER_GID" -m 0600 "$RUN_DIR/proxy.key" "$OUTPUT_DIR/proxy.key"
rm -rf -- "$RUN_DIR"
trap - INT TERM
printf '{"status":"provisioned","grant_expires_at":"%s"}\n' "$EXP"
