name: CI

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  repo-hygiene:
    runs-on: ubuntu-latest

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

      - name: Enforce no generated artifacts
        run: ./scripts/check_no_generated_artifacts.sh

      - name: Enforce env contract parity
        run: python3 scripts/check_env_contract.py

  lint:
    runs-on: ubuntu-latest
    needs: [repo-hygiene]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - uses: astral-sh/setup-uv@v4
      - run: uv sync --extra dev
      - name: Ruff check
        run: uv run ruff check .
      - name: Ruff format check
        run: uv run ruff format --check .
      - name: Mypy
        run: uv run mypy app/ --ignore-missing-imports

  test:
    runs-on: ubuntu-latest
    needs:
      - repo-hygiene
      - lint
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: scholar
          POSTGRES_USER: scholar
          POSTGRES_PASSWORD: scholar
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U scholar -d scholar"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 20

    env:
      DATABASE_URL: postgresql+asyncpg://scholar:scholar@localhost:5432/scholar
      SCHOLAR_IMAGE_UPLOAD_DIR: /tmp/scholarr_uploads/scholar_images

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

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Setup uv
        uses: astral-sh/setup-uv@v4

      - name: Install dependencies
        run: uv sync --extra dev

      - name: Migration smoke
        run: uv run alembic upgrade head

      - name: Unit tests
        run: uv run pytest tests/unit

      - name: Integration tests
        run: uv run pytest -m integration

  frontend-quality:
    runs-on: ubuntu-latest
    needs:
      - repo-hygiene

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

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: API contract drift check
        run: python3 scripts/check_frontend_api_contract.py

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install frontend dependencies
        working-directory: frontend
        run: npm ci

      - name: Frontend theme token policy
        working-directory: frontend
        run: npm run check:theme-tokens

      - name: Frontend typecheck
        working-directory: frontend
        run: npm run typecheck

      - name: Frontend unit tests
        working-directory: frontend
        run: npm run test:run

      - name: Frontend build
        working-directory: frontend
        run: npm run build

  docs-quality:
    runs-on: ubuntu-latest
    needs:
      - repo-hygiene

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

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install docs dependencies
        run: npm ci --prefix docs/website

      - name: Docs build
        run: npm --prefix docs/website run build

  docker-publish:
    runs-on: ubuntu-latest
    needs:
      - repo-hygiene
      - test
      - frontend-quality
      - docs-quality
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    permissions:
      contents: read

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

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

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Derive image metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: justinzeus/scholarr
          tags: |
            type=raw,value=latest
            type=sha,format=short,prefix=sha-

      - name: Build and push multi-arch image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./Dockerfile
          target: prod
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
