name: 'Test Linux App'

on:
  workflow_dispatch:

concurrency:
  group: test-linux-app-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse

jobs:
  test-linux-app:
    runs-on: ubuntu-24.04
    timeout-minutes: 120
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

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

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7
        with:
          toolchain: stable

      - name: Rust cache
        uses: swatinem/rust-cache@ad397744b0d591a723ab90405b7247fac0e6b8db
        with:
          workspaces: './src-tauri -> target'
          cache-on-failure: true

      - name: Install Linux system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libwebkit2gtk-4.1-dev \
            libappindicator3-dev \
            librsvg2-dev \
            patchelf \
            gstreamer1.0-plugins-base \
            gstreamer1.0-plugins-good \
            xwayland-run \
            xvfb \
            imagemagick \
            xdotool

      - name: Install frontend dependencies
        run: npm ci

      - name: Bundle Node.js runtime
        shell: bash
        env:
          NODE_VERSION: '22.14.0'
          NODE_TARGET: 'x86_64-unknown-linux-gnu'
        run: bash scripts/download-node.sh --target "$NODE_TARGET"

      - name: Build Tauri app
        uses: tauri-apps/tauri-action@79c624843491f12ae9d63592534ed49df3bc4adb
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          VITE_VARIANT: full
          VITE_DESKTOP_RUNTIME: '1'
          CONVEX_URL: ${{ secrets.CONVEX_URL }}
        with:
          args: ''
          retryAttempts: 1

      - name: Smoke-test AppImage
        shell: bash
        run: |
          APPIMAGE=$(find src-tauri/target/release/bundle/appimage -name '*.AppImage' | head -1)
          if [ -z "$APPIMAGE" ]; then
            echo "::error::No AppImage found after build"
            exit 1
          fi
          chmod +x "$APPIMAGE"
          APPIMAGE_ABS=$(realpath "$APPIMAGE")

          # Write the inner test script (runs inside the display server)
          cat > /tmp/smoke-test.sh <<'SCRIPT'
          #!/bin/bash
          set -x
          echo "DISPLAY=$DISPLAY WAYLAND_DISPLAY=${WAYLAND_DISPLAY:-unset}"

          GDK_BACKEND=x11 "$APPIMAGE_ABS" --no-sandbox 2>&1 | tee /tmp/app.log &
          APP_PID=$!
          sleep 20

          # Screenshot via X11
          import -window root /tmp/screenshot.png 2>/dev/null || true

          # Verify app is still running
          if kill -0 $APP_PID 2>/dev/null; then
            echo "APP_STATUS=running"
          else
            echo "APP_STATUS=crashed"
            echo "--- App log ---"
            tail -50 /tmp/app.log || true
          fi

          # Window info
          xdotool search --name "" getwindowname 2>/dev/null | head -5 || true

          kill $APP_PID 2>/dev/null || true
          SCRIPT
          chmod +x /tmp/smoke-test.sh

          export APPIMAGE_ABS
          RESULT=0

          # --- Try 1: xwfb-run (Xwayland on headless Wayland compositor) ---
          if command -v xwfb-run &>/dev/null; then
            echo "=== Using xwfb-run (Xwayland + headless compositor) ==="
            timeout 90 xwfb-run -- bash /tmp/smoke-test.sh 2>&1 | tee /tmp/display-server.log || RESULT=$?
          else
            echo "xwfb-run not found, skipping"
            RESULT=1
          fi

          # --- Fallback: plain Xvfb ---
          if [ $RESULT -ne 0 ] || [ ! -f /tmp/screenshot.png ]; then
            echo "=== Falling back to Xvfb ==="
            Xvfb :99 -screen 0 1440x900x24 &
            XVFB_PID=$!
            export DISPLAY=:99
            sleep 2
            bash /tmp/smoke-test.sh 2>&1 | tee /tmp/display-server.log
            kill $XVFB_PID 2>/dev/null || true
          fi

          # --- Copy screenshot to workspace ---
          cp /tmp/screenshot.png screenshot.png 2>/dev/null || true

          # --- Check results ---
          if grep -q "APP_STATUS=crashed" /tmp/display-server.log 2>/dev/null; then
            echo "❌ AppImage crashed during startup"
            exit 1
          fi

          if grep -q "APP_STATUS=running" /tmp/display-server.log 2>/dev/null; then
            echo "✅ AppImage launched successfully"
          else
            echo "⚠️ Could not determine app status"
          fi

          # --- Check screenshot has non-black content ---
          if [ -f screenshot.png ]; then
            COLORS=$(identify -verbose screenshot.png 2>/dev/null | grep "Colors:" | awk '{print $2}')
            echo "Screenshot unique colors: ${COLORS:-unknown}"
            if [ "${COLORS:-0}" -le 5 ]; then
              echo "⚠️ Screenshot appears blank (only $COLORS colors). App may not have rendered."
            else
              echo "✅ Screenshot has content ($COLORS unique colors)"
            fi
          fi

      - name: Upload smoke test screenshot
        if: always()
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        with:
          name: linux-smoke-test-screenshot
          path: screenshot.png
          if-no-files-found: warn

      - name: Upload logs
        if: always()
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        with:
          name: linux-smoke-test-logs
          path: |
            /tmp/display-server.log
            /tmp/app.log
          if-no-files-found: warn
