name: Sencho CI

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

# Cancel previous runs on the same branch/PR
concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  backend:
    name: Backend (Build, Test, Lint)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: backend/package-lock.json

      - name: Install Dependencies
        working-directory: ./backend
        run: npm ci

      - name: Build (TypeScript)
        working-directory: ./backend
        run: npm run build

      - name: Unit Tests (Vitest)
        working-directory: ./backend
        run: npm test

      - name: Lint (ESLint)
        working-directory: ./backend
        run: npm run lint

      - name: Audit Dependencies
        working-directory: ./backend
        run: npm audit --audit-level=high

  frontend:
    name: Frontend (Build, Lint)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: frontend/package-lock.json

      - name: Install Dependencies
        working-directory: ./frontend
        run: npm ci

      - name: Build (Vite/React)
        working-directory: ./frontend
        run: npm run build

      - name: Lint (ESLint)
        working-directory: ./frontend
        run: npm run lint

      - name: Audit Dependencies
        working-directory: ./frontend
        run: npm audit --audit-level=high

  docker-validate:
    name: Docker Build & Scan
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v6

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

      - name: Build Docker image (validation only)
        uses: docker/build-push-action@v7
        with:
          context: .
          push: false
          load: true
          tags: sencho:pr-test
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Scan image for vulnerabilities (Trivy)
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: sencho:pr-test
          exit-code: '0'
          severity: 'CRITICAL,HIGH'
          format: 'table'
        continue-on-error: true

  e2e:
    name: E2E Tests (Playwright)
    runs-on: ubuntu-latest
    needs: [backend, frontend]
    steps:
      - name: Checkout Code
        uses: actions/checkout@v6

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

      - name: Install root dependencies (Playwright)
        run: npm ci

      - name: Install backend dependencies
        working-directory: ./backend
        run: npm ci

      - name: Build backend
        working-directory: ./backend
        run: npm run build

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

      - name: Create compose directory
        run: mkdir -p /tmp/compose

      - name: Start backend
        working-directory: ./backend
        run: node dist/index.js &
        env:
          JWT_SECRET: ci-test-secret-key-not-for-production
          COMPOSE_DIR: /tmp/compose
          PORT: 3000
          NODE_ENV: test

      - name: Start frontend dev server
        working-directory: ./frontend
        run: npm run dev &

      - name: Wait for services to be ready
        run: npx wait-on http://localhost:3000/api/health http://localhost:5173 --timeout 30000

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Run E2E tests
        run: npx playwright test
        env:
          E2E_USERNAME: admin
          E2E_PASSWORD: password123

      - name: Upload E2E report
        if: failure()
        uses: actions/upload-artifact@v7
        with:
          name: playwright-report
          path: |
            e2e/report/
            test-results/
          retention-days: 7

  update-screenshots:
    name: Refresh Doc Screenshots
    runs-on: ubuntu-latest
    # Only on main pushes (merged PRs); skip bot commits to avoid infinite loop
    if: "github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'docs: refresh screenshots')"
    needs: [backend, frontend]
    permissions:
      contents: write
      pull-requests: write
    steps:
      - name: Checkout Code
        uses: actions/checkout@v6
        with:
          token: ${{ secrets.DOCS_REPO_TOKEN }}

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

      - name: Install root dependencies (Playwright)
        run: npm ci

      - name: Install backend dependencies
        working-directory: ./backend
        run: npm ci

      - name: Build backend
        working-directory: ./backend
        run: npm run build

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

      - name: Create compose directory
        run: mkdir -p /tmp/compose

      - name: Start backend
        working-directory: ./backend
        run: node dist/index.js &
        env:
          JWT_SECRET: ci-test-secret-key-not-for-production
          COMPOSE_DIR: /tmp/compose
          PORT: 3000
          NODE_ENV: test

      - name: Start frontend dev server
        working-directory: ./frontend
        run: npm run dev &

      - name: Wait for services to be ready
        run: npx wait-on http://localhost:3000/api/health http://localhost:5173 --timeout 30000

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Capture screenshots
        run: npx playwright test e2e/screenshots.spec.ts --project=chromium
        env:
          E2E_USERNAME: admin
          E2E_PASSWORD: password123

      - name: Open / update screenshots PR
        id: create-pr
        uses: peter-evans/create-pull-request@v8
        with:
          token: ${{ secrets.DOCS_REPO_TOKEN }}
          branch: chore/refresh-screenshots
          commit-message: "docs: refresh screenshots"
          title: "docs: refresh screenshots"
          body: "Automated screenshot refresh — generated by the `update-screenshots` CI job on push to `main`."
          add-paths: docs/images/
          delete-branch: true

      - name: Auto-merge screenshots PR
        if: steps.create-pr.outputs.pull-request-number != ''
        env:
          GH_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
        run: |
          gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} \
            --auto --squash \
            --repo ${{ github.repository }}

  sync-docs:
    name: Sync Docs to sencho-docs
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - name: Checkout Sencho repo
        uses: actions/checkout@v6
        with:
          path: sencho

      - name: Clone or init sencho-docs
        env:
          DOCS_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
        run: |
          rm -rf sencho-docs

          REMOTE="https://x-access-token:${DOCS_TOKEN}@github.com/AnsoCode/sencho-docs.git"

          if git clone "${REMOTE}" sencho-docs 2>/dev/null; then
            echo "Cloned existing sencho-docs."
          else
            echo "Clone failed (repo is empty or has no default branch) — initializing."
            mkdir -p sencho-docs
            cd sencho-docs
            git init
            git checkout -b main
            git remote add origin "${REMOTE}"
          fi

      - name: Copy /docs into sencho-docs root
        run: rsync -av --delete --exclude='.git' sencho/docs/ sencho-docs/

      - name: Commit and push to sencho-docs
        working-directory: sencho-docs
        run: |
          git config user.email "docs-bot@sencho.io"
          git config user.name "Sencho Docs Bot"
          git add -A
          git commit -m "docs: sync from main@${{ github.sha }}" || echo "No changes to commit"
          git push origin HEAD:main
