#!/bin/bash

# Claude Code Configuration Script for XCodeCLI
# This script configures Claude Code to use your XCodeCLI instance
# Automatically tests multiple API endpoints and selects the working one

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
DEFAULT_BASE_URL="https://api2.xcodecli.com"
CLAUDE_CONFIG_DIR="$HOME/.claude"
CLAUDE_SETTINGS_FILE="$CLAUDE_CONFIG_DIR/settings.json"
TOOL_COMMAND="claude"
TOOL_NAME="Claude Code"
TOOL_PACKAGE="@anthropic-ai/claude-code"

# ========== Shell 环境变量配置 ==========
get_shell_rc() {
    if [ -n "${ZSH_VERSION:-}" ] || [ "${SHELL##*/}" = "zsh" ]; then
        echo "$HOME/.zshrc"
    elif [ -n "${BASH_VERSION:-}" ] || [ "${SHELL##*/}" = "bash" ]; then
        if [ -f "$HOME/.bashrc" ]; then
            echo "$HOME/.bashrc"
        else
            echo "$HOME/.bash_profile"
        fi
    else
        print_error "不支持当前 shell: ${SHELL##*/}"
        print_error "仅支持 bash 和 zsh"
        exit 1
    fi
}

write_env_to_shell() {
    local var_name="$1"
    local var_value="$2"
    local rc_file
    rc_file=$(get_shell_rc)

    mkdir -p "$(dirname "$rc_file")"
    touch "$rc_file"

    if [ -s "$rc_file" ] && [ "$(tail -c1 "$rc_file" | wc -l)" -eq 0 ]; then
        echo "" >>"$rc_file"
    fi

    local export_line="export $var_name='$var_value'"

    local tmp_file
    tmp_file=$(mktemp)
    if [ -s "$rc_file" ]; then
        grep -v "^export $var_name=" "$rc_file" >"$tmp_file" 2>/dev/null || true
    fi
    echo "$export_line" >>"$tmp_file"

    cat "$tmp_file" >"$rc_file"
    rm -f "$tmp_file"

    export "$var_name=$var_value"
}

# Function to print colored output
print_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

print_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# ========== Node.js 环境检测 ==========
get_node_version() {
    if command -v node >/dev/null 2>&1; then
        node --version 2>/dev/null | sed 's/v//'
    fi
}

get_node_major_version() {
    local version
    version=$(get_node_version)
    if [ -n "$version" ]; then
        echo "$version" | cut -d. -f1
    fi
}

install_fnm() {
    echo ""
    print_info "正在安装 fnm (Fast Node Manager)..."

    if curl -fsSL https://fnm.vercel.app/install | bash; then
        export PATH="$HOME/.local/share/fnm:$PATH"
        if [ -f "$HOME/.local/share/fnm/fnm" ]; then
            eval "$(~/.local/share/fnm/fnm env)"
        fi

        if command -v fnm >/dev/null 2>&1; then
            print_success "fnm 安装成功!"
            return 0
        else
            print_warning "fnm 可能已安装，但需要重新打开终端才能生效"
            print_info "请重新打开终端后再运行此脚本"
            return 1
        fi
    else
        print_error "fnm 安装失败"
        return 1
    fi
}

install_node_with_fnm() {
    print_info "使用 fnm 安装 Node.js 24.x..."

    if fnm install 24 && fnm use 24 && fnm default 24; then
        eval "$(fnm env)"

        if command -v node >/dev/null 2>&1; then
            local version
            version=$(get_node_version)
            print_success "Node.js v$version 安装成功!"
            return 0
        else
            print_warning "Node.js 可能已安装，但需要重新打开终端才能生效"
            return 1
        fi
    else
        print_error "Node.js 安装失败"
        return 1
    fi
}

ensure_node_environment() {
    local version major

    version=$(get_node_version)
    if [ -n "$version" ]; then
        major=$(get_node_major_version)
        print_info "检测到 Node.js v$version"

        if [ "$major" -lt 20 ]; then
            print_warning "Node.js 版本过低 (需要 >= 20.x)"

            read -p "是否使用 fnm 安装 Node.js 24.x? (Y/n): " -r
            if [[ $REPLY =~ ^[Nn]$ ]]; then
                print_error "Node.js 版本不满足要求，请手动升级后重试"
                return 1
            fi

            if ! command -v fnm >/dev/null 2>&1; then
                install_fnm || return 1
            fi

            install_node_with_fnm || return 1
        fi

        return 0
    fi

    print_warning "未检测到 Node.js"
    print_info "将使用 fnm 安装 Node.js 24.x"

    read -p "是否继续? (Y/n): " -r
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        return 1
    fi

    if ! command -v fnm >/dev/null 2>&1; then
        install_fnm || return 1
    fi

    install_node_with_fnm || return 1
}

install_tool() {
    ensure_node_environment || return 1

    print_info "使用 npm 安装 $TOOL_NAME..."
    echo "  执行: npm install -g $TOOL_PACKAGE"

    if npm install -g "$TOOL_PACKAGE"; then
        if command -v "$TOOL_COMMAND" >/dev/null 2>&1; then
            print_success "$TOOL_NAME 安装成功!"
            return 0
        else
            print_warning "$TOOL_NAME 可能已安装，但需要重新打开终端才能生效"
            read -p "是否继续进行配置? (Y/n): " -r
            if [[ $REPLY =~ ^[Nn]$ ]]; then
                return 1
            fi
            return 0
        fi
    else
        print_error "安装失败"
        return 1
    fi
}

# Function to check if jq is installed
check_jq() {
    if ! command -v jq &>/dev/null; then
        print_error "jq is required but not installed."
        print_info "Please install jq:"
        print_info "  macOS: brew install jq"
        print_info "  Ubuntu/Debian: sudo apt-get install jq"
        print_info "  CentOS/RHEL: sudo yum install jq"
        exit 1
    fi
}

# Function to backup existing settings
backup_settings() {
    if [ -f "$CLAUDE_SETTINGS_FILE" ]; then
        local backup_file="${CLAUDE_SETTINGS_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
        cp "$CLAUDE_SETTINGS_FILE" "$backup_file"
        print_info "Backed up existing settings to: $backup_file"
    fi
    local config_json_path="$CLAUDE_CONFIG_DIR/config.json"
    if [ -f "$config_json_path" ]; then
        local backup_file="${config_json_path}.backup.$(date +%Y%m%d_%H%M%S)"
        cp "$config_json_path" "$backup_file"
        print_info "Backed up existing config to: $backup_file"
    fi
}

# Function to create settings directory
create_settings_dir() {
    if [ ! -d "$CLAUDE_CONFIG_DIR" ]; then
        mkdir -p "$CLAUDE_CONFIG_DIR"
        print_info "Created Claude configuration directory: $CLAUDE_CONFIG_DIR"
    fi
}

# Function to validate API key format
validate_api_key() {
    local api_key="$1"
    if [[ ! "$api_key" =~ ^[A-Za-z0-9_-]+$ ]]; then
        print_error "Invalid API key format. API key should contain only alphanumeric characters, hyphens, and underscores."
        return 1
    fi
    return 0
}

# Function to extract model count from API response (supports both data[] and models[])
get_model_count() {
    local response_file="$1"
    local count="0"
    if command -v jq >/dev/null 2>&1; then
        count=$(jq -r '
            if (.data | type) == "array" and (.data | length) > 0 then (.data | length)
            elif (.models | type) == "array" and (.models | length) > 0 then (.models | length)
            else 0 end
        ' "$response_file" 2>/dev/null || echo "0")
    else
        if grep -qE '"(data|models)"[[:space:]]*:[[:space:]]*\[' "$response_file" 2>/dev/null; then
            count=$(grep -oE '"id"[[:space:]]*:' "$response_file" | wc -l | tr -d ' ')
        fi
    fi
    [ -z "$count" ] && count="0"
    echo "$count"
}

# Function to test API connection and return working base URL
test_api_connection() {
    local api_key="$1"

    local test_urls=(
        "https://api2.xcodecli.com"
        "https://api.xcodecli.com"
    )

    print_info "Testing API connections..." >&2

    for base_url in "${test_urls[@]}"; do
        print_info "Testing $base_url..." >&2

        local test_endpoint="$base_url/v1/models"

        # Test a simple request to the API
        local response
        response=$(curl -s -w "%{http_code}" -o /tmp/claude_test_response \
            -X GET "$test_endpoint" \
            -H "Content-Type: application/json" \
            -H "Authorization: Bearer $api_key" \
            2>/dev/null || echo "000")

        if [ "$response" = "200" ]; then
            local model_count
            model_count=$(get_model_count /tmp/claude_test_response)
            if [ "$model_count" -gt "0" ]; then
                print_success "API connection successful! Found $model_count models at $base_url" >&2
                rm -f /tmp/claude_test_response
                echo "$base_url"
                return 0
            else
                print_warning "API responded but no models found at $base_url" >&2
            fi
        elif [ "$response" = "401" ]; then
            print_warning "API key authentication failed for $base_url" >&2
        elif [ "$response" = "000" ]; then
            print_warning "Cannot connect to $base_url" >&2
        else
            print_warning "API test failed for $base_url with HTTP status: $response" >&2
        fi

        rm -f /tmp/claude_test_response
    done

    print_error "All API connections failed. Please check your API key and internet connection." >&2
    return 1
}

# Function to create Claude Code settings
create_settings() {
    local base_url="$1"
    local api_key="$2"

    # Create JSON using jq to ensure proper escaping
    local settings_json
    settings_json=$(jq -n \
        --arg base_url "$base_url" \
        --arg api_key "$api_key" \
        '{
            "env": {
                "ANTHROPIC_AUTH_TOKEN": $api_key,
                "ANTHROPIC_BASE_URL": $base_url,
                "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
                "DISABLE_TELEMETRY": "1",
                "DISABLE_ERROR_REPORTING": "1",
                "API_TIMEOUT_MS": "600000"
            },
            "permissions": {
                "allow": [],
                "deny": []
            },
            "model": "opus",
            "alwaysThinkingEnabled": true
        }')

    # Validate JSON
    if ! echo "$settings_json" | jq . >/dev/null 2>&1; then
        print_error "Generated settings JSON is invalid"
        return 1
    fi

    # Write settings file
    echo "$settings_json" >"$CLAUDE_SETTINGS_FILE"
    print_success "Claude Code settings written to: $CLAUDE_SETTINGS_FILE"

    # Write config.json for VSCode Claude extension
    local config_json_path="$CLAUDE_CONFIG_DIR/config.json"
    cat <<EOF >"$config_json_path"
{
  "primaryApiKey": "xcodecli"
}
EOF
    print_success "VSCode Claude config written to: $config_json_path"

    # Write environment variables to shell config
    local rc_file
    rc_file=$(get_shell_rc)
    print_info "Writing environment variables to: $rc_file"
    write_env_to_shell "ANTHROPIC_BASE_URL" "$base_url"
    write_env_to_shell "ANTHROPIC_AUTH_TOKEN" "$api_key"
    print_success "Environment variables written to shell config"
}

# Function to display current settings
display_settings() {
    if [ -f "$CLAUDE_SETTINGS_FILE" ]; then
        print_info "Current Claude Code settings:"
        echo "----------------------------------------"
        cat "$CLAUDE_SETTINGS_FILE" | jq .
        echo "----------------------------------------"
    else
        print_info "No existing Claude Code settings found."
    fi
}

# Main function
main() {
    print_info "Claude Code Configuration Script for XCodeCLI"
    echo "======================================================="
    echo

    # Check dependencies
    check_jq

    # Parse command line arguments
    local api_key=""
    local test_only=false
    local show_settings=false

    # Check for environment variable API_KEY
    if [ -n "$API_KEY" ]; then
        api_key="$API_KEY"
    fi

    while [[ $# -gt 0 ]]; do
        case $1 in
        -k | --key)
            api_key="$2"
            shift 2
            ;;
        -t | --test)
            test_only=true
            shift
            ;;
        -s | --show)
            show_settings=true
            shift
            ;;
        -h | --help)
            cat <<EOF
Usage: $0 [OPTIONS]

This script automatically tests multiple API endpoints and selects the working one:
  - https://api2.xcodecli.com
  - https://api.xcodecli.com

Options:
  -k, --key KEY     Set the API key
  -t, --test        Test API connections only (requires -k)
  -s, --show        Show current settings and exit
  -h, --help        Show this help message

Examples:
  $0 --key your-api-key-here
  $0 --test --key your-api-key-here
  $0 --show

Interactive mode (no arguments):
  $0

Environment Variables:
  API_KEY           API key for authentication
EOF
            exit 0
            ;;
        *)
            print_error "Unknown option: $1"
            print_info "Use --help for usage information"
            exit 1
            ;;
        esac
    done

    # Show settings and exit if requested
    if [ "$show_settings" = true ]; then
        display_settings
        exit 0
    fi

    # 检测工具是否已安装
    if ! command -v "$TOOL_COMMAND" >/dev/null 2>&1; then
        echo ""
        print_warning "$TOOL_NAME 未安装"
        read -p "是否立即安装? (Y/n): " -r
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            print_info "已取消"
            exit 0
        fi

        install_tool || exit 1
    else
        print_success "$TOOL_NAME 已安装"
    fi

    # Interactive mode if no API key provided
    if [ -z "$api_key" ]; then
        print_info "Interactive setup mode"
        echo

        # Get API key
        while [ -z "$api_key" ]; do
            read -p "Enter your API key: " api_key
            if [ -z "$api_key" ]; then
                print_warning "API key is required"
            elif ! validate_api_key "$api_key"; then
                api_key=""
            fi
        done
    fi

    # Validate inputs
    if [ -z "$api_key" ]; then
        print_error "API key is required"
        print_info "Use --help for usage information"
        exit 1
    fi

    # Validate API key
    if ! validate_api_key "$api_key"; then
        exit 1
    fi

    print_info "API Key: ${api_key:0:8}...${api_key: -4}"
    echo

    # Test API connection and get working base URL
    local base_url
    base_url=$(test_api_connection "$api_key")

    if [ $? -ne 0 ] || [ -z "$base_url" ]; then
        if [ "$test_only" = true ]; then
            exit 1
        fi

        read -p "All API tests failed. Continue anyway? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            print_info "Setup cancelled"
            exit 1
        fi

        # If user chooses to continue anyway, use default URL
        base_url="$DEFAULT_BASE_URL"
        print_warning "Using default URL: $base_url"
    else
        print_info "Selected working base URL: $base_url"
    fi

    # Exit if test only
    if [ "$test_only" = true ]; then
        print_success "API test completed successfully"
        exit 0
    fi

    # Create settings directory
    create_settings_dir

    # Backup existing settings
    backup_settings

    # Create new settings
    if create_settings "$base_url" "$api_key"; then
        echo
        print_success "Claude Code has been configured successfully!"
        print_info "You can now use Claude Code with your API router."
        print_info ""
        print_info "To verify the setup, run:"
        print_info "  claude --version"
        print_info ""
        print_info "Configuration file location: $CLAUDE_SETTINGS_FILE"

        if [ -f "$CLAUDE_SETTINGS_FILE" ]; then
            echo
            print_info "Current settings:"
            cat "$CLAUDE_SETTINGS_FILE" | jq .
        fi

        echo
        print_warning "⚠️  请重启终端（或执行 'source $(get_shell_rc)'）使环境变量生效，然后再启动 Claude Code"
    else
        print_error "Failed to create Claude Code settings"
        exit 1
    fi
}

# Run main function
main "$@"
