name: Build Windows
run-name: 构建Win流程

on:
  push:
    branches:
      - main
      - dev
  pull_request:
    branches:
      - main
      - dev

jobs:
  # 先编译 libcore
  build-libcore:
    name: 编译 libcore (Windows)
    runs-on: client-server
    container:
      image: node:20
    strategy:
      matrix:
        # 只有node支持版本号别名
        node: ['20.15.1']

    steps:
    - name: 📥 Checkout 代码
      uses: actions/checkout@v4
      with:
        submodules: recursive
        fetch-depth: 0

    - name: 🔧 设置 Go 环境
      uses: actions/setup-go@v5
      with:
        go-version: '1.23'
        cache: true
        cache-dependency-path: libcore/go.sum

    - name: 🔧 安装 MinGW
      run: |
        # 在 GitHub 托管 runner（有 sudo）与 act/自托管容器（无 sudo）均可运行
        if command -v sudo >/dev/null 2>&1; then
          sudo apt-get update
          sudo apt-get install -y mingw-w64
        else
          echo "sudo 不存在，按 root 用户直接执行 apt-get"
          export DEBIAN_FRONTEND=noninteractive
          apt-get update || apt update
          apt-get install -y mingw-w64 || apt install -y mingw-w64
        fi

    - name: 📦 编译 libcore.dll
      working-directory: libcore
      run: |
        echo "🚀 开始编译 Windows libcore..."
        make windows-amd64
        
        if [ -f "bin/libcore.dll" ] && [ -f "bin/HiddifyCli.exe" ]; then
          echo "✅ Windows libcore 编译成功"
          ls -lh bin/
        else
          echo "❌ Windows libcore 编译失败"
          exit 1
        fi

    - name: 📤 上传 Windows libcore
      uses: actions/upload-artifact@v3
      with:
        name: libcore-windows
        path: |
          libcore/bin/libcore.dll
          libcore/bin/HiddifyCli.exe
          libcore/bin/webui/**
        retention-days: 7


  # 构建 Windows 应用
  build:
    runs-on: windows-latest
    needs: build-libcore
    steps:
    - name: 🔧 Add Git to PATH (Windows)
      if: ${{ runner.os == 'Windows' }}
      shell: powershell
      run: |
        $paths = @(
          'C:\Program Files\Git\cmd',
          'C:\Program Files\Git\bin',
          'C:\Program Files (x86)\Git\cmd',
          'C:\Program Files (x86)\Git\bin'
        )
        foreach ($p in $paths) {
          if (Test-Path $p) {
            Add-Content -Path $env:GITHUB_PATH -Value $p
            $env:PATH = "$p;$env:PATH"
            Write-Host ("Added to PATH: {0}" -f $p)
          }
        }
        $candidates = @(
          'C:\Program Files\Git\cmd\git.exe',
          'C:\Program Files\Git\bin\git.exe',
          'C:\Program Files (x86)\Git\cmd\git.exe',
          'C:\Program Files (x86)\Git\bin\git.exe'
        )
        $found = $false
        foreach ($g in $candidates) {
          if (Test-Path $g) {
            & $g --version
            $found = $true
            break
          }
        }
        if (-not $found) {
          Write-Host "Git executable not found in common locations; continuing."
        }

    - name: 📥 Checkout 代码
      uses: actions/checkout@v4
      with:
        submodules: recursive
        fetch-depth: 0

    - name: 📥 下载 libcore
      uses: actions/download-artifact@v3
      with:
        name: libcore-windows
        path: .

    - name: 🔧 复制 libcore 文件到正确位置并重命名
      shell: cmd
      run: call copy_libcore.bat

    - name: 🔍 Verify jq Installation (ACT)
      shell: powershell
      run: |
        # Check if jq is available
        $jqFound = $false
        try {
          $version = jq --version 2>&1
          if ($version -match 'jq-[\d\.]+') {
            Write-Host "jq is already installed: $version"
            $jqFound = $true
          }
        } catch {
          Write-Host "jq not installed or not in PATH"
        }
        if (-not $jqFound) {
          Write-Host "Preparing to install jq..."
          # Check if Chocolatey is available
          $chocoFound = $false
          try {
            choco --version 2>&1 | Out-Null
            $chocoFound = $true
          } catch {}
          if (-not $chocoFound) {
            Write-Host "Installing Chocolatey..."
            Set-ExecutionPolicy Bypass -Scope Process -Force
            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
            iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
            # Refresh PATH
            $env:PATH = [System.Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';' + [System.Environment]::GetEnvironmentVariable('PATH', 'User')
            Write-Host "Chocolatey installed successfully"
          }
          Write-Host "Installing jq using Chocolatey..."
          choco install jq -y
          if ($LASTEXITCODE -eq 0) {
            Write-Host "jq installed successfully"
            # Verify again
            $version = jq --version 2>&1
            Write-Host "jq version: $version"
          } else {
            Write-Host "jq installation failed, exit code: $LASTEXITCODE"
            exit 1
          }
        }

    - name: Add jq to PATH
      shell: powershell
      run: |
        $jqPath = "C:\ProgramData\chocolatey\bin"
        if (Test-Path $jqPath) {
          Add-Content -Path $env:GITHUB_PATH -Value $jqPath
          $env:PATH = "$jqPath;$env:PATH"
          Write-Host "Added jq path to GITHUB_PATH and current PATH"
        } else {
          Write-Host "jq installation path not found"
          exit 1
        }

    - name: Add Flutter to PATH
      shell: powershell
      run: |
        # Add Flutter to PATH for current session and GitHub Actions
        $flutterPath = "C:\flutter\bin"
        if (Test-Path $flutterPath) {
          Write-Host "Adding Flutter to PATH: $flutterPath"
          $env:PATH = "$flutterPath;$env:PATH"
          Add-Content -Path $env:GITHUB_PATH -Value $flutterPath
          
          # Verify Flutter is accessible
          $flutterVersion = flutter --version 2>&1
          if ($LASTEXITCODE -eq 0) {
            Write-Host "Flutter verified: $flutterVersion"
          } else {
            Write-Host "Flutter not found at $flutterPath"
            exit 1
          }
        } else {
          Write-Host "ERROR: Flutter not found at C:\flutter\bin"
          exit 1
        }

    - name: Enable Windows desktop
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;$env:PATH"
        flutter config --enable-windows-desktop

    - name: Get dependencies
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;$env:PATH"
        flutter pub get

    - name: Generate code
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;$env:PATH"
        dart run build_runner build --delete-conflicting-outputs

    - name: Install NuGet
      shell: powershell
      run: |
        Write-Host "Installing NuGet..."
        
        # Check if NuGet is already available
        $nugetPath = Get-Command nuget -ErrorAction SilentlyContinue
        if ($nugetPath) {
          Write-Host "NuGet already installed: $($nugetPath.Source)"
          $nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
          Write-Host "NuGet version: $nugetVersion"
          return
        }
        
        # Use Chocolatey to install NuGet (proven to work)
        Write-Host "Installing NuGet via Chocolatey..."
        choco install nuget.commandline -y
        
        # Update PATH to include Chocolatey
        $env:PATH = "C:\ProgramData\chocolatey\bin;$env:PATH"
        Add-Content -Path $env:GITHUB_PATH -Value "C:\ProgramData\chocolatey\bin"
        
        # Verify installation
        if (Get-Command nuget -ErrorAction SilentlyContinue) {
          Write-Host "NuGet installed successfully via Chocolatey"
          $nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
          Write-Host "NuGet version: $nugetVersion"
        } else {
          Write-Host "WARNING: NuGet installation may have failed, but continuing..."
        }

    - name: Fix long paths
      shell: powershell
      run: |
        Write-Host "Enabling long path support..."
        
        # Enable long paths in Windows
        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force
        
        # Also set for current user
        Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\AppModel\StateRepository\Cache\Package\Data\" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force -ErrorAction SilentlyContinue
        
        Write-Host "Long path support enabled"

    - name: Clean build cache
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;$env:PATH"
        Write-Host "Cleaning build cache..."
        flutter clean
        
        Write-Host "Removing old build directories..."
        if (Test-Path "build") {
          Remove-Item -Path "build" -Recurse -Force
        }
        if (Test-Path "windows") {
          Remove-Item -Path "windows" -Recurse -Force
        }
        
        Write-Host "Recreating Windows project..."
        flutter create --platforms=windows .

    - name: Build Windows Debug
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
        flutter build windows

    - name: Build Windows Release
      shell: powershell
      run: |
        $env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
        flutter build windows --release

    - name: Upload Debug build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: windows-debug-build
        path: build/windows/x64/runner/Debug/

    - name: Upload Release build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: windows-release-build
        path: build/windows/x64/runner/Release/

    - name: Install Build Tools
      shell: powershell
      run: |
        choco install 7zip -y
        choco install enigma-virtual-box -y

    - name: Package Single EXE
      shell: powershell
      run: |
        Write-Host "=== 开始打包单文件 EXE ==="
        
        $buildPath = "build\windows\x64\runner\Release"
        $outputPath = "dist"
        $enigmaPath = "C:\Program Files\Enigma Virtual Box\enigmavb.exe"
        
        # 创建输出目录
        if (-not (Test-Path $outputPath)) {
          New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
        }
        
        # 获取主程序
        $exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
        if (-not $exeFile) {
          Write-Host "❌ 未找到可执行文件"
          exit 1
        }
        
        $inputExe = $exeFile.FullName
        $outputExe = "$outputPath\$($exeFile.BaseName)_Single.exe"
        
        Write-Host "主程序: $inputExe"
        Write-Host "输出: $outputExe"
        
        # 尝试使用 Enigma Virtual Box
        if (Test-Path $enigmaPath) {
          Write-Host "使用 Enigma Virtual Box 打包..."
          
          # 创建配置文件
          $configContent = "[Config]`nInputFile=$inputExe`nOutputFile=$outputExe`nFiles=%DEFAULT FOLDER%`nVirtualizationMode=Never Write To Disk`nCompression=Yes`nShareVirtualSystem=Yes`n`n[Files]`nFolder=$buildPath\*"
          
          $configFile = "$outputPath\package_config.evb"
          Set-Content -Path $configFile -Value $configContent
          
          # 执行打包
          $process = Start-Process -FilePath $enigmaPath -ArgumentList "/sf", $inputExe, "/lf", $outputExe, "/folder", $buildPath, "/compress" -Wait -PassThru -NoNewWindow
          
          if ($process.ExitCode -eq 0) {
            Write-Host "✅ 单文件打包成功!"
            
            # 显示压缩信息
            $originalSize = (Get-Item $inputExe).Length / 1MB
            $packedSize = (Get-Item $outputExe).Length / 1MB
            Write-Host "原始大小: $([math]::Round($originalSize, 2)) MB"
            Write-Host "打包大小: $([math]::Round($packedSize, 2)) MB"
          } else {
            Write-Host "⚠️ Enigma 打包失败，使用备选方案"
            exit 1
          }
        } else {
          Write-Host "⚠️ Enigma 未找到，使用 7-Zip 自解压方案"
          exit 1
        }

    - name: Package with 7-Zip Alternative
      if: failure()
      shell: powershell
      run: |
        Write-Host "使用 7-Zip 自解压方案..."
        
        $buildPath = "build\windows\x64\runner\Release"
        $outputPath = "dist"
        
        # 检查 7-Zip
        $7zipPath = "C:\Program Files\7-Zip\7z.exe"
        
        # 获取主程序名称
        $exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
        $outputSfx = "$outputPath\$($exeFile.BaseName)_Package.exe"
        
        Write-Host "创建自解压包..."
        
        # 创建配置文件
        $configContent = @"
;!@Install@!UTF-8!
Title="HostExecutor Windows Package"
BeginPrompt="正在解压 HostExecutor..."
ExtractDialogText="请稍候，正在解压文件..."
ExtractPathText="解压路径:"
ExtractTitle="解压中"
FinishMessage="解压完成!"
GUIFlags="8"
;!@InstallEnd@!
"@
        
        $configFile = "$outputPath\config.txt"
        Set-Content -Path $configFile -Value $configContent -Encoding UTF8
        
        # 创建压缩包
        & $7zipPath a -sfx7z.sfx -r "$outputSfx" "$buildPath\*" -scsUTF-8 -y
        Copy-Item "$configFile" -Destination "$outputSfx" -Force
        
        if (Test-Path $outputSfx) {
          Write-Host "✅ 7-Zip 自解压包创建成功!"
          Write-Host "输出文件: $outputSfx"
          
          $size = (Get-Item $outputSfx).Length / 1MB
          Write-Host "文件大小: $([math]::Round($size, 2)) MB"
        } else {
          Write-Host "❌ 7-Zip 打包失败"
        }

    - name: Upload Single EXE Package
      uses: actions/upload-artifact@v3
      with:
        name: windows-single-exe
        path: dist/*.exe
      if: always()
