#!/usr/bin/env bash
set -euo pipefail

# mosaic-upgrade — Clean up stale per-project files after Mosaic centralization
#
# SOUL.md    → Now global at ~/.config/mosaic/SOUL.md (remove from projects)
# CLAUDE.md  → Now a thin pointer or removable (replace with pointer or remove)
# AGENTS.md  → Keep project-specific content, strip stale load-order directives
#
# Usage:
#   mosaic-upgrade [path]          Upgrade a specific project (default: current dir)
#   mosaic-upgrade --all           Scan ~/src/* for projects to upgrade
#   mosaic-upgrade --dry-run       Show what would change without touching anything

MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"

# Colors (disabled if not a terminal)
if [[ -t 1 ]]; then
  GREEN='\033[0;32m' YELLOW='\033[0;33m' RED='\033[0;31m'
  CYAN='\033[0;36m' BOLD='\033[1m' DIM='\033[2m' RESET='\033[0m'
else
  GREEN='' YELLOW='' RED='' CYAN='' BOLD='' DIM='' RESET=''
fi

ok()   { echo -e "  ${GREEN}✓${RESET} $1"; }
skip() { echo -e "  ${DIM}–${RESET} $1"; }
warn() { echo -e "  ${YELLOW}⚠${RESET} $1"; }
act()  { echo -e "  ${CYAN}→${RESET} $1"; }

DRY_RUN=false
ALL=false
TARGET=""
SEARCH_ROOT="${HOME}/src"

usage() {
  cat <<USAGE
mosaic-upgrade — Clean up stale per-project files

Usage:
  mosaic-upgrade [path]          Upgrade a specific project (default: cwd)
  mosaic-upgrade --all           Scan ~/src/* for all git projects
  mosaic-upgrade --dry-run       Preview changes without writing
  mosaic-upgrade --all --dry-run Preview all projects

After Mosaic centralization:
  SOUL.md    → Removed (now global at ~/.config/mosaic/SOUL.md)
  CLAUDE.md  → Replaced with thin pointer or removed
  AGENTS.md  → Stale load-order sections stripped; project content preserved
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)  DRY_RUN=true; shift ;;
    --all)      ALL=true; shift ;;
    --root)     SEARCH_ROOT="$2"; shift 2 ;;
    -h|--help)  usage; exit 0 ;;
    -*)         echo "Unknown flag: $1" >&2; usage >&2; exit 1 ;;
    *)          TARGET="$1"; shift ;;
  esac
done

# Generate the thin CLAUDE.md pointer
CLAUDE_POINTER='# CLAUDE Compatibility Pointer

This file exists so Claude Code sessions load Mosaic standards.

## MANDATORY — Read Before Any Response

BEFORE responding to any user message, READ `~/.config/mosaic/AGENTS.md`.

That file is the universal agent configuration. Do NOT respond until you have loaded it.
Then read the project-local `AGENTS.md` in this repository for project-specific guidance.'

upgrade_project() {
  local project_dir="$1"
  local project_name
  project_name="$(basename "$project_dir")"
  local changed=false

  echo -e "\n${BOLD}$project_name${RESET} ${DIM}($project_dir)${RESET}"

  # ── SOUL.md ──────────────────────────────────────────────
  local soul="$project_dir/SOUL.md"
  if [[ -f "$soul" ]]; then
    if [[ "$DRY_RUN" == "true" ]]; then
      act "Would remove SOUL.md (now global at ~/.config/mosaic/SOUL.md)"
    else
      rm "$soul"
      ok "Removed SOUL.md (now global)"
    fi
    changed=true
  else
    skip "No SOUL.md (already clean)"
  fi

  # ── CLAUDE.md ────────────────────────────────────────────
  local claude_md="$project_dir/CLAUDE.md"
  if [[ -f "$claude_md" ]]; then
    local claude_content
    claude_content="$(cat "$claude_md")"

    # Check if it's already a thin pointer to AGENTS.md
    if echo "$claude_content" | grep -q "READ.*~/.config/mosaic/AGENTS.md"; then
      skip "CLAUDE.md already points to global AGENTS.md"
    else
      if [[ "$DRY_RUN" == "true" ]]; then
        act "Would replace CLAUDE.md with thin pointer to global AGENTS.md"
      else
        # Back up the original
        cp "$claude_md" "${claude_md}.mosaic-bak"
        echo "$CLAUDE_POINTER" > "$claude_md"
        ok "Replaced CLAUDE.md with pointer (backup: CLAUDE.md.mosaic-bak)"
      fi
      changed=true
    fi
  else
    skip "No CLAUDE.md"
  fi

  # ── AGENTS.md (strip stale load-order, preserve project content) ─
  local agents="$project_dir/AGENTS.md"
  if [[ -f "$agents" ]]; then
    # Detect stale load-order patterns
    local has_stale=false

    # Pattern 1: References to SOUL.md in load order
    if grep -qE "(Read|READ|Load).*SOUL\.md" "$agents" 2>/dev/null; then
      has_stale=true
    fi

    # Pattern 2: Old "## Load Order" section that references centralized files
    if grep -q "## Load Order" "$agents" 2>/dev/null && \
       grep -qE "STANDARDS\.md|SOUL\.md" "$agents" 2>/dev/null; then
      has_stale=true
    fi

    # Pattern 3: Old ~/.mosaic/ path (pre-centralization)
    if grep -q '~/.mosaic/' "$agents" 2>/dev/null; then
      has_stale=true
    fi

    if [[ "$has_stale" == "true" ]]; then
      if [[ "$DRY_RUN" == "true" ]]; then
        act "Would strip stale load-order section from AGENTS.md"
        # Show what we detect
        if grep -qn "## Load Order" "$agents" 2>/dev/null; then
          local line
          line=$(grep -n "## Load Order" "$agents" | head -1 | cut -d: -f1)
          echo -e "    ${DIM}Line $line: Found '## Load Order' section referencing SOUL.md/STANDARDS.md${RESET}"
        fi
        if grep -qn '~/.mosaic/' "$agents" 2>/dev/null; then
          echo -e "    ${DIM}Found references to old ~/.mosaic/ path${RESET}"
        fi
      else
        cp "$agents" "${agents}.mosaic-bak"

        # Strip the Load Order section (from "## Load Order" to next "##" or "---")
        if grep -q "## Load Order" "$agents"; then
          awk '
            /^## Load Order/ { skip=1; next }
            skip && /^(## |---)/ { skip=0 }
            skip { next }
            { print }
          ' "${agents}.mosaic-bak" > "$agents"
        fi

        # Fix old ~/.mosaic/ → ~/.config/mosaic/
        if grep -q '~/.mosaic/' "$agents"; then
          sed -i 's|~/.mosaic/|~/.config/mosaic/|g' "$agents"
        fi

        ok "Stripped stale load-order from AGENTS.md (backup: AGENTS.md.mosaic-bak)"
      fi
      changed=true
    else
      skip "AGENTS.md has no stale directives"
    fi
  else
    skip "No AGENTS.md"
  fi

  # ── .claude/settings.json (leave alone) ──────────────────
  # Project-specific settings are fine — don't touch them.

  if [[ "$changed" == "false" ]]; then
    echo -e "  ${GREEN}Already up to date.${RESET}"
  fi
}

# ── Main ───────────────────────────────────────────────────

if [[ "$DRY_RUN" == "true" ]]; then
  echo -e "${BOLD}Mode: DRY RUN (no files will be changed)${RESET}"
fi

if [[ "$ALL" == "true" ]]; then
  echo -e "${BOLD}Scanning $SEARCH_ROOT for projects...${RESET}"
  count=0
  for dir in "$SEARCH_ROOT"/*/; do
    [[ -d "$dir/.git" ]] || continue
    upgrade_project "$dir"
    count=$((count + 1))
  done
  echo -e "\n${BOLD}Scanned $count projects.${RESET}"
elif [[ -n "$TARGET" ]]; then
  if [[ ! -d "$TARGET" ]]; then
    echo "[mosaic-upgrade] ERROR: $TARGET is not a directory." >&2
    exit 1
  fi
  upgrade_project "$TARGET"
else
  upgrade_project "$(pwd)"
fi

if [[ "$DRY_RUN" == "true" ]]; then
  echo -e "\n${YELLOW}This was a dry run. Run without --dry-run to apply changes.${RESET}"
fi
