name: Release

on:
  release:
    types: [ created ]

env:
  CARGO_TERM_COLOR: always
  RUST_VERSION: 1.95.0
  DOCKER_IMAGE: ghcr.io/${{ github.repository }}

permissions:
  contents: write    # Required for creating releases and uploading assets
  packages: write    # Required for pushing to GitHub Container Registry

jobs:
  # ---------------------------------------------------------------------------
  # Desktop / server binaries (Linux, macOS, Windows)
  # ---------------------------------------------------------------------------
  build-binaries:
    name: Desktop · ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: mediaflow-proxy-light
            asset_name: mediaflow-proxy-light-linux-x86_64
          # Native ARM runner — avoids cross-compile entirely.  Cross-compiling
          # boring-sys2 via gcc-aarch64-linux-gnu is unreliable (cc-rs / CMake /
          # bindgen can silently fall back to host gcc, producing x86_64 .o files
          # in the rlib → `Relocations in generic ELF (EM: 62)` at final link).
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            artifact_name: mediaflow-proxy-light
            asset_name: mediaflow-proxy-light-linux-aarch64
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: mediaflow-proxy-light
            asset_name: mediaflow-proxy-light-macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: mediaflow-proxy-light
            asset_name: mediaflow-proxy-light-macos-aarch64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: mediaflow-proxy-light.exe
            asset_name: mediaflow-proxy-light-windows-x86_64.exe

    steps:
      - uses: actions/checkout@v5

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

      - name: Build
        # Default features include `tls-rustls` (pure-Rust TLS), so no system
        # OpenSSL is needed on any target.  Each matrix entry runs on a native
        # host for its target, so no cross-compile env vars are needed.
        run: cargo build --release --target ${{ matrix.target }}

      - name: Upload binary to release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
          asset_name: ${{ matrix.asset_name }}
          tag: ${{ github.ref }}
          overwrite: true

  # ---------------------------------------------------------------------------
  # iOS — .xcframework containing static libs for device + simulator.
  # Used by the companion iOS app which links the proxy as a Rust library via
  # the C FFI (see `include/mediaflow_ffi.h`).
  # ---------------------------------------------------------------------------
  build-ios:
    name: iOS · xcframework
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v5

      - name: Install Rust + iOS targets
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ env.RUST_VERSION }}
          targets: aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios

      - name: Cache cargo build
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ios-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Build xcframework
        run: ./tools/build-ios.sh

      - name: Archive xcframework
        run: |
          zip -r MediaflowProxy.xcframework.zip MediaflowProxy.xcframework

      - name: Upload xcframework
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: MediaflowProxy.xcframework.zip
          asset_name: mediaflow-proxy-light-ios.xcframework.zip
          tag: ${{ github.ref }}
          overwrite: true

  # ---------------------------------------------------------------------------
  # Android — native proxy binaries per ABI.
  #
  # This repo produces ONLY the stripped `libmediaflow-proxy.so` artifacts for
  # each supported ABI.  The full APK (Kotlin UI + these binaries bundled in
  # `jniLibs/`) is built by the companion `mediaflow-android` repo's own
  # release workflow, which consumes these artifacts.
  # ---------------------------------------------------------------------------
  build-android:
    name: Android · ${{ matrix.abi }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - abi: arm64-v8a
            target: aarch64-linux-android
          - abi: armeabi-v7a
            target: armv7-linux-androideabi
          - abi: x86_64
            target: x86_64-linux-android
          - abi: x86
            target: i686-linux-android
    steps:
      - uses: actions/checkout@v5

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

      - name: Set up Android NDK
        id: ndk
        uses: nttld/setup-ndk@v1
        with:
          ndk-version: r26d

      - name: Build for ${{ matrix.abi }}
        env:
          ANDROID_NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
          # Build only this one ABI to keep job parallelism from the matrix.
          ABIS: ${{ matrix.abi }}
          # Skip the auto-copy-into-sibling-Android-project step — no sibling
          # checkout exists on the runner.
          ANDROID_APP_DIR: ""
        run: |
          chmod +x tools/build-android.sh
          ./tools/build-android.sh

      - name: Package binary
        run: |
          OUT="mediaflow-proxy-light-android-${{ matrix.abi }}.tar.gz"
          tar -czvf "$OUT" \
            -C target/${{ matrix.target }}/release \
            libmediaflow-proxy.so
          echo "ASSET=$OUT" >> $GITHUB_ENV

      - name: Upload to release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ env.ASSET }}
          asset_name: ${{ env.ASSET }}
          tag: ${{ github.ref }}
          overwrite: true

  # ---------------------------------------------------------------------------
  # Docker multi-arch image — reuses the Linux binaries just produced by
  # `build-binaries`, so no Rust toolchain is pulled into the image and the
  # build is ~seconds instead of ~hour (no QEMU Rust cross-compile).
  # ---------------------------------------------------------------------------
  build-docker:
    name: Docker multi-arch image
    runs-on: ubuntu-latest
    needs: build-binaries
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v5

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata for Docker
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.DOCKER_IMAGE }}
          tags: |
            type=ref,event=tag
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Extract release version
        id: version
        run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Build and push (using pre-built binaries)
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile.prebuilt
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          build-args: |
            RELEASE_VERSION=${{ steps.version.outputs.RELEASE_VERSION }}
            BUILDKIT_INLINE_CACHE=1

  # ---------------------------------------------------------------------------
  # AI-generated release notes — replaces the GitHub-generated release body
  # with a curated, emoji-friendly summary produced by Gemini from the commit
  # log between the previous tag and this one.  Mirrors the `generate-notes`
  # flow used by the upstream mediaflow-proxy repo.
  # ---------------------------------------------------------------------------
  generate_release_notes:
    name: Generate release notes
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Install jq
        run: sudo apt-get install -y jq

      - name: Persist GitHub-generated release body
        run: |
          cat << 'EOF' > github_generated_release_body.md
          ${{ github.event.release.body }}
          EOF

      - name: Extract previous version
        id: extract_versions
        run: |
          if ! PREVIOUS_VERSION=$(grep -o '/compare/.*\.\.\.' github_generated_release_body.md | sed 's/\/compare\///' | sed 's/\.\.\.//' || true); then
            echo "Error: Failed to extract previous version from release body"
            exit 1
          fi
          if [ -z "$PREVIOUS_VERSION" ]; then
            PREVIOUS_VERSION=$(git describe --tags --abbrev=0 "${{ github.ref_name }}^" 2>/dev/null || echo "")
          fi
          echo "PREVIOUS_VERSION=${PREVIOUS_VERSION}" >> "$GITHUB_OUTPUT"

      - name: Generate Release Notes
        run: |
          make generate-notes \
            VERSION_OLD=${{ steps.extract_versions.outputs.PREVIOUS_VERSION }} \
            VERSION_NEW=${{ github.ref_name }} \
            GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }} \
            GITHUB_RELEASE_BODY_FILE=github_generated_release_body.md \
            > release_notes.md

      - name: Update Release Notes
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          body_path: release_notes.md
          token: ${{ secrets.GITHUB_TOKEN }}
