name: Build App (Preview)

# Builds the Tauri app for branches other than main and exposes the bundles as
# workflow artifacts. No Gitea release, no GitHub sync — intended for local
# smoke-testing of feature branches before they merge.

on:
  workflow_dispatch:

jobs:
  compute-version:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.VERSION }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Compute preview version
        id: version
        run: |
          MAJOR_MINOR=$(cat VERSION | tr -d '[:space:]')
          SHORT_SHA=$(git rev-parse --short HEAD)
          VERSION="${MAJOR_MINOR}.0-preview.${SHORT_SHA}"
          echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
          echo "Computed preview version: ${VERSION}"

  build-linux:
    runs-on: ubuntu-latest
    needs: [compute-version]
    steps:
      - name: Install Node.js 22
        run: |
          NEED_INSTALL=false
          if command -v node >/dev/null 2>&1; then
            NODE_MAJOR=$(node --version | sed 's/v\([0-9]*\).*/\1/')
            OLD_NODE_DIR=$(dirname "$(which node)")
            echo "Found Node.js $(node --version) at $(which node) (major: ${NODE_MAJOR})"
            if [ "$NODE_MAJOR" -lt 22 ]; then
              echo "Node.js ${NODE_MAJOR} is too old, removing before installing 22..."
              sudo rm -f "${OLD_NODE_DIR}/node" "${OLD_NODE_DIR}/npm" "${OLD_NODE_DIR}/npx" "${OLD_NODE_DIR}/corepack"
              hash -r
              NEED_INSTALL=true
            fi
          else
            echo "Node.js not found, installing 22..."
            NEED_INSTALL=true
          fi
          if [ "$NEED_INSTALL" = true ]; then
            curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
            sudo apt-get install -y nodejs
            hash -r
          fi
          node --version
          npm --version

      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set app version
        run: |
          # Tauri / Cargo require a strict semver; strip the preview suffix for
          # the bundle version but keep it in the artifact filename.
          BASE_VERSION="$(echo '${{ needs.compute-version.outputs.version }}' | cut -d'-' -f1)"
          sed -i "s/\"version\": \".*\"/\"version\": \"${BASE_VERSION}\"/" app/src-tauri/tauri.conf.json
          sed -i "s/\"version\": \".*\"/\"version\": \"${BASE_VERSION}\"/" app/package.json
          sed -i "s/^version = \".*\"/version = \"${BASE_VERSION}\"/" app/src-tauri/Cargo.toml
          echo "Patched version to ${BASE_VERSION}"

      - name: Install system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \
            libwebkit2gtk-4.1-dev \
            libayatana-appindicator3-dev \
            librsvg2-dev \
            libsoup-3.0-dev \
            libssl-dev \
            libxdo-dev \
            patchelf \
            pkg-config \
            build-essential \
            curl \
            wget \
            file \
            xdg-utils

      - name: Install Rust stable
        run: |
          if command -v rustup >/dev/null 2>&1; then
            rustup update stable
            rustup default stable
          else
            curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
          fi
          export PATH="$HOME/.cargo/bin:$PATH"
          rustc --version
          cargo --version

      - name: Install frontend dependencies
        working-directory: ./app
        run: |
          rm -rf node_modules package-lock.json
          npm install

      - name: Install Tauri CLI
        working-directory: ./app
        run: |
          export PATH="$HOME/.cargo/bin:$PATH"
          npx tauri --version || npm install @tauri-apps/cli

      - name: Build Tauri app
        working-directory: ./app
        run: |
          export PATH="$HOME/.cargo/bin:$PATH"
          npx tauri build

      - name: Collect artifacts
        run: |
          mkdir -p artifacts
          cp app/src-tauri/target/release/bundle/appimage/*.AppImage artifacts/ 2>/dev/null || true
          cp app/src-tauri/target/release/bundle/deb/*.deb artifacts/ 2>/dev/null || true
          cp app/src-tauri/target/release/bundle/rpm/*.rpm artifacts/ 2>/dev/null || true
          ls -la artifacts/

      - name: Upload Linux artifacts
        uses: actions/upload-artifact@v4
        with:
          name: triple-c-${{ needs.compute-version.outputs.version }}-linux
          path: artifacts/
          if-no-files-found: error
          retention-days: 14

  build-macos:
    runs-on: macos-latest
    needs: [compute-version]
    steps:
      - name: Install Node.js 22
        run: |
          NEED_INSTALL=false
          if command -v node >/dev/null 2>&1; then
            NODE_MAJOR=$(node --version | sed 's/v\([0-9]*\).*/\1/')
            if [ "$NODE_MAJOR" -lt 22 ]; then
              NEED_INSTALL=true
            fi
          else
            NEED_INSTALL=true
          fi
          if [ "$NEED_INSTALL" = true ]; then
            brew install node@22
            brew link --overwrite node@22
          fi
          node --version
          npm --version

      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set app version
        run: |
          BASE_VERSION="$(echo '${{ needs.compute-version.outputs.version }}' | cut -d'-' -f1)"
          sed -i '' "s/\"version\": \".*\"/\"version\": \"${BASE_VERSION}\"/" app/src-tauri/tauri.conf.json
          sed -i '' "s/\"version\": \".*\"/\"version\": \"${BASE_VERSION}\"/" app/package.json
          sed -i '' "s/^version = \".*\"/version = \"${BASE_VERSION}\"/" app/src-tauri/Cargo.toml
          echo "Patched version to ${BASE_VERSION}"

      - name: Install Rust stable
        run: |
          if command -v rustup >/dev/null 2>&1; then
            rustup update stable
            rustup default stable
          else
            curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
          fi
          export PATH="$HOME/.cargo/bin:$PATH"
          rustup target add aarch64-apple-darwin x86_64-apple-darwin
          rustc --version
          cargo --version

      - name: Install frontend dependencies
        working-directory: ./app
        run: |
          rm -rf node_modules
          npm install

      - name: Install Tauri CLI
        working-directory: ./app
        run: |
          export PATH="$HOME/.cargo/bin:$PATH"
          npx tauri --version || npm install @tauri-apps/cli

      - name: Build Tauri app (universal)
        working-directory: ./app
        run: |
          export PATH="$HOME/.cargo/bin:$PATH"
          npx tauri build --target universal-apple-darwin

      - name: Collect artifacts
        run: |
          mkdir -p artifacts
          cp app/src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg artifacts/ 2>/dev/null || true
          cp app/src-tauri/target/universal-apple-darwin/release/bundle/macos/*.app.tar.gz artifacts/ 2>/dev/null || true
          ls -la artifacts/

      - name: Upload macOS artifacts
        uses: actions/upload-artifact@v4
        with:
          name: triple-c-${{ needs.compute-version.outputs.version }}-macos
          path: artifacts/
          if-no-files-found: error
          retention-days: 14

  build-windows:
    runs-on: windows-latest
    needs: [compute-version]
    defaults:
      run:
        shell: cmd
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set app version
        shell: powershell
        run: |
          $raw = "${{ needs.compute-version.outputs.version }}"
          $version = $raw.Split('-')[0]
          (Get-Content app/src-tauri/tauri.conf.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/src-tauri/tauri.conf.json
          (Get-Content app/package.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/package.json
          (Get-Content app/src-tauri/Cargo.toml) -replace '^version = ".*?"', "version = `"$version`"" | Set-Content app/src-tauri/Cargo.toml
          Write-Host "Patched version to $version"

      - name: Install Rust stable
        run: |
          where rustup >nul 2>&1 && (
            rustup update stable
            rustup default stable
          ) || (
            curl -fSL -o rustup-init.exe https://win.rustup.rs/x86_64
            rustup-init.exe -y --default-toolchain stable
            del rustup-init.exe
          )

      - name: Install Node.js
        run: |
          where node >nul 2>&1 && (
            node --version
          ) || (
            curl -fSL -o node-install.msi "https://nodejs.org/dist/v22.14.0/node-v22.14.0-x64.msi"
            msiexec /i node-install.msi /quiet /norestart
            del node-install.msi
          )

      - name: Verify tools
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          rustc --version
          cargo --version
          node --version
          npm --version

      - name: Install Tauri CLI via cargo
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          cargo install tauri-cli --version "^2"

      - name: Fix npm platform detection
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          npm config set os win32
          npm config list

      - name: Install frontend dependencies
        working-directory: ./app
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          if exist node_modules rmdir /s /q node_modules
          npm ci

      - name: Build frontend
        working-directory: ./app
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          npm run build

      - name: Build Tauri app
        working-directory: ./app
        env:
          TAURI_CONFIG: "{\"build\":{\"beforeBuildCommand\":\"\"}}"
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          cargo tauri build

      - name: Collect artifacts
        run: |
          set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
          mkdir artifacts
          copy app\src-tauri\target\release\bundle\msi\*.msi artifacts\ 2>nul
          copy app\src-tauri\target\release\bundle\nsis\*.exe artifacts\ 2>nul
          dir artifacts\

      - name: Upload Windows artifacts
        uses: actions/upload-artifact@v4
        with:
          name: triple-c-${{ needs.compute-version.outputs.version }}-windows
          path: artifacts/
          if-no-files-found: error
          retention-days: 14
