name: Release

on:
  push:
    tags:
      - 'v[0-9]+.*'

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always
  CARGO_INCREMENTAL: 0

jobs:
  create-release:
    name: Create Release
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.tag.outputs.tag }}
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Get tag
        id: tag
        run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"

      - name: Verify version matches Cargo.toml
        run: |
          CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)
          TAG_VERSION=${GITHUB_REF#refs/tags/v}
          if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
            echo "::error::Tag version ($TAG_VERSION) does not match Cargo.toml ($CARGO_VERSION)"
            exit 1
          fi

      - name: Generate changelog
        uses: orhun/git-cliff-action@v4
        with:
          config: cliff.toml
          args: --latest --strip header
        env:
          OUTPUT: CHANGELOG.md
          GITHUB_REPO: ${{ github.repository }}

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          body_path: CHANGELOG.md
          draft: false
          prerelease: ${{ contains(steps.tag.outputs.tag, '-') }}
          generate_release_notes: false

  build-binaries:
    name: Build ${{ matrix.target }}
    needs: create-release
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-apple-darwin
            os: macos-latest
          - target: x86_64-pc-windows-msvc
            os: windows-latest
    steps:
      - uses: actions/checkout@v6

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

      - uses: Swatinem/rust-cache@v2
        with:
          key: release-${{ matrix.target }}

      - name: Build
        run: cargo build --release --target ${{ matrix.target }}

      - name: Package (Unix)
        if: runner.os != 'Windows'
        shell: bash
        run: |
          tag="${{ needs.create-release.outputs.tag }}"
          bin="tally"
          src="target/${{ matrix.target }}/release/${bin}"
          archive="${bin}-${tag}-${{ matrix.target }}.tar.gz"

          # Strip debug symbols
          strip "${src}" 2>/dev/null || true

          tar czf "${archive}" -C "target/${{ matrix.target }}/release" "${bin}"

          # SHA256 — cross-platform
          if command -v sha256sum &>/dev/null; then
            sha256sum "${archive}" > "${archive}.sha256"
          else
            shasum -a 256 "${archive}" > "${archive}.sha256"
          fi

          echo "ARCHIVE=${archive}" >> "$GITHUB_ENV"

      - name: Package (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          $tag = "${{ needs.create-release.outputs.tag }}"
          $bin = "tally.exe"
          $src = "target/${{ matrix.target }}/release/$bin"
          $archive = "tally-${tag}-${{ matrix.target }}.zip"

          Compress-Archive -Path $src -DestinationPath $archive

          $hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLower()
          "$hash  $archive" | Out-File -Encoding ascii "${archive}.sha256"

          echo "ARCHIVE=${archive}" >> $env:GITHUB_ENV

      - name: Upload to Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            ${{ env.ARCHIVE }}
            ${{ env.ARCHIVE }}.sha256

  publish-crate:
    name: Publish to crates.io
    needs: [create-release, build-binaries]
    runs-on: ubuntu-latest
    if: ${{ !contains(needs.create-release.outputs.tag, '-') }}
    steps:
      - uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable

      - name: Verify package
        run: cargo package --allow-dirty

      - name: Publish
        run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        continue-on-error: true

  update-homebrew:
    name: Update Homebrew Formula
    needs: [create-release, build-binaries]
    runs-on: ubuntu-latest
    if: ${{ !contains(needs.create-release.outputs.tag, '-') }}
    steps:
      - name: Compute SHA256 and update formula
        env:
          GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
        run: |
          tag="${{ needs.create-release.outputs.tag }}"
          version="${tag#v}"
          url="https://github.com/1898andCo/tally/archive/refs/tags/${tag}.tar.gz"

          # Download tarball and compute SHA-256
          sha256=$(curl -sL "$url" | sha256sum | cut -d' ' -f1)
          echo "SHA256: ${sha256}"

          # Generate updated formula
          cat > /tmp/tally.rb <<FORMULA
          class Tally < Formula
            desc "Git-backed findings tracker for AI coding agents"
            homepage "https://github.com/1898andCo/tally"
            url "${url}"
            sha256 "${sha256}"
            license "Apache-2.0"
            head "https://github.com/1898andCo/tally.git", branch: "develop"

            depends_on "rust" => :build

            def install
              system "cargo", "install", *std_cargo_args
            end

            test do
              system "#{bin}/tally", "--version"
            end
          end
          FORMULA

          # Remove leading whitespace from heredoc
          sed -i 's/^          //' /tmp/tally.rb

          # Push to homebrew-tap via GitHub API
          existing_sha=$(gh api repos/1898andCo/homebrew-tap/contents/Formula/tally.rb --jq '.sha')
          gh api repos/1898andCo/homebrew-tap/contents/Formula/tally.rb \
            -X PUT \
            --field message="tally ${version}" \
            --field content="$(base64 -w0 /tmp/tally.rb)" \
            --field sha="$existing_sha"
        continue-on-error: true
