name: native-build

on:
  workflow_dispatch:
    inputs:
      tag:
        required: true
        description: "Ref to build from (e.g. v1.0.0)"
      useWorkflowSpec:
        type: boolean
        default: false
        description: "Use app.spec from workflow branch instead of tag"
  push:
    tags:
      - "v*"

jobs:
  build:
    if: ${{ vars.REGISTRY == '' }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            arch: amd64
          - os: ubuntu-latest
            arch: arm64
          - os: macos-latest
            arch: arm64
          - os: windows-latest
            arch: amd64
          - os: windows-latest
            arch: arm64

    permissions:
      packages: write
      contents: write

    env:
      PYTHON_VERSION: 3.11
      BUN_VERSION: latest
      NODE_VERSION: 20
      TAG_NAME: ${{ github.event.inputs.tag || github.ref_name }}

    steps:
      - name: Checkout source repo
        uses: actions/checkout@v4
        with:
          ref: ${{ env.TAG_NAME }}

      - name: Overwrite app.spec from workflow branch
        if: ${{ github.event.inputs.useWorkflowSpec == 'true' }}
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
          sparse-checkout: |
            app.spec
          sparse-checkout-cone-mode: false
          path: temp-spec

      - name: Replace app.spec with version from workflow branch
        if: ${{ github.event.inputs.useWorkflowSpec == 'true' }}
        shell: bash
        run: cp temp-spec/app.spec ./app.spec

      - name: Cache Python venv
        id: cache-python
        uses: actions/cache@v4
        with:
          path: .venv
          key: uv-${{ runner.os }}-${{ matrix.arch }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
          restore-keys: |
            uv-${{ runner.os }}-${{ matrix.arch }}-${{ env.PYTHON_VERSION }}-

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
          architecture: "x64"

      - name: Install Python dependencies
        shell: bash
        run: |
          pip install uv
          uv venv --system-site-packages --relocatable
          uv sync --link-mode=copy --active --extra installer

      - name: Cache bun installation
        id: cache-bun
        uses: actions/cache@v4
        with:
          path: ~/.bun/install/cache
          key: ${{ runner.os }}-${{ matrix.arch }}-bun-${{ hashFiles('**/bun.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.arch }}-bun-

      - name: Install bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: ${{ env.BUN_VERSION }}

      - name: Install Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}

      - name: Build frontend
        working-directory: ui
        shell: bash
        run: |
          bun install --production --prefer-offline --frozen-lockfile
          bun run generate

      - name: Clean build outputs (Unix)
        if: runner.os != 'Windows'
        shell: bash
        run: rm -rf build dist release || true

      - name: Clean build outputs (Windows)
        if: runner.os == 'Windows'
        shell: powershell
        run: |
          if (Test-Path build)   { Remove-Item -Recurse -Force build }
          if (Test-Path dist)    { Remove-Item -Recurse -Force dist }
          if (Test-Path release) { Remove-Item -Recurse -Force release }

      - name: Build native binary (Windows)
        if: matrix.os == 'windows-latest'
        shell: powershell
        run: |
          .\.venv\Scripts\activate
          uv run pyinstaller ./app.spec

      - name: Build native binary (Linux/macOS)
        if: matrix.os != 'windows-latest'
        shell: bash
        run: |
          . .venv/bin/activate
          uv run pyinstaller ./app.spec

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: app-${{ runner.os }}-${{ matrix.arch }}-${{ env.TAG_NAME }}
          path: dist/YTPTube/**

      - name: Package artifact (Unix)
        if: startsWith(env.TAG_NAME, 'v') && runner.os != 'Windows'
        shell: bash
        run: |
          mkdir -p release
          PKG_DIR="YTPTube-${{ env.TAG_NAME }}"
          ZIP_NAME="ytptube-${{ runner.os }}-${{ matrix.arch }}-${{ env.TAG_NAME }}.zip"

          if [ ! -f "dist/YTPTube/YTPTube" ]; then
            echo "Missing dist/YTPTube/YTPTube"
            find dist -maxdepth 3 -type f | head -n 200
            exit 1
          fi

          rm -rf "dist/${PKG_DIR}"
          mv "dist/YTPTube" "dist/${PKG_DIR}"

          zip -r "release/${ZIP_NAME}" "dist/${PKG_DIR}"

      - name: Package artifact (Windows)
        if: startsWith(env.TAG_NAME, 'v') && runner.os == 'Windows'
        shell: powershell
        run: |
          $pkgDir = "YTPTube-${{ env.TAG_NAME }}"
          $zipName = "ytptube-${{ runner.os }}-${{ matrix.arch }}-${{ env.TAG_NAME }}.zip"
          New-Item -ItemType Directory -Force -Path release | Out-Null

          if (!(Test-Path "dist\YTPTube\YTPTube.exe")) {
            Write-Host "Missing dist\YTPTube\YTPTube.exe"
            Get-ChildItem -Recurse dist | Select-Object -First 200 | Format-Table -AutoSize
            exit 1
          }

          if (Test-Path "dist\$pkgDir") { Remove-Item -Recurse -Force "dist\$pkgDir" }
          Move-Item "dist\YTPTube" "dist\$pkgDir"

          Compress-Archive -Path "dist\$pkgDir" -DestinationPath "release\$zipName" -Force

      - name: Upload to GitHub Release
        if: startsWith(env.TAG_NAME, 'v')
        uses: softprops/action-gh-release@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ env.TAG_NAME }}
          files: release/*.zip
