name: Build Electron Desktop App

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      version:
        description: "Release version (e.g., v1.6.8)"
        required: true
        type: string

permissions:
  contents: write

jobs:
  validate:
    name: Validate version
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.validate.outputs.version }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Validate version format
        id: validate
        run: |
          if [[ "${{ github.event_name }}" == "push" ]]; then
            VERSION="${GITHUB_REF#refs/tags/}"
          else
            VERSION="${{ inputs.version }}"
          fi

          if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "Error: Invalid version format. Expected: v1.6.8"
            exit 1
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "✓ Valid version: $VERSION"

  build:
    name: Build Electron (${{ matrix.platform }})
    needs: validate
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: windows
            runner: windows-latest
            target: win
            ext: .exe
          - platform: macos-intel
            runner: macos-15-intel
            target: mac-x64
            ext: .dmg
          - platform: macos-arm64
            runner: macos-latest
            target: mac-arm64
            ext: -arm64.dmg
          - platform: linux
            runner: ubuntu-latest
            target: linux
            ext: .AppImage
            deb_ext: .deb

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm

      - name: Cache node_modules
        uses: actions/cache@v5
        with:
          path: node_modules
          key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm ci

      - name: Build Next.js standalone
        env:
          JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
        run: npm run build

      - name: Sync version in electron/package.json
        shell: bash
        run: |
          VERSION="${{ needs.validate.outputs.version }}"
          VERSION_NO_V="${VERSION#v}"
          node -e "
            const fs = require('fs');
            const pkg = JSON.parse(fs.readFileSync('electron/package.json'));
            pkg.version = '$VERSION_NO_V';
            fs.writeFileSync('electron/package.json', JSON.stringify(pkg, null, 2) + '\\n');
          "
          echo "✓ electron/package.json version set to $VERSION_NO_V"

      - name: Install fpm (Linux .deb packaging tool)
        if: matrix.platform == 'linux'
        run: sudo gem install fpm --no-document

      - name: Install Electron dependencies
        working-directory: electron
        run: npm install --no-audit --no-fund

      - name: Build Electron for ${{ matrix.platform }}
        working-directory: electron
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npm run build:${{ matrix.target }}

      - name: Collect installers
        shell: bash
        run: |
          mkdir -p release-assets
          cd electron/dist-electron
          # Copy only installer files for this platform
          for file in *${{ matrix.ext }}; do
            [ -f "$file" ] && cp "$file" ../../release-assets/
          done
          # Linux: also copy .deb package
          if [ "${{ matrix.platform }}" = "linux" ]; then
            for file in *.deb; do
              [ -f "$file" ] && cp "$file" ../../release-assets/
            done
          fi
          # Windows: also copy portable standalone exe as OmniRoute.exe
          if [ "${{ matrix.platform }}" = "windows" ]; then
            for file in *.exe; do
              # Skip the NSIS installer (contains "Setup")
              case "$file" in *Setup*) continue ;; esac
              [ -f "$file" ] && cp "$file" "../../release-assets/OmniRoute.exe" && break
            done
          fi

      - name: Upload artifacts
        uses: actions/upload-artifact@v7
        with:
          name: electron-${{ matrix.platform }}
          path: release-assets/

  release:
    name: Create Release
    needs: [validate, build]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Download all artifacts
        uses: actions/download-artifact@v8
        with:
          path: release-assets
          merge-multiple: true

      - name: Create source archives
        run: |
          # Create source code archives (excluding dev dependencies and build artifacts)
          export TARBALL="OmniRoute-${{ needs.validate.outputs.version }}.source.tar.gz"
          export ZIPBALL="OmniRoute-${{ needs.validate.outputs.version }}.source.zip"

          # Use git archive for clean source export
          git archive --format=tar.gz --prefix=OmniRoute-${{ needs.validate.outputs.version }}/ HEAD -o "release-assets/$TARBALL"
          git archive --format=zip --prefix=OmniRoute-${{ needs.validate.outputs.version }}/ HEAD -o "release-assets/$ZIPBALL"

          echo "✓ Created source archives:"
          ls -lh "release-assets/$TARBALL" "release-assets/$ZIPBALL"

      - name: List release files
        run: ls -la release-assets/

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.validate.outputs.version }}
          draft: false
          prerelease: false
          generate_release_notes: true
          fail_on_unmatched_files: false
          files: |
            release-assets/*.dmg
            release-assets/*.exe
            release-assets/*.AppImage
            release-assets/*.deb
            release-assets/*.blockmap
            release-assets/*.source.tar.gz
            release-assets/*.source.zip
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
