name: Build Mod Package

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:

permissions:
  contents: write

jobs:
  build:
    runs-on:
      - win11

    defaults:
      run:
        shell: powershell

    steps:
      - name: Prepare workspace
        run: |
          $ErrorActionPreference = "Stop"
          $workspace = "${{ gitea.workspace }}"
          $repoUrl = "${{ gitea.server_url }}/${{ gitea.repository }}.git"
          $repoRef = "${{ gitea.ref }}"
          $authPair = "${{ gitea.actor }}:${{ secrets.GITEA_TOKEN }}"
          $authBytes = [System.Text.Encoding]::ASCII.GetBytes($authPair)
          $authBasic = [Convert]::ToBase64String($authBytes)

          New-Item -ItemType Directory -Path $workspace -Force | Out-Null
          Set-Location $workspace

          if (-not (Test-Path -LiteralPath ".git")) {
              git init | Out-Null
              git remote add origin $repoUrl
          } else {
              git remote set-url origin $repoUrl
          }

          git -c "http.extraHeader=Authorization: Basic $authBasic" fetch --depth 1 origin $repoRef
          git checkout --force FETCH_HEAD

          if (-not (Test-Path -LiteralPath "Mods\\DnD 5.5e AIO Russian\\Localization\\Russian\\russian.xml")) {
              throw "Repository sources are not available in the runner workspace."
          }

          New-Item -ItemType Directory -Path ".tools\\lslib" -Force | Out-Null
          New-Item -ItemType Directory -Path "build" -Force | Out-Null

      - name: Download latest LSLib release
        run: |
          $ErrorActionPreference = "Stop"
          $release = Invoke-RestMethod -Uri "https://api.github.com/repos/Norbyte/lslib/releases/latest"
          $asset = $release.assets | Where-Object { $_.name -match '\.zip$' } | Select-Object -First 1

          if (-not $asset) {
              throw "Could not find a downloadable LSLib zip asset in the latest release."
          }

          Invoke-WebRequest -UseBasicParsing -Uri $asset.browser_download_url -OutFile ".tools/lslib/lslib.zip"
          Expand-Archive -LiteralPath ".tools/lslib/lslib.zip" -DestinationPath ".tools/lslib" -Force

      - name: Build .pak
        run: |
          $ErrorActionPreference = "Stop"
          $divine = Get-ChildItem -Path ".tools/lslib" -Recurse -File |
            Where-Object { $_.Name -ieq "Divine.exe" } |
            Select-Object -First 1

          if (-not $divine) {
              throw "Divine.exe was not found in the downloaded LSLib release."
          }

          & ".\\scripts\\build.ps1" -DivinePath $divine.FullName -Workspace "${{ gitea.workspace }}" -VersionTag "${{ gitea.ref_name }}"

      - name: Show build result
        run: |
          $ErrorActionPreference = "Stop"
          $workspace = "${{ gitea.workspace }}"
          $refName = "${{ gitea.ref_name }}"
          $archiveBaseName = "DnD 5.5e AIO Russian"
          if ($refName -and $refName -like "v*") {
              $archiveBaseName = "DnD 5.5e AIO Russian $refName"
          }
          $zipPath = [System.IO.Path]::GetFullPath((Join-Path $workspace "build/$archiveBaseName.zip"))

          Get-ChildItem "build/DnD 5.5e AIO Russian.pak", "build/info.json", $zipPath |
            Select-Object FullName, Length, LastWriteTime

      - name: Publish archive to release
        if: startsWith(gitea.ref, 'refs/tags/v')
        run: |
          $ErrorActionPreference = "Stop"
          $workspace = "${{ gitea.workspace }}"
          $serverUrl = "${{ gitea.server_url }}"
          $repository = "${{ gitea.repository }}"
          $tagName = "${{ gitea.ref_name }}"
          $zipPath = [System.IO.Path]::GetFullPath((Join-Path $workspace "build/DnD 5.5e AIO Russian $tagName.zip"))
          $assetName = [System.IO.Path]::GetFileName($zipPath)
          $repoParts = $repository.Split("/", 2)

          if ($repoParts.Length -ne 2) {
              throw "Could not parse repository owner and name from '$repository'."
          }

          if (-not (Test-Path -LiteralPath $zipPath)) {
              throw "Release archive was not found at '$zipPath'."
          }

          $owner = $repoParts[0]
          $repo = $repoParts[1]
          $apiBase = "$serverUrl/api/v1/repos/$owner/$repo"
          $headers = @{
              Authorization = "token ${{ secrets.GITEA_TOKEN }}"
              Accept = "application/json"
          }

          $release = $null
          try {
              $release = Invoke-RestMethod -Method Get -Uri "$apiBase/releases/tags/$tagName" -Headers $headers
          } catch {
              $statusCode = $null
              if ($_.Exception.Response) {
                  $statusCode = [int]$_.Exception.Response.StatusCode
              }

              if ($statusCode -ne 404) {
                  throw
              }
          }

          if (-not $release) {
              $releaseBody = @{
                  tag_name = $tagName
                  name = $tagName
                  target_commitish = "${{ gitea.sha }}"
                  draft = $false
                  prerelease = $false
              } | ConvertTo-Json

              $release = Invoke-RestMethod -Method Post -Uri "$apiBase/releases" -Headers $headers -ContentType "application/json" -Body $releaseBody
          }

          $existingAsset = $null
          if ($release.assets) {
              $existingAsset = $release.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
          }

          if ($existingAsset) {
              Invoke-RestMethod -Method Delete -Uri "$apiBase/releases/$($release.id)/assets/$($existingAsset.id)" -Headers $headers
          }

          $uploadHeaders = @{
              Authorization = "token ${{ secrets.GITEA_TOKEN }}"
              Accept = "application/json"
          }

          Invoke-WebRequest -UseBasicParsing -Method Post -Uri "$apiBase/releases/$($release.id)/assets?name=$([uri]::EscapeDataString($assetName))" -Headers $uploadHeaders -ContentType "application/octet-stream" -InFile $zipPath
