name: Release

on:
  push:
    tags:
      - 'v*'

env:
  SERVER_HOST: git.dolgolyov-family.by
  REGISTRY: git.dolgolyov-family.by/alexei.dolgolyov/tiny-forge

jobs:
  # ───────────────────────────────────────────────────────────────────────
  # Gate the release on a passing test suite. A tagged release must never
  # ship code that fails `go vet` / `go test`.
  # ───────────────────────────────────────────────────────────────────────
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version: '1.25'
          cache-dependency-path: go.sum

      - name: Vet Go code
        run: go vet ./...

      - name: Run Go tests
        run: go test ./internal/... -count=1

  # ───────────────────────────────────────────────────────────────────────
  # Build + push the image FIRST. If this fails, no release is created
  # (create-release depends on it) — so we never leave an orphan release
  # pointing at a tag with no published image.
  # ───────────────────────────────────────────────────────────────────────
  build-docker:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Compute tags
        id: meta
        run: |
          TAG="${{ gitea.ref_name }}"
          VERSION="${TAG#v}"
          echo "tag=$TAG" >> "$GITHUB_OUTPUT"
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"
          # Detect pre-release (alpha/beta/rc) — these do NOT get :latest.
          if echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
            echo "is_pre=true" >> "$GITHUB_OUTPUT"
          else
            echo "is_pre=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Gitea Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.SERVER_HOST }}
          username: ${{ gitea.actor }}
          password: ${{ secrets.DEPLOY_TOKEN }}

      - name: Build and push image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ env.REGISTRY }}:${{ steps.meta.outputs.tag }}
            ${{ env.REGISTRY }}:${{ steps.meta.outputs.version }}
            ${{ env.REGISTRY }}:sha-${{ gitea.sha }}
            ${{ steps.meta.outputs.is_pre == 'false' && format('{0}:latest', env.REGISTRY) || '' }}
          cache-from: type=registry,ref=${{ env.REGISTRY }}:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}:buildcache,mode=max

      - name: Trigger redeploy webhook
        if: steps.meta.outputs.is_pre == 'false'
        continue-on-error: true
        run: |
          if [ -n "${{ secrets.DOCKER_REDEPLOY_WEBHOOK_URL }}" ]; then
            echo "Triggering redeploy webhook..."
            curl -sf -X POST "${{ secrets.DOCKER_REDEPLOY_WEBHOOK_URL }}" \
              --max-time 30 || echo "::warning::Redeploy webhook failed"
          else
            echo "DOCKER_REDEPLOY_WEBHOOK_URL not set — skipping auto-deploy"
          fi

  # ───────────────────────────────────────────────────────────────────────
  # Create the Gitea release LAST — body = RELEASE_NOTES.md + auto-changelog.
  # ───────────────────────────────────────────────────────────────────────
  create-release:
    needs: build-docker
    runs-on: ubuntu-latest
    steps:
      - name: Checkout (full history for changelog)
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate changelog
        id: changelog
        run: |
          PREV_TAG=$(git tag --sort=-v:refname | head -2 | tail -1)
          if [ -z "$PREV_TAG" ] || [ "$PREV_TAG" = "${{ gitea.ref_name }}" ]; then
            git log --oneline --no-decorate -n 20 > /tmp/changelog.txt
          else
            git log --oneline --no-decorate "${PREV_TAG}..HEAD" > /tmp/changelog.txt
          fi

      - name: Create Gitea release
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          TAG="${{ gitea.ref_name }}"
          VERSION="${TAG#v}"
          BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}"

          # Detect pre-release (alpha/beta/rc)
          IS_PRE="false"
          if echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
            IS_PRE="true"
          fi

          # Read release notes if present
          if [ -f RELEASE_NOTES.md ]; then
            export RELEASE_NOTES=$(cat RELEASE_NOTES.md)
            echo "Found RELEASE_NOTES.md"
          else
            export RELEASE_NOTES=""
            echo "No RELEASE_NOTES.md found — release body = changelog only"
          fi

          # Build release body (notes + changelog) via Python to avoid shell
          # escaping and CLI length limits.
          export TAG VERSION IS_PRE
          python3 <<'PY'
          import json, os

          notes = os.environ.get('RELEASE_NOTES', '')
          changelog = open('/tmp/changelog.txt').read().strip()

          sections = []
          if notes.strip():
              sections.append(notes.strip())
          if changelog:
              sections.append('## Changelog\n\n' + changelog)

          payload = {
              'tag_name': os.environ['TAG'],
              'name': os.environ['VERSION'],
              'body': '\n\n'.join(sections),
              'draft': False,
              'prerelease': os.environ['IS_PRE'] == 'true',
          }
          with open('/tmp/release-payload.json', 'w') as f:
              json.dump(payload, f)
          PY

          HTTP=$(curl -s -o /tmp/release-resp.json -w "%{http_code}" \
            -X POST "$BASE_URL/releases" \
            -H "Authorization: token $DEPLOY_TOKEN" \
            -H "Content-Type: application/json" \
            --data-binary @/tmp/release-payload.json)

          echo "POST /releases → HTTP $HTTP"
          if [ "$HTTP" = "201" ]; then
            RELEASE_ID=$(python3 -c "import json; print(json.load(open('/tmp/release-resp.json'))['id'])")
            echo "Created release $RELEASE_ID for $TAG"
          elif [ "$HTTP" = "409" ] || grep -q "already exists" /tmp/release-resp.json; then
            echo "::warning::Release already exists for tag $TAG — reusing"
          else
            echo "::error::Failed to create release for $TAG (HTTP $HTTP)"
            head -c 2000 /tmp/release-resp.json; echo
            exit 1
          fi
