name: Release and Build Image

on:
  push:
    tags:
      - "v*"

jobs:
  release:
    runs-on: ubuntu-latest

    env:
      # Internal/origin Gitea URL. Do NOT use the Cloudflare fronted URL here.
      # Examples:
      #   http://gitea.internal.lan:3000
      #   https://gitea-origin.yourdomain.local
      GITEA_INTERNAL_URL: "http://10.75.9.150:3100" #"https://git.tuffraid.net"

      # Internal/origin registry host. Usually same host as above, but without protocol.
      # Example:
      #   gitea.internal:3000
      REGISTRY_HOST:  "10.75.9.150:3100" #"git.tuffraid.net"

    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Prepare release metadata
        shell: bash
        run: |
          set -euo pipefail

          TAG="${GITHUB_REF_NAME:-${GITHUB_REF##refs/tags/}}"
          VERSION="${TAG#v}"
          IMAGE_NAME="${REGISTRY_HOST}/${{ gitea.repository }}"

          echo "TAG=$TAG" >> "$GITHUB_ENV"
          echo "VERSION=$VERSION" >> "$GITHUB_ENV"
          echo "IMAGE_NAME=$IMAGE_NAME" >> "$GITHUB_ENV"

          if [[ "$TAG" == *-* ]]; then
            echo "PRERELEASE=true" >> "$GITHUB_ENV"
          else
            echo "PRERELEASE=false" >> "$GITHUB_ENV"
          fi

          echo "Resolved TAG=$TAG"
          echo "Resolved VERSION=$VERSION"
          echo "Resolved IMAGE_NAME=$IMAGE_NAME"

      - name: Log in to Gitea container registry
        shell: bash
        env:
          REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
          REGISTRY_TOKEN: ${{ secrets.RELEASE_TOKEN }}
        run: |
          set -euo pipefail
          echo "$REGISTRY_TOKEN" | docker login "$REGISTRY_HOST" -u "$REGISTRY_USERNAME" --password-stdin

      - name: Build Docker image
        shell: bash
        run: |
          set -euo pipefail
          docker build \
            -t "$IMAGE_NAME:$TAG" \
            -t "$IMAGE_NAME:latest" \
            .

      - name: Push version tag
        shell: bash
        run: |
          set -euo pipefail
          docker push "$IMAGE_NAME:$TAG"

      - name: Push latest tag
        if: ${{ !contains(env.TAG, '-') }}
        shell: bash
        run: |
          set -euo pipefail
          docker push "$IMAGE_NAME:latest"

      - name: Push prerelease channel tag
        if: ${{ contains(env.TAG, '-') }}
        shell: bash
        env:
          TAG: ${{ env.TAG }}
        run: |
          set -euo pipefail
          CHANNEL="${TAG#*-}"
          CHANNEL="${CHANNEL%%.*}"

          echo "Resolved prerelease channel: $CHANNEL"

          docker tag "$IMAGE_NAME:$TAG" "$IMAGE_NAME:$CHANNEL"
          docker push "$IMAGE_NAME:$CHANNEL"

      - name: Extract matching CHANGELOG section
        shell: bash
        env:
          VERSION: ${{ env.VERSION }}
        run: |
          set -euo pipefail
          python3 - <<'PY'
          import os
          import re
          from pathlib import Path

          version = os.environ["VERSION"]
          changelog_path = Path("CHANGELOG.md")

          if not changelog_path.exists():
              Path("release_body.md").write_text(f"Release {version}\n", encoding="utf-8")
              raise SystemExit(0)

          text = changelog_path.read_text(encoding="utf-8")

          # Matches headings like:
          # ## [0.1.0]
          # ## 0.1.0
          # ## [0.1.0-alpha.1]
          pattern = re.compile(
              rf"^##\s+\[?{re.escape(version)}\]?[^\n]*\n(.*?)(?=^##\s+\[?[^\n]+|\Z)",
              re.MULTILINE | re.DOTALL,
          )

          match = pattern.search(text)
          if match:
              body = match.group(1).strip()
          else:
              body = f"Release {version}"

          if not body:
              body = f"Release {version}"

          Path("release_body.md").write_text(body + "\n", encoding="utf-8")
          print("----- release_body.md -----")
          print(body)
          print("---------------------------")
          PY

      - name: Create Gitea release
        shell: bash
        env:
          RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
          GITEA_REPOSITORY: ${{ gitea.repository }}
          GITEA_INTERNAL_URL: ${{ env.GITEA_INTERNAL_URL }}
          TAG: ${{ env.TAG }}
          PRERELEASE: ${{ env.PRERELEASE }}
        run: |
          set -euo pipefail
          python3 - <<'PY'
          import json
          import os
          import urllib.request
          import urllib.error
          from pathlib import Path

          tag = os.environ["TAG"]
          prerelease = os.environ["PRERELEASE"].lower() == "true"
          server_url = os.environ["GITEA_INTERNAL_URL"].rstrip("/")
          repo = os.environ["GITEA_REPOSITORY"]
          token = os.environ["RELEASE_TOKEN"]

          body = Path("release_body.md").read_text(encoding="utf-8").strip()

          # Check if the release already exists for this tag
          get_url = f"{server_url}/api/v1/repos/{repo}/releases/tags/{tag}"
          get_req = urllib.request.Request(
              get_url,
              method="GET",
              headers={
                  "Authorization": f"token {token}",
                  "Accept": "application/json",
                  "User-Agent": "lst-release-workflow/1.0",
              },
          )

          existing_release = None
          try:
              with urllib.request.urlopen(get_req) as resp:
                  existing_release = json.loads(resp.read().decode("utf-8"))
          except urllib.error.HTTPError as e:
              if e.code != 404:
                  details = e.read().decode("utf-8", errors="replace")
                  print("Failed checking existing release:")
                  print(details)
                  raise

          payload = {
              "tag_name": tag,
              "name": tag,
              "body": body,
              "draft": False,
              "prerelease": prerelease,
          }

          data = json.dumps(payload).encode("utf-8")

          if existing_release:
              release_id = existing_release["id"]
              url = f"{server_url}/api/v1/repos/{repo}/releases/{release_id}"
              method = "PATCH"
              print(f"Release already exists for tag {tag}, updating release id {release_id}")
          else:
              url = f"{server_url}/api/v1/repos/{repo}/releases"
              method = "POST"
              print(f"No release exists for tag {tag}, creating a new one")

          req = urllib.request.Request(
              url,
              data=data,
              method=method,
              headers={
                  "Authorization": f"token {token}",
                  "Content-Type": "application/json",
                  "Accept": "application/json",
                  "User-Agent": "lst-release-workflow/1.0",
              },
          )

          try:
              with urllib.request.urlopen(req) as resp:
                  print(resp.read().decode("utf-8"))
          except urllib.error.HTTPError as e:
              details = e.read().decode("utf-8", errors="replace")
              print("Release create/update failed:")
              print(details)
              raise
          PY