# GitLink CLI Windows 安装脚本
# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1
# 支持: .\install.ps1 -Version 0.1.0 -InstallDir "C:\GitLink"

param(
    [string]$Version = "latest",
    [string]$InstallDir = "$HOME\.gitlink-cli\bin",
    [switch]$Help = $false,
    [switch]$Uninstall = $false,
    [switch]$ListVersions = $false,
    [switch]$Debug = $false
)

$ErrorActionPreference = "Stop"
$REPO_OWNER = "Gitlink"
$REPO_NAME = "gitlink-cli"
$BINARY_NAME = "gitlink-cli"
$API_BASE = "https://www.gitlink.org.cn"
$SKILLS_DIR = "$HOME\.gitlink\skills"

# 颜色输出
function Info {
    param([string]$msg)
    Write-Host "[INFO]  $msg" -ForegroundColor Green
}

function Warn {
    param([string]$msg)
    Write-Host "[WARN]  $msg" -ForegroundColor Yellow
}

function ErrorMsg {
    param([string]$msg)
    Write-Host "[ERROR] $msg" -ForegroundColor Red
}

function Step {
    param([string]$msg)
    Write-Host "[STEP]  $msg" -ForegroundColor Cyan
}

function DebugMsg {
    param([string]$msg)
    if ($Debug) {
        Write-Host "[DEBUG] $msg" -ForegroundColor Blue
    }
}

# 显示帮助
function Show-Help {
    Write-Host @"
GitLink CLI Windows 安装脚本

用法:
  .\install.ps1 [选项]

选项:
  -Version <version>    指定版本 (默认: latest)
  -InstallDir <path>    安装目录 (默认: $HOME\.gitlink-cli\bin)
  -Uninstall            卸载
  -ListVersions         列出可用版本
  -Debug                显示调试信息
  -Help                 显示此帮助

示例:
  # 安装最新版本
  .\install.ps1

  # 安装指定版本
  .\install.ps1 -Version "0.1.0"

  # 安装到指定目录
  .\install.ps1 -InstallDir "C:\Tools\gitlink-cli"

  # 列出可用版本
  .\install.ps1 -ListVersions

  # 卸载
  .\install.ps1 -Uninstall

  # 在线安装
  powershell -NoProfile -ExecutionPolicy Bypass -Command "iex (irm https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.ps1)"
"@
}

# 检测架构
function Get-PlatformInfo {
    $arch = switch ([System.Runtime.InteropServices::RuntimeInformation]::OSArchitecture) {
        "X64" { "amd64" }
        "Arm64" { "arm64" }
        "X86" { "386"; Warn "32位系统支持有限" }
        default { throw "不支持的架构: $arch" }
    }
    return @{ Platform = "windows"; Arch = $arch }
}

# 检查环境
function Test-Environment {
    Step "检查安装环境..."

    # 检查磁盘空间（至少50MB）
    $drive = (Get-Item $InstallDir).PSDrive.Name
    $driveInfo = Get-PSDrive $drive
    $freeSpaceMB = [math]::Round($driveInfo.Free / 1MB, 2)

    if ($freeSpaceMB -lt 50) {
        ErrorMsg "磁盘空间不足（需要至少50MB，可用: ${freeSpaceMB}MB）"
        exit 1
    }
    DebugMsg "磁盘空间检查通过: ${freeSpaceMB}MB"

    # 检查网络连接
    try {
        $response = Invoke-WebRequest -Uri $API_BASE -UseBasicParsing -TimeoutSec 5 -Method Head
        DebugMsg "网络连接检查通过"
    }
    catch {
        ErrorMsg "无法连接到 GitLink 服务器: $API_BASE"
        ErrorMsg "请检查网络连接"
        exit 1
    }

    Info "环境检查通过"
}

# 下载文件（带重试）
function Download-File {
    param(
        [string]$Url,
        [string]$Output,
        [int]$MaxAttempts = 3
    )

    $attempt = 1
    while ($attempt -le $MaxAttempts) {
        try {
            Step "下载 (尝试 $attempt/$MaxAttempts): $(Split-Path $Url -Leaf)"
            DebugMsg "URL: $Url"

            # 使用WebClient，支持进度显示
            $webClient = New-Object System.Net.WebClient

            # 注册下载进度事件
            Register-ObjectEvent -InputObject $webClient -EventName DownloadProgressChanged -SourceIdentifier WebClient.DownloadProgressChanged -Action {
                global:Progress = $EventArgs.ProgressPercentage
                Write-Progress -Activity "下载中" -Status "$($EventArgs.ProgressPercentage)% 完成" -PercentComplete $EventArgs.ProgressPercentage
            } | Out-Null

            # 注册下载完成事件
            Register-ObjectEvent -InputObject $webClient -EventName DownloadFileCompleted -SourceIdentifier WebClient.DownloadFileCompleted -Action {
                global:DownloadComplete = $true
            } | Out-Null

            # 开始下载
            $webClient.DownloadFileAsync($Url, $Output)

            # 等待下载完成
            while (-not $global:DownloadComplete) {
                Start-Sleep -Milliseconds 100
            }

            Write-Progress -Activity "下载中" -Completed

            # 清理事件
            Unregister-Event -SourceIdentifier WebClient.DownloadProgressChanged -ErrorAction SilentlyContinue
            Unregister-Event -SourceIdentifier WebClient.DownloadFileCompleted -ErrorAction SilentlyContinue
            $webClient.Dispose()

            if (Test-Path $Output) {
                $size = [math]::Round((Get-Item $Output).Length / 1MB, 2)
                Info "下载成功: $(Split-Path $Output -Leaf) (${size}MB)"
                return $true
            }
            else {
                Warn "下载文件为空"
            }
        }
        catch {
            Warn "下载失败: $_"
        }

        if ($attempt -lt $MaxAttempts) {
            $waitTime = $attempt * 2
            Warn "等待 ${waitTime}s 后重试..."
            Start-Sleep -Seconds $waitTime
        }

        $attempt++
    }

    ErrorMsg "下载失败，已尝试 $MaxAttempts 次"
    ErrorMsg "URL: $Url"
    return $false
}

# 获取最新版本
function Get-LatestVersion {
    Step "获取最新版本..."

    try {
        $releasesUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases.json"
        $releases = Invoke-RestMethod -Uri $releasesUrl -TimeoutSec 30 -UseBasicParsing

        if ($releases -and $releases.Count -gt 0) {
            return $releases[0].tag_name
        }
        else {
            Warn "无法获取版本信息，使用默认版本"
            return "v0.1.0"
        }
    }
    catch {
        Warn "获取版本失败: $_"
        return "v0.1.0"
    }
}

# 列出可用版本
function Show-AvailableVersions {
    Step "查询可用版本..."

    try {
        $releasesUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases.json"
        $releases = Invoke-RestMethod -Uri $releasesUrl -TimeoutSec 30 -UseBasicParsing

        if ($releases -and $releases.Count -gt 0) {
            Info "可用版本:"
            foreach ($release in $releases | Select-Object -First 10) {
                Write-Host "  - $($release.tag_name)" -ForegroundColor Cyan
            }
        }
        else {
            Warn "无法获取版本列表"
        }
    }
    catch {
        ErrorMsg "获取版本列表失败: $_"
    }
}

# 解压zip文件
function Expand-ZipFile {
    param(
        [string]$ZipPath,
        [string]$DestDir
    )

    Step "解压..."
    DebugMsg "解压 $ZipPath 到 $DestDir"

    try {
        Expand-Archive -Force -Path $ZipPath -DestinationPath $DestDir
        Info "解压完成"
    }
    catch {
        ErrorMsg "解压失败: $_"
        throw
    }
}

# 添加到PATH
function Add-ToPath {
    param([string]$Dir)

    $path = [Environment]::GetEnvironmentVariable("Path", "User")
    if ($path -notlike "*$Dir*") {
        Step "添加到PATH: $Dir"
        [Environment]::SetEnvironmentVariable("Path", "$path;$Dir", "User")
        Warn "请重启终端使PATH生效"
    }
    else {
        DebugMsg "已在PATH中: $Dir"
    }
}

# 验证安装
function Test-Installation {
    Step "验证安装..."

    $binaryPath = Join-Path $InstallDir "$BINARY_NAME.exe"

    if (Test-Path $binaryPath) {
        try {
            $versionOutput = & $binaryPath version 2>$null
            Info "安装成功! $versionOutput"

            # 添加到PATH
            Add-ToPath $InstallDir

            Write-Host ""
            Info "快速开始:"
            Info "  gitlink-cli auth login   # 登录账号"
            Info "  gitlink-cli --help        # 查看所有命令"
            Info "  gitlink-cli version       # 查看版本信息"
            Write-Host ""

            return $true
        }
        catch {
            ErrorMsg "执行二进制文件失败: $_"
            return $false
        }
    }
    else {
        ErrorMsg "安装验证失败: $binaryPath 不存在"
        return $false
    }
}

# 主安装流程
function Install-CLI {
    Write-Host ""
    Write-Host "  ╔══════════════════════════════════════╗"
    Write-Host "  ║     GitLink CLI 一键安装 (Windows)    ║"
    Write-Host "  ╚══════════════════════════════════════╝"
    Write-Host ""

    # 检测平台
    $platform = Get-PlatformInfo
    Info "检测到平台: $($platform.Platform)-$($platform.Arch)"

    # 创建安装目录
    if (!(Test-Path $InstallDir)) {
        New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
        Info "创建安装目录: $InstallDir"
    }

    # 检查环境
    Test-Environment

    # 获取版本
    if ($Version -eq "latest") {
        $Version = Get-LatestVersion
        Info "最新版本: $Version"
    }
    else {
        Info "指定版本: $Version"
    }

    # 下载
    $zipName = "$BINARY_NAME_${Version}_windows_$($platform.Arch).zip"
    $zipUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases/$Version/assets/$zipName"
    $zipPath = Join-Path $env:TEMP $zipName

    if (-not (Download-File -Url $zipUrl -Output $zipPath)) {
        ErrorMsg "请确认以下版本已发布: $Version"
        ErrorMsg "发布页: $API_BASE/$REPO_OWNER/$REPO_NAME/releases"
        exit 1
    }

    # 解压
    Expand-ZipFile -ZipPath $zipPath -DestDir $InstallDir
    Remove-Item $zipPath

    # 安装skills
    Step "安装 skills..."
    if (!(Test-Path $SKILLS_DIR)) {
        New-Item -ItemType Directory -Path $SKILLS_DIR -Force | Out-Null
    }

    $skillsZipName = "$BINARY_NAME_${Version}_skills.zip"
    $skillsUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases/$Version/assets/$skillsZipName"
    $skillsZipPath = Join-Path $env:TEMP $skillsZipName

    if (Download-File -Url $skillsUrl -Output $skillsZipPath) {
        try {
            Expand-Archive -Force -Path $skillsZipPath -DestinationPath $SKILLS_DIR
            Info "Skills 安装到: $SKILLS_DIR"
        }
        catch {
            Warn "Skills 解压失败（可稍后手动安装）"
        }
        Remove-Item $skillsZipPath -ErrorAction SilentlyContinue
    }
    else {
        Warn "Skills 包不可用（可稍后手动安装）"
    }

    # 验证
    if (-not (Test-Installation)) {
        exit 1
    }
}

# 卸载
function Uninstall-CLI {
    Step "卸载 $BINARY_NAME..."

    # 删除二进制
    $binaryPath = Join-Path $InstallDir "$BINARY_NAME.exe"
    if (Test-Path $binaryPath) {
        Remove-Item $binaryPath -Force
        Info "已删除: $binaryPath"
    }

    # 删除skills
    if (Test-Path $SKILLS_DIR) {
        Remove-Item $SKILLS_DIR -Recurse -Force
        Info "已删除: $SKILLS_DIR"
    }

    # 删除配置（可选）
    $response = Read-Host "是否删除配置文件? [y/N]"
    if ($response -eq 'y' -or $response -eq 'Y') {
        $configDir = Join-Path $env:APPDATA "gitlink-cli"
        if (Test-Path $configDir) {
            Remove-Item $configDir -Recurse -Force
            Info "已删除配置文件"
        }
    }

    Info "卸载完成"
}

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

    if ($ListVersions) {
        Show-AvailableVersions
        exit 0
    }

    if ($Uninstall) {
        Uninstall-CLI
        exit 0
    }

    try {
        Install-CLI
    }
    catch {
        ErrorMsg "安装失败: $_"
        exit 1
    }
}

Main
