name: Build Paarrot Windows

on:
  push:
    branches: [ main, development ]
  pull_request:
    branches: [ main ]

concurrency:
  group: build-${{ github.ref }}
  cancel-in-progress: true

jobs:
  start-vm:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    
    steps:
      - name: Check if VM is already running
        id: check-vm
        run: |
          if pgrep -f "qemu-system-x86_64.*windows.qcow2" > /dev/null; then
            echo "VM is already running"
            echo "vm_running=true" >> $GITHUB_OUTPUT
          else
            echo "VM is not running"
            echo "vm_running=false" >> $GITHUB_OUTPUT
          fi

      - name: Start Windows VM with retry
        run: |
          MAX_RETRIES=3
          RETRY_COUNT=0
          BOOT_WAIT=90
          RUNNER_CHECK_TIMEOUT=120
          
          start_vm() {
            echo "Starting Windows QEMU VM (attempt $((RETRY_COUNT + 1))/$MAX_RETRIES)..."
            sudo -u litruv setsid bash -c 'DISPLAY=:0 XAUTHORITY=/home/litruv/.Xauthority qemu-system-x86_64 \
              -m 18G \
              -smp 4 \
              -enable-kvm \
              -cpu host \
              -drive file=/home/litruv/windows.qcow2,format=qcow2 \
              -boot d \
              -vga virtio \
              -display vnc=:0 \
              > /tmp/qemu.log 2>&1' &
            disown
          }
          
          kill_vm() {
            echo "Killing VM..."
            sudo pkill -9 qemu-system-x86 || true
            sleep 5
          }
          
          check_runner() {
            API_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/actions/runners"
            RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.CI_BOT_TOKEN }}" "$API_URL" 2>/dev/null)
            
            if [ -z "$RESPONSE" ]; then
              echo "  Could not query runner API"
              return 1
            fi
            
            ONLINE=$(echo "$RESPONSE" | jq -r '.runners[] | select(.labels[].name == "windows-vm") | select(.status == "online") | .name' 2>/dev/null)
            
            if [ -n "$ONLINE" ]; then
              echo "  Runner found online!"
              return 0
            fi
            
            echo "  Windows runner (windows-vm) is NOT online"
            return 1
          }
          
          wait_for_runner() {
            local max_checks=$1
            local required_successes=${2:-1}
            local successes=0
            echo "Waiting for runner to come online (need ${required_successes} successful checks, max ${max_checks} attempts)..."
            for i in $(seq 1 $max_checks); do
              if check_runner; then
                successes=$((successes + 1))
                echo "Runner online check $successes/$required_successes passed ($i/$max_checks)"
                if [ $successes -ge $required_successes ]; then
                  echo "Runner confirmed online after $successes consecutive checks!"
                  return 0
                fi
              else
                successes=0
                echo "Waiting for runner... ($i/$max_checks)"
              fi
              sleep 5
            done
            return 1
          }
          
          echo "Checking if runner is online..."
          if wait_for_runner 12 12; then
            echo "Runner verified online!"
            exit 0
          fi
          
          if [ "${{ steps.check-vm.outputs.vm_running }}" == "true" ]; then
            echo "VM process exists but runner not responding, restarting VM..."
            kill_vm
          fi
          
          while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
            start_vm
            echo "Waiting ${BOOT_WAIT}s for VM to boot..."
            sleep $BOOT_WAIT
            
            if ! pgrep -f "qemu-system-x86_64.*windows.qcow2" > /dev/null; then
              echo "VM process not found, retrying..."
              RETRY_COUNT=$((RETRY_COUNT + 1))
              continue
            fi
            
            if wait_for_runner $((RUNNER_CHECK_TIMEOUT / 5)); then
              exit 0
            fi
            
            echo "Runner did not come online, killing VM and retrying..."
            kill_vm
            RETRY_COUNT=$((RETRY_COUNT + 1))
          done
          
          echo "ERROR: Failed to start VM after $MAX_RETRIES attempts"
          exit 1

      - name: VM Status
        run: |
          if [ "${{ steps.check-vm.outputs.vm_running }}" == "true" ]; then
            echo "Using existing VM"
          else
            echo "Started new VM"
          fi
          
          if pgrep -f "qemu-system-x86_64.*windows.qcow2" > /dev/null; then
            echo "VM process confirmed running"
          else
            echo "ERROR: VM process not found!"
            exit 1
          fi

  build:
    runs-on: windows-vm
    needs: start-vm
    timeout-minutes: 60
    
    steps:
      - name: Cancel pending shutdown
        shell: powershell
        run: |
          shutdown /s /t 1000 2>$null
          shutdown /a 2>$null
          Write-Host "Cancelled any pending shutdown"

      - name: Disable sleep and power saving
        shell: powershell
        run: |
          powercfg /change standby-timeout-ac 0
          powercfg /change standby-timeout-dc 0
          powercfg /change hibernate-timeout-ac 0
          powercfg /change hibernate-timeout-dc 0
          powercfg /change monitor-timeout-ac 0
          powercfg /change monitor-timeout-dc 0
          powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
          Write-Host "Power saving disabled for build"

      - name: Fast checkout (persistent repo)
        shell: powershell
        run: |
          $ErrorActionPreference = "Continue"
          
          $repoDir = "C:\BuildCache\cinny-desktop\Repo"
          $serverUrl = "${{ github.server_url }}"
          $repo = "${{ github.repository }}"
          $branch = "${{ github.ref_name }}"
          $token = "${{ secrets.CI_BOT_TOKEN }}"
          
          $uri = [System.Uri]$serverUrl
          $scheme = $uri.Scheme
          $authority = $uri.Authority
          $repoUrl = "${scheme}://${authority}/${repo}"
          
          Write-Host "Using server: ${scheme}://${authority}"
          
          if (-not (Test-Path "C:\BuildCache\cinny-desktop")) {
            New-Item -ItemType Directory -Path "C:\BuildCache\cinny-desktop" -Force
          }
          
          git config --global credential.helper ""
          git config --global "http.${scheme}://${authority}/.extraheader" "Authorization: token $token"
          
          function Remove-GitLocks {
            $lockFiles = @(
              "$repoDir\.git\shallow.lock",
              "$repoDir\.git\index.lock",
              "$repoDir\.git\HEAD.lock",
              "$repoDir\.git\config.lock"
            )
            foreach ($lock in $lockFiles) {
              if (Test-Path $lock) {
                Write-Host "Removing stale lock: $lock"
                Remove-Item -Force $lock
              }
            }
          }
          
          function Do-Clone {
            Write-Host "Cloning repository fresh..."
            if (Test-Path $repoDir) {
              Remove-Item -Recurse -Force $repoDir
            }
            
            $cloneSuccess = $false
            for ($i = 1; $i -le 3; $i++) {
              Write-Host "Clone attempt $i/3..."
              & git clone --depth=1 --branch $branch $repoUrl $repoDir 2>&1 | Out-Host
              if ($LASTEXITCODE -eq 0) {
                $cloneSuccess = $true
                break
              }
              Write-Host "Clone attempt $i failed, retrying in 5 seconds..."
              if (Test-Path $repoDir) {
                Remove-Item -Recurse -Force $repoDir
              }
              Start-Sleep -Seconds 5
            }
            
            if (-not $cloneSuccess) {
              throw "Clone failed after 3 attempts"
            }
            
            Push-Location $repoDir
            & git submodule update --init --recursive --depth=1 2>&1 | Out-Host
            Pop-Location
          }
          
          function Do-Update {
            Write-Host "Updating existing repo..."
            Push-Location $repoDir
            
            Remove-GitLocks
            
            git remote set-url origin $repoUrl 2>$null
            Write-Host "Remote URL updated"
            
            git reset --hard HEAD 2>$null
            if ($LASTEXITCODE -ne 0) {
              Write-Host "Reset failed, repo may be corrupted"
              Pop-Location
              return $false
            }
            
            git clean -fdx -e node_modules/ -e cinny/node_modules/ 2>$null
            
            $fetchSuccess = $false
            for ($i = 1; $i -le 3; $i++) {
              Write-Host "Fetch attempt $i/3..."
              & git fetch origin $branch --depth=1 2>&1 | Out-Host
              if ($LASTEXITCODE -eq 0) {
                $fetchSuccess = $true
                break
              }
              Write-Host "Fetch attempt $i failed, retrying in 5 seconds..."
              Start-Sleep -Seconds 5
            }
            
            if (-not $fetchSuccess) {
              Write-Host "All fetch attempts failed"
              Pop-Location
              return $false
            }
            
            & git checkout -B $branch origin/$branch 2>&1 | Out-Host
            if ($LASTEXITCODE -ne 0) {
              Write-Host "Checkout failed"
              Pop-Location
              return $false
            }
            
            & git submodule update --init --recursive --depth=1 2>&1 | Out-Host
            
            Pop-Location
            return $true
          }
          
          if (Test-Path "$repoDir\.git") {
            $success = Do-Update
            if (-not $success) {
              Write-Host "Update failed, will re-clone..."
              Do-Clone
            }
          } else {
            Do-Clone
          }
          
          if (-not (Test-Path "$repoDir\package.json")) {
            throw "Checkout verification failed - package.json not found"
          }
          
          Write-Host "Checkout complete at: $repoDir"

      - name: Install dependencies
        shell: powershell
        run: |
          $ErrorActionPreference = "Stop"
          $repoDir = "C:\BuildCache\cinny-desktop\Repo"
          
          Push-Location $repoDir
          
          Write-Host "Installing root dependencies..."
          npm ci --prefer-offline --no-audit
          
          Write-Host "Installing cinny dependencies..."
          Push-Location cinny
          npm ci --prefer-offline --no-audit
          Pop-Location
          
          Pop-Location
          Write-Host "Dependencies installed"

      - name: Build Paarrot
        shell: powershell
        run: |
          $ErrorActionPreference = "Stop"
          $repoDir = "C:\BuildCache\cinny-desktop\Repo"
          
          Push-Location $repoDir
          
          Write-Host "Building Paarrot..."
          npm run build:win
          
          Pop-Location
          Write-Host "Build completed successfully!"

      - name: Upload artifacts
        shell: powershell
        run: |
          $ErrorActionPreference = "Stop"
          $repoDir = "C:\BuildCache\cinny-desktop\Repo"
          $artifactDir = "$repoDir\dist-electron"
          
          if (-not (Test-Path $artifactDir)) {
            Write-Error "Build artifacts not found at $artifactDir"
            exit 1
          }
          
          Write-Host "Build artifacts:"
          Get-ChildItem $artifactDir -Recurse | Select-Object FullName
          
          # TODO: Copy artifacts to artifact server or release location
          Write-Host "Artifacts ready at: $artifactDir"

      - name: Schedule delayed shutdown
        if: always()
        shell: powershell
        run: |
          shutdown /s /t 900 /c "Build complete - shutting down in 15 minutes"
          Write-Host "VM will shutdown in 15 minutes unless another build starts"
