#!/usr/bin/env bash
#MISE description="Phase 3 of 4: Sync released version to local Claude Code environment. Updates marketplace repo, syncs hooks to settings.json, syncs commands to ~/.claude/commands/, auto-enables new plugins, and adds the new version to the plugin cache without removing older versions (live sessions need them). Run release:clean separately to prune."
set -euo pipefail

echo "═══════════════════════════════════════════════════════════"
echo "  Phase 3: SYNC (hooks + commands + cache)"
echo "═══════════════════════════════════════════════════════════"

MARKETPLACE_DIR="$HOME/.claude/plugins/marketplaces/cc-skills"
CACHE_DIR="$HOME/.claude/plugins/cache/cc-skills"

# Get current version
VERSION=$(jq -r '.version' package.json)
echo "Syncing version: v$VERSION"

# Step 1: Update marketplace repo
#
# Iter-25 destructive-symlink-loop guard: when the marketplace path is a
# symlink that resolves back to the SOURCE repo we're running from (the
# `claude plugin marketplace add` default during development), the original
# `git reset --hard $VERSION; git clean -fd` here would silently wipe every
# uncommitted edit and untracked file in the source tree. This destroyed
# the iter-23 scripts/sync-*.sh fix and the iter-25 heartbeat-tick perf
# work each time it was tested, masquerading as a "file revert mystery"
# across multiple debugging sessions. The fix: compare physical paths via
# `cd … && pwd -P`; if they match, the marketplace is *already* on the
# code we're editing — no fetch/reset needed, and the destructive ops MUST
# be skipped.
echo "→ Updating marketplace repo..."
SOURCE_REPO_PHYS=$(cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" && pwd -P)
MARKETPLACE_PHYS=""
if [[ -d "$MARKETPLACE_DIR" ]]; then
    MARKETPLACE_PHYS=$(cd "$MARKETPLACE_DIR" 2>/dev/null && pwd -P || echo "")
fi

if [[ -n "$MARKETPLACE_PHYS" && "$MARKETPLACE_PHYS" == "$SOURCE_REPO_PHYS" ]]; then
    echo "  ⚠ Marketplace symlinks to source repo ($SOURCE_REPO_PHYS)"
    echo "    Skipping git fetch/reset/clean — would wipe uncommitted operator work."
    echo "    Marketplace state IS the source tree; nothing to sync."
elif [[ -d "$MARKETPLACE_DIR/.git" ]]; then
    cd "$MARKETPLACE_DIR"
    git fetch origin --tags --quiet
    git reset --hard "v$VERSION" --quiet 2>/dev/null || git reset --hard origin/main --quiet
    git clean -fd --quiet
    echo "  ✓ Marketplace updated to v$VERSION"
    cd - > /dev/null
else
    echo "  ⚠ Marketplace not found at $MARKETPLACE_DIR"
fi

# Step 2: Sync hooks to settings.json
echo "→ Syncing hooks to settings.json..."
if [[ -x "./scripts/sync-hooks-to-settings.sh" ]]; then
    ./scripts/sync-hooks-to-settings.sh
else
    echo "  ⚠ Hook sync script not found"
fi

# Step 2b: Sync commands to ~/.claude/commands/
echo "→ Syncing commands to ~/.claude/commands/..."
if [[ -x "./scripts/sync-commands-to-settings.sh" ]]; then
    ./scripts/sync-commands-to-settings.sh
else
    echo "  ⚠ Command sync script not found"
fi

# Step 2c: Auto-enable new plugins in settings.json
echo "→ Enabling new plugins in settings.json..."
if [[ -x "./scripts/sync-enabled-plugins.sh" ]]; then
    ./scripts/sync-enabled-plugins.sh
else
    echo "  ⚠ Plugin sync script not found"
fi

# Step 3: Add new version to plugin cache (keeps older versions for live sessions)
# IMPORTANT: do NOT wipe $CACHE_DIR — live Claude Code sessions pin plugin paths
# at startup and break with "Plugin directory does not exist" if their version is
# yanked mid-session. Older versions are pruned later by `mise run release:clean`,
# which keeps the last N versions (default 3).
echo "→ Adding v$VERSION to plugin cache..."
CACHE_COUNT=0
for plugin_source in "$MARKETPLACE_DIR/plugins"/*/; do
    [[ -d "$plugin_source" ]] || continue
    plugin_name=$(basename "$plugin_source")
    plugin_target="$CACHE_DIR/$plugin_name/$VERSION"
    # Replace just this version's dir (idempotent re-runs of sync).
    # iter-45 SC2115 rm-rf-slash safety: ${VAR:?} aborts the script if
    # CACHE_DIR, plugin_name, or VERSION is somehow empty. Catastrophic
    # data-loss insurance for the release pipeline's most sensitive site
    # (this rm runs every release on every plugin's cache directory).
    rm -rf "${CACHE_DIR:?CACHE_DIR_must_be_set}/${plugin_name:?plugin_name_must_be_set}/${VERSION:?VERSION_must_be_set}"
    mkdir -p "$plugin_target"
    [[ -d "$plugin_source/skills" ]] && cp -r "$plugin_source/skills" "$plugin_target/"
    [[ -d "$plugin_source/hooks" ]] && cp -r "$plugin_source/hooks" "$plugin_target/"
    [[ -f "$plugin_source/plugin.json" ]] && cp "$plugin_source/plugin.json" "$plugin_target/"
    ((CACHE_COUNT+=1)) || true  # iter-45 defensive ((VAR+=N)) guard
done
echo "  ✓ Cache populated: $CACHE_COUNT plugin(s) at v$VERSION (older versions preserved)"

echo "→ Syncing installed_plugins.json..."
INSTALLED="$HOME/.claude/plugins/installed_plugins.json"
if [[ -f "$INSTALLED" ]]; then
    jq --arg v "$VERSION" --arg base "$CACHE_DIR" '
      del(.plugins["ralph@cc-skills"]) |
      del(.plugins["gmail-tools@cc-skills"]) |
      .plugins |= with_entries(
        if (.key | test("@cc-skills$")) then
          .value[0].version = $v |
          .value[0].installPath = ($base + "/" + (.key | split("@")[0]) + "/" + $v) |
          .value[0].lastUpdated = (now | todate)
        else . end
      )
    ' "$INSTALLED" > /tmp/cc_skills_installed.json \
    && mv /tmp/cc_skills_installed.json "$INSTALLED"
    echo "  ✓ installed_plugins.json synced to v$VERSION"

    # Bootstrap new plugins missing from installed_plugins.json
    MARKETPLACE_JSON="$MARKETPLACE_DIR/.claude-plugin/marketplace.json"
    GIT_SHA=$(git rev-parse HEAD)
    BOOTSTRAPPED=0
    for PLUGIN in $(jq -r '.plugins[].name' "$MARKETPLACE_JSON"); do
        KEY="${PLUGIN}@cc-skills"
        EXISTS=$(jq -r --arg k "$KEY" '.plugins[$k] // "missing"' "$INSTALLED")
        if [[ "$EXISTS" == "missing" ]]; then
            echo "  + Bootstrapping: $KEY"
            jq --arg k "$KEY" --arg v "$VERSION" \
               --arg p "$CACHE_DIR/$PLUGIN/$VERSION" \
               --arg sha "$GIT_SHA" \
            '.plugins[$k] = [{"scope":"user","installPath":$p,"version":$v,
              "installedAt":(now|todate),"lastUpdated":(now|todate),"gitCommitSha":$sha}]
            ' "$INSTALLED" > /tmp/cc_skills_installed.json \
            && mv /tmp/cc_skills_installed.json "$INSTALLED"
            ((BOOTSTRAPPED+=1))
        fi
    done
    [[ $BOOTSTRAPPED -gt 0 ]] && echo "  + Bootstrapped $BOOTSTRAPPED new plugin(s)"
else
    echo "  ⚠ installed_plugins.json not found at $INSTALLED"
fi

echo ""
echo "✓ Sync phase complete"
echo ""
