name: Auto Versioning and Release

on:
  push:
    branches: [ main ]

permissions:
  contents: write
  pull-requests: write

jobs:
  version:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
        with:
          fetch-depth: 0

      - name: Calculate Semantic Version
        id: semver
        uses: paulhatch/semantic-version@a8f8f59fd7f0625188492e945240f12d7ad2dca3 # v5.4.0
        with:
          # The prefix to use to create tags
          tag_prefix: "v"
          # Regex pattern for major version bump (breaking changes)
          # Matches: "feat!:", "fix!:", "BREAKING CHANGE:" in commit messages
          major_pattern: "/!:|BREAKING CHANGE:/"
          # Regex pattern for minor version bump (new features)
          # Matches: "feat:" prefix in commit messages (Conventional Commits)
          minor_pattern: "/feat:/"
          # Pattern to determine formatting
          version_format: "${major}.${minor}.${patch}"
          # If no tags are found, this version is used
          version_from_branch: "0.0.0"
          # This helps it search through history to find the last tag
          search_commit_body: true
          # Important: This enables the output 'changed' which your other steps rely on
          enable_prerelease_mode: false

      - name: Show version
        run: |
          echo "Next version: ${{ steps.semver.outputs.version }}"

      - id: create_tag
        name: Create annotated tag and push
        if: ${{ steps.semver.outputs.changed }}
        run: |
          # Ensure a committer identity is configured in the runner so git tag works
          git config --global user.email "actions@github.com"
          git config --global user.name "GitHub Actions"

          # Normalize the version: remove any leading 'v' so we don't end up with 'vvX.Y.Z'
          RAW="${{ steps.semver.outputs.version }}"
          VERSION_NO_V="${RAW#v}"

          TAG="v${VERSION_NO_V}"
          echo "TAG=${TAG}"

          # If tag already exists, skip creation to avoid failure
          if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
            echo "Tag ${TAG} already exists; skipping tag creation"
          else
            git tag -a "${TAG}" -m "Release ${TAG}"
            git push origin "${TAG}"
          fi

          # Export the tag for downstream steps
          echo "tag=${TAG}" >> $GITHUB_OUTPUT
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Determine tag
        id: determine_tag
        run: |
          # Prefer created tag output; if empty fallback to semver version
          TAG="${{ steps.create_tag.outputs.tag }}"
          if [ -z "$TAG" ]; then
            # semver.version contains a tag value like 'vX.Y.Z' or fallback 'v0.0.0'
            VERSION_RAW="${{ steps.semver.outputs.version }}"
            VERSION_NO_V="${VERSION_RAW#v}"
            TAG="v${VERSION_NO_V}"
          fi
          echo "Determined tag: $TAG"
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Check for existing GitHub Release
        id: check_release
        run: |
          TAG=${{ steps.determine_tag.outputs.tag }}
          echo "Checking for release for tag: ${TAG}"
          STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github+json" "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}") || true
          if [ "${STATUS}" = "200" ]; then
            echo "exists=true" >> $GITHUB_OUTPUT
          else
            echo "exists=false" >> $GITHUB_OUTPUT
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create GitHub Release (tag-only, no workspace changes)
        if: ${{ steps.semver.outputs.changed == 'true' && steps.check_release.outputs.exists == 'false' }}
        uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
        with:
          tag_name: ${{ steps.determine_tag.outputs.tag }}
          name: Release ${{ steps.determine_tag.outputs.tag }}
          generate_release_notes: true
          make_latest: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
