name: E2E Integration Tests

on:
  push:
    branches: ["*"]
    paths-ignore:
      - "README.md"
      - "docs/**"
      - "CHANGELOG.md"
      - "LICENSE"
      - "www/**"
      - "helm/**"
  pull_request:
    branches: ["*"]
    paths-ignore:
      - "README.md"
      - "docs/**"
      - "CHANGELOG.md"
      - "LICENSE"
      - "www/**"
      - "helm/**"
  workflow_dispatch:
    inputs:
      debug_enabled:
        description: "Enable debug logging"
        required: false
        default: "false"
        type: boolean

permissions:
  contents: read
  actions: read

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

env:
  GITEA_PORT: 3333
  FAKE_GITHUB_PORT: 4580
  GIT_SERVER_PORT: 4590
  APP_PORT: 4321
  BUN_VERSION: "1.3.10"

jobs:
  e2e-tests:
    name: E2E Integration Tests
    runs-on: ubuntu-latest
    timeout-minutes: 25

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: ${{ env.BUN_VERSION }}

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

      - name: Install dependencies
        run: |
          bun install
          echo "✓ Dependencies installed"

      - name: Install Playwright
        run: |
          npx playwright install chromium
          npx playwright install-deps chromium
          echo "✓ Playwright ready"

      - name: Create test git repositories
        run: |
          echo "Creating bare git repos for E2E testing..."
          bun run tests/e2e/create-test-repos.ts --output-dir tests/e2e/git-repos

          if [ ! -f tests/e2e/git-repos/manifest.json ]; then
            echo "ERROR: Test git repos were not created (manifest.json missing)"
            exit 1
          fi

          echo "✓ Test repos created:"
          cat tests/e2e/git-repos/manifest.json | jq -r '.repos[] | "  • \(.owner)/\(.name) — \(.description)"'

      - name: Start Gitea and git-server containers
        run: |
          echo "Starting containers via docker compose..."
          docker compose -f tests/e2e/docker-compose.e2e.yml up -d

          # Wait for git-server
          echo "Waiting for git HTTP server..."
          for i in $(seq 1 30); do
            if curl -sf http://localhost:${{ env.GIT_SERVER_PORT }}/manifest.json > /dev/null 2>&1; then
              echo "✓ Git HTTP server is ready"
              break
            fi
            if [ $i -eq 30 ]; then
              echo "ERROR: Git HTTP server did not start"
              docker compose -f tests/e2e/docker-compose.e2e.yml logs git-server
              exit 1
            fi
            sleep 1
          done

          # Wait for Gitea
          echo "Waiting for Gitea to be ready..."
          for i in $(seq 1 60); do
            if curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version > /dev/null 2>&1; then
              version=$(curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version | jq -r '.version // "unknown"')
              echo "✓ Gitea is ready (version: $version)"
              break
            fi
            if [ $i -eq 60 ]; then
              echo "ERROR: Gitea did not become healthy within 120s"
              docker compose -f tests/e2e/docker-compose.e2e.yml logs gitea-e2e --tail=30
              exit 1
            fi
            sleep 2
          done

      - name: Initialize database
        run: |
          bun run manage-db init
          echo "✓ Database initialized"

      - name: Build application
        env:
          GH_API_URL: http://localhost:4580
          BETTER_AUTH_SECRET: e2e-test-secret
        run: |
          bun run build
          echo "✓ Build complete"

      - name: Start fake GitHub API server
        run: |
          # Start with GIT_SERVER_URL pointing to the git-server container name
          # (Gitea will resolve it via Docker networking)
          PORT=${{ env.FAKE_GITHUB_PORT }} GIT_SERVER_URL="http://git-server" \
            npx tsx tests/e2e/fake-github-server.ts &
          echo $! > /tmp/fake-github.pid

          echo "Waiting for fake GitHub API..."
          for i in $(seq 1 30); do
            if curl -sf http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/health > /dev/null 2>&1; then
              echo "✓ Fake GitHub API is ready"
              break
            fi
            if [ $i -eq 30 ]; then
              echo "ERROR: Fake GitHub API did not start"
              exit 1
            fi
            sleep 1
          done

          # Ensure clone URLs are set for the git-server container
          curl -sf -X POST http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/set-clone-url \
            -H "Content-Type: application/json" \
            -d '{"url": "http://git-server"}' || true
          echo "✓ Clone URLs configured for git-server container"

      - name: Start gitea-mirror application
        env:
          GH_API_URL: http://localhost:4580
          BETTER_AUTH_SECRET: e2e-test-secret
          BETTER_AUTH_URL: http://localhost:4321
          DATABASE_URL: file:data/gitea-mirror.db
          HOST: 0.0.0.0
          PORT: ${{ env.APP_PORT }}
          NODE_ENV: production
          PRE_SYNC_BACKUP_ENABLED: "false"
          ENCRYPTION_SECRET: "e2e-encryption-secret-32char!!"
        run: |
          # Re-init DB in case build step cleared it
          bun run manage-db init 2>/dev/null || true

          bun run start &
          echo $! > /tmp/app.pid

          echo "Waiting for gitea-mirror app..."
          for i in $(seq 1 90); do
            if curl -sf http://localhost:${{ env.APP_PORT }}/api/health > /dev/null 2>&1 || \
               curl -sf -o /dev/null -w "%{http_code}" http://localhost:${{ env.APP_PORT }}/ 2>/dev/null | grep -q "^[23]"; then
              echo "✓ gitea-mirror app is ready"
              break
            fi
            if ! kill -0 $(cat /tmp/app.pid) 2>/dev/null; then
              echo "ERROR: App process died"
              exit 1
            fi
            if [ $i -eq 90 ]; then
              echo "ERROR: gitea-mirror app did not start within 180s"
              exit 1
            fi
            sleep 2
          done

      - name: Run E2E tests
        env:
          APP_URL: http://localhost:${{ env.APP_PORT }}
          GITEA_URL: http://localhost:${{ env.GITEA_PORT }}
          FAKE_GITHUB_URL: http://localhost:${{ env.FAKE_GITHUB_PORT }}
          GIT_SERVER_URL: http://localhost:${{ env.GIT_SERVER_PORT }}
          CI: true
        run: |
          mkdir -p tests/e2e/test-results
          npx playwright test \
            --config tests/e2e/playwright.config.ts \
            --reporter=github,html

      - name: Diagnostic info on failure
        if: failure()
        run: |
          echo "═══════════════════════════════════════════════════════════"
          echo " Diagnostic Information"
          echo "═══════════════════════════════════════════════════════════"

          echo ""
          echo "── Git server status ──"
          curl -sf http://localhost:${{ env.GIT_SERVER_PORT }}/manifest.json 2>/dev/null | jq . || echo "(unreachable)"

          echo ""
          echo "── Gitea status ──"
          curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version 2>/dev/null || echo "(unreachable)"

          echo ""
          echo "── Fake GitHub status ──"
          curl -sf http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/health 2>/dev/null | jq . || echo "(unreachable)"

          echo ""
          echo "── App status ──"
          curl -sf http://localhost:${{ env.APP_PORT }}/api/health 2>/dev/null || echo "(unreachable)"

          echo ""
          echo "── Docker containers ──"
          docker compose -f tests/e2e/docker-compose.e2e.yml ps 2>/dev/null || true

          echo ""
          echo "── Gitea container logs (last 50 lines) ──"
          docker compose -f tests/e2e/docker-compose.e2e.yml logs gitea-e2e --tail=50 2>/dev/null || echo "(no container)"

          echo ""
          echo "── Git server logs (last 20 lines) ──"
          docker compose -f tests/e2e/docker-compose.e2e.yml logs git-server --tail=20 2>/dev/null || echo "(no container)"

          echo ""
          echo "── Running processes ──"
          ps aux | grep -E "(fake-github|astro|bun|node)" | grep -v grep || true

      - name: Upload Playwright report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: e2e-playwright-report
          path: tests/e2e/playwright-report/
          retention-days: 14

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: e2e-test-results
          path: tests/e2e/test-results/
          retention-days: 14

      - name: Cleanup
        if: always()
        run: |
          # Stop background processes
          if [ -f /tmp/fake-github.pid ]; then
            kill $(cat /tmp/fake-github.pid) 2>/dev/null || true
            rm -f /tmp/fake-github.pid
          fi
          if [ -f /tmp/app.pid ]; then
            kill $(cat /tmp/app.pid) 2>/dev/null || true
            rm -f /tmp/app.pid
          fi

          # Stop containers
          docker compose -f tests/e2e/docker-compose.e2e.yml down --volumes --remove-orphans 2>/dev/null || true

          echo "✓ Cleanup complete"
