name: Canonical Release

on:
  workflow_dispatch:
    inputs:
      bump_type:
        description: 'Version bump type'
        required: true
        type: choice
        options:
          - auto
          - patch
          - minor
          - major
        default: auto
      dry_run:
        description: 'Dry run (no actual release)'
        required: false
        type: boolean
        default: false

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  release:
    name: Canonical Release
    runs-on: ubuntu-22.04
    permissions:
      contents: write
      packages: write
      
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for changelog generation
          token: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      
      - name: Cache Cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-release-
      
      - name: Install release tools
        run: |
          echo "📦 Installing release tools..."
          cargo install cargo-release --locked
          cargo install cargo-semver-checks --locked
          cargo install cargo-audit --locked
          cargo install cargo-outdated --locked
          echo "✅ Release tools installed"
      
      - name: Configure Git
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
      
      - name: Pre-release checks
        run: |
          echo "🔍 Running pre-release quality gates..."
          make pre-release-checks
      
      - name: Determine version bump
        id: version
        run: |
          if [ "${{ inputs.bump_type }}" = "auto" ]; then
            echo "🤖 Auto-determining version bump..."
            
            # Check for breaking changes
            if cargo semver-checks check-release 2>&1 | grep -q "MAJOR\|breaking"; then
              echo "bump=major" >> $GITHUB_OUTPUT
              echo "💥 Breaking changes detected - MAJOR release"
            # Check for new features
            elif git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo HEAD~10)..HEAD | grep -qE '^[a-f0-9]+ feat:'; then
              echo "bump=minor" >> $GITHUB_OUTPUT
              echo "✨ New features detected - MINOR release"
            else
              echo "bump=patch" >> $GITHUB_OUTPUT
              echo "🐛 Bug fixes only - PATCH release"
            fi
          else
            echo "bump=${{ inputs.bump_type }}" >> $GITHUB_OUTPUT
            echo "📌 Manual version bump: ${{ inputs.bump_type }}"
          fi
      
      - name: Get current version
        id: current
        run: |
          CURRENT=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)
          echo "version=$CURRENT" >> $GITHUB_OUTPUT
          echo "Current version: $CURRENT"
      
      - name: Calculate new version
        id: new
        run: |
          CURRENT="${{ steps.current.outputs.version }}"
          IFS='.' read -ra PARTS <<< "$CURRENT"
          MAJOR="${PARTS[0]}"
          MINOR="${PARTS[1]}"
          PATCH="${PARTS[2]}"
          
          case "${{ steps.version.outputs.bump }}" in
            major)
              MAJOR=$((MAJOR + 1))
              MINOR=0
              PATCH=0
              ;;
            minor)
              MINOR=$((MINOR + 1))
              PATCH=0
              ;;
            patch)
              PATCH=$((PATCH + 1))
              ;;
          esac
          
          NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
          echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
          echo "New version: $NEW_VERSION"
      
      - name: Dry run check
        if: inputs.dry_run
        run: |
          echo "🧪 DRY RUN MODE - No actual release will be created"
          echo "Would bump from ${{ steps.current.outputs.version }} to ${{ steps.new.outputs.version }}"
          cargo release ${{ steps.version.outputs.bump }} --dry-run
          exit 0
      
      - name: Update changelog
        run: |
          echo "📝 Updating CHANGELOG.md..."
          DATE=$(date +%Y-%m-%d)
          sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n## [${{ steps.new.outputs.version }}] - $DATE/" CHANGELOG.md
          git add CHANGELOG.md
      
      - name: Perform release
        run: |
          echo "🚀 Creating release v${{ steps.new.outputs.version }}..."
          cargo release ${{ steps.version.outputs.bump }} --execute --no-confirm
      
      - name: Build release binaries
        run: |
          echo "🔨 Building release binaries..."
          cargo build --release --locked
          strip target/release/pmat
          
          # Create archive
          cd target/release
          tar czf pmat-${{ steps.new.outputs.version }}-x86_64-unknown-linux-gnu.tar.gz pmat
          cd ../..
      
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: v${{ steps.new.outputs.version }}
          name: v${{ steps.new.outputs.version }}
          draft: false
          prerelease: false
          generate_release_notes: true
          files: |
            target/release/pmat-${{ steps.new.outputs.version }}-x86_64-unknown-linux-gnu.tar.gz
      
      - name: Publish to crates.io
        run: |
          echo "📦 Publishing to crates.io..."
          cd server
          cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      
      - name: Verify release
        run: |
          echo "🔍 Verifying release..."
          sleep 30  # Wait for crates.io to update
          
          # Check crates.io
          cargo search pmat | head -1
          
          # Test installation
          cargo install pmat --force
          pmat --version | grep -q "${{ steps.new.outputs.version }}"
          
          echo "✅ Release v${{ steps.new.outputs.version }} completed successfully!"
      
      - name: Post-release notification
        if: success() && !inputs.dry_run
        run: |
          echo "🎉 Release v${{ steps.new.outputs.version }} has been published!"
          echo "📦 Crates.io: https://crates.io/crates/pmat"
          echo "🏷️ GitHub: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.new.outputs.version }}"