name: Release

on:
  push:
    tags:
      - "v*"

env:
  ReleaseFileName: MozaPlugin_${{ github.ref_name }}.zip

jobs:
  build:
    runs-on: windows-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v5
        with:
          dotnet-version: "8.0.x"

      - name: Extract version from tag
        id: version
        shell: bash
        run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT

      - name: Restore dependencies
        run: dotnet restore

      - name: Build plugin DLL
        run: dotnet build -c Release --no-restore /p:Version=${{ steps.version.outputs.version }}

      - name: Stage release files
        shell: pwsh
        run: |
          $staging = "staging"
          New-Item -ItemType Directory -Path $staging -Force | Out-Null
          Copy-Item ./bin/x86/Release/MozaPlugin.dll $staging/
          # All localized resources are embedded inside MozaPlugin.dll (see the
          # i18n resource group in MozaPlugin.csproj), so the single DLL is the
          # full deployment — no per-culture satellite folders to stage.

      - name: Zip release files
        run: Compress-Archive -Path ./staging/* -DestinationPath ./${{ env.ReleaseFileName }}

      - name: Upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: build-file
          path: ${{ env.ReleaseFileName }}

  create-release:
    runs-on: ubuntu-latest
    needs:
      - build
    permissions:
      contents: write
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v8
        with:
          name: build-file

      - name: Create release
        uses: softprops/action-gh-release@v3
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ReleaseFileName }}

      - name: Repoint dev-latest shepherd release
        continue-on-error: true
        env:
          GH_TOKEN: ${{ github.token }}
        shell: bash
        run: |
          set -euo pipefail
          # Legacy dev-channel plugins poll /releases/tags/dev-latest. That
          # channel is gone (replaced by per-PR builds), so keep the tag alive
          # mirroring each new stable — those clients see it as newer than
          # their -dev build and get offered the upgrade path out.
          gh release delete dev-latest --yes --cleanup-tag --repo "$GITHUB_REPOSITORY" || true
          gh release create dev-latest "$ReleaseFileName" \
            --repo "$GITHUB_REPOSITORY" \
            --target "$GITHUB_SHA" \
            --prerelease \
            --title "dev-latest (${GITHUB_REF_NAME#v})" \
            --notes "The development channel has been replaced by per-PR builds (update your plugin and pick a PR in the release-channel dropdown). This release mirrors stable ${GITHUB_REF_NAME} so plugins still on the dev channel can update."

      - name: Notify Discord
        if: success()
        continue-on-error: true
        env:
          DISCORD_RELEASE_WEBHOOK_URL: ${{ secrets.DISCORD_RELEASE_WEBHOOK_URL }}
          DISCORD_DEV_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
          TAG: ${{ github.ref_name }}
          GH_TOKEN: ${{ github.token }}
        shell: bash
        run: |
          set -euo pipefail
          release_url="https://github.com/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
          download_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/MozaPlugin_${TAG}.zip"
          # Prefer the release body the maintainer entered when cutting the
          # tag — that's the authoritative changelog. Fall back to the head
          # commit's subject if no notes were provided so the notification
          # still says *something* meaningful.
          release_body=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
            --jq '.body // ""' 2>/dev/null || printf '')
          if [ -z "$release_body" ]; then
            release_body=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}" \
              --jq '.commit.message' | head -n1)
          fi
          # Build the payload entirely inside jq so every interpolated value is
          # JSON-encoded safely. Unicode-safe slicing keeps us under Discord's
          # embed limits (title 256 chars, description 4096 chars). The body is
          # capped separately so the header/footer always survive truncation.
          payload=$(jq -n \
            --arg tag          "$TAG" \
            --arg download_url "$download_url" \
            --arg release_body "$release_body" \
            --arg release_url  "$release_url" \
            '{
              embeds: [{
                title: (("Moza SimHub Plugin — release " + $tag)[0:250]),
                url: $release_url,
                description: ((
                  (if ($release_body | length) > 3500
                     then ($release_body[0:3500] + "\n…")
                     else $release_body end) +
                  "\n\n[Download release](" + $download_url + ")"
                )[0:4090]),
                color: 3066993
              }]
            }')

          post_discord() {
            local name="$1" url="$2"
            if [ -z "$url" ]; then
              echo "$name: webhook not set, skipping."
              return 0
            fi
            local response_file http_code
            response_file=$(mktemp)
            http_code=$(curl -sS -o "$response_file" -w '%{http_code}' \
              -H "Content-Type: application/json" \
              -X POST -d "$payload" "$url") || http_code="000"
            if [[ "$http_code" =~ ^2[0-9][0-9]$ ]]; then
              echo "$name: notification sent (HTTP $http_code)."
            else
              echo "::warning::$name: notification failed (HTTP $http_code)"
              echo "Payload:"
              echo "$payload"
              echo "Response body:"
              cat "$response_file" || true
              echo
            fi
            rm -f "$response_file"
          }

          post_discord "release channel" "${DISCORD_RELEASE_WEBHOOK_URL:-}"
          post_discord "dev channel"     "${DISCORD_DEV_WEBHOOK_URL:-}"
