#!/usr/bin/env bash
# scripts/update-agent-docs.sh
#
# Regenerates AI agent config files across all repos listed in repos.txt.
#
# Files always regenerated (overwritten):
#   .cursorrules, .windsurfrules, .clinerules, .aider.conf.yml,
#   .editorconfig, .github/copilot-instructions.md
#
# Files created only if missing (never overwritten):
#   CLAUDE.md  — hand-crafted summary; script creates a placeholder if absent
#
# Files never touched:
#   AGENTS.md  — canonical source of truth; must be maintained manually
#
# Usage:
#   ./scripts/update-agent-docs.sh           # regenerate + commit
#   ./scripts/update-agent-docs.sh --dry-run # show what would change, no writes

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPOS_TXT="${SCRIPT_DIR}/../.windsurf/workflows/repos.txt"
BASE_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
DRY_RUN=false
CHANGED_REPOS=()

[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true

# ── colours ────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
info()  { echo -e "${BLUE}[INFO]${NC}  $*"; }
ok()    { echo -e "${GREEN}[OK]${NC}    $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
header(){ echo -e "\n${CYAN}══ $* ══${NC}"; }

# ── per-repo single-line metadata ──────────────────────────────────────────
set_meta() {
  NAME="" ID="" TAGLINE="" STACK="" BUILD_VFY="" LINT1="" LINT2="" LINT3="" AIDER_READ2="README.md"
  case "$1" in
    learning_ai_common_plat)
      NAME="@bytelyst Common Platform"
      ID="(product-agnostic)"
      TAGLINE="Shared packages + microservices for the ByteLyst ecosystem"
      STACK="TypeScript, ESM, pnpm workspace, Fastify 5, Vitest, Azure Cosmos DB"
      BUILD_VFY="pnpm build && pnpm test && pnpm typecheck"
      LINT1="pnpm build 2>&1 | tail -10"
      LINT2="pnpm test 2>&1 | tail -10"
      LINT3="pnpm typecheck 2>&1 | tail -10"
      AIDER_READ2="README.md"
      ;;
    learning_voice_ai_agent)
      NAME="LysnrAI"
      ID="lysnrai"
      TAGLINE="Cross-platform voice-to-text dictation platform"
      STACK="Python 3.12 (desktop/backend) + Next.js 16 (dashboards) + Fastify 5 (microservices in sibling repo)"
      BUILD_VFY="python -m pytest tests/ -v --tb=short"
      LINT1="cd user-dashboard-web && npx tsc --noEmit 2>&1 | tail -10"
      LINT2="python -m pytest tests/ -x --tb=short 2>&1 | tail -10"
      AIDER_READ2="README_MONO_REPO.md"
      ;;
    learning_multimodal_memory_agents)
      NAME="MindLyst"
      ID="mindlyst"
      TAGLINE="Role-Based Life OS — AI-powered multimodal second brain"
      STACK="KMP (shared) + SwiftUI (iOS) + Jetpack Compose (Android) + Next.js 16 (web)"
      BUILD_VFY="./gradlew :shared:compileKotlinIosSimulatorArm64"
      LINT1="cd mindlyst-native && ./gradlew :shared:compileKotlinIosSimulatorArm64 2>&1 | tail -5"
      LINT2="cd mindlyst-native/web && npx next build 2>&1 | tail -10"
      AIDER_READ2="ARCHITECTURE.md"
      ;;
    learning_ai_clock)
      NAME="ChronoMind"
      ID="chronomind"
      TAGLINE="AI-Powered Contextual Clock & Timer"
      STACK="Next.js 16 (web) + SwiftUI (iOS/Watch/Mac) + Jetpack Compose (Android) + Fastify 5 (backend)"
      BUILD_VFY="cd web && npm test && npm run typecheck && npm run build"
      LINT1="cd web && npm test 2>&1 | tail -10"
      LINT2="cd web && npm run typecheck 2>&1 | tail -10"
      AIDER_READ2="docs/PRD.md"
      ;;
    learning_ai_fastgap)
      NAME="NomGap"
      ID="nomgap"
      TAGLINE="Fasting visualization and coaching app"
      STACK="React Native (Expo SDK 55) + TypeScript + Fastify 5 (backend)"
      BUILD_VFY="npm test && npm run typecheck"
      LINT1="npm test 2>&1 | tail -10"
      LINT2="npm run typecheck 2>&1 | tail -10"
      AIDER_READ2="docs/PRD.md"
      ;;
    learning_ai_jarvis_jr)
      NAME="JarvisJr"
      ID="jarvisjr"
      TAGLINE="Voice-first multi-agent coaching platform"
      STACK="SwiftUI (iOS/Watch/Mac) + Next.js 16 (web) + Jetpack Compose (Android) + Fastify 5 (backend)"
      BUILD_VFY="cd web && npm test && npm run typecheck && npm run build"
      LINT1="cd web && npm test 2>&1 | tail -10"
      LINT2="cd web && npm run typecheck 2>&1 | tail -10"
      AIDER_READ2="docs/ENHANCED_IDEA_v2.md"
      ;;
    learning_ai_peakpulse)
      NAME="PeakPulse"
      ID="peakpulse"
      TAGLINE="Sensor-driven adventure tracker for hikers and skiers"
      STACK="SwiftUI (iOS 17+), SwiftData, MapKit, WeatherKit, ActivityKit, WidgetKit, App Intents"
      BUILD_VFY="cd ios && xcodegen generate && xcodebuild -scheme PeakPulse -sdk iphonesimulator build"
      LINT1="cd ios && xcodebuild -scheme PeakPulse -sdk iphonesimulator build 2>&1 | tail -20"
      AIDER_READ2="docs/PRD.md"
      ;;
    *)
      warn "Unknown repo: $1 — skipping"
      return 1
      ;;
  esac
}

# ── per-repo multi-line content ─────────────────────────────────────────────
repo_rules() {
  case "$1" in
    learning_ai_common_plat)
      echo "- Package manager: pnpm — NEVER use npm"
      echo "- ESM everywhere: \"type\": \"module\", .js extensions in imports"
      echo "- Fastify module pattern: types.ts → repository.ts → routes.ts"
      echo "- Use req.log / app.log — never console.log"
      echo "- Every Cosmos document MUST include a productId field"
      echo "- peerDependencies for heavy deps; workspace:* for inter-package deps"
      echo "- Services re-export @bytelyst/* in src/lib/ for clean internal imports"
      ;;
    learning_voice_ai_agent)
      echo "- Python: structlog (never print), ruff lint, type hints required, pydantic-settings"
      echo "- TypeScript: App Router (not Pages), @bytelyst/api-client for service clients"
      echo "- All Cosmos documents MUST include productId field"
      echo "- Use PRODUCT_ID from @bytelyst/config — never hardcode \"lysnrai\""
      echo "- Dashboards: TailwindCSS v4, shadcn/ui, Recharts"
      echo "- Desktop build requires --webpack flag for Next.js"
      ;;
    learning_multimodal_memory_agents)
      echo "- ALL business logic in shared/src/commonMain/ — NEVER in platform UI code"
      echo "- Android/iOS/Web are thin UI shells consuming shared repositories via StateFlow"
      echo "- Koin for DI — register all new deps in SharedModule.kt"
      echo "- MindLystTokens.kt is the single source of design tokens"
      echo "- Web: Pages Router, vanilla CSS with --ml-* props, NO Tailwind"
      echo "- Use compilerOptions {} (not deprecated kotlinOptions {})"
      echo "- Use StateFlow for observable state, never LiveData"
      ;;
    learning_ai_clock)
      echo "- Web engine logic in web/src/lib/ — pure TS, no React imports"
      echo "- Components in web/src/components/ — React UI only"
      echo "- iOS shared logic in ios/ChronoMind/Shared/ — consumed by all Apple targets"
      echo "- Android engine in android/.../engine/ — pure Kotlin, no Android framework deps"
      echo "- Web build: must use --webpack flag (Serwist incompatible with Turbopack)"
      echo "- Every Cosmos doc: productId: \"chronomind\""
      echo "- Theme: --cm-* CSS custom properties (web), ChronoMindTheme (native)"
      ;;
    learning_ai_fastgap)
      echo "- All engine logic in src/lib/ — zero React Native imports"
      echo "- Screens are thin composites wiring store + engines + components"
      echo "- Theme tokens from src/theme/ — never hardcode colors, spacing, or fonts"
      echo "- Expo native modules mocked in __mocks__/ for Vitest"
      echo "- Engine modules are pure functions — testable without mocking RN"
      echo "- Every Cosmos doc: productId: \"nomgap\""
      ;;
    learning_ai_jarvis_jr)
      echo "- iOS shared logic in ios/JarvisJr/Shared/ — consumed by iOS, Watch, Mac"
      echo "- Web engine in web/src/lib/ — pure TS, no React imports"
      echo "- Web components in web/src/components/ — React UI only"
      echo "- Android engine in android/.../engine/ — pure Kotlin, no Android framework deps"
      echo "- Web build: must use --webpack flag (Serwist incompatible with Turbopack)"
      echo "- Never use print() in Swift — use os.Logger"
      echo "- Theme: --jj-* CSS custom properties (web), JarvisJrTheme (native)"
      echo "- Every Cosmos doc: productId: \"jarvisjr\""
      ;;
    learning_ai_peakpulse)
      echo "- Models in ios/PeakPulse/Models/ — SwiftData @Model + Codable structs"
      echo "- Services in ios/PeakPulse/Services/ — pure Swift engine logic"
      echo "- ViewModels in ios/PeakPulse/ViewModels/ — @Observable MVVM"
      echo "- Platform/ files are thin wrappers over ByteLystPlatformSDK — never reimplement"
      echo "- All logging via os.Logger — never use print()"
      echo "- All colors from PeakPulseTheme — never hardcode"
      echo "- Every Cosmos doc: productId: \"peakpulse\""
      ;;
  esac
}

repo_paths() {
  case "$1" in
    learning_ai_common_plat)
      echo "- packages/ — @bytelyst/* shared libraries (errors, cosmos, config, auth, api-client, fastify-core, react-auth, logger, testing, blob, extraction, monitoring, design-tokens)"
      echo "- services/platform-service/ — consolidated platform service (port 4003)"
      echo "- services/extraction-service/ — text extraction + Python sidecar (port 4005)"
      echo "- dashboards/admin-web/ — admin console (port 3001)"
      echo "- dashboards/tracker-web/ — issue tracker (port 3003)"
      ;;
    learning_voice_ai_agent)
      echo "- src/ — Desktop app (Python 3.12, tkinter, Azure Speech SDK)"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4015)"
      echo "- user-dashboard-web/ — Next.js 16 user portal (port 3002)"
      echo "- ../learning_ai_common_plat/services/ — platform-service (4003), extraction-service (4005)"
      echo "- ../learning_ai_common_plat/dashboards/ — admin-web (3001), tracker-web (3003)"
      echo "- mobile_app/ios/ — Swift + SwiftUI"
      echo "- mobile_app/android/ — Kotlin + Jetpack Compose"
      ;;
    learning_multimodal_memory_agents)
      echo "- mindlyst-native/shared/src/commonMain/ — KMP shared logic (ALL business logic)"
      echo "- mindlyst-native/androidApp/ — Jetpack Compose Android app"
      echo "- mindlyst-native/iosApp/ — SwiftUI iOS app"
      echo "- mindlyst-native/web/ — Next.js 16 web dashboard"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4014)"
      echo "- design-system/ — design tokens source"
      ;;
    learning_ai_clock)
      echo "- web/src/lib/ — Pure TS engine modules (timer, cascade, urgency, nl-parser, etc.)"
      echo "- web/src/components/ — React UI components"
      echo "- ios/ChronoMind/Shared/ — Shared Swift code (iOS + Watch + Mac + Widgets)"
      echo "- android/app/.../engine/ — Pure Kotlin engine"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4011)"
      ;;
    learning_ai_fastgap)
      echo "- src/lib/ — Pure engine modules (NO React Native deps)"
      echo "- src/screens/ — Screen components (thin UI composites)"
      echo "- src/components/ — Reusable UI components"
      echo "- src/store/ — Zustand store"
      echo "- src/theme/ — Design tokens (colors, typography, spacing)"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4013)"
      ;;
    learning_ai_jarvis_jr)
      echo "- ios/JarvisJr/Shared/ — Cross-platform Swift code (iOS + Watch + Mac)"
      echo "- web/src/lib/ — Pure TS engine + API clients"
      echo "- web/src/app/ — Next.js App Router pages"
      echo "- android/app/.../engine/ — Pure Kotlin engine"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4012)"
      ;;
    learning_ai_peakpulse)
      echo "- ios/PeakPulse/Models/ — SwiftData models"
      echo "- ios/PeakPulse/Services/ — Pure Swift engine logic"
      echo "- ios/PeakPulse/ViewModels/ — @Observable MVVM"
      echo "- ios/PeakPulse/Views/ — SwiftUI screens + components"
      echo "- ios/PeakPulse/Platform/ — ByteLystPlatformSDK thin wrappers"
      echo "- backend/ — Fastify 5 + TypeScript backend (port 4010)"
      ;;
  esac
}

# ── file generators ─────────────────────────────────────────────────────────

write_editorconfig() {
  cat > "$1" << 'EOF'
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
EOF
}

write_cursorrules() {
  local dest="$1" repo="$2"
  local RULES PATHS
  RULES=$(repo_rules "$repo")
  PATHS=$(repo_paths "$repo")
  cat > "$dest" << EOF
# ${NAME} — Cursor Rules
# Read AGENTS.md for full context.

Project: ${NAME} — ${TAGLINE}
Product ID: ${ID}
Stack: ${STACK}

## Architecture
${PATHS}

## Rules
${RULES}
- Commits: feat(scope): description / fix(scope): description
- Never delete existing comments/documentation unless asked
- Never add emojis unless asked
- Never hardcode secrets, colors, or API URLs

## Build Verification
- ${BUILD_VFY}

## Key Documents
- AGENTS.md — Full AI agent instructions (read this first)
EOF
}

write_windsurfrules() {
  local dest="$1" repo="$2"
  local RULES PATHS
  RULES=$(repo_rules "$repo")
  PATHS=$(repo_paths "$repo")
  cat > "$dest" << EOF
# ${NAME} — Windsurf / Codeium Rules
# Read AGENTS.md for full context. These are the critical rules.

Project: ${NAME} — ${TAGLINE}
Stack: ${STACK}

## Architecture Rules
${PATHS}

## Conventions
${RULES}
- Commits: feat(scope): description / fix(scope): description

## Build Verification
- ${BUILD_VFY}
EOF
}

write_clinerules() {
  local dest="$1" repo="$2"
  local RULES PATHS
  RULES=$(repo_rules "$repo")
  PATHS=$(repo_paths "$repo")
  cat > "$dest" << EOF
# .clinerules — Cline / Roo Code Rules for ${NAME}
# Read AGENTS.md for the complete onboarding guide.

## Project: ${NAME} — ${TAGLINE}
Architecture: ${STACK}

## Mandatory Rules
${RULES}
- Commits: \`type(scope): description\`
- After changes, verify: \`${BUILD_VFY}\`

## Key File Locations
${PATHS}
- Full guide: \`AGENTS.md\`
EOF
}

write_aider_conf() {
  local dest="$1"
  # Build lint-cmd list (skip empty entries)
  local lint_block=""
  for cmd in "${LINT1:-}" "${LINT2:-}" "${LINT3:-}"; do
    [[ -z "$cmd" ]] && continue
    lint_block+="  - '${cmd}'"$'\n'
  done
  # Build read list
  local read_block="  - AGENTS.md"$'\n'
  [[ -n "${AIDER_READ2:-}" ]] && read_block+="  - ${AIDER_READ2}"$'\n'

  cat > "$dest" << EOF
# .aider.conf.yml — Aider Configuration for ${NAME}
# Helps Aider understand the project structure and conventions.

read:
${read_block}
conventions: AGENTS.md

lint-cmd:
${lint_block}
auto-commits: false
EOF
}

write_copilot_instructions() {
  local dest_dir="$1" repo="$2"
  local RULES PATHS
  RULES=$(repo_rules "$repo")
  PATHS=$(repo_paths "$repo")
  mkdir -p "$dest_dir"
  cat > "${dest_dir}/copilot-instructions.md" << EOF
# GitHub Copilot Instructions — ${NAME}

> For full agent instructions, read [\`AGENTS.md\`](../AGENTS.md) at the repo root.

## Project Context

**${NAME}** — ${TAGLINE}.
Stack: ${STACK}

## Code Generation Rules

### Always
${RULES}
- Include \`productId: "${ID}"\` in every Cosmos DB document
- Use \`type(scope): description\` commit message format
- Fix source code, not tests (unless the test itself is wrong)

### Never
- \`console.log\` or \`print()\` in production code
- Hardcoded secrets, API keys, colors, or URLs
- Delete existing comments or documentation unless explicitly asked
- Add emojis unless asked

## Key Paths
${PATHS}

## Build Verification
\`\`\`bash
${BUILD_VFY}
\`\`\`
EOF
}

write_claude_placeholder() {
  local dest="$1" repo="$2"
  local PATHS
  PATHS=$(repo_paths "$repo")
  cat > "$dest" << EOF
# ${NAME} — Claude Code Instructions

> This file is read automatically by Claude Code. For full agent instructions
> shared across all AI tools, see [\`AGENTS.md\`](AGENTS.md).

## Quick Context

**Product:** ${NAME} — ${TAGLINE}
**Product ID:** \`${ID}\`
**Stack:** ${STACK}

## Rules

1. **Read \`AGENTS.md\` first** — it has coding conventions, file ownership, and tech stack rules.
2. **Every Cosmos document** must have a \`productId: "${ID}"\` field.
3. **Commit messages:** \`type(scope): description\` (feat, fix, docs, refactor, test, chore).
4. **Fix source, not tests** — unless the test itself is wrong.
5. **Never use** \`console.log\`, \`print()\`, or hardcoded colors/secrets/URLs.

## Architecture

${PATHS}

## Build Verification

\`\`\`bash
${BUILD_VFY}
\`\`\`
EOF
}

# ── main loop ───────────────────────────────────────────────────────────────

if [[ ! -f "$REPOS_TXT" ]]; then
  echo -e "${RED}[ERROR]${NC} repos.txt not found at: ${REPOS_TXT}"
  exit 1
fi

REPOS=()
while IFS= read -r line; do
  [[ "$line" =~ ^[[:space:]]*# ]] && continue
  [[ -z "${line// }" ]] && continue
  REPOS+=("$line")
done < "$REPOS_TXT"
info "Base directory: ${BASE_DIR}"
info "Repos to process: ${#REPOS[@]}"
$DRY_RUN && warn "DRY RUN — no files will be written or committed"

for REPO in "${REPOS[@]}"; do
  header "$REPO"
  REPO_DIR="${BASE_DIR}/${REPO}"

  if [[ ! -d "$REPO_DIR" ]]; then
    warn "Directory not found at ${REPO_DIR} — skipping"
    continue
  fi

  if ! set_meta "$REPO"; then
    continue
  fi

  if [[ ! -f "${REPO_DIR}/AGENTS.md" ]]; then
    warn "AGENTS.md not found in ${REPO} — skipping (run manually to bootstrap)"
    continue
  fi

  if $DRY_RUN; then
    info "Would generate agent docs for ${NAME} (${ID})"
    info "  build: ${BUILD_VFY}"
    continue
  fi

  # .editorconfig — always overwrite (identical across all repos)
  write_editorconfig "${REPO_DIR}/.editorconfig"
  ok ".editorconfig"

  # .cursorrules — always overwrite
  write_cursorrules "${REPO_DIR}/.cursorrules" "$REPO"
  ok ".cursorrules"

  # .windsurfrules — always overwrite
  write_windsurfrules "${REPO_DIR}/.windsurfrules" "$REPO"
  ok ".windsurfrules"

  # .clinerules — always overwrite
  write_clinerules "${REPO_DIR}/.clinerules" "$REPO"
  ok ".clinerules"

  # .aider.conf.yml — always overwrite
  write_aider_conf "${REPO_DIR}/.aider.conf.yml"
  ok ".aider.conf.yml"

  # .github/copilot-instructions.md — always overwrite
  write_copilot_instructions "${REPO_DIR}/.github" "$REPO"
  ok ".github/copilot-instructions.md"

  # CLAUDE.md — create only if missing
  if [[ ! -f "${REPO_DIR}/CLAUDE.md" ]]; then
    write_claude_placeholder "${REPO_DIR}/CLAUDE.md" "$REPO"
    ok "CLAUDE.md (created — was missing)"
  else
    info "CLAUDE.md exists — skipping (hand-crafted; delete to regenerate)"
  fi

  # Commit if there are any changes in this repo
  if git -C "$REPO_DIR" status --porcelain 2>/dev/null | grep -q .; then
    git -C "$REPO_DIR" add \
      .editorconfig .cursorrules .windsurfrules .clinerules \
      .aider.conf.yml CLAUDE.md .github/copilot-instructions.md \
      2>/dev/null || true
    git -C "$REPO_DIR" commit -m "chore(docs): regenerate AI agent config files" \
      --no-verify 2>/dev/null || true
    ok "Committed changes in ${REPO}"
    CHANGED_REPOS+=("$REPO")
  else
    info "No changes in ${REPO}"
  fi
done

# ── summary ──────────────────────────────────────────────────────────────────
echo ""
if [[ ${#CHANGED_REPOS[@]} -gt 0 ]]; then
  ok "Updated and committed ${#CHANGED_REPOS[@]} repo(s):"
  for r in "${CHANGED_REPOS[@]}"; do
    echo "   • $r"
  done
  echo ""
  info "Push with:"
  for r in "${CHANGED_REPOS[@]}"; do
    echo "   git -C ${BASE_DIR}/${r} push"
  done
else
  ok "All repos already up-to-date — no changes."
fi
