name: Release & Publish

on:
  push:
    branches:
      - main

permissions:
  contents: write
  pull-requests: write

jobs:
  validate:
    name: Tests, Formatting & Security
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Check formatting
        run: cargo fmt --all -- --check
      - name: Run tests
        run: cargo test --all-targets --all-features
      - name: Security audit (cargo-deny)
        uses: EmbarkStudios/cargo-deny-action@v2
        with:
          command: check bans licenses

  release-please:
    needs: validate
    runs-on: ubuntu-latest
    outputs:
      release_created: ${{ steps.release.outputs.release_created }}
      tag_name: ${{ steps.release.outputs.tag_name }}
    steps:
      - name: Run Release Please
        id: release
        uses: googleapis/release-please-action@v4
        with:
          release-type: rust

  publish-cargo:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo publish --token ${{ secrets.CRATES_TOKEN }} --no-verify

  build-c-libs:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            artifact_name: aam-c-linux-x86_64
            lib_name: aam-c.so
          - os: macos-latest
            artifact_name: aam-c-macos-x86_64
            lib_name: aam-c.dylib
          - os: windows-latest
            artifact_name: aam-c-windows-x86_64
            lib_name: aam-c.dll
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: bash
    steps:
      - uses: actions/checkout@v6
      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
      - name: Install cargo-binstall
        uses: cargo-bins/cargo-binstall@main
      - name: Install cbindgen
        run: cargo binstall cbindgen -y
      - name: Build release library
        run: cargo build --release --locked
      - name: Prepare C/C++ Package Structure
        run: |
          mkdir -p package/include package/lib/cmake/aam-c package/bin package/examples
          cbindgen --config cbindgen.toml --crate aam_rs --output package/include/aam-c.h
          cp LICENSE package/ 2>/dev/null || true
          cp examples/c/*.c package/examples/ 2>/dev/null || true
          cp examples/c/*.aam package/examples/ 2>/dev/null || true
          cp examples/c/Makefile package/examples/ 2>/dev/null || true
          cp examples/c/CMakeLists.txt package/examples/ 2>/dev/null || true
          cp aam-cConfig.cmake package/lib/cmake/aam-c/ 2>/dev/null || true
          if [ "${{ runner.os }}" == "Windows" ]; then
            cp target/release/aam_rs.dll package/bin/aam-c.dll
            cp target/release/aam_rs.dll.lib package/lib/aam-c.lib
          elif [ "${{ runner.os }}" == "macOS" ]; then
            cp target/release/libaam_rs.dylib package/lib/libaam-c.dylib
          else
            cp target/release/libaam_rs.so package/lib/libaam-c.so
          fi
      - name: Zip Package
        run: |
          cd package
          zip -r ../${{ matrix.artifact_name }}.zip ./*
      - name: Upload Release Artifact
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.release-please.outputs.tag_name }}
          files: ${{ matrix.artifact_name }}.zip

  linux:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-22.04
            target: x86_64
          - runner: ubuntu-22.04
            target: x86
          - runner: ubuntu-22.04
            target: aarch64
          - runner: ubuntu-22.04
            target: armv7
          - runner: ubuntu-22.04
            target: s390x
          - runner: ubuntu-22.04
            target: ppc64le
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          sccache: false
          manylinux: auto
      - name: Build free-threaded wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist -i python3.14t
          sccache: false
          manylinux: auto
      - name: Upload wheels
        uses: actions/upload-artifact@v5
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist

  musllinux:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-22.04
            target: x86_64
          - runner: ubuntu-22.04
            target: x86
          - runner: ubuntu-22.04
            target: aarch64
          - runner: ubuntu-22.04
            target: armv7
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          sccache: false
          manylinux: musllinux_1_2
      - name: Build free-threaded wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist -i python3.14t
          sccache: false
          manylinux: musllinux_1_2
      - name: Upload wheels
        uses: actions/upload-artifact@v5
        with:
          name: wheels-musllinux-${{ matrix.platform.target }}
          path: dist

  windows:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: windows-latest
            target: x64
            python_arch: x64
          - runner: windows-latest
            target: x86
            python_arch: x86
          - runner: windows-11-arm
            target: aarch64
            python_arch: arm64
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: 3.13
          architecture: ${{ matrix.platform.python_arch }}
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          sccache: false
      - uses: actions/setup-python@v6
        with:
          python-version: 3.14t
          architecture: ${{ matrix.platform.python_arch }}
      - name: Build free-threaded wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist -i python3.14t
          sccache: false
      - name: Upload wheels
        uses: actions/upload-artifact@v5
        with:
          name: wheels-windows-${{ matrix.platform.target }}
          path: dist

  macos:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: macos-15-intel
            target: x86_64
          - runner: macos-latest
            target: aarch64
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          sccache: false
      - name: Build free-threaded wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist -i python3.14t
          sccache: false
      - name: Upload wheels
        uses: actions/upload-artifact@v5
        with:
          name: wheels-macos-${{ matrix.platform.target }}
          path: dist

  sdist:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - name: Upload sdist
        uses: actions/upload-artifact@v5
        with:
          name: wheels-sdist
          path: dist

  publish-pypi:
    name: Publish to PyPI
    needs: [ release-please, linux, musllinux, windows, macos, sdist ]
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      attestations: write
    steps:
      - uses: actions/download-artifact@v6
        with:
          pattern: wheels-*
          merge-multiple: true
          path: dist
      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v3
        with:
          subject-path: 'dist/*'
      - name: Install uv
        uses: astral-sh/setup-uv@v7
      - name: Publish to PyPI
        run: uv publish dist/*
        env:
          UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
