# XCodeCLI Setup Launcher (Windows)
# 一站式安装和配置 Claude Code, Gemini CLI, Codex

param(
    [string]$ApiKey,
    [switch]$Help
)

# 支持一行命令传入 API Key: $key='xxx'; iex (irm URL)
if (-not $ApiKey -and (Test-Path Variable:key)) { $ApiKey = $key }

# ========== UTF-8 编码兼容 ==========
# 确保中文字符在各种 PowerShell 环境中正确显示
# 兼容: Windows PowerShell 5.x, PowerShell 7.x, Windows Terminal, conhost, ISE, iwr|iex
try {
    # 1. 先设置控制台代码页为 UTF-8
    if ($env:OS -eq 'Windows_NT') {
        & cmd /c "chcp 65001 >nul" 2>&1 | Out-Null
    }
    # 2. 设置 .NET 控制台编码 (Write-Host 依赖此设置)
    [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
    [Console]::InputEncoding = [System.Text.Encoding]::UTF8
    # 3. 设置 PowerShell 管道/cmdlet 输出编码
    $OutputEncoding = [System.Text.Encoding]::UTF8
} catch {
    # 静默处理 - ISE 等环境可能不支持 Console 类操作
}
# ========== 颜色输出函数 ==========
function Write-Info { param([string]$Message); Write-Host "[INFO]" -ForegroundColor Blue -NoNewline; Write-Host " $Message" }
function Write-Success { param([string]$Message); Write-Host "[SUCCESS]" -ForegroundColor Green -NoNewline; Write-Host " $Message" }
function Write-Warning { param([string]$Message); Write-Host "[WARNING]" -ForegroundColor Yellow -NoNewline; Write-Host " $Message" }
function Write-Error { param([string]$Message); Write-Host "[ERROR]" -ForegroundColor Red -NoNewline; Write-Host " $Message" }

# ========== 工具配置表 ==========
$ToolsConfig = @{
    1 = @{
        Name     = "Claude Code"
        Command  = "claude"
        Package  = "@anthropic-ai/claude-code"
        SetupUrl = "https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/ClaudeCode/setup-claude-code.ps1"
    }
    2 = @{
        Name     = "Gemini CLI"
        Command  = "gemini"
        Package  = "@google/gemini-cli@latest"
        SetupUrl = "https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/GeminiCLI/setup-gemini.ps1"
    }
    3 = @{
        Name     = "Codex"
        Command  = "codex"
        Package  = "@openai/codex"
        SetupUrl = "https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/codex/setup-codex.ps1"
    }
}

# ========== 帮助信息 ==========
function Show-Help {
    Write-Host @"
XCodeCLI Setup Launcher (Windows)
一站式安装和配置 Claude Code, Gemini CLI, Codex

Usage: powershell -ExecutionPolicy Bypass -File setup.ps1 [OPTIONS]

Options:
  -ApiKey <KEY>  预设 API 密钥（可选）
  -Help          显示此帮助信息

环境要求:
  - Node.js >= 20.x
  - 若未安装 Node.js，脚本会自动通过 fnm 安装 Node.js 24.x

一行命令快速使用:
  `$key='YOUR_API_KEY'; $f="$env:TEMP\xc.ps1";iwr -useb https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/setup.ps1 -OutFile $f;& $f
"@
    exit 0
}

# ========== 工具函数 ==========
function Test-Command {
    param([string]$Name)
    return [bool](Get-Command $Name -ErrorAction SilentlyContinue)
}

function Refresh-Path {
    $env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
}

# ========== Node.js 版本检测 ==========
function Get-NodeVersion {
    if (Test-Command "node") {
        try {
            $versionStr = (& node --version 2>$null) -replace 'v', ''
            $major = [int]($versionStr -split '\.')[0]
            return @{ Version = $versionStr; Major = $major }
        }
        catch { }
    }
    return $null
}

# ========== fnm 安装 ==========
function Install-Fnm {
    Write-Host ""
    Write-Info "正在安装 fnm (Fast Node Manager)..."

    try {
        # 使用 winget 安装 fnm
        if (Test-Command "winget") {
            Write-Info "使用 winget 安装 fnm..."
            & winget install Schniz.fnm -e --accept-source-agreements --accept-package-agreements
        }
        else {
            # 备选：使用 cargo 或手动下载
            Write-Info "使用 PowerShell 脚本安装 fnm..."
            Invoke-Expression "& { $(Invoke-RestMethod https://fnm.vercel.app/install.ps1) }"
        }

        Refresh-Path

        # 配置 fnm 环境
        if (Test-Command "fnm") {
            Write-Success "fnm 安装成功!"
            # 初始化 fnm
            $fnmEnv = & fnm env --use-on-cd 2>$null
            if ($fnmEnv) {
                $fnmEnv | Out-String | Invoke-Expression
            }
            return $true
        }
        else {
            Write-Warning "fnm 可能已安装，但需要重新打开终端才能生效"
            Write-Info "请重新打开 PowerShell 后再运行此脚本"
            return $false
        }
    }
    catch {
        Write-Error "fnm 安装失败: $($_.Exception.Message)"
        return $false
    }
}

# ========== 使用 fnm 安装 Node.js ==========
function Install-NodeWithFnm {
    Write-Info "使用 fnm 安装 Node.js 24.x..."

    try {
        & fnm install 24
        & fnm use 24
        & fnm default 24
        Refresh-Path

        if (Test-Command "node") {
            $nodeInfo = Get-NodeVersion
            Write-Success "Node.js v$($nodeInfo.Version) 安装成功!"
            return $true
        }
        else {
            Write-Warning "Node.js 可能已安装，但需要重新打开终端才能生效"
            return $false
        }
    }
    catch {
        Write-Error "Node.js 安装失败: $($_.Exception.Message)"
        return $false
    }
}

# ========== 确保 Node.js 环境就绪 ==========
function Ensure-NodeEnvironment {
    $nodeInfo = Get-NodeVersion

    if ($nodeInfo) {
        Write-Info "检测到 Node.js v$($nodeInfo.Version)"

        if ($nodeInfo.Major -lt 20) {
            Write-Warning "Node.js 版本过低 (需要 >= 20.x)"
            Write-Info "请升级 Node.js 或让脚本使用 fnm 安装新版本"

            $upgrade = Read-Host "是否使用 fnm 安装 Node.js 24.x? (Y/n)"
            if ($upgrade -eq "n" -or $upgrade -eq "N") {
                Write-Error "Node.js 版本不满足要求，请手动升级后重试"
                return $false
            }

            # 安装 fnm (如果未安装)
            if (-not (Test-Command "fnm")) {
                if (-not (Install-Fnm)) { return $false }
            }

            return Install-NodeWithFnm
        }

        return $true
    }

    # 未安装 Node.js
    Write-Warning "未检测到 Node.js"
    Write-Info "将使用 fnm 安装 Node.js 24.x"

    $install = Read-Host "是否继续? (Y/n)"
    if ($install -eq "n" -or $install -eq "N") {
        return $false
    }

    # 安装 fnm
    if (-not (Test-Command "fnm")) {
        if (-not (Install-Fnm)) { return $false }
    }

    return Install-NodeWithFnm
}

# ========== 工具安装 ==========
function Install-Tool {
    param(
        [hashtable]$Tool
    )

    # 所有工具统一使用 npm 安装 (需要 Node.js)
    if (-not (Ensure-NodeEnvironment)) {
        return $false
    }

    Write-Info "使用 npm 安装 $($Tool.Name)..."
    $installCmd = "npm install -g $($Tool.Package)"
    Write-Host "  执行: $installCmd" -ForegroundColor Gray

    try {
        Invoke-Expression $installCmd
        $exitCode = $LASTEXITCODE
        Refresh-Path

        if ($exitCode -ne 0) {
            Write-Error "安装命令返回错误码: $exitCode"
            return $false
        }

        if (Test-Command $Tool.Command) {
            Write-Success "$($Tool.Name) 安装成功!"
            return $true
        }
        else {
            Write-Warning "$($Tool.Name) 可能已安装，但需要重新打开终端才能生效"
            $continue = Read-Host "是否继续进行配置? (Y/n)"
            return ($continue -ne "n" -and $continue -ne "N")
        }
    }
    catch {
        Write-Error "安装失败: $($_.Exception.Message)"
        return $false
    }
}

# ========== 远程配置脚本调用 ==========
function Invoke-RemoteSetup {
    param(
        [hashtable]$Tool,
        [string]$ApiKey
    )

    Write-Host ""
    Write-Info "下载并执行 $($Tool.Name) 配置脚本..."
    Write-Host "  URL: $($Tool.SetupUrl)" -ForegroundColor Gray
    Write-Host ""

    $tempFile = $null
    try {
        # 下载脚本到临时文件
        $tempFile = [System.IO.Path]::ChangeExtension([System.IO.Path]::GetTempFileName(), ".ps1")
        Invoke-WebRequest -Uri $Tool.SetupUrl -UseBasicParsing -OutFile $tempFile

        # 执行脚本，正确传递参数
        $LASTEXITCODE = 0
        if ($ApiKey) {
            & $tempFile -ApiKey $ApiKey
        }
        else {
            & $tempFile
        }

        $scriptSucceeded = $?
        $exitCode = $LASTEXITCODE

        # 清理临时文件
        Remove-Item $tempFile -ErrorAction SilentlyContinue

        # 检查执行结果
        if (-not $scriptSucceeded -or $exitCode -ne 0) {
            Write-Error "配置脚本执行失败，退出码: $exitCode"
            return $false
        }

        Write-Host ""
        Write-Success "$($Tool.Name) 配置完成!"
        return $true
    }
    catch {
        if ($tempFile) { Remove-Item $tempFile -ErrorAction SilentlyContinue }
        Write-Error "配置脚本执行失败: $($_.Exception.Message)"
        return $false
    }
}

# ========== 菜单显示 ==========
function Show-Menu {
    Write-Host ""
    Write-Host "========================================" -ForegroundColor Cyan
    Write-Host "       XCodeCLI Setup Launcher" -ForegroundColor Cyan
    Write-Host "========================================" -ForegroundColor Cyan
    Write-Host ""

    # 显示 Node.js 环境状态
    $nodeInfo = Get-NodeVersion
    if ($nodeInfo) {
        $nodeStatus = if ($nodeInfo.Major -ge 20) { "[OK]" } else { "[需升级]" }
        $nodeColor = if ($nodeInfo.Major -ge 20) { "Green" } else { "Yellow" }
        Write-Host "  Node.js: v$($nodeInfo.Version) " -NoNewline
        Write-Host $nodeStatus -ForegroundColor $nodeColor
    }
    else {
        Write-Host "  Node.js: " -NoNewline
        Write-Host "[未安装]" -ForegroundColor Red
    }
    Write-Host ""

    Write-Host "选择要安装和配置的工具:" -ForegroundColor Yellow
    Write-Host ""

    foreach ($key in ($ToolsConfig.Keys | Sort-Object)) {
        $tool = $ToolsConfig[$key]
        $installed = Test-Command $tool.Command
        $status = if ($installed) { "[已安装]" } else { "[未安装]" }
        $color = if ($installed) { "Green" } else { "Red" }
        $label = "  [$key] $($tool.Name.PadRight(12))"
        Write-Host "$label " -NoNewline
        Write-Host $status -ForegroundColor $color
    }

    Write-Host ""
    Write-Host "  [0] 退出" -ForegroundColor Gray
    Write-Host ""
}

# ========== 主函数 ==========
function Main {
    if ($Help) { Show-Help }

    Show-Menu
    $choice = Read-Host "请选择 (0-3)"

    # 退出选项
    if ($choice -eq "0") {
        Write-Info "再见!"
        exit 0
    }

    # 验证选择
    $choiceNum = 0
    if (-not [int]::TryParse($choice, [ref]$choiceNum) -or $choiceNum -lt 1 -or $choiceNum -gt 3) {
        Write-Error "无效的选择"
        exit 1
    }

    $tool = $ToolsConfig[$choiceNum]

    # 检测是否已安装
    if (-not (Test-Command $tool.Command)) {
        Write-Host ""
        Write-Warning "$($tool.Name) 未安装"
        $install = Read-Host "是否立即安装? (Y/n)"

        if ($install -eq "n" -or $install -eq "N") {
            Write-Info "已取消"
            exit 0
        }

        if (-not (Install-Tool -Tool $tool)) {
            exit 1
        }
    }
    else {
        Write-Host ""
        Write-Success "$($tool.Name) 已安装"
    }

    # 调用远程配置脚本
    if (-not (Invoke-RemoteSetup -Tool $tool -ApiKey $ApiKey)) {
        exit 1
    }
}

Main
