#!/usr/bin/env bash
# Wire the adom auto-update hook into Claude Code and Codex, idempotently, and
# retire any legacy update hook (gallia's, or the pre-rename check-updates.sh) so
# an existing workspace MIGRATES to the registry-native hook instead of stacking
# both. The current hook is adom-core-update.sh, which is preserved.
set -euo pipefail
PKG_DIR="$(cd "$(dirname "$0")" && pwd)"

HOOK_DIR="${HOME}/.adom/hooks"
HOOK="${HOOK_DIR}/adom-core-update.sh"
mkdir -p "$HOOK_DIR"
install -m 0755 "$PKG_DIR/check-updates.sh" "$HOOK"
HOOK_CMD="bash $HOOK"

# Drop the stale launcher file from older adom/hook installs (now adom-core-update.sh).
rm -f "${HOOK_DIR}/check-updates.sh" 2>/dev/null || true

if ! command -v python3 >/dev/null 2>&1; then
  echo "  warning: python3 not found; cannot wire agent configs. Hook script staged at $HOOK." >&2
  exit 0
fi

# Wire HOOK_CMD into one agent config's hooks.UserPromptSubmit, removing any legacy
# auto-update hook first. $1 = config path, $2 = "1" to include a timeout field.
wire() {
  local path="$1" with_timeout="$2"
  mkdir -p "$(dirname "$path")"
  python3 - "$path" "$HOOK_CMD" "$with_timeout" <<'PY'
import json, sys
path, cmd, with_timeout = sys.argv[1], sys.argv[2], sys.argv[3] == "1"
try:
    with open(path) as f: d = json.load(f)
    if not isinstance(d, dict): d = {}
except Exception:
    d = {}
ups = d.setdefault("hooks", {}).setdefault("UserPromptSubmit", [])
# A legacy update hook is any command pointing at a check-updates.sh (gallia's
# hooks/check-updates.sh, or this package's own pre-rename name). adom-core-update.sh
# does not match, so the current hook is never removed.
def is_legacy(h):
    return isinstance(h, dict) and "check-updates.sh" in str(h.get("command", ""))
removed = 0
kept_groups = []
for g in ups:
    if not isinstance(g, dict):
        kept_groups.append(g); continue
    hooks = g.get("hooks", [])
    keep = [h for h in hooks if not is_legacy(h)]
    removed += len(hooks) - len(keep)
    if keep:
        g["hooks"] = keep
        kept_groups.append(g)
ups[:] = kept_groups
present = any(
    isinstance(h, dict) and h.get("command") == cmd
    for g in ups if isinstance(g, dict)
    for h in g.get("hooks", [])
)
changed = removed > 0
if not present:
    entry = {"type": "command", "command": cmd}
    if with_timeout:
        entry["timeout"] = 15
    ups.append({"hooks": [entry]})
    changed = True
if changed:
    with open(path, "w") as f:
        json.dump(d, f, indent=2)
    note = " (retired %d legacy hook(s))" % removed if removed else ""
    print("  wired adom-core-update into %s%s" % (path, note))
else:
    print("  adom-core-update already wired in %s" % path)
PY
}

wire "${HOME}/.claude/settings.json" 1
wire "${HOME}/.codex/hooks.json" 0

# ---------------------------------------------------------------------------
# Headless trigger (adom/hook #1). UserPromptSubmit only fires inside Claude Code
# / Codex, so a lite/service container -- arguably where currency matters MOST,
# since that is where prod releases run -- has no trigger at all and rots until
# someone SSHes in.
#
# Register cron ALWAYS, not only when Claude is absent. The script's throttle
# stamp (ADOM_HOOK_INTERVAL, default 30m) makes a second trigger a no-op, so this
# is strictly additive: an interactive box keeps the fast prompt trigger AND gains
# a backstop for when it sits idle for a day. Auto-detecting "no Claude here"
# would leave that idle gap open and adds a branch that can guess wrong.
#
# Note stdout is meaningless under cron (it becomes mail or /dev/null) -- the
# observable surface for a headless box is the status/log file the script writes
# (~/.adom/last-update.status, ~/.adom/last-update.log), plus the CLI version it
# reports to the registry on each update.
CRON_LINE_INTERVAL="*/30 * * * * $HOOK_CMD >/dev/null 2>&1"
CRON_LINE_REBOOT="@reboot $HOOK_CMD >/dev/null 2>&1"
if command -v crontab >/dev/null 2>&1; then
  # Idempotent: strip any prior adom-core-update entries, then re-add both.
  if { crontab -l 2>/dev/null | grep -v "adom-core-update.sh" || true; \
       echo "$CRON_LINE_INTERVAL"; echo "$CRON_LINE_REBOOT"; } | crontab - 2>/dev/null; then
    echo "  registered cron for headless updates (*/30 + @reboot)"
    if ! pgrep -x crond >/dev/null 2>&1 && ! pgrep -x cron >/dev/null 2>&1; then
      echo "  warning: crond is NOT running, so the schedule will not fire. Start cron in this image," >&2
      echo "           or have the app call '$HOOK' on its own loop." >&2
    fi
  else
    echo "  warning: could not write the crontab; this container will only update on a Claude/Codex prompt." >&2
  fi
else
  echo "  note: no crontab in this image, so there is no headless trigger. Either install cron, or have the"
  echo "        app call '$HOOK' on its own interval (it is throttled + idempotent, safe to call often)."
fi

# Default model (fleet policy, 2026-07-17): new/unset workspaces default to Opus
# with the 1M context window. Sonnet cold-starts describe the platform skills
# without ACTING on them (observed: it never ran the identity/profile lookups an
# Opus session does), so an unconfigured container gives a visibly worse first
# session. ONLY-IF-ABSENT: a user's explicit model choice (or an org's managed
# settings) is never overwritten -- change it any time with /model, and this
# respects that choice on every later run. ADOM_HOOK_NO_MODEL_DEFAULT=1 skips.
if [ -z "${ADOM_HOOK_NO_MODEL_DEFAULT:-}" ]; then
  python3 - "${HOME}/.claude/settings.json" <<'PY'
import json, sys
path = sys.argv[1]
try:
    with open(path) as f: d = json.load(f)
    if not isinstance(d, dict): d = {}
except Exception:
    d = {}
if not d.get("model"):
    d["model"] = "opus[1m]"
    import os
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w") as f: json.dump(d, f, indent=2)
    print("  set default Claude Code model: opus[1m] (override any time with /model)")
PY
fi

# Retire a gallia statusline if one is wired (gallia is gone; revert to default).
# Targeted: only removed when the statusline command points at gallia.
python3 - "${HOME}/.claude/settings.json" <<'PY'
import json, sys
path = sys.argv[1]
try:
    with open(path) as f: d = json.load(f)
    if not isinstance(d, dict): raise ValueError
except Exception:
    sys.exit(0)
sl = d.get("statusLine")
if isinstance(sl, dict) and "gallia" in str(sl.get("command", "")):
    d.pop("statusLine", None)
    with open(path, "w") as f: json.dump(d, f, indent=2)
    print("  retired the gallia statusline (reverted to default)")
PY

# Stage the skill doc for discovery.
if [ -f "$PKG_DIR/SKILL.md" ]; then
  mkdir -p "$HOME/.claude/skills/adom-hook"
  cp "$PKG_DIR/SKILL.md" "$HOME/.claude/skills/adom-hook/SKILL.md"
fi

echo "Installed adom-hook (auto-update wired for Claude + Codex; checks every ${ADOM_HOOK_INTERVAL:-1800}s)"
