name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  # =============================================================================
  # Backend Tests - PHP 8.5, PHPStan, PHPUnit
  # =============================================================================
  test-backend:
    name: Backend Tests
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: backend

    services:
      postgres:
        image: postgres:18.1-alpine
        env:
          POSTGRES_DB: classeo_test
          POSTGRES_USER: classeo
          POSTGRES_PASSWORD: classeo
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

      redis:
        image: redis:7.4-alpine
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.5'
          extensions: intl, pdo_pgsql, amqp, redis, zip
          coverage: xdebug

      - name: Get Composer cache directory
        id: composer-cache
        run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

      - name: Cache Composer dependencies
        uses: actions/cache@v4
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: ${{ runner.os }}-composer-

      - name: Install dependencies
        run: composer install --prefer-dist --no-progress

      - name: Run PHP CS Fixer (check)
        run: composer cs-check

      - name: Run PHPStan
        run: composer phpstan

      - name: Create test database and run migrations
        run: |
          php bin/console doctrine:database:create --if-not-exists --env=test
          php bin/console doctrine:migrations:migrate --no-interaction --env=test
        env:
          DATABASE_URL: postgresql://classeo:classeo@localhost:5432/classeo_test?serverVersion=18
          REDIS_URL: redis://localhost:6379

      - name: Run PHPUnit
        run: composer test
        env:
          DATABASE_URL: postgresql://classeo:classeo@localhost:5432/classeo_test?serverVersion=18
          REDIS_URL: redis://localhost:6379

      - name: Run BC Isolation Check
        working-directory: .
        run: ./scripts/check-bc-isolation.sh

  # =============================================================================
  # Frontend Tests - Vitest, Playwright
  # =============================================================================
  test-frontend:
    name: Frontend Tests
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: frontend

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Setup pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 9

      - name: Get pnpm store directory
        id: pnpm-cache
        run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

      - name: Cache pnpm dependencies
        uses: actions/cache@v4
        with:
          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Run linter
        run: pnpm run lint

      - name: Run TypeScript check
        run: pnpm run check

      - name: Run unit tests
        run: pnpm run test

  # =============================================================================
  # E2E Tests - Playwright with Docker backend
  # =============================================================================
  test-e2e:
    name: E2E Tests
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Setup pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 9

      - name: Get pnpm store directory
        id: pnpm-cache
        run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

      - name: Cache pnpm dependencies
        uses: actions/cache@v4
        with:
          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: ${{ runner.os }}-pnpm-store-

      - name: Install frontend dependencies
        working-directory: frontend
        run: pnpm install --frozen-lockfile

      - name: Install Playwright browsers
        working-directory: frontend
        run: pnpm exec playwright install --with-deps

      - name: Build and start backend services
        run: |
          # Build images first (with Docker layer caching)
          docker compose build php
          # Start services (includes db, redis, rabbitmq dependencies)
          # Use null mailer transport since mailpit is not available in CI
          # Use test environment to disable rate limiting for E2E tests
          APP_ENV=test MAILER_DSN="null://null" docker compose up -d php
        timeout-minutes: 10

      - name: Wait for backend to be ready
        run: |
          echo "Waiting for backend to be ready (composer install + app startup)..."
          # Wait up to 5 minutes for the backend to respond
          # Using /api/docs which is a public endpoint (no auth required)
          timeout 300 bash -c 'until curl -sf http://localhost:18000/api/docs > /dev/null 2>&1; do
            echo "Waiting for backend..."
            sleep 5
          done'
          echo "Backend is ready!"

      - name: Generate JWT keys for authentication
        run: |
          # Generate JWT keys if they don't exist (required for login/token endpoints)
          docker compose exec -T php php bin/console lexik:jwt:generate-keypair --skip-if-exists

      - name: Create test database and run migrations
        run: |
          # Create test database (Symfony adds _test suffix in test environment)
          docker compose exec -T php php bin/console doctrine:database:create --if-not-exists
          # Run migrations to create all tables (including audit_log)
          docker compose exec -T php php bin/console doctrine:migrations:migrate --no-interaction

      - name: Show backend logs on failure
        if: failure()
        run: docker compose logs php

      - name: Configure hosts for multi-tenant testing
        run: |
          echo "127.0.0.1 classeo.local" | sudo tee -a /etc/hosts
          echo "127.0.0.1 ecole-alpha.classeo.local" | sudo tee -a /etc/hosts
          echo "127.0.0.1 ecole-beta.classeo.local" | sudo tee -a /etc/hosts
          cat /etc/hosts

      - name: Reset rate limiter before E2E tests
        run: docker compose exec -T php php bin/console app:dev:reset-rate-limit

      - name: Run E2E tests
        working-directory: frontend
        run: pnpm run test:e2e
        env:
          # Frontend serves on 4173 (preview mode), backend on 18000 (Docker)
          PUBLIC_API_PORT: "18000"
          PUBLIC_API_URL: http://localhost:18000/api

      - name: Upload Playwright report
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: frontend/playwright-report/
          retention-days: 7

      - name: Stop backend services
        if: always()
        run: docker compose down

  # =============================================================================
  # Naming Conventions Check
  # =============================================================================
  check-naming:
    name: Naming Conventions
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Run Naming Check
        run: ./scripts/check-naming.sh

  # =============================================================================
  # Build Check
  # =============================================================================
  build:
    name: Build Check
    runs-on: ubuntu-latest
    needs: [test-backend, test-frontend, test-e2e]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build backend image
        uses: docker/build-push-action@v6
        with:
          context: ./backend
          push: false
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Build frontend image
        uses: docker/build-push-action@v6
        with:
          context: ./frontend
          push: false
          cache-from: type=gha
          cache-to: type=gha,mode=max
