name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_call: # allow other workflows to run CI as a gate

permissions:
  contents: read

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm run lint

  typecheck:
    name: Typecheck
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm run typecheck

  test:
    name: Vitest
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - name: Build plugin (needed by ecosystem fixtures)
        run: pnpm run build
      - run: pnpm test

  create-next-app:
    name: create-next-app (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - name: Build plugin
        run: pnpm run build
      - name: Pack vinext for local install
        run: npm pack --pack-destination "${{ runner.temp }}"
        working-directory: packages/vinext
      - name: Scaffold a fresh create-next-app project
        run: npx create-next-app@latest "${{ runner.temp }}/cna-test" --yes
      - name: Install vinext from local tarball
        working-directory: ${{ runner.temp }}/cna-test
        shell: bash
        run: npm install "${{ runner.temp }}"/vinext-*.tgz
      - name: Run vinext init
        working-directory: ${{ runner.temp }}/cna-test
        run: npx vinext init --skip-check
      - name: Start dev server and verify HTTP 200
        working-directory: ${{ runner.temp }}/cna-test
        shell: node {0}
        run: |
          const { spawn } = require("child_process");
          const http = require("http");

          const isWin = process.platform === "win32";
          const server = spawn("npx", ["vite", "dev", "--port", "3099"], {
            cwd: process.cwd(),
            stdio: "inherit",
            shell: true,
          });

          let attempts = 0;
          const maxAttempts = 30;
          const interval = setInterval(() => {
            attempts++;
            http.get("http://localhost:3099/", (res) => {
              if (res.statusCode === 200) {
                console.log(`Server responded with HTTP 200 (attempt ${attempts})`);
                clearInterval(interval);
                if (isWin) {
                  spawn("taskkill", ["/pid", String(server.pid), "/T", "/F"], { stdio: "ignore" });
                } else {
                  server.kill("SIGTERM");
                }
                process.exit(0);
              }
            }).on("error", () => {});
            if (attempts >= maxAttempts) {
              console.error("Server did not respond with HTTP 200 within 30 seconds");
              clearInterval(interval);
              if (isWin) {
                spawn("taskkill", ["/pid", String(server.pid), "/T", "/F"], { stdio: "ignore" });
              } else {
                server.kill("SIGTERM");
              }
              process.exit(1);
            }
          }, 1000);

  e2e:
    name: E2E (${{ matrix.project }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        project:
          - pages-router
          - app-router
          - cloudflare-pages-router
          - pages-router-prod
          - cloudflare-workers
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - name: Build plugin
        run: pnpm run build
      - run: pnpm exec playwright install chromium
      - run: pnpm exec playwright test
        env:
          CI: true
          PLAYWRIGHT_PROJECT: ${{ matrix.project }}
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report-${{ matrix.project }}
          path: playwright-report/
          retention-days: 7
