name: Release

on:
  push:
    tags: ['v*']
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to release'
        required: true
        type: string

# Cancel in-progress runs when new commits are pushed
concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

permissions:
  contents: write

env:
  CARGO_PROFILE_DEV_DEBUG: line-tables-only

jobs:
  create-release:
    name: Create Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.get_version.outputs.version }}

    steps:
    - uses: actions/checkout@v6
      with:
        fetch-depth: 0

    - name: Get version
      id: get_version
      run: |
        if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
          echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
        else
          echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
        fi

    - name: Generate release notes
      id: release_notes
      run: |
        echo "# Release ${{ steps.get_version.outputs.version }}" > release_notes.md
        echo "" >> release_notes.md
        echo "## Changes" >> release_notes.md

        # Get the previous tag
        PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")

        if [[ -n "$PREVIOUS_TAG" ]]; then
          echo "Changes since $PREVIOUS_TAG:" >> release_notes.md
          git log --oneline --format="- %s" $PREVIOUS_TAG..HEAD >> release_notes.md
        else
          echo "Initial release" >> release_notes.md
          git log --oneline --format="- %s" >> release_notes.md
        fi

    - name: Create Release
      id: create_release
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        gh release create "${{ steps.get_version.outputs.version }}" \
          --title "Release ${{ steps.get_version.outputs.version }}" \
          --notes-file release_notes.md \
          --draft=false \
          --prerelease=false

  build-release:
    name: Build Release
    needs: create-release
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            binary: debtmap
            archive: tar.gz
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            binary: debtmap
            archive: tar.gz
          - os: macos-latest
            target: x86_64-apple-darwin
            binary: debtmap
            archive: tar.gz
          - os: macos-latest
            target: aarch64-apple-darwin
            binary: debtmap
            archive: tar.gz
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            binary: debtmap.exe
            archive: zip

    steps:
    - uses: actions/checkout@v6

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

    - name: Cache Rust dependencies
      uses: Swatinem/rust-cache@v2
      with:
        cache-bin: "false"

    - name: Install musl tools
      if: matrix.target == 'x86_64-unknown-linux-musl'
      run: |
        sudo apt-get update
        sudo apt-get install -y musl-tools pkg-config

    - name: Install OpenSSL (Windows)
      if: runner.os == 'Windows'
      shell: pwsh
      run: |
        echo "Installing OpenSSL via vcpkg..."
        vcpkg integrate install
        vcpkg install openssl:x64-windows-static-md
        $opensslDir = "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows-static-md"
        echo "OPENSSL_DIR=$opensslDir" >> $env:GITHUB_ENV
        echo "OPENSSL_LIB_DIR=$opensslDir\lib" >> $env:GITHUB_ENV
        echo "OPENSSL_INCLUDE_DIR=$opensslDir\include" >> $env:GITHUB_ENV

    - name: Build release binary
      run: cargo build --release --target ${{ matrix.target }}
      env:
        OPENSSL_STATIC: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}

    - name: Create archive (Unix)
      if: matrix.archive == 'tar.gz'
      run: |
        mkdir -p release
        cp target/${{ matrix.target }}/release/${{ matrix.binary }} release/
        cp README.md LICENSE release/
        cd release
        tar -czf ../debtmap-${{ matrix.target }}.tar.gz .

    - name: Create archive (Windows)
      if: matrix.archive == 'zip'
      run: |
        mkdir release
        cp target/${{ matrix.target }}/release/${{ matrix.binary }} release/
        cp README.md release/
        cp LICENSE release/
        cd release
        7z a ../debtmap-${{ matrix.target }}.zip .

    - name: Generate checksums
      shell: bash
      run: |
        if [[ "${{ matrix.archive }}" == "tar.gz" ]]; then
          if [[ "${{ runner.os }}" == "macOS" ]]; then
            shasum -a 256 debtmap-${{ matrix.target }}.tar.gz > debtmap-${{ matrix.target }}.tar.gz.sha256
          else
            sha256sum debtmap-${{ matrix.target }}.tar.gz > debtmap-${{ matrix.target }}.tar.gz.sha256
          fi
        else
          if [[ "${{ runner.os }}" == "Windows" ]]; then
            powershell -Command "Get-FileHash -Algorithm SHA256 debtmap-${{ matrix.target }}.zip | ForEach-Object { \$_.Hash.ToLower() + '  ' + \$_.Path.Split('\')[-1] }" > debtmap-${{ matrix.target }}.zip.sha256
          else
            sha256sum debtmap-${{ matrix.target }}.zip > debtmap-${{ matrix.target }}.zip.sha256
          fi
        fi

    - name: Upload Release Assets
      shell: bash
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        if [[ "${{ matrix.archive }}" == "tar.gz" ]]; then
          gh release upload "${{ needs.create-release.outputs.version }}" \
            "debtmap-${{ matrix.target }}.tar.gz" \
            "debtmap-${{ matrix.target }}.tar.gz.sha256"
        else
          gh release upload "${{ needs.create-release.outputs.version }}" \
            "debtmap-${{ matrix.target }}.zip" \
            "debtmap-${{ matrix.target }}.zip.sha256"
        fi
