#!/bin/bash
# InterGenOS Claude Code Installer
#
# Installs Claude Code CLI and VS Code extension from Anthropic.
# License: https://code.claude.com/docs/en/legal-and-compliance
#
# H-007 Phase B migration: records the install footprint via the
# /usr/share/igos/helpers/helper-lib.sh API.

set -e

source /usr/share/igos/helpers/helper-lib.sh

ACCEPTANCE_DIR="/var/lib/intergen/legal"
ACCEPTANCE_FILE="$ACCEPTANCE_DIR/claude-code-helper-1.0-accepted.json"

echo ""
echo "  InterGenOS Claude Code Installer"
echo "  ================================="
echo ""
echo "  Claude Code is proprietary software by Anthropic."
echo "  License: https://code.claude.com/docs/en/legal-and-compliance"
echo ""

# Canonical invocation guard. claude-code's npm install -g needs root,
# AND pkm's manifest ingestion at /var/lib/igos/helpers needs root,
# so direct invocation only works as root anyway — but it also
# bypasses pkm's _run_helper which is what threads the manifest into
# the DB. Send users at the supported entry point.
if [ "$(id -u)" -ne 0 ]; then
    echo "  ERROR: Run via 'sudo pkm install-helper claude-code' instead."
    echo "  Direct invocation bypasses pkm's manifest ingestion;"
    echo "  pkm files/verify/remove will not see the installed files."
    exit 1
fi

# Check for npm
if ! command -v npm >/dev/null 2>&1; then
    echo "  ERROR: npm not found. Install Node.js first."
    exit 1
fi

# EULA acceptance gate. The acceptance record at /var/lib/intergen/legal/
# is intentionally NOT manifest-tracked: pkm remove leaves it in place
# so a subsequent reinstall reads existing acceptance and skips the
# re-prompt (Row F decision 2026-05-19; ffmpeg-nonfree-helper canonical
# K21.C pattern). The record IS captured in pkm's operation log as
# transparency content via the post_install_action below.
if [ -f "$ACCEPTANCE_FILE" ]; then
    echo "  Acceptance already recorded at $ACCEPTANCE_FILE"
    echo "  Proceeding to install."
else
    echo ""
    echo "  Do you accept Anthropic's commercial terms above and authorize"
    echo "  installing Claude Code on this machine for your own use?"
    echo "  Type 'I ACCEPT' (exact match, capitals) to proceed:"
    echo ""
    read -r REPLY
    if [ "$REPLY" != "I ACCEPT" ]; then
        echo "  Acceptance not given. Exiting."
        exit 1
    fi
    mkdir -p "$ACCEPTANCE_DIR"
    cat > "$ACCEPTANCE_FILE" <<JSON
{
  "helper": "claude-code-helper",
  "version": "1.0",
  "payload_license": "LicenseRef-Anthropic-Commercial-Terms",
  "accepted_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "user": "$(logname 2>/dev/null || echo unknown)"
}
JSON
    chmod 644 "$ACCEPTANCE_FILE"
    echo "  Acceptance recorded at $ACCEPTANCE_FILE"
fi

igos_helper_init "claude-code"

# K21.C: capture the consent event in pkm's operation log as
# transparency content. The acceptance JSON itself is intentionally
# NOT manifest-tracked (see EULA acceptance gate above).
igos_helper_record_post_install_action \
    "User accepted Anthropic commercial terms (acceptance artifact at $ACCEPTANCE_FILE)"

# K21.F: trust-anchor + integrity-gate hardening for the npm-registry
# install path. Differences from the K21.E apt-Release pattern (used by
# brave/chrome/edge/vscode/spotify):
#
#   - npm registry is the trust boundary (Anthropic publishes signed
#     packages to https://registry.npmjs.org/@anthropic-ai/claude-code/);
#     npm 9+ auto-verifies the registry signature on each install. We
#     don't replicate that chain manually; we anchor on the registry's
#     existing trust + sharpen the install posture.
#
#   - Anthropic's @anthropic-ai/claude-code publishes WITH npm registry
#     signature (signatures[0].sig + keyid present in registry metadata)
#     but WITHOUT npm provenance attestations (dist.attestations = none
#     at clear-time 2026-05-21). Provenance is an upstream-side opt-in
#     (npm publish --provenance) -- our helper cannot add it.
#
#   - PIN to a specific version rather than @latest. Reproducibility +
#     defense against silent package-upgrade-attack on a future install.
#     Bump the pin via a helper-version-bump commit when Anthropic
#     publishes a new release.
#
#   - Run `npm audit --audit-level=critical` pre-install against the
#     pinned version's dep tree; if a critical-severity advisory exists,
#     refuse install with loud error per Holy Grail Rule 10 default-deny.

# Pinned version (bump via helper-version-bump commit on Anthropic
# release). Current pin matches the latest at K21.F clear-time
# 2026-05-21; npm view @anthropic-ai/claude-code latest = 2.1.146.
CLAUDE_CODE_PINNED_VERSION="2.1.146"

# K21.F: pre-install audit against critical-severity npm advisories.
# This runs `npm audit` against a transient package.json in TMPDIR
# (the pinned version's dep tree) and refuses install on critical
# findings. --audit-level=critical means lower-severity advisories
# (high / moderate / low) are reported informationally but do not
# refuse install -- prevents over-blocking on transitive deps the
# user can't easily fix while still hardening against critical-CVE
# install paths.
echo "  Running npm audit pre-install check against critical-severity advisories..."
AUDIT_TMPDIR=$(mktemp -d -t igos-claude-audit-XXXXXX)
cat > "$AUDIT_TMPDIR/package.json" << JSONEOF
{
  "name": "igos-claude-code-helper-audit-shim",
  "version": "0.0.0",
  "private": true,
  "dependencies": {
    "@anthropic-ai/claude-code": "${CLAUDE_CODE_PINNED_VERSION}"
  }
}
JSONEOF
(cd "$AUDIT_TMPDIR" && npm install --package-lock-only --no-audit --no-fund --silent 2>/dev/null) || {
    echo "  WARNING: npm install --package-lock-only failed for the audit shim;"
    echo "  proceeding without pre-install audit (registry signature verification"
    echo "  remains active via npm install -g below)."
    AUDIT_SKIPPED=1
}
if [ "${AUDIT_SKIPPED:-0}" != "1" ]; then
    if ! (cd "$AUDIT_TMPDIR" && npm audit --audit-level=critical 2>&1); then
        echo ""
        echo "  ERROR: npm audit found CRITICAL-severity advisories in the"
        echo "  @anthropic-ai/claude-code@${CLAUDE_CODE_PINNED_VERSION} dep"
        echo "  tree. Refusing install per default-deny posture."
        echo "  Investigate the advisory above + either bump the pinned"
        echo "  version (helper-version-bump commit) or document an"
        echo "  operator-ratified Option B accept-with-disclosure."
        rm -rf "$AUDIT_TMPDIR"
        exit 1
    fi
fi
rm -rf "$AUDIT_TMPDIR"
echo "  npm audit: no critical-severity advisories."

echo "  Installing Claude Code CLI via npm (pinned version ${CLAUDE_CODE_PINNED_VERSION})..."
npm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_PINNED_VERSION}"

# K21.F: pinned version IS what was installed; record it directly
# rather than re-parsing `npm list` output. Falls back to npm list
# for defense if npm renamed the package under the hood.
CLAUDE_VERSION="$CLAUDE_CODE_PINNED_VERSION"
if [ -z "$CLAUDE_VERSION" ]; then
    CLAUDE_VERSION=$(npm list -g @anthropic-ai/claude-code 2>/dev/null \
                      | grep '@anthropic-ai/claude-code@' \
                      | sed 's/.*@anthropic-ai\/claude-code@//' \
                      | head -1)
fi
igos_helper_set_version "${CLAUDE_VERSION:-unknown}"

NPM_GLOBAL_ROOT=$(npm root -g 2>/dev/null || echo "/usr/lib/node_modules")
CLAUDE_DIR="$NPM_GLOBAL_ROOT/@anthropic-ai/claude-code"

# H-007: record every file under the npm-installed module dir. npm's
# global prefix typically lands under /usr/lib/node_modules which
# matches the manifest's /usr/ allowlist.
if [ -d "$CLAUDE_DIR" ]; then
    while IFS= read -r f; do
        igos_helper_record_file "$f"
    done < <(find "$CLAUDE_DIR" -type f -o -type l 2>/dev/null)
fi

# Verify installation
if command -v claude >/dev/null 2>&1; then
    echo "  Claude Code CLI installed: $(claude --version 2>/dev/null || echo 'OK')"
    # npm creates a symlink at <prefix>/bin/claude pointing into the
    # module dir. Record it so pkm remove unlinks the binary surface.
    CLAUDE_BIN=$(command -v claude)
    CLAUDE_TARGET=$(readlink -f "$CLAUDE_BIN" 2>/dev/null || echo "$CLAUDE_BIN")
    if [ -L "$CLAUDE_BIN" ]; then
        igos_helper_record_symlink "$CLAUDE_BIN" "$CLAUDE_TARGET"
    elif [ -f "$CLAUDE_BIN" ]; then
        igos_helper_record_file "$CLAUDE_BIN"
    fi
else
    echo "  WARNING: claude command not found in PATH"
    echo "  You may need to add npm's global bin directory to your PATH"
fi

igos_helper_record_dep nodejs

# Install VS Code extension if VS Code or Code-OSS is available
if command -v code >/dev/null 2>&1; then
    echo "  Installing Claude Code extension for VS Code..."
    code --install-extension anthropic.claude-code 2>/dev/null && \
        echo "  VS Code extension installed" || \
        echo "  NOTE: Extension install failed — you can install manually from the marketplace"
elif command -v code-oss >/dev/null 2>&1; then
    echo "  Installing Claude Code extension for Code-OSS..."
    echo "  NOTE: Claude Code may not be available on Open VSX Registry."
    echo "  You may need to download the .vsix from the VS Code Marketplace"
    echo "  and install with: code-oss --install-extension claude-code.vsix"
fi

# Record the VS Code extension install as a descriptive post-install
# action (the extension files live under the user's home directory,
# which is outside the manifest's path allowlist; pkm doesn't track
# per-user state in v1.0).
igos_helper_record_post_install_action \
    "VS Code extension anthropic.claude-code installed (per-user; not pkm-tracked)"

igos_helper_commit

echo ""
echo "  Claude Code installed!"
echo ""
echo "  To authenticate:"
echo "    claude          # Opens browser for OAuth login"
echo "    # OR"
echo "    export ANTHROPIC_API_KEY=your-key-here"
echo "    claude"
echo ""
