# Release (GitHub) — pipeline release primaria
#
# Strategia hosting:
#   - Repo primario su Gitea (push iniziale)
#   - Push mirror automatico Gitea -> GitHub
#   - GitHub esegue TUTTA la CI (Gitea non esegue Actions)
#
# Trigger:
#   - push di un tag v* (propagato dal mirror Gitea)
#
#   - run manuale via UI (con input 'tag')

name: Release

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      tag:
        description: 'Tag versione (es. v1.7.0)'
        required: true
        type: string

permissions:
  contents: write

jobs:
  build:
    runs-on: windows-latest
    strategy:
      fail-fast: false
      matrix:
        config: [x86-ansi, x86-unicode, x64-unicode]
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.11'

      - name: Setup MSBuild
        uses: microsoft/setup-msbuild@v3

      - name: Build ${{ matrix.config }}
        run: python build_plugin.py --configs ${{ matrix.config }} --verbosity normal

      - name: Collect DLL
        shell: pwsh
        run: |
          $map = @{ 'x86-ansi' = 'x86-ansi'; 'x86-unicode' = 'x86-unicode'; 'x64-unicode' = 'amd64-unicode' }
          $dir = $map['${{ matrix.config }}']
          $src = "plugins\$dir\nsis7z.dll"
          $dst = "dll-bundle\$dir"
          New-Item -ItemType Directory -Force -Path $dst | Out-Null
          Copy-Item $src $dst

      - name: Upload DLL
        uses: actions/upload-artifact@v7
        with:
          name: dll-win-${{ matrix.config }}
          path: dll-bundle/**
          if-no-files-found: error

  build-linux:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        config: [x86-ansi, x86-unicode, x64-unicode]
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.11'

      - name: Install MinGW toolchain
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            make \
            binutils-mingw-w64-i686 \
            binutils-mingw-w64-x86-64 \
            g++-mingw-w64-i686 \
            g++-mingw-w64-x86-64

      - name: Build ${{ matrix.config }} on Linux
        run: python build_plugin.py --host linux --configs ${{ matrix.config }} --verbose



  publish:
    needs: [build, build-linux]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Resolve release tag
        id: tag
        shell: bash
        run: |
          tag="${{ github.ref_name }}"
          if [ -z "$tag" ] || [ "$tag" = "main" ]; then
            tag="${{ inputs.tag }}"
          fi
          if [ -z "$tag" ]; then
            echo "Tag non disponibile. Imposta l'input 'tag' (es. v2.2.1)." >&2
            exit 1
          fi
          case "$tag" in
            v*) ;;
            *) tag="v$tag" ;;
          esac
          echo "tag=$tag" >> "$GITHUB_OUTPUT"

      - name: Download DLL artifacts
        uses: actions/download-artifact@v8
        with:
          path: dll-bundle
          pattern: dll-win-*
          merge-multiple: true

      - name: Extract changelog section
        run: |
          tag="${{ steps.tag.outputs.tag }}"
          version="${tag#v}"
          awk -v ver="[$version]" '
            /^## / && index($0, ver) { found=1; next }
            found && /^## / { exit }
            found { print }
          ' CHANGELOG.md > release_body.md
          # Append Gitea notice
          echo "" >> release_body.md
          echo "---" >> release_body.md
          echo "_Repository primario: vedi link Gitea nel README. Il mirror GitHub è generato automaticamente._" >> release_body.md

      - name: Package plugins ZIP
        id: pkg
        run: |
          tag="${{ steps.tag.outputs.tag }}"
          version="${tag#v}"
          zip_name="${{ github.event.repository.name }}-${version}-bundle.zip"
          (cd dll-bundle && zip -r "../$zip_name" .)
          echo "zip_name=$zip_name" >> "$GITHUB_OUTPUT"

      - name: SHA256SUMS
        run: |
          sha256sum "${{ steps.pkg.outputs.zip_name }}" > SHA256SUMS.txt
          cat SHA256SUMS.txt

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v3
        with:
          tag_name: ${{ steps.tag.outputs.tag }}
          name: ${{ steps.tag.outputs.tag }}
          files: |
            ${{ steps.pkg.outputs.zip_name }}
            SHA256SUMS.txt
          body_path: release_body.md

      - name: Update Gitea Release and upload assets
        env:
          GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
          GITEA_TAG: ${{ steps.tag.outputs.tag }}
          ZIP_NAME: ${{ steps.pkg.outputs.zip_name }}
        run: |
          python3 - <<'PY'
          import json
          import mimetypes
          import os
          import urllib.error
          import urllib.request
          from pathlib import Path

          base = "https://gitea.emulab.it/api/v1"
          repo = "Simone/nsis-plugin-ns7zip"
          tag = os.environ.get("GITEA_TAG", "").strip()
          token = os.environ.get("GITEA_TOKEN", "").strip()
          zip_name = os.environ.get("ZIP_NAME", "").strip()

          if not tag:
            raise SystemExit("Tag non disponibile: imposta input 'tag' in workflow_dispatch")
          if not token:
            raise SystemExit("GITEA_TOKEN is missing or empty")

          with open("release_body.md", "r", encoding="utf-8") as f:
            body = f.read()

          def request(method, path, payload=None, auth_scheme="token"):
            data = json.dumps(payload).encode("utf-8") if payload is not None else None
            req = urllib.request.Request(
              f"{base}{path}",
              data=data,
              method=method,
              headers={
                "Authorization": f"{auth_scheme} {token}",
                "Content-Type": "application/json",
                "Accept": "application/json",
                "User-Agent": "GitHubActions-GiteaReleaseSync/1.0",
              },
            )
            with urllib.request.urlopen(req) as resp:
              return json.loads(resp.read().decode("utf-8"))

          def upload_asset(rid, path, auth_scheme):
            p = Path(path)
            mime = mimetypes.guess_type(p.name)[0] or "application/octet-stream"
            data = p.read_bytes()
            boundary = "----FormBoundary7MA4YWxkTrZu0gW"
            body_parts = (
              f"--{boundary}\r\n"
              f'Content-Disposition: form-data; name="attachment"; filename="{p.name}"\r\n'
              f"Content-Type: {mime}\r\n\r\n"
            ).encode() + data + f"\r\n--{boundary}--\r\n".encode()
            req = urllib.request.Request(
              f"{base}/repos/{repo}/releases/{rid}/assets?name={p.name}",
              data=body_parts,
              method="POST",
              headers={
                "Authorization": f"{auth_scheme} {token}",
                "Content-Type": f"multipart/form-data; boundary={boundary}",
                "User-Agent": "GitHubActions-GiteaReleaseSync/1.0",
              },
            )
            with urllib.request.urlopen(req) as resp:
              return json.loads(resp.read().decode("utf-8"))

          auth_scheme = None
          last_error = None
          for scheme in ("token", "Bearer"):
            try:
              user = request("GET", "/user", auth_scheme=scheme)
              auth_scheme = scheme
              print(f"Gitea auth OK via '{scheme}' as user: {user.get('login', '<unknown>')}")
              break
            except urllib.error.HTTPError as e:
              try:
                details = e.read().decode("utf-8", errors="replace")
              except Exception:
                details = ""
              last_error = f"HTTP {e.code} {e.reason} ({scheme}) {details}".strip()

          if not auth_scheme:
            raise SystemExit(
              "Gitea authentication failed for both 'token' and 'Bearer'. "
              "Check secret GITEA_TOKEN value and permissions (Repository Read+Write). "
              f"Last error: {last_error}"
            )

          try:
            release = request("GET", f"/repos/{repo}/releases/tags/{tag}", auth_scheme=auth_scheme)
            rid = release["id"]
            request("PATCH", f"/repos/{repo}/releases/{rid}", {"body": body}, auth_scheme=auth_scheme)
            print(f"Updated existing Gitea release id={rid} for tag {tag}")
          except urllib.error.HTTPError as e:
            if e.code != 404:
              try:
                details = e.read().decode("utf-8", errors="replace")
              except Exception:
                details = ""
              raise SystemExit(f"Gitea release lookup/update failed: HTTP {e.code} {e.reason}. {details}".strip())

            created = request(
              "POST",
              f"/repos/{repo}/releases",
              {
                "tag_name": tag,
                "name": tag,
                "body": body,
                "draft": False,
                "prerelease": False,
              },
              auth_scheme=auth_scheme,
            )
            rid = created["id"]
            print(f"Created Gitea release id={rid} for tag {tag}")

          # Rimuovi asset già presenti con lo stesso nome (retag idempotente)
          existing = request("GET", f"/repos/{repo}/releases/{rid}/assets", auth_scheme=auth_scheme)
          upload_names = {zip_name, "SHA256SUMS.txt"}
          for asset in existing:
            if asset["name"] in upload_names:
              request("DELETE", f"/repos/{repo}/releases/assets/{asset['id']}", auth_scheme=auth_scheme)
              print(f"Deleted existing asset: {asset['name']}")

          # Carica ZIP e SHA256SUMS
          for f in [zip_name, "SHA256SUMS.txt"]:
            if Path(f).exists():
              result = upload_asset(rid, f, auth_scheme)
              print(f"Uploaded {f} -> {result.get('browser_download_url', result.get('id'))}")
            else:
              print(f"WARNING: {f} not found, skipping upload")
          PY

