#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# Agent Recon — Native Linux Setup
# Run this script on a native Linux machine (not WSL) to wire the Agent Recon
# hooks into your Claude Code installation.
#
#   bash setup-linux.sh
#
# What it does:
#   1. Creates ~/.claude/hooks/
#   2. Copies (or updates) send-event.js there (with sha256 drift detection)
#   3. Removes any legacy send-event*.py hook script
#   4. Verifies node is available
#   5. Tests connectivity to localhost:3131
#   6. Writes (or merges) ~/.claude/settings.json with all 24 hook registrations
#   7. Checks for libsecret credential backend (secret-tool)
#   8. Optionally installs a systemd user service for auto-start
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
HOOK_SRC="$SCRIPT_DIR/.claude/hooks/send-event.js"
HOOK_DST="$HOME/.claude/hooks/send-event.js"
SETTINGS="$HOME/.claude/settings.json"
HOOK_CMD="node $HOOK_DST"
SERVICE_SRC="$SCRIPT_DIR/service/agent-recon.service"

# ── Validate ─────────────────────────────────────────────────────────────────
if [[ ! -f "$HOOK_SRC" ]]; then
  echo "ERROR: Cannot find hook source at $HOOK_SRC"
  echo "  Run this script from the agent-recon project root directory."
  exit 1
fi

if ! command -v node &>/dev/null; then
  echo "ERROR: node not found. Install Node.js 22+ with your package manager:"
  echo "  Debian/Ubuntu : curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt install -y nodejs"
  echo "  Fedora        : sudo dnf install nodejs"
  echo "  Arch          : sudo pacman -S nodejs npm"
  exit 1
fi

echo "✓  node found: $(node --version 2>&1)"

# ── Install / sync hook script ───────────────────────────────────────────────
mkdir -p "$HOME/.claude/hooks"

if [[ -f "$HOOK_DST" ]]; then
  SRC_HASH=$(sha256sum "$HOOK_SRC" | cut -d' ' -f1)
  DST_HASH=$(sha256sum "$HOOK_DST" | cut -d' ' -f1)
  if [[ "$SRC_HASH" != "$DST_HASH" ]]; then
    echo "↻  Hook script updated — syncing to $HOOK_DST"
    cp "$HOOK_SRC" "$HOOK_DST"
    chmod +x "$HOOK_DST"
    echo "✓  Synced"
  else
    echo "✓  Hook script already up-to-date: $HOOK_DST"
  fi
else
  cp "$HOOK_SRC" "$HOOK_DST"
  chmod +x "$HOOK_DST"
  echo "✓  Installed hook forwarder → $HOOK_DST"
fi

# ── Remove legacy Python hook scripts (v1.0.x → v1.1.x migration) ────────────
for legacy in "$HOME/.claude/hooks/send-event.py" "$HOME/.claude/hooks/send-event-wsl.py"; do
  if [[ -f "$legacy" ]]; then
    rm -f "$legacy" && echo "✓  Removed legacy hook: $(basename "$legacy")"
  fi
done

# ── Test Agent Recon server connectivity ─────────────────────────────────────
echo ""
echo "── Connectivity check ──────────────────────────────────────────────────"

if curl -sf --max-time 2 "http://localhost:3131/health" > /dev/null 2>&1; then
  echo "  ✓ localhost:3131  REACHABLE"
else
  echo "  ✗ localhost:3131  not reachable"
  echo ""
  echo "  ⚠  Agent Recon server is not running."
  echo "     Start it with:"
  echo "       cd $SCRIPT_DIR/server && node start.js"
  echo "     Then re-run this script to verify connectivity."
fi

# ── Write settings.json ─────────────────────────────────────────────────────
echo ""
echo "── Hook registration ─────────────────────────────────────────────────"

if [[ -f "$SETTINGS" ]]; then
  # Merge hooks into existing settings.json using Node so we don't clobber
  # other fields (e.g. skipDangerousModePermissionPrompt).
  node - "$SETTINGS" "$HOOK_CMD" <<'NODEEOF'
const fs = require('fs');
const settingsPath = process.argv[2];
const hookCmd      = process.argv[3];

let cfg = {};
try { cfg = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch {}
if (!cfg || typeof cfg !== 'object') cfg = {};
if (!cfg.hooks) cfg.hooks = {};
const hooks = cfg.hooks;

function hookEntry(matcher) {
  const entry = { type: 'command', command: hookCmd, async: true, timeout: 10 };
  return matcher ? { matcher: '', hooks: [entry] } : { hooks: [entry] };
}

// Keep in sync with installer/steps/hooks.js
const EVENTS_PLAIN = [
  'SessionStart','SessionEnd','UserPromptSubmit',
  'SubagentStart','SubagentStop','Stop','TeammateIdle','TaskCompleted',
  'StopFailure','PostCompact','InstructionsLoaded','ConfigChange',
  'CwdChanged','FileChanged',
  'TaskCreated','ElicitationResult',
];
const EVENTS_MATCHER = [
  'PreToolUse','PostToolUse','PostToolUseFailure','Notification','PreCompact',
  'PermissionRequest','Elicitation','PermissionDenied',
];

// Strip legacy Python hook registrations (preserve third-party hooks)
for (const ev of Object.keys(hooks)) {
  if (!Array.isArray(hooks[ev])) continue;
  hooks[ev] = hooks[ev].filter(group => {
    const hs = group.hooks || [];
    return !hs.some(h => h.command && /send-event(-wsl)?\.py/.test(h.command));
  });
  if (hooks[ev].length === 0) delete hooks[ev];
}

function alreadyRegistered(groups) {
  for (const g of (groups || [])) {
    for (const h of (g.hooks || [])) {
      if (h.command === hookCmd) return true;
    }
  }
  return false;
}

const added = [];
for (const ev of EVENTS_PLAIN) {
  if (!hooks[ev]) { hooks[ev] = [hookEntry(false)]; added.push(ev); }
  else if (!alreadyRegistered(hooks[ev])) { hooks[ev].push(hookEntry(false)); added.push(ev); }
}
for (const ev of EVENTS_MATCHER) {
  if (!hooks[ev]) { hooks[ev] = [hookEntry(true)]; added.push(ev); }
  else if (!alreadyRegistered(hooks[ev])) { hooks[ev].push(hookEntry(true)); added.push(ev); }
}

// Strip deprecated events — only remove AR hooks, preserve third-party hooks
const DEPRECATED = ['WorktreeCreate', 'WorktreeRemove'];
for (const ev of DEPRECATED) {
  if (!hooks[ev]) continue;
  hooks[ev] = hooks[ev].filter(g => !(g.hooks || []).some(h => h.command === hookCmd));
  if (hooks[ev].length === 0) delete hooks[ev];
}

fs.writeFileSync(settingsPath, JSON.stringify(cfg, null, 2) + '\n');

if (added.length) {
  console.log('✓  Merged hooks into', settingsPath);
  console.log('   Added:', added.join(', '));
} else {
  console.log('✓  All hooks already present in', settingsPath, '— nothing changed');
}
NODEEOF
else
  # Keep in sync with installer/steps/hooks.js
  cat > "$SETTINGS" <<SETTINGSEOF
{
  "hooks": {
    "SessionStart":        [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "SessionEnd":          [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "UserPromptSubmit":    [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PreToolUse":          [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PostToolUse":         [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PostToolUseFailure":  [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "SubagentStart":       [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "SubagentStop":        [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "Stop":                [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "Notification":        [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "TeammateIdle":        [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "TaskCompleted":       [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PreCompact":          [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "StopFailure":         [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PostCompact":         [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "InstructionsLoaded":  [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "ConfigChange":        [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "CwdChanged":          [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "FileChanged":         [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "TaskCreated":         [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "ElicitationResult":   [{"hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PermissionRequest":   [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "Elicitation":         [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}],
    "PermissionDenied":    [{"matcher": "","hooks": [{"type": "command","command": "$HOOK_CMD","async": true,"timeout": 10}]}]
  }
}
SETTINGSEOF
  # Validate JSON
  if ! node -e "JSON.parse(require('fs').readFileSync('$SETTINGS','utf8'))" > /dev/null 2>&1; then
    echo "⚠  Warning: generated settings.json may be malformed"
  fi
  echo "✓  Created $SETTINGS"
fi

# ── Check libsecret credential backend ──────────────────────────────────────
echo ""
echo "── Credential backend check ──────────────────────────────────────────"

if command -v secret-tool &>/dev/null; then
  echo "  ✓ secret-tool found (libsecret credential backend available)"

  # Test store/lookup/clear cycle
  TEST_KEY="agent-recon-setup-test-$$"
  SECRET_OK=true

  if ! echo -n "test-value" | secret-tool store --label="Agent Recon test" agent-recon-key "$TEST_KEY" 2>/dev/null; then
    SECRET_OK=false
  fi

  if $SECRET_OK; then
    LOOKUP=$(secret-tool lookup agent-recon-key "$TEST_KEY" 2>/dev/null || true)
    if [[ "$LOOKUP" == "test-value" ]]; then
      echo "  ✓ secret-tool store/lookup cycle passed"
    else
      SECRET_OK=false
    fi
    # Clean up test entry
    secret-tool clear agent-recon-key "$TEST_KEY" 2>/dev/null || true
  fi

  if ! $SECRET_OK; then
    echo "  ⚠  secret-tool is installed but the test cycle failed."
    echo "     This may happen if no keyring daemon is running (e.g. headless server)."
    echo "     PBKDF2 fallback will be used for credential storage."
  fi
else
  echo "  ⚠  secret-tool not found — PBKDF2 fallback will be used for credentials."
  echo "     To install libsecret for native keyring support:"
  echo "       Debian/Ubuntu : sudo apt install libsecret-tools"
  echo "       Fedora        : sudo dnf install libsecret"
  echo "       Arch          : sudo pacman -S libsecret"
fi

# ── Optional systemd user service ───────────────────────────────────────────
echo ""
echo "── Systemd user service ────────────────────────────────────────────────"

if [[ ! -f "$SERVICE_SRC" ]]; then
  echo "  ⚠  Service unit file not found at $SERVICE_SRC — skipping."
else
  echo "  A systemd user service can auto-start Agent Recon on login."
  echo ""
  read -r -p "  Install systemd user service? [y/N] " INSTALL_SERVICE
  if [[ "${INSTALL_SERVICE,,}" == "y" ]]; then
    SERVICE_DIR="$HOME/.config/systemd/user"
    mkdir -p "$SERVICE_DIR"

    # Replace {{INSTALL_DIR}} placeholder with the actual project path
    sed "s|{{INSTALL_DIR}}|$SCRIPT_DIR|g" "$SERVICE_SRC" > "$SERVICE_DIR/agent-recon.service"

    systemctl --user daemon-reload
    systemctl --user enable agent-recon
    echo "  ✓  Service installed and enabled."
    echo ""
    read -r -p "  Start the service now? [y/N] " START_NOW
    if [[ "${START_NOW,,}" == "y" ]]; then
      systemctl --user start agent-recon
      echo "  ✓  Service started."
      echo "     Check status: systemctl --user status agent-recon"
      echo "     View logs   : journalctl --user -u agent-recon -f"
    else
      echo "  Service enabled but not started. Start it later with:"
      echo "    systemctl --user start agent-recon"
    fi
  else
    echo "  Skipped. You can install it manually later:"
    echo "    mkdir -p ~/.config/systemd/user"
    echo "    sed 's|{{INSTALL_DIR}}|$SCRIPT_DIR|g' $SERVICE_SRC > ~/.config/systemd/user/agent-recon.service"
    echo "    systemctl --user daemon-reload"
    echo "    systemctl --user enable agent-recon"
    echo "    systemctl --user start agent-recon"
  fi
fi

# ── Summary ──────────────────────────────────────────────────────────────────
echo ""
echo "────────────────────────────────────────────────────────────────────────"
echo "  Linux setup complete!"
echo ""
echo "  Hook script : $HOOK_DST"
echo "  Server URL  : http://localhost:3131"
echo ""
echo "  Start server: cd $SCRIPT_DIR/server && node start.js"
echo "  (start.js auto-rebuilds the SQLite binary if platform mismatches)"
echo ""
echo "  Start a Claude session in any directory and events will stream"
echo "  to http://localhost:3131"
echo ""
echo "  Debug mode  : AGENT_RECON_DEBUG=1 claude  →  ~/.claude/agent-recon-debug.log"
echo "────────────────────────────────────────────────────────────────────────"
