#!/bin/bash
# Codex Configuration Script for XCodeCLI
# This script configures Codex to use your XCodeCLI instance
# Automatically tests multiple API endpoints and selects the working one

set -e

# Color functions for output
print_info() {
    echo -e "\033[34m[INFO]\033[0m $1"
}

print_success() {
    echo -e "\033[32m[SUCCESS]\033[0m $1"
}

print_warning() {
    echo -e "\033[33m[WARNING]\033[0m $1"
}

print_error() {
    echo -e "\033[31m[ERROR]\033[0m $1"
}

# Default values
TEST_ONLY=false
SHOW_SETTINGS=false
DEFAULT_BASE_URL="https://api2.xcodecli.com"
TOOL_COMMAND="codex"
TOOL_PACKAGE="@openai/codex"
TOOL_NAME="Codex"

# ========== 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"
}

# ========== 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 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"
}

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

# Function to show help
show_help() {
    cat <<EOF
Codex Configuration Script for XCodeCLI

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

Usage: $0 [OPTIONS]

Options:
  --key KEY        Set the API key
  --test           Test API connections only (requires --key)
  --show           Show current settings and exit
  --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
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
    --key)
        API_KEY="$2"
        shift 2
        ;;
    --test)
        TEST_ONLY=true
        shift
        ;;
    --show)
        SHOW_SETTINGS=true
        shift
        ;;
    --help)
        show_help
        exit 0
        ;;
    *)
        print_error "Unknown option: $1"
        show_help
        exit 1
        ;;
    esac
done

# Use environment variable if no --key provided
if [ -z "$API_KEY" ] && [ -n "$API_KEY_FROM_ENV" ]; then
    API_KEY="$API_KEY_FROM_ENV"
fi

# Function to backup existing configuration
backup_config() {
    if [ -f "$HOME/.codex/config.toml" ]; then
        local timestamp=$(date +%Y%m%d_%H%M%S)
        local backup_file="$HOME/.codex/config.toml.backup.$timestamp"
        local backup_auth_file="$HOME/.codex/auth.json.backup.$timestamp"
        cp "$HOME/.codex/config.toml" "$backup_file"
        if [ -f "$HOME/.codex/auth.json" ]; then
            cp "$HOME/.codex/auth.json" "$backup_auth_file"
            print_info "Backed up existing auth file to: $backup_auth_file"
        fi
        print_info "Backed up existing configuration to: $backup_file"
    fi
}

# 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"

        local response
        response=$(curl -s -w "%{http_code}" -o /tmp/codex_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/codex_test_response)
            if [ "$model_count" -gt "0" ]; then
                print_success "API connection successful! Found $model_count models at $base_url" >&2
                rm -f /tmp/codex_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/codex_test_response
    done

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

# Function to create Codex configuration
create_codex_config() {
    local base_url="$1"
    local api_key="$2"

    # Create config directory if it doesn't exist
    mkdir -p "$HOME/.codex"

    # Create config.toml
    cat >"$HOME/.codex/config.toml" <<EOF
model_provider = "xcodecli"
model = "gpt-5.1-codex"
model_reasoning_effort = "high"
disable_response_storage = true
preferred_auth_method = "apikey"

[model_providers.xcodecli]
name = "xcodecli"
base_url = "${base_url}/v1"
wire_api = "responses"
requires_openai_auth = true
env_key = "XCODECLI_OAI_KEY"
EOF

    # Create auth.json with OPENAI_API_KEY
    cat >"$HOME/.codex/auth.json" <<EOF
{
  "OPENAI_API_KEY": "$api_key"
}
EOF

    print_success "Codex configuration written to: $HOME/.codex/config.toml"
    print_success "Codex auth file written to: $HOME/.codex/auth.json"

    # Write environment variable XCODECLI_OAI_KEY to shell config
    local rc_file
    rc_file=$(get_shell_rc)
    print_info "Writing environment variables to: $rc_file"
    write_env_to_shell "XCODECLI_OAI_KEY" "$api_key"
    print_success "Environment variables written to shell config"

    return 0
}

# Function to show current settings
show_current_settings() {
    print_info "Current Codex settings:"
    echo "----------------------------------------"

    if [ -f "$HOME/.codex/config.toml" ]; then
        print_info "Configuration file: $HOME/.codex/config.toml"
        echo ""
        cat "$HOME/.codex/config.toml"
        echo ""
    else
        print_info "No configuration file found at $HOME/.codex/config.toml"
    fi

    echo "----------------------------------------"

    if [ -f "$HOME/.codex/auth.json" ]; then
        print_info "Auth file: $HOME/.codex/auth.json"
        cat "$HOME/.codex/auth.json"
        echo "----------------------------------------"
    fi

    # Show XCODECLI_OAI_KEY from environment
    if [ -n "$XCODECLI_OAI_KEY" ]; then
        local masked_key="${XCODECLI_OAI_KEY:0:8}...${XCODECLI_OAI_KEY: -4}"
        print_info "XCODECLI_OAI_KEY (env): $masked_key"
    else
        print_warning "XCODECLI_OAI_KEY environment variable not set"
    fi
}

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

    # Show current settings and exit if requested
    if [ "$SHOW_SETTINGS" = true ]; then
        show_current_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 format
    if ! validate_api_key "$API_KEY"; then
        exit 1
    fi

    # Mask API key for display
    if [ ${#API_KEY} -gt 12 ]; then
        masked_key="${API_KEY:0:8}...${API_KEY: -4}"
    else
        masked_key="${API_KEY:0:4}..."
    fi
    print_info "API Key: $masked_key"
    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

        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

    # Backup existing configuration
    backup_config

    # Create Codex configuration
    if ! create_codex_config "$BASE_URL" "$API_KEY"; then
        print_error "Failed to create Codex configuration"
        exit 1
    fi

    echo ""
    print_success "Codex has been configured successfully!"
    print_info "You can now use Codex with your XCodeCLI API router."
    print_info ""
    print_info "Configuration file: $HOME/.codex/config.toml"
    print_info "Auth file: $HOME/.codex/auth.json"
    print_info "Environment variable: XCODECLI_OAI_KEY"

    # Show current settings
    echo ""
    show_current_settings

    echo ""
    print_warning "⚠️  请重启终端（或执行 'source $(get_shell_rc)'）使环境变量生效，然后再启动 Codex"
}

# Run main function
main
