#!/usr/bin/env bash
# seat-launcher — runs inside agent-seat-*.scope + seat netns as per-seat implementer (ods-<seat-id>).
set -euo pipefail

state_dir=""
seat_id=""
seat_host=""
model=""
_startup_status_marker_written=0

_resolve_state_dir() {
  if [ -n "${state_dir:-}" ]; then
    printf '%s' "$state_dir"
    return 0
  fi
  local sid="${OVERDECK_SEAT_ID:-}"
  if [ -n "$sid" ]; then
    printf '%s' "${OVERDECK_SEAT_STATE_DIR:-$HOME/.local/state/overdeck/seats/${sid}}"
    return 0
  fi
  return 1
}

_startup_status_write() {
  local marker="$1"
  case "$marker" in
    starting|env-json|seat-metadata|profile-nonconcrete|profile-dir|secure-storage|account-slug|netns-path|netns-membership|claude-bin|guard-bin|checkout|artifacts|forwarded|model-count|exec) ;;
    exit-*)
      local code="${marker#exit-}"
      case "$code" in
        ''|*[!0-9]*) return 1 ;;
      esac
      ;;
    *) return 1 ;;
  esac
  local dir
  dir="$(_resolve_state_dir)" || return 1
  mkdir -p "$dir" 2>/dev/null || return 1
  chmod 700 "$dir" 2>/dev/null || true
  printf '%s\n' "$marker" > "${dir}/startup.status"
  _startup_status_marker_written=1
}

_startup_status_fail() {
  local marker="$1"
  _startup_status_write "$marker" || true
  exit "${2:-2}"
}

_startup_status_on_exit() {
  local code=$?
  if [ "${_startup_status_marker_written:-0}" -eq 1 ]; then
    return
  fi
  _startup_status_write "exit-$code" || true
}
trap _startup_status_on_exit EXIT

if [ -n "${OVERDECK_SEAT_ID:-}" ] && [ -n "${OVERDECK_SEAT_HOST:-}" ] && [ -n "${OVERDECK_SEAT_MODEL:-}" ]; then
  seat_id="$OVERDECK_SEAT_ID"
  seat_host="$OVERDECK_SEAT_HOST"
  model="$OVERDECK_SEAT_MODEL"
  state_dir="${OVERDECK_SEAT_STATE_DIR:-$HOME/.local/state/overdeck/seats/${seat_id}}"
fi

_launch_seat_id="${OVERDECK_SEAT_ID:-}"
_launch_seat_host="${OVERDECK_SEAT_HOST:-}"
_launch_seat_model="${OVERDECK_SEAT_MODEL:-}"
_launch_state_dir="${OVERDECK_SEAT_STATE_DIR:-}"
_launch_claude_bin="${OVERDECK_CLAUDE_BIN:-}"
_launch_guard_bin="${OVERDECK_SEAT_GUARD_BIN:-}"
_launch_checkout="${OVERDECK_SEAT_CHECKOUT:-}"
_launch_profile_dir="${CLAUDE_CONFIG_DIR:-}"
_launch_secure_storage_dir="${CLAUDE_SECURESTORAGE_CONFIG_DIR:-}"
_launch_account_slug="${SYSTRAY_CLAUDE_ACCOUNT_SLUG:-}"

env_json="${state_dir}/trusted-config/seat-env.json"
if [ -f "$env_json" ]; then
  env_tmp="$(mktemp)"
  if ! python3 -c '
import json, sys
CONTROL = set(range(0, 9)) | {11, 12} | set(range(14, 32)) | {127}
ALLOW = {
  "PATH", "SHELL", "LANG", "LC_ALL", "LC_CTYPE", "LC_MESSAGES", "TERM",
  "ANTHROPIC_BASE_URL",
}
AUTHORITY = {
  "HOME", "USER", "LOGNAME",
  "CLAUDE_CONFIG_DIR", "CLAUDE_SECURESTORAGE_CONFIG_DIR", "SYSTRAY_CLAUDE_ACCOUNT_HOME",
  "SYSTRAY_CLAUDE_ACCOUNT_SLUG", "OVERDECK_SEAT_HOST", "OVERDECK_SEAT_ID", "OVERDECK_SEAT_MODEL",
  "OVERDECK_CLAUDE_BIN", "OVERDECK_SEAT_GUARD_BIN", "OVERDECK_SEAT_CHECKOUT",
  "OVERDECK_SEAT_STATE_DIR",
}
DENY = {
  "ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN", "OPENAI_API_KEY", "CCP_CONFIG_DIR", "CCP_BIND_ADDRESS",
  "CCP_CODEX_MODEL", "CCP_CODEX_SERVICE_TIER", "ANTHROPIC_MODEL", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY",
  "DBUS_SESSION_BUS_ADDRESS", "XDG_RUNTIME_DIR",
}
SHELL_HOME_MARKERS = ("$HOME", "$(", chr(96))
path = sys.argv[1]
with open(path, encoding="utf-8") as fh:
    data = json.load(fh)
if not isinstance(data, dict):
    raise SystemExit("seat-env-not-object")
seen = set()
for key, value in data.items():
    if key in seen:
        raise SystemExit(f"seat-env-duplicate:{key}")
    seen.add(key)
    if key in AUTHORITY:
        raise SystemExit(f"seat-env-reject-authority:{key}")
    if key not in ALLOW or key in DENY:
        raise SystemExit(f"seat-env-reject:{key}")
    if not isinstance(value, str):
        raise SystemExit(f"seat-env-type:{key}")
    if any(ord(ch) in CONTROL for ch in value):
        raise SystemExit(f"seat-env-control:{key}")
    if any(marker in value for marker in SHELL_HOME_MARKERS):
        raise SystemExit(f"seat-env-shell-home:{key}")
    sys.stdout.write(key)
    sys.stdout.write("=")
    sys.stdout.write(value)
    sys.stdout.write("\0")
' "$env_json" >"$env_tmp"; then
    rm -f "$env_tmp"
    _startup_status_fail env-json
  fi
  while IFS= read -r -d '' kv; do
    key=${kv%%=*}
    val=${kv#*=}
    export "$key=$val"
  done <"$env_tmp"
  rm -f "$env_tmp"
fi

if [ -n "$_launch_seat_id" ]; then seat_id="$_launch_seat_id"; fi
if [ -n "$_launch_seat_host" ]; then seat_host="$_launch_seat_host"; fi
if [ -n "$_launch_seat_model" ]; then model="$_launch_seat_model"; fi
if [ -n "$_launch_state_dir" ]; then state_dir="$_launch_state_dir"; fi
if [ -z "$state_dir" ] && [ -n "${OVERDECK_SEAT_ID:-}" ]; then state_dir="$HOME/.local/state/overdeck/seats/${OVERDECK_SEAT_ID}"; fi
if [ -z "$state_dir" ] && [ -n "$seat_id" ]; then state_dir="$HOME/.local/state/overdeck/seats/${seat_id}"; fi

_startup_status_write starting || true

if [ -z "$seat_id" ] || [ -z "$seat_host" ] || [ -z "$model" ]; then
  echo "seat-launcher: missing OVERDECK_SEAT_ID/HOST/MODEL" >&2
  _startup_status_fail seat-metadata
fi

netns_name="overdeck-seat-${seat_id}"
netns_path="/var/run/netns/${netns_name}"

if [ ! -e "$netns_path" ]; then
  echo "seat-launcher: seat netns missing ($netns_path)" >&2
  _startup_status_fail netns-path
fi

identified=$(ip netns identify 2>/dev/null || true)
if [ "$identified" != "$netns_name" ]; then
  echo "seat-launcher: not in seat netns (got ${identified:-none}, want $netns_name)" >&2
  _startup_status_fail netns-membership
fi

guard_bin="${_launch_guard_bin:-${OVERDECK_SEAT_GUARD_BIN:-}}"
trusted_dir="$state_dir/trusted-config"
settings="$trusted_dir/seat-settings.json"
mcp_config="$trusted_dir/empty-mcp.json"
forwarded_json="$trusted_dir/claude-forwarded.json"
claude_bin="${_launch_claude_bin:-${OVERDECK_CLAUDE_BIN:-}}"
checkout="${_launch_checkout:-${OVERDECK_SEAT_CHECKOUT:-}}"
profile_dir="${_launch_profile_dir:-${CLAUDE_CONFIG_DIR:-}}"
secure_storage_dir="${_launch_secure_storage_dir:-${CLAUDE_SECURESTORAGE_CONFIG_DIR:-}}"
account_slug="${_launch_account_slug:-${SYSTRAY_CLAUDE_ACCOUNT_SLUG:-}}"

case "$claude_bin" in *'$HOME'*|*'$('* ) echo "seat-launcher: claude binary must be concrete" >&2; _startup_status_fail claude-bin 127 ;;
esac
case "$profile_dir" in *'$HOME'*|*'$('* ) echo "seat-launcher: profile path must be concrete" >&2; _startup_status_fail profile-nonconcrete ;;
esac

if [ -z "$claude_bin" ] || [ ! -x "$claude_bin" ]; then
  echo "seat-launcher: claude binary missing (OVERDECK_CLAUDE_BIN)" >&2
  _startup_status_fail claude-bin 127
fi
if [ -z "$guard_bin" ] || [ ! -d "$guard_bin" ]; then
  echo "seat-launcher: seat guard missing (OVERDECK_SEAT_GUARD_BIN)" >&2
  _startup_status_fail guard-bin
fi
if [ -z "$checkout" ] || [ ! -d "$checkout" ]; then
  echo "seat-launcher: checkout missing (OVERDECK_SEAT_CHECKOUT)" >&2
  _startup_status_fail checkout
fi
if [ -z "$profile_dir" ] || [ ! -d "$profile_dir" ]; then
  echo "seat-launcher: profile missing (CLAUDE_CONFIG_DIR)" >&2
  _startup_status_fail profile-dir
fi
if [ -z "$secure_storage_dir" ] || [ ! -d "$secure_storage_dir" ]; then
  echo "seat-launcher: secure-storage missing (CLAUDE_SECURESTORAGE_CONFIG_DIR)" >&2
  _startup_status_fail secure-storage
fi
if [ -z "$account_slug" ]; then
  echo "seat-launcher: account slug missing (SYSTRAY_CLAUDE_ACCOUNT_SLUG)" >&2
  _startup_status_fail account-slug
fi

if [ ! -f "$settings" ] || [ ! -f "$mcp_config" ] || [ ! -f "$forwarded_json" ] || [ ! -f "$env_json" ]; then
  echo "seat-launcher: seat artifacts missing under $trusted_dir" >&2
  _startup_status_fail artifacts
fi

unset DBUS_SESSION_BUS_ADDRESS XDG_RUNTIME_DIR \
  ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN OPENAI_API_KEY \
  CCP_CONFIG_DIR CCP_BIND_ADDRESS CCP_CODEX_MODEL CCP_CODEX_SERVICE_TIER \
  ANTHROPIC_MODEL CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY

export PATH="${guard_bin}:${PATH:-/usr/bin:/bin}"
export OVERDECK_SEAT_ID="$seat_id"
export OVERDECK_SEAT_HOST="$seat_host"
export OVERDECK_SEAT_MODEL="$model"
export OVERDECK_SEAT_STATE_DIR="$state_dir"
export CLAUDE_CONFIG_DIR="$profile_dir"
export CLAUDE_SECURESTORAGE_CONFIG_DIR="$secure_storage_dir"
export SYSTRAY_CLAUDE_ACCOUNT_HOME="$profile_dir"
export SYSTRAY_CLAUDE_ACCOUNT_SLUG="$account_slug"

cd "$checkout"

mapfile -t forwarded < <(python3 -c '
import json, sys
CONTROL = set(range(0, 9)) | {11, 12} | set(range(14, 32)) | {127}
DENY_EXACT = {
  "--model", "--fallback-model", "--settings", "--setting-sources", "--disallowedTools", "--allowedTools",
  "--disallowed-tools", "--allowed-tools", "--tools",
  "--agents", "--strict-mcp-config", "--mcp-config", "--plugin", "--plugins", "--plugin-dir", "--plugin-url",
  "--marketplace",
  "--enable-workflows", "--enable-workflow", "--agent", "--workflow", "Agent", "Workflow",
}
DENY_PREFIX = (
  "--model=", "--fallback-model=", "--settings=", "--setting-sources=", "--disallowedTools=",
  "--allowedTools=", "--disallowed-tools=", "--allowed-tools=", "--tools=",
  "--agents=", "--strict-mcp-config=", "--mcp-config=", "--plugin=", "--plugins=", "--plugin-dir=", "--plugin-url=",
  "--marketplace=",
  "--enable-workflows=", "--enable-workflow=", "--agent=", "--workflow=",
)
path = sys.argv[1]
with open(path, encoding="utf-8") as fh:
    data = json.load(fh)
if not isinstance(data, list):
    raise SystemExit("forwarded-not-array")
for idx, item in enumerate(data):
    if not isinstance(item, str):
        raise SystemExit(f"forwarded-not-string:{idx}")
    if any(ord(ch) in CONTROL for ch in item):
        raise SystemExit(f"forwarded-control:{idx}")
    if item in DENY_EXACT:
        raise SystemExit(f"forwarded-deny:{item}")
    for prefix in DENY_PREFIX:
        if item.startswith(prefix):
            raise SystemExit(f"forwarded-deny:{item}")
    print(item)
' "$forwarded_json") || _startup_status_fail forwarded

claude_argv=(
  "$claude_bin"
  --model "$model"
  --settings "$settings"
  --setting-sources ""
  --disallowedTools Agent Workflow
  --agents '{}'
  --strict-mcp-config
  --mcp-config "$mcp_config"
)

for arg in "${forwarded[@]}"; do
  claude_argv+=("$arg")
done

model_count=0
for arg in "${claude_argv[@]}"; do
  if [ "$arg" = "--model" ] || [[ "$arg" == --model=* ]]; then model_count=$((model_count + 1)); fi
done
if [ "$model_count" -ne 1 ]; then
  echo "seat-launcher: expected exactly one --model" >&2
  _startup_status_fail model-count
fi

_startup_status_write exec
exec "${claude_argv[@]}"
