#!/usr/bin/env bash
# agents-install.sh — Project-level AI agent bootstrap
# Usage: ./agents-install.sh <language>
# Run from project root.

set -euo pipefail

# =============================================================================
# SECTION 1: MCP DEFINITIONS
# Format: "name|command|arg1,arg2,arg3"
# =============================================================================

MCP_CONTEXT7="context7|npx|-y,@upstash/context7-mcp"
MCP_JCODEMUNCH="jcodemunch-mcp|uvx|jcodemunch-mcp"
MCP_LARAVEL_BOOST="laravel-boost|php|artisan,boost:mcp"

COMMON_MCPS=(
    "$MCP_CONTEXT7"
    "$MCP_JCODEMUNCH"
)

declare -A LANGUAGE_MCPS
LANGUAGE_MCPS["laravel"]="$MCP_LARAVEL_BOOST"

# =============================================================================
# SECTION 2: INSTRUCTION FILE CONTENTS
# Key = filename under .agents/instructions/
# COMMON_INSTRUCTION_FILES apply to every language.
# LANGUAGE_INSTRUCTION_FILES adds language-specific files on top.
# All files are concatenated into .agents/instructions/mcp-instructions.md
# =============================================================================

declare -A INSTRUCTIONS

INSTRUCTIONS["context7.md"]=$(cat <<'EOF'
# Context7 MCP

Fetches up-to-date, version-specific documentation from official sources.

## When to use
- Before writing code that uses any library, framework, or external API
- When unsure of the correct API signature, options, or version behaviour

## How to use
1. Call `resolve-library-id` with the library name
2. Call `get-library-docs` with that ID and a focused topic
3. Write the code only after reading the docs

Never rely on training data for library APIs. Always fetch first.
EOF
)

INSTRUCTIONS["jcodemunch.md"]=$(cat <<'EOF'
# JcodeMunch MCP

Compresses large codebases into a navigable summary to save context.

## Code Exploration Policy
Always use jCodemunch-MCP tools — never fall back to Read, Grep, Glob, or Bash for code exploration.
- Before reading a file: use get_file_outline or get_file_content
- Before searching: use search_symbols or search_text
- Before exploring structure: use get_file_tree or get_repo_outline
- Call resolve_repo with the current directory first; if not indexed, call index_folder.
EOF
)

INSTRUCTIONS["laravel-boost.md"]=$(cat <<'EOF'
# Laravel Boost MCP

Exposes your local Laravel application's internals — routes, models,
config, migrations — so the agent generates accurate code without guessing.

## When to use
- Before creating or editing any models, controllers, migrations, or routes
- When checking registered routes, middleware, or app config

## How to use
- Inspect model structure before writing Eloquent queries
- List routes before adding or modifying route definitions
- Read existing migrations before writing new ones

Never scaffold Laravel code without first inspecting the app structure.
EOF
)

COMMON_INSTRUCTION_FILES=(
    "context7.md"
    "jcodemunch.md"
)

declare -A LANGUAGE_INSTRUCTION_FILES
LANGUAGE_INSTRUCTION_FILES["laravel"]="laravel-boost.md"

# =============================================================================
# SECTION 3: PATHS
# =============================================================================

AGENTS_DIR=".agents"
CONFIGS_DIR="$AGENTS_DIR/configs"
INSTRUCTIONS_DIR="$AGENTS_DIR/instructions"

SYMLINK_MAP=(
    "$CONFIGS_DIR/claude/mcp.json|.mcp.json"
    "$CONFIGS_DIR/gemini/settings.json|.gemini/settings.json"
    "$CONFIGS_DIR/codex/config.toml|.codex/config.toml"
    "$CONFIGS_DIR/antigravity/mcp_config.json|.gemini/antigravity/mcp_config.json"
)

# =============================================================================
# SECTION 4: HELPERS
# =============================================================================

ok() { echo "  ✔ $*"; }

relative_symlink_path() {
    local src="$1" dst="$2"
    local dst_dir prefix=""
    dst_dir="$(dirname "$dst")"
    if [ "$dst_dir" != "." ]; then
        local depth
        depth=$(echo "$dst_dir" | tr -cd '/' | wc -c)
        depth=$(( depth + 1 ))
        for (( i=0; i<depth; i++ )); do prefix="../$prefix"; done
    fi
    echo "${prefix}${src}"
}

# =============================================================================
# SECTION 5: PRE-FLIGHT
# =============================================================================

preflight_check() {
    local conflicts=()

    [ -e "$AGENTS_DIR" ] && conflicts+=("$AGENTS_DIR/")

    for entry in "${SYMLINK_MAP[@]}"; do
        local dst="${entry#*|}"
        { [ -e "$dst" ] || [ -L "$dst" ]; } && conflicts+=("$dst")
    done

    { [ -e "CLAUDE.md" ] || [ -L "CLAUDE.md" ]; } && conflicts+=("CLAUDE.md")

    if [ "${#conflicts[@]}" -gt 0 ]; then
        echo "The following already exist. Back up and remove them, then re-run:"
        echo ""
        for c in "${conflicts[@]}"; do echo "  $c"; done
        echo ""
        echo "  TS=\$(date +%Y%m%d_%H%M%S)"
        for c in "${conflicts[@]}"; do
            local s="${c%/}"
            echo "  cp -rP \"$s\" \"${s}.bak.\$TS\" && rm -rf \"$s\""
        done
        echo ""
        exit 1
    fi
}

# =============================================================================
# SECTION 6: WRITE AGENT CONFIGS
# =============================================================================

write_json_mcp() {
    local file="$1"; shift; local mcps=("$@")
    mkdir -p "$(dirname "$file")"
    {
        echo '{ "mcpServers": {'
        local first=true
        for mcp in "${mcps[@]}"; do
            IFS='|' read -r name cmd args_str <<< "$mcp"
            IFS=',' read -ra args <<< "$args_str"
            $first || echo ","
            first=false
            printf '  "%s": { "command": "%s", "args": [' "$name" "$cmd"
            local fa=true
            for a in "${args[@]}"; do $fa || printf ", "; fa=false; printf '"%s"' "$a"; done
            printf "] }"
        done
        printf "\n} }\n"
    } > "$file"
}

write_toml_mcp() {
    local file="$1"; shift; local mcps=("$@")
    mkdir -p "$(dirname "$file")"
    {
        for mcp in "${mcps[@]}"; do
            IFS='|' read -r name cmd args_str <<< "$mcp"
            IFS=',' read -ra args <<< "$args_str"
            echo "[mcp_servers.$name]"
            echo "command = \"$cmd\""
            printf 'args = ['
            local fa=true
            for a in "${args[@]}"; do $fa || printf ", "; fa=false; printf '"%s"' "$a"; done
            printf "]\n\n"
        done
    } > "$file"
}

write_configs() {
    local -n _mcps=$1

    write_json_mcp "$CONFIGS_DIR/claude/mcp.json"             "${_mcps[@]}"
    write_json_mcp "$CONFIGS_DIR/antigravity/mcp_config.json" "${_mcps[@]}"
    write_toml_mcp "$CONFIGS_DIR/codex/config.toml"           "${_mcps[@]}"

    mkdir -p "$CONFIGS_DIR/gemini"
    {
        echo '{ "context": { "fileName": "AGENTS.md" },'
        echo '  "mcpServers": {'
        local first=true
        for mcp in "${_mcps[@]}"; do
            IFS='|' read -r name cmd args_str <<< "$mcp"
            IFS=',' read -ra args <<< "$args_str"
            $first || echo ","
            first=false
            printf '  "%s": { "command": "%s", "args": [' "$name" "$cmd"
            local fa=true
            for a in "${args[@]}"; do $fa || printf ", "; fa=false; printf '"%s"' "$a"; done
            printf "] }"
        done
        printf "\n} }\n"
    } > "$CONFIGS_DIR/gemini/settings.json"

    ok "Agent config files written"
}

# =============================================================================
# SECTION 7: WRITE INSTRUCTIONS
# =============================================================================

write_instructions() {
    local language="$1"
    mkdir -p "$INSTRUCTIONS_DIR"

    local all_files=("${COMMON_INSTRUCTION_FILES[@]}")
    local lang_file="${LANGUAGE_INSTRUCTION_FILES[$language]:-}"
    [ -n "$lang_file" ] && all_files+=("$lang_file")

    for fname in "${all_files[@]}"; do
        printf '%s\n' "${INSTRUCTIONS[$fname]}" > "$INSTRUCTIONS_DIR/$fname"
        ok "Created $INSTRUCTIONS_DIR/$fname"
    done

    local assembled="$INSTRUCTIONS_DIR/mcp-instructions.md"
    : > "$assembled"
    for fname in "${all_files[@]}"; do
        cat "$INSTRUCTIONS_DIR/$fname" >> "$assembled"
        printf '\n---\n\n' >> "$assembled"
    done
    ok "Assembled $assembled"

    printf '@AGENTS.md\n' > CLAUDE.md
    ok "Created CLAUDE.md"
}

# =============================================================================
# SECTION 8: SYMLINKS + link.sh
# =============================================================================

create_symlinks() {
    mkdir -p .gemini/antigravity .codex

    for entry in "${SYMLINK_MAP[@]}"; do
        local src="${entry%|*}" dst="${entry#*|}"
        local rel
        rel=$(relative_symlink_path "$src" "$dst")
        ln -s "$rel" "$dst"
        ok "Linked: $dst → $rel"
    done

    cat > "$AGENTS_DIR/link.sh" <<'EOF'
#!/usr/bin/env bash
# Restore agent symlinks. Run from project root after a fresh clone.
set -euo pipefail
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
mkdir -p .gemini/antigravity .codex
ln -sf .agents/configs/claude/mcp.json                      .mcp.json
ln -sf ../.agents/configs/gemini/settings.json               .gemini/settings.json
ln -sf ../.agents/configs/codex/config.toml                  .codex/config.toml
ln -sf ../../.agents/configs/antigravity/mcp_config.json     .gemini/antigravity/mcp_config.json
echo "Symlinks restored."
EOF
    chmod +x "$AGENTS_DIR/link.sh"
    ok "Created $AGENTS_DIR/link.sh"
}

# =============================================================================
# SECTION 9: MAIN
# =============================================================================

main() {
    local language="${1:-}"
    [ -z "$language" ] && { echo "Usage: $0 <language>"; exit 1; }

    local all_mcps=("${COMMON_MCPS[@]}")
    local lang_mcp="${LANGUAGE_MCPS[$language]:-}"
    [ -n "$lang_mcp" ] && all_mcps+=("$lang_mcp")

    echo "Setting up agents for: $language"

    preflight_check
    write_configs all_mcps
    write_instructions "$language"
    create_symlinks

    echo ""
    echo "Done. Commit: .agents/  CLAUDE.md  .mcp.json  .gemini/  .codex/"
    echo "Create AGENTS.md manually. Reference @.agents/instructions/mcp-instructions.md inside it."
}

main "$@"

