name: Release

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      dry-run:
        description: "Build only, don't publish"
        required: false
        type: boolean
        default: false

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always
  RUST_TOOLCHAIN: nightly-2025-12-04
  RUSTC_BOOTSTRAP: 1

jobs:
  # ============================================================================
  # STAGE 1: Verify version and run checks
  # ============================================================================

  verify:
    name: Verify Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      tag: ${{ steps.version.outputs.tag }}
    steps:
      - uses: actions/checkout@v4

      - name: Get version from tag or Cargo.toml
        id: version
        run: |
          if [[ "$GITHUB_REF" == refs/tags/* ]]; then
            TAG=${GITHUB_REF#refs/tags/}
            VERSION=${TAG#v}
          else
            VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
            TAG="v$VERSION"
          fi
          echo "tag=$TAG" >> $GITHUB_OUTPUT
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Tag: $TAG"
          echo "Version: $VERSION"

      - name: Verify Cargo.toml version matches tag
        if: startsWith(github.ref, 'refs/tags/')
        env:
          TAG_VERSION: ${{ steps.version.outputs.version }}
        run: |
          CARGO_VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)

          echo "Tag version: $TAG_VERSION"
          echo "Cargo.toml version: $CARGO_VERSION"

          if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
            echo "ERROR: Tag version ($TAG_VERSION) doesn't match Cargo.toml ($CARGO_VERSION)"
            exit 1
          fi
          echo "Version match confirmed"

      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          components: rustfmt, clippy

      - uses: Swatinem/rust-cache@v2

      - name: Check formatting
        run: cargo fmt --check

      - name: Clippy
        run: cargo clippy -- -D warnings

      - name: Build
        run: cargo check

  # ============================================================================
  # STAGE 2: Build binaries (parallel)
  # ============================================================================

  build-binaries:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: true
      matrix:
        include:
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: og-aarch64-apple-darwin
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          targets: ${{ matrix.target }}

      - uses: Swatinem/rust-cache@v2

      - name: Build release binary
        run: |
          cargo build --release --target ${{ matrix.target }}
          mkdir -p dist
          cp target/${{ matrix.target }}/release/og dist/

      - name: Create tarball
        run: |
          cd dist
          tar czf ${{ matrix.artifact_name }}.tar.gz og
          if command -v sha256sum &> /dev/null; then
            sha256sum ${{ matrix.artifact_name }}.tar.gz > ${{ matrix.artifact_name }}.tar.gz.sha256
          else
            shasum -a 256 ${{ matrix.artifact_name }}.tar.gz > ${{ matrix.artifact_name }}.tar.gz.sha256
          fi

      - uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.artifact_name }}
          path: dist/${{ matrix.artifact_name }}.tar.gz*

  # ============================================================================
  # STAGE 3: Create GitHub Release
  # ============================================================================

  create-release:
    name: Create GitHub Release
    needs: [verify, build-binaries]
    if: startsWith(github.ref, 'refs/tags/') && !inputs.dry-run
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/download-artifact@v4
        with:
          path: artifacts
          merge-multiple: true

      - name: List artifacts
        run: ls -la artifacts/

      - name: Create Release
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ needs.verify.outputs.tag }}
        run: |
          # Delete any existing draft for this tag (re-run safety)
          gh release delete "$TAG" --yes 2>/dev/null || true
          gh release create "$TAG" \
            --title "$TAG" \
            --generate-notes \
            --draft \
            artifacts/*

  # ============================================================================
  # STAGE 4: Publish to crates.io (trusted publishing via OIDC)
  # ============================================================================

  publish-crates:
    name: Publish to crates.io
    needs: [verify, build-binaries]
    if: startsWith(github.ref, 'refs/tags/') && !inputs.dry-run
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}

      - name: Get crates.io token via OIDC
        uses: rust-lang/crates-io-auth-action@v1
        id: crates-io-auth

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }}
          VERSION: ${{ needs.verify.outputs.version }}
        run: |
          if OUTPUT=$(cargo publish 2>&1); then
            echo "$OUTPUT"
          else
            STATUS=$?
            echo "$OUTPUT"
            if echo "$OUTPUT" | grep -q "already exists on crates.io"; then
              echo "Version $VERSION already published to crates.io, skipping"
            else
              exit $STATUS
            fi
          fi

  # ============================================================================
  # STAGE 5: Update Homebrew tap
  # ============================================================================

  update-homebrew:
    name: Update Homebrew Tap
    needs: [verify, create-release]
    if: startsWith(github.ref, 'refs/tags/') && !inputs.dry-run
    continue-on-error: true
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: nijaru/homebrew-tap
          token: ${{ secrets.TAP_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}

      - name: Download checksums
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ needs.verify.outputs.tag }}
        run: |
          gh release download "$TAG" \
            --repo nijaru/omengrep \
            --pattern '*.sha256'

      - name: Update formula
        env:
          TAG: ${{ needs.verify.outputs.tag }}
          VERSION: ${{ needs.verify.outputs.version }}
        run: |
          MAC_ARM64_SHA=$(cat og-aarch64-apple-darwin.tar.gz.sha256 | awk '{print $1}')
          SOURCE_SHA=$(curl -sL "https://github.com/nijaru/omengrep/archive/refs/tags/$TAG.tar.gz" | sha256sum | awk '{print $1}')

          sed -i "s/version \".*\"/version \"$VERSION\"/" Formula/og.rb
          sed -i "s|/v[0-9.]*[^/]*/og-|/$TAG/og-|g" Formula/og.rb
          sed -i "s|/v[0-9.]*[^/]*.tar.gz|/$TAG.tar.gz|g" Formula/og.rb

          python3 -c "
          import re
          with open('Formula/og.rb') as f:
              content = f.read()
          shas = ['$MAC_ARM64_SHA', '$SOURCE_SHA']
          # Match any existing sha256 value (including PLACEHOLDER)
          pattern = r'sha256 \"[^\"]*\"'
          matches = list(re.finditer(pattern, content))
          for i, m in enumerate(matches):
              if i < len(shas):
                  content = content[:m.start()] + f'sha256 \"{shas[i]}\"' + content[m.end():]
                  matches = list(re.finditer(pattern, content))
          with open('Formula/og.rb', 'w') as f:
              f.write(content)
          "

      - name: Commit and push
        env:
          TAG: ${{ needs.verify.outputs.tag }}
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add Formula/og.rb
          if ! git diff --staged --quiet; then
            git commit -m "chore: update og to $TAG"
            git push
          else
            echo "Formula already up to date"
          fi

  # ============================================================================
  # STAGE 6: Finalize release
  # ============================================================================

  finalize:
    name: Finalize Release
    needs: [verify, create-release, publish-crates, update-homebrew]
    if: startsWith(github.ref, 'refs/tags/') && !inputs.dry-run
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Publish GitHub release
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ needs.verify.outputs.tag }}
        run: gh release edit "$TAG" --draft=false

      - name: Summary
        env:
          VERSION: ${{ needs.verify.outputs.version }}
          TAG: ${{ needs.verify.outputs.tag }}
        run: |
          echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "- **Version**: $VERSION" >> $GITHUB_STEP_SUMMARY
          echo "- **GitHub Release**: https://github.com/nijaru/omengrep/releases/tag/$TAG" >> $GITHUB_STEP_SUMMARY
          echo "- **crates.io**: https://crates.io/crates/omengrep/$VERSION" >> $GITHUB_STEP_SUMMARY
          echo "- **Homebrew**: \`brew upgrade og\`" >> $GITHUB_STEP_SUMMARY
