name: Manual Release

on:
  workflow_dispatch:
    inputs:
      version_type:
        description: 'Version bump type'
        required: true
        default: 'patch'
        type: choice
        options:
          - major
          - minor
          - patch

env:
  CARGO_TERM_COLOR: always

permissions:
  contents: write

jobs:
  release:
    name: Create Release
    runs-on: ubuntu-latest
    outputs:
      new_version: ${{ steps.version.outputs.new_version }}
      upload_url: ${{ steps.create_release.outputs.upload_url }}
      tag_sha: ${{ steps.tag_sha.outputs.tag_sha }}
    steps:
      - uses: actions/checkout@v6
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0

      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2

      - name: Install cargo-edit
        run: cargo install cargo-edit

      - name: Bump version
        id: version
        run: |
          cargo set-version --bump ${{ github.event.inputs.version_type }} -p splashboard
          NEW_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "splashboard") | .version')
          echo "new_version=v$NEW_VERSION" >> $GITHUB_OUTPUT
          echo "New version: v$NEW_VERSION"

      - name: Run tests
        run: cargo test

      - name: Install Nix
        uses: cachix/install-nix-action@v31

      - name: Update flake.nix
        run: |
          NEW_VERSION=$(echo "${{ steps.version.outputs.new_version }}" | sed 's/^v//')
          sed -i "s/version = \"[0-9.]\+\"/version = \"$NEW_VERSION\"/" flake.nix
          echo "Version updated in flake.nix to $NEW_VERSION"

      - name: Create temporary tag
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add Cargo.toml Cargo.lock flake.nix
          git commit -m "chore: bump version to ${{ steps.version.outputs.new_version }}"
          git tag ${{ steps.version.outputs.new_version }}

      - name: Generate Changelog
        run: |
          chmod +x generate_changelog.sh
          ./generate_changelog.sh

      - name: Commit changelog and push
        run: |
          git add CHANGELOG.md
          git commit --amend --no-edit
          git tag -f ${{ steps.version.outputs.new_version }}
          git push origin main
          git push origin ${{ steps.version.outputs.new_version }}

      - name: Resolve tag commit SHA
        id: tag_sha
        run: |
          TAG_SHA=$(git rev-list -n 1 ${{ steps.version.outputs.new_version }})
          echo "tag_sha=$TAG_SHA" >> $GITHUB_OUTPUT
          echo "Tag commit SHA: $TAG_SHA"

      - name: Extract Release Notes
        id: extract_notes
        run: |
          VERSION=$(echo "${{ steps.version.outputs.new_version }}" | sed 's/^v//')
          awk "/## \[$VERSION\]/{flag=1; next} /## \[/{flag=0} flag" CHANGELOG.md > release_notes.md
          if [ ! -s release_notes.md ]; then
            echo "## What's Changed" > release_notes.md
            echo "" >> release_notes.md
            echo "See the full changelog for details." >> release_notes.md
          fi
          echo "RELEASE_NOTES<<EOF" >> $GITHUB_OUTPUT
          cat release_notes.md >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Create Release
        id: create_release
        uses: softprops/action-gh-release@v3
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ steps.version.outputs.new_version }}
          name: Release ${{ steps.version.outputs.new_version }}
          body: ${{ steps.extract_notes.outputs.RELEASE_NOTES }}
          draft: true
          prerelease: false

  build-and-upload:
    name: Build and Upload
    needs: release
    strategy:
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-22.04
            use_zigbuild: true
            zig_target: x86_64-unknown-linux-gnu.2.17
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-22.04
            use_zigbuild: true
            zig_target: aarch64-unknown-linux-gnu.2.17
          - target: x86_64-pc-windows-msvc
            os: windows-latest
          - target: x86_64-apple-darwin
            os: macos-latest
          - target: aarch64-apple-darwin
            os: macos-latest
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ needs.release.outputs.new_version }}
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - name: Install Zig (for zigbuild)
        if: matrix.use_zigbuild
        uses: mlugg/setup-zig@v2
        with:
          version: 0.13.0
      - name: Install cargo-zigbuild
        if: matrix.use_zigbuild
        run: cargo install --locked cargo-zigbuild
      - name: Build (zigbuild, pinned glibc)
        if: matrix.use_zigbuild
        run: cargo zigbuild --release --target ${{ matrix.zig_target }} -p splashboard
      - name: Build
        if: '!matrix.use_zigbuild'
        run: cargo build --release --target ${{ matrix.target }} -p splashboard
      - name: Create archive (Unix)
        if: matrix.os != 'windows-latest'
        run: |
          cd target/${{ matrix.target }}/release
          tar -czf ../../../splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.tar.gz splashboard
      - name: Create archive (Windows)
        if: matrix.os == 'windows-latest'
        run: |
          cd target/${{ matrix.target }}/release
          Compress-Archive -Path splashboard.exe -DestinationPath ../../../splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.zip
      - name: Upload Release Asset (Unix)
        if: matrix.os != 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.release.outputs.upload_url }}
          asset_path: ./splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.tar.gz
          asset_name: splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.tar.gz
          asset_content_type: application/gzip
      - name: Upload Release Asset (Windows)
        if: matrix.os == 'windows-latest'
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.release.outputs.upload_url }}
          asset_path: ./splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.zip
          asset_name: splashboard-${{ needs.release.outputs.new_version }}-${{ matrix.target }}.zip
          asset_content_type: application/zip

  publish-release:
    name: Publish Release
    runs-on: ubuntu-latest
    needs: [release, build-and-upload]
    permissions:
      contents: write
    steps:
      - name: Mark release as published
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: gh release edit ${{ needs.release.outputs.new_version }} --draft=false --repo ${{ github.repository }}

  publish-crates:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: [release, build-and-upload]
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ needs.release.outputs.new_version }}
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Publish to crates.io
        run: cargo publish -p splashboard --token ${{ secrets.CARGO_REGISTRY_TOKEN }}

  update-flake-hashes:
    name: Update flake.nix Hashes
    runs-on: ubuntu-latest
    needs: release
    steps:
      - uses: actions/checkout@v6
        with:
          ref: main
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0

      - uses: cachix/install-nix-action@v31

      - name: Calculate and update hashes
        run: |
          VERSION=${{ needs.release.outputs.new_version }}

          git pull origin main

          SRC_HASH=$(nix flake prefetch --json github:unhappychoice/splashboard/$VERSION 2>/dev/null | jq -r .hash)
          echo "Source hash: $SRC_HASH"

          sed -i "s|hash = \"sha256-[A-Za-z0-9+/=]\+\"|hash = \"$SRC_HASH\"|" flake.nix

          nix build .#default 2>&1 | tee /tmp/build.log || true
          CARGO_HASH=$(grep -oP "got:\s+\Ksha256-[A-Za-z0-9+/=]+" /tmp/build.log | head -1 || echo "")

          if [ -n "$CARGO_HASH" ]; then
            echo "Cargo hash: $CARGO_HASH"
            sed -i "s|cargoHash = \"sha256-[A-Za-z0-9+/=]\+\"|cargoHash = \"$CARGO_HASH\"|" flake.nix
          else
            echo "Warning: Could not determine cargo hash"
          fi

      - name: Update flake.lock
        run: nix flake lock

      - name: Commit and push changes
        run: |
          VERSION=${{ needs.release.outputs.new_version }}
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add flake.nix flake.lock
          git commit -m "chore: update flake.nix hashes for $VERSION" || echo "No changes to commit"
          git push origin main

  update-homebrew:
    name: Update Homebrew Formula
    runs-on: ubuntu-latest
    needs: [release, publish-release]
    steps:
      - name: Checkout homebrew tap
        uses: actions/checkout@v6
        with:
          repository: unhappychoice/homebrew-tap
          token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
          path: homebrew-tap

      - name: Update Homebrew formula
        run: |
          VERSION=${{ needs.release.outputs.new_version }}

          MACOS_INTEL_URL="https://github.com/unhappychoice/splashboard/releases/download/$VERSION/splashboard-$VERSION-x86_64-apple-darwin.tar.gz"
          MACOS_INTEL_SHA=$(curl -sL "$MACOS_INTEL_URL" | sha256sum | cut -d' ' -f1)

          MACOS_ARM_URL="https://github.com/unhappychoice/splashboard/releases/download/$VERSION/splashboard-$VERSION-aarch64-apple-darwin.tar.gz"
          MACOS_ARM_SHA=$(curl -sL "$MACOS_ARM_URL" | sha256sum | cut -d' ' -f1)

          LINUX_INTEL_URL="https://github.com/unhappychoice/splashboard/releases/download/$VERSION/splashboard-$VERSION-x86_64-unknown-linux-gnu.tar.gz"
          LINUX_INTEL_SHA=$(curl -sL "$LINUX_INTEL_URL" | sha256sum | cut -d' ' -f1)

          LINUX_ARM_URL="https://github.com/unhappychoice/splashboard/releases/download/$VERSION/splashboard-$VERSION-aarch64-unknown-linux-gnu.tar.gz"
          LINUX_ARM_SHA=$(curl -sL "$LINUX_ARM_URL" | sha256sum | cut -d' ' -f1)

          echo "Calculated SHAs:"
          echo "macOS Intel: $MACOS_INTEL_SHA"
          echo "macOS ARM: $MACOS_ARM_SHA"
          echo "Linux Intel: $LINUX_INTEL_SHA"
          echo "Linux ARM: $LINUX_ARM_SHA"

          cd homebrew-tap

          sed -i "s|https://github.com/unhappychoice/splashboard/releases/download/v[0-9.]\+/splashboard-v[0-9.]\+-x86_64-apple-darwin.tar.gz|$MACOS_INTEL_URL|g" Formula/splashboard.rb
          sed -i "s|https://github.com/unhappychoice/splashboard/releases/download/v[0-9.]\+/splashboard-v[0-9.]\+-aarch64-apple-darwin.tar.gz|$MACOS_ARM_URL|g" Formula/splashboard.rb
          sed -i "s|https://github.com/unhappychoice/splashboard/releases/download/v[0-9.]\+/splashboard-v[0-9.]\+-x86_64-unknown-linux-gnu.tar.gz|$LINUX_INTEL_URL|g" Formula/splashboard.rb
          sed -i "s|https://github.com/unhappychoice/splashboard/releases/download/v[0-9.]\+/splashboard-v[0-9.]\+-aarch64-unknown-linux-gnu.tar.gz|$LINUX_ARM_URL|g" Formula/splashboard.rb

          FIRST_SHA_LINE=$(grep -n 'sha256 "' Formula/splashboard.rb | head -1 | cut -d: -f1)
          sed -i "${FIRST_SHA_LINE}s/sha256 \"[a-f0-9]\+\"/sha256 \"$MACOS_INTEL_SHA\"/" Formula/splashboard.rb

          SECOND_SHA_LINE=$(grep -n 'sha256 "' Formula/splashboard.rb | head -2 | tail -1 | cut -d: -f1)
          sed -i "${SECOND_SHA_LINE}s/sha256 \"[a-f0-9]\+\"/sha256 \"$MACOS_ARM_SHA\"/" Formula/splashboard.rb

          THIRD_SHA_LINE=$(grep -n 'sha256 "' Formula/splashboard.rb | head -3 | tail -1 | cut -d: -f1)
          sed -i "${THIRD_SHA_LINE}s/sha256 \"[a-f0-9]\+\"/sha256 \"$LINUX_INTEL_SHA\"/" Formula/splashboard.rb

          FOURTH_SHA_LINE=$(grep -n 'sha256 "' Formula/splashboard.rb | head -4 | tail -1 | cut -d: -f1)
          sed -i "${FOURTH_SHA_LINE}s/sha256 \"[a-f0-9]\+\"/sha256 \"$LINUX_ARM_SHA\"/" Formula/splashboard.rb

          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add Formula/splashboard.rb
          git commit -m "chore: update splashboard to $VERSION"
          git push
