$ErrorActionPreference = "Stop"

$coreDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$appDir = Split-Path -Parent $coreDir
$runtimeDir = Join-Path $coreDir "runtime"
$pythonDir = Join-Path $runtimeDir "python"
$sitePackagesDir = Join-Path $runtimeDir "site-packages"
$pythonExe = Join-Path $pythonDir "python.exe"
$archive = Join-Path $runtimeDir "python-3.13.14-embed-amd64.zip"
$getPip = Join-Path $runtimeDir "get-pip.py"
$sentinel = Join-Path $runtimeDir "coco-deps-v1"
$logPath = Join-Path $appDir "bootstrap.log"
$pythonVersion = "3.13.14"
$pythonUrl = "https://www.python.org/ftp/python/$pythonVersion/python-$pythonVersion-embed-amd64.zip"
$getPipUrl = "https://bootstrap.pypa.io/get-pip.py"

$dependencies = @(
    "PyYAML>=6.0",
    "requests>=2.28",
    "numpy>=1.24",
    "edge-tts>=6.1",
    "sounddevice>=0.4",
    "tencentcloud-sdk-python-asr>=3.1",
    "PyQt6>=6.11,<6.12",
    "PyQt6-WebEngine>=6.11,<6.12"
)

function Download-File {
    param(
        [string]$Url,
        [string]$Target
    )

    Write-Host "下载: $Url"
    Invoke-WebRequest -Uri $Url -OutFile $Target -UseBasicParsing
}

function Assert-ExitCode {
    param([string]$Action)
    if ($LASTEXITCODE -ne 0) {
        throw "$Action 失败，退出码: $LASTEXITCODE"
    }
}

function Configure-EmbeddedPython {
    $pth = Get-ChildItem -LiteralPath $pythonDir -Filter "python*._pth" -File |
        Select-Object -First 1
    if (-not $pth) {
        throw "找不到 Python 嵌入式路径配置文件"
    }

    $lines = @(
        Get-Content -LiteralPath $pth.FullName -Encoding UTF8 |
            ForEach-Object {
                $line = $_.Trim()
                if ($line -eq "#import site") {
                    "import site"
                } else {
                    $line
                }
            }
    )

    if (-not ($lines | Where-Object { $_ -replace "/", "\" -ieq "Lib\site-packages" })) {
        $lines += "Lib\site-packages"
    }
    if (-not ($lines | Where-Object { $_ -replace "/", "\" -ieq "..\site-packages" })) {
        $lines += "..\site-packages"
    }
    if (-not ($lines | Where-Object { $_ -ieq "import site" })) {
        $lines += "import site"
    }

    $utf8NoBom = New-Object System.Text.UTF8Encoding($false)
    [IO.File]::WriteAllText(
        $pth.FullName,
        ($lines -join [Environment]::NewLine),
        $utf8NoBom
    )
}

function Ensure-PortablePython {
    if (Test-Path -LiteralPath $pythonExe) {
        & $pythonExe -c "import sys; print(sys.version)"
        if ($LASTEXITCODE -eq 0) {
            return
        }
        Remove-Item -LiteralPath $pythonDir -Recurse -Force
    }

    New-Item -ItemType Directory -Path $runtimeDir -Force | Out-Null
    if (-not (Test-Path -LiteralPath $archive)) {
        Download-File $pythonUrl $archive
    }

    Write-Host "解压便携式 Python..."
    New-Item -ItemType Directory -Path $pythonDir -Force | Out-Null
    Expand-Archive -LiteralPath $archive -DestinationPath $pythonDir -Force
    Configure-EmbeddedPython
}

function Ensure-Pip {
    & $pythonExe -m pip --version *> $null
    if ($LASTEXITCODE -eq 0) {
        return
    }

    if (-not (Test-Path -LiteralPath $getPip)) {
        Download-File $getPipUrl $getPip
    }
    Write-Host "安装 pip..."
    & $pythonExe $getPip --disable-pip-version-check --no-warn-script-location
    Assert-ExitCode "pip 安装"
}

function Install-Dependencies {
    New-Item -ItemType Directory -Path $sitePackagesDir -Force | Out-Null
    $total = $dependencies.Count
    $index = 0
    $indexUrl = $env:coco_pip_index_url

    foreach ($dependency in $dependencies) {
        $index++
        Write-Host ""
        Write-Host "[$index/$total] 正在安装 $dependency"

        $arguments = @(
            "-m", "pip", "install",
            "--target", $sitePackagesDir,
            "--upgrade",
            "--only-binary=:all:",
            "--disable-pip-version-check",
            "--no-warn-script-location",
            "--progress-bar", "on"
        )
        if ($indexUrl) {
            $arguments += @("--index-url", $indexUrl)
        }
        $arguments += $dependency

        & $pythonExe @arguments
        Assert-ExitCode $dependency
        Write-Host "[$index/$total] $dependency 安装完成"
    }
}

function Verify-Dependencies {
    $checkCode = @'
import importlib

modules = [
    ("yaml", "PyYAML"),
    ("requests", "requests"),
    ("numpy", "numpy"),
    ("edge_tts", "edge-tts"),
    ("sounddevice", "sounddevice"),
    ("tencentcloud", "tencentcloud-sdk-python-asr"),
    ("PyQt6.QtCore", "PyQt6"),
    ("PyQt6.QtWebEngineWidgets", "PyQt6-WebEngine"),
]

missing = []
for module_name, package_name in modules:
    try:
        importlib.import_module(module_name)
    except Exception as exc:
        print(f"{package_name}: {type(exc).__name__}: {exc}")
        missing.append(package_name)

raise SystemExit(1 if missing else 0)
'@

    Write-Host ""
    Write-Host "检查安装结果..."
    & $pythonExe -c $checkCode
    Assert-ExitCode "依赖检查"
}

try {
    New-Item -ItemType Directory -Path $runtimeDir -Force | Out-Null
    Start-Transcript -LiteralPath $logPath -Append | Out-Null
    Write-Host "安装目录: $appDir"
    Ensure-PortablePython
    Ensure-Pip
    Install-Dependencies
    Verify-Dependencies
    Set-Content -LiteralPath $sentinel -Value ([DateTimeOffset]::UtcNow.ToUnixTimeSeconds()) -Encoding ASCII
    Write-Host ""
    Write-Host "全部依赖安装完成，正在启动 coco..."
    exit 0
} catch {
    Write-Host ""
    Write-Host "安装失败: $($_.Exception.Message)"
    exit 1
} finally {
    try {
        Stop-Transcript | Out-Null
    } catch {
    }
}
