name: Build Release Binaries

on:
  workflow_call:
  workflow_dispatch:
    inputs:
      upload:
        description: "Upload to release (requires a release to exist)"
        required: false
        default: "false"
        type: choice
        options:
          - "true"
          - "false"
      tag:
        description: "Release tag to upload to (only if upload is true)"
        required: false
        type: string

jobs:
  build-binaries:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        include:
          # Linux x86_64 (glibc)
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
            build_packages: true

          # Linux ARM64 (glibc)
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-24.04-arm
            build_packages: true

          # Linux x86_64 (musl)
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
            build_packages: false

          # Linux ARM64 (musl)
          - target: aarch64-unknown-linux-musl
            os: ubuntu-24.04-arm
            build_packages: false

          # macOS x86_64
          - target: x86_64-apple-darwin
            os: macos-15-intel
            build_packages: false

          # macOS ARM64 (Apple Silicon)
          - target: aarch64-apple-darwin
            os: macos-latest
            build_packages: false

          # Windows x86_64
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            build_packages: false

          # Windows ARM64
          - target: aarch64-pc-windows-msvc
            os: windows-11-arm
            build_packages: false

    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.release.tag_name || github.ref }}

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

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{
            hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.target }}-cargo-

      - name: Install musl toolchain
        if: endsWith(matrix.target, '-unknown-linux-musl')
        run: sudo apt-get update && sudo apt-get install -y musl-tools

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

      - name: Strip binary (Unix)
        if: runner.os != 'Windows'
        run: strip target/${{ matrix.target }}/release/panache

      - name: Create archive (Unix)
        if: runner.os != 'Windows'
        run: |
          mkdir -p dist
          cp target/${{ matrix.target }}/release/panache dist/
          cp -r target/man dist/
          cp -r target/completions dist/
          cp LICENSE dist/
          tar czf panache-${{ matrix.target }}.tar.gz -C dist .
          rm -rf dist

      - name: Create archive (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          New-Item -ItemType Directory -Path dist -Force
          Copy-Item target/${{ matrix.target }}/release/panache.exe dist/
          Copy-Item -Recurse target/man dist/
          Copy-Item -Recurse target/completions dist/
          Copy-Item LICENSE dist/
          Compress-Archive -Path dist/* -DestinationPath panache-${{ matrix.target }}.zip
          Remove-Item -Recurse -Force dist

      - name: Upload artifact (for testing)
        uses: actions/upload-artifact@v7
        with:
          name: panache-${{ matrix.target }}
          path: |
            panache-${{ matrix.target }}.tar.gz
            panache-${{ matrix.target }}.zip

      - name: Upload binary to release
        if: github.event_name == 'workflow_dispatch' && inputs.upload == 'true'
        shell: bash
        run: |
          TAG="${{ github.event.release.tag_name || inputs.tag }}"
          if [ -f panache-${{ matrix.target }}.tar.gz ]; then
            gh release upload --clobber "$TAG" panache-${{ matrix.target }}.tar.gz
          fi
          if [ -f panache-${{ matrix.target }}.zip ]; then
            gh release upload --clobber "$TAG" panache-${{ matrix.target }}.zip
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Install cargo-deb and cargo-generate-rpm
        if: matrix.build_packages == true
        run: |
          cargo install cargo-deb
          cargo install cargo-generate-rpm

      - name: Build DEB package
        if: matrix.build_packages == true
        run: |
          rm -rf target/${{ matrix.target }}/debian
          cargo deb --target ${{ matrix.target }} --no-build

      - name: Build RPM package
        if: matrix.build_packages == true
        run: |
          rm -rf target/${{ matrix.target }}/generate-rpm
          cargo generate-rpm --target ${{ matrix.target }}

      - name: Upload DEB artifact (for testing)
        if: matrix.build_packages == true
        run: |
          DEB_FILE=$(ls target/${{ matrix.target }}/debian/*.deb)
          cp "$DEB_FILE" .
        continue-on-error: true

      - name: Upload RPM artifact (for testing)
        if: matrix.build_packages == true
        run: |
          RPM_FILE=$(ls target/${{ matrix.target }}/generate-rpm/*.rpm)
          cp "$RPM_FILE" .
        continue-on-error: true

      - name: Upload package artifacts
        if: matrix.build_packages == true
        uses: actions/upload-artifact@v7
        with:
          name: panache-packages-${{ matrix.target }}
          path: |
            *.deb
            *.rpm

      - name: Upload DEB package
        if: matrix.build_packages == true && github.event_name == 'workflow_dispatch' && inputs.upload == 'true'
        run: |
          TAG="${{ github.event.release.tag_name || inputs.tag }}"
          DEB_FILE=$(ls target/${{ matrix.target }}/debian/*.deb)
          gh release upload --clobber "$TAG" "$DEB_FILE"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Upload RPM package
        if: matrix.build_packages == true && github.event_name == 'workflow_dispatch' && inputs.upload == 'true'
        run: |
          TAG="${{ github.event.release.tag_name || inputs.tag }}"
          RPM_FILE=$(ls target/${{ matrix.target }}/generate-rpm/*.rpm)
          gh release upload --clobber "$TAG" "$RPM_FILE"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
