name: E2E Tests
on:
  push:
    branches: [main]
    paths-ignore:
      - "docs/**"
      - "**.md"
      - ".github/**"
  pull_request:
    branches: [main, breaking/**]
    paths-ignore:
      - "docs/**"
      - "**.md"
      - ".github/**"

jobs:
  build:
    if: github.event.pull_request.head.ref != 'i18n_crowdin'
    timeout-minutes: 20
    permissions:
      contents: read
      actions: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

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

      - name: Build and export
        uses: docker/build-push-action@v6
        with:
          context: .
          file: docker/Dockerfile
          push: false
          load: false
          tags: pocket-id:test
          outputs: type=docker,dest=/tmp/docker-image.tar
          build-args: BUILD_TAGS=e2etest
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Upload Docker image artifact
        uses: actions/upload-artifact@v4
        with:
          name: docker-image
          path: /tmp/docker-image.tar
          retention-days: 1

  test:
    if: github.event.pull_request.head.ref != 'i18n_crowdin'
    permissions:
      contents: read
      actions: write
    runs-on: ubuntu-latest
    needs: build
    strategy:
      fail-fast: false
      matrix:
        include:
          - db: sqlite
            storage: filesystem
          - db: postgres
            storage: filesystem
          - db: sqlite
            storage: s3
          - db: sqlite
            storage: database
          - db: postgres
            storage: database

    steps:
      - uses: actions/checkout@v5

      - name: Setup pnpm
        uses: pnpm/action-setup@v4

      - name: Setup Node.js
        uses: actions/setup-node@v5
        with:
          node-version: 24

      - name: Cache Playwright Browsers
        uses: actions/cache@v4
        id: playwright-cache
        with:
          path: ~/.cache/ms-playwright
          key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}

      - name: Cache PostgreSQL Docker image
        uses: actions/cache@v4
        id: postgres-cache
        with:
          path: /tmp/postgres-image.tar
          key: postgres-17-${{ runner.os }}
      - name: Pull and save PostgreSQL image
        if: matrix.db == 'postgres' && steps.postgres-cache.outputs.cache-hit != 'true'
        run: |
          docker pull postgres:17
          docker save postgres:17 > /tmp/postgres-image.tar
      - name: Load PostgreSQL image
        if: matrix.db == 'postgres' && steps.postgres-cache.outputs.cache-hit == 'true'
        run: docker load < /tmp/postgres-image.tar

      - name: Cache LLDAP Docker image
        uses: actions/cache@v4
        id: lldap-cache
        with:
          path: /tmp/lldap-image.tar
          key: lldap-stable-${{ runner.os }}
      - name: Pull and save LLDAP image
        if: steps.lldap-cache.outputs.cache-hit != 'true'
        run: |
          docker pull lldap/lldap:2025-05-19
          docker save lldap/lldap:2025-05-19 > /tmp/lldap-image.tar
      - name: Load LLDAP image
        if: steps.lldap-cache.outputs.cache-hit == 'true'
        run: docker load < /tmp/lldap-image.tar

      - name: Cache SCIM Test Server Docker image
        uses: actions/cache@v4
        id: scim-cache
        with:
          path: /tmp/scim-test-server-image.tar
          key: scim-test-server-${{ runner.os }}
      - name: Pull and save SCIM Test Server image
        if: steps.scim-cache.outputs.cache-hit != 'true'
        run: |
          docker pull ghcr.io/pocket-id/scim-test-server
          docker save ghcr.io/pocket-id/scim-test-server > /tmp/scim-test-server-image.tar
      - name: Load SCIM Test Server image
        if: steps.scim-cache.outputs.cache-hit == 'true'
        run: docker load < /tmp/scim-test-server-image.tar

      - name: Cache Localstack S3 Docker image
        if: matrix.storage == 's3'
        uses: actions/cache@v4
        id: s3-cache
        with:
          path: /tmp/localstack-s3-image.tar
          key: localstack-s3-latest-${{ runner.os }}
      - name: Pull and save Localstack S3 image
        if: matrix.storage == 's3' && steps.s3-cache.outputs.cache-hit != 'true'
        run: |
          docker pull localstack/localstack:s3-latest
          docker save localstack/localstack:s3-latest > /tmp/localstack-s3-image.tar
      - name: Load Localstack S3 image
        if: matrix.storage == 's3' && steps.s3-cache.outputs.cache-hit == 'true'
        run: docker load < /tmp/localstack-s3-image.tar

      - name: Cache AWS CLI Docker image
        if: matrix.storage == 's3'
        uses: actions/cache@v4
        id: aws-cli-cache
        with:
          path: /tmp/aws-cli-image.tar
          key: aws-cli-latest-${{ runner.os }}
      - name: Pull and save AWS CLI image
        if: matrix.storage == 's3' && steps.aws-cli-cache.outputs.cache-hit != 'true'
        run: |
          docker pull amazon/aws-cli:latest
          docker save amazon/aws-cli:latest > /tmp/aws-cli-image.tar
      - name: Load AWS CLI image
        if: matrix.storage == 's3' && steps.aws-cli-cache.outputs.cache-hit == 'true'
        run: docker load < /tmp/aws-cli-image.tar

      - name: Download Docker image artifact
        uses: actions/download-artifact@v4
        with:
          name: docker-image
          path: /tmp

      - name: Load Docker image
        run: docker load -i /tmp/docker-image.tar

      - name: Install test dependencies
        run: pnpm --filter pocket-id-tests install --frozen-lockfile

      - name: Install Playwright Browsers
        working-directory: ./tests
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: pnpm exec playwright install --with-deps chromium

      - name: Run Docker containers
        working-directory: ./tests/setup
        run: |
          DOCKER_COMPOSE_FILE=docker-compose.yml

          cat > .env <<EOF
          FILE_BACKEND=${{ matrix.storage }}
          SCIM_SERVICE_PROVIDER_URL=http://localhost:18123/v2
          SCIM_SERVICE_PROVIDER_URL_INTERNAL=http://scim-test-server:8080/v2
          EOF

          if [ "${{ matrix.db }}" = "postgres" ]; then
            DOCKER_COMPOSE_FILE=docker-compose-postgres.yml
          elif [ "${{ matrix.storage }}" = "s3" ]; then
            DOCKER_COMPOSE_FILE=docker-compose-s3.yml
          fi

          docker compose -f "$DOCKER_COMPOSE_FILE" up -d

          {
            LOG_FILE="/tmp/backend.log"
            while true; do
              CID=$(docker compose -f "$DOCKER_COMPOSE_FILE" ps -q pocket-id)
              if [ -n "$CID" ]; then
                echo "[$(date)] Attaching logs for $CID" >> "$LOG_FILE"
                docker logs -f --since=0 "$CID" >> "$LOG_FILE" 2>&1
              else
                echo "[$(date)] Container not yet running…" >> "$LOG_FILE"
              fi
              sleep 1
            done
          } &

      - name: Run Playwright tests
        working-directory: ./tests
        run: pnpm exec playwright test

      - name: Upload Test Report
        uses: actions/upload-artifact@v4
        if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
        with:
          name: playwright-report-${{ matrix.db }}-${{ matrix.storage }}
          path: tests/.report
          include-hidden-files: true
          retention-days: 15

      - name: Upload Backend Test Report
        uses: actions/upload-artifact@v4
        if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
        with:
          name: backend-${{ matrix.db }}-${{ matrix.storage }}
          path: /tmp/backend.log
          include-hidden-files: true
          retention-days: 15
