# CI (triggered)
name: CI

on:
  push:
    branches: [master, main]
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  # Check if CI should be skipped based on branch name or commit message
  skip-ci-check:
    runs-on: ubuntu-latest
    outputs:
      should-skip: ${{ steps.check.outputs.skip || 'false' }}
    steps:
      - name: Check out code (for commit message)
        uses: actions/checkout@v4
        with:
          fetch-depth: 1

      - name: Check if CI should be skipped
        id: check
        run: |
          SKIP=false

          # Simple skip pattern: @skipci (case-insensitive)
          SKIP_PATTERN="@skipci"

          # Get branch name (works for both push and PR)
          BRANCH_NAME="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"

          # Get commit message (works for both push and PR)
          COMMIT_MSG="${GITHUB_EVENT_HEAD_COMMIT_MESSAGE:-}"
          if [ -z "$COMMIT_MSG" ]; then
            COMMIT_MSG="${GITHUB_EVENT_PULL_REQUEST_HEAD_COMMIT_MESSAGE:-}"
          fi
          if [ -z "$COMMIT_MSG" ]; then
            COMMIT_MSG=$(git log -1 --pretty=%B 2>/dev/null || echo "")
          fi

          # Check branch name (case-insensitive)
          if echo "$BRANCH_NAME" | grep -qiF "$SKIP_PATTERN"; then
            echo "Skipping CI: branch name contains '$SKIP_PATTERN'"
            SKIP=true
          fi

          # Check commit message (case-insensitive)
          if [ "$SKIP" = "false" ] && [ -n "$COMMIT_MSG" ]; then
            if echo "$COMMIT_MSG" | grep -qiF "$SKIP_PATTERN"; then
              echo "Skipping CI: commit message contains '$SKIP_PATTERN'"
              SKIP=true
            fi
          fi

          echo "skip=$SKIP" >> "$GITHUB_OUTPUT"
          echo "Branch: $BRANCH_NAME"
          echo "Commit: ${COMMIT_MSG:0:50}..."
          echo "Skip CI: $SKIP"

  lint-and-type-check:
    needs: skip-ci-check
    runs-on: ubuntu-latest
    if: &should_run ${{ needs.skip-ci-check.outputs.should-skip != 'true' }}
    container:
      image: node:20-bullseye
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Generate Prisma Client
        run: npm run db:generate
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public

      - name: Run ESLint
        run: npm run lint

      - name: Type check
        run: npm run type-check

  test:
    needs: skip-ci-check
    runs-on: ubuntu-latest
    if: *should_run
    container:
      image: node:20-bullseye
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: mirrormatch_test
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    env:
      DATABASE_URL: postgresql://postgres:postgres@postgres:5432/mirrormatch_test?schema=public
      NEXTAUTH_SECRET: test-secret-key-for-ci
      NEXTAUTH_URL: http://localhost:3000
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Generate Prisma Client
        run: npm run db:generate

      - name: Run database migrations
        run: npm run db:push

      - name: Run tests
        run: npm run test:ci

      - name: Upload coverage reports
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage/coverage-final.json
          flags: unittests
          name: codecov-umbrella
          fail_ci_if_error: false
        continue-on-error: true

  build:
    needs: skip-ci-check
    runs-on: ubuntu-latest
    if: *should_run
    container:
      image: node:20-bullseye
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Generate Prisma Client
        run: npm run db:generate
        env:
          # Use the same connection string we provide to the build step so Prisma can generate types
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public

      - name: Build application
        run: npm run build
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public
          NEXTAUTH_SECRET: test-secret-key-for-ci
          NEXTAUTH_URL: http://localhost:3000

  secret-scanning:
    needs: skip-ci-check
    if: *should_run
    runs-on: ubuntu-latest
    container:
      image: zricethezav/gitleaks:latest
    steps:
      - name: Install Node.js for checkout action
        run: |
          apk add --no-cache nodejs npm curl

      - name: Check out code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Scan for secrets
        run: gitleaks detect --source . --no-banner --redact --exit-code 0
        continue-on-error: true

  dependency-scan:
    needs: skip-ci-check
    if: *should_run
    runs-on: ubuntu-latest
    container:
      image: aquasec/trivy:latest
    steps:
      - name: Install Node.js for checkout action
        run: |
          apk add --no-cache nodejs npm curl

      - name: Check out code
        uses: actions/checkout@v4

      - name: Dependency vulnerability scan (Trivy)
        run: |
          trivy fs \
            --scanners vuln \
            --severity HIGH,CRITICAL \
            --ignore-unfixed \
            --timeout 10m \
            --skip-dirs .git,node_modules \
            --exit-code 0 \
            .

      - name: Secret scan (Trivy)
        run: |
          trivy fs \
            --scanners secret \
            --timeout 10m \
            --skip-dirs .git,node_modules \
            --exit-code 0 \
            .

  sast-scan:
    needs: skip-ci-check
    if: *should_run
    runs-on: ubuntu-latest
    container:
      image: ubuntu:22.04
    steps:
      - name: Install Node.js for checkout action
        run: |
          apt-get update && apt-get install -y curl
          curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
          apt-get install -y nodejs

      - name: Check out code
        uses: actions/checkout@v4

      - name: Install Semgrep
        run: |
          apt-get update && apt-get install -y python3 python3-pip
          pip3 install semgrep

      - name: Run Semgrep scan
        run: semgrep --config=auto --error
        continue-on-error: true

  workflow-summary:
    runs-on: ubuntu-latest
    needs: [lint-and-type-check, test, build, secret-scanning, dependency-scan, sast-scan]
    if: always()
    steps:
      - name: Generate workflow summary
        run: |
          echo "## 🔍 CI Workflow Summary" >> $GITHUB_STEP_SUMMARY || true
          echo "" >> $GITHUB_STEP_SUMMARY || true
          echo "### Job Results" >> $GITHUB_STEP_SUMMARY || true
          echo "" >> $GITHUB_STEP_SUMMARY || true
          echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY || true
          echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY || true
          echo "| 📝 Lint & Type Check | ${{ needs.lint-and-type-check.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "| 🧪 Tests | ${{ needs.test.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "| 🏗️ Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "| 🔐 Secret Scanning | ${{ needs.secret-scanning.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "| 📦 Dependency Scan | ${{ needs.dependency-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "| 🔍 SAST Scan | ${{ needs.sast-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true
          echo "" >> $GITHUB_STEP_SUMMARY || true
          echo "### 📊 Summary" >> $GITHUB_STEP_SUMMARY || true
          echo "" >> $GITHUB_STEP_SUMMARY || true
          echo "All security and validation checks have completed." >> $GITHUB_STEP_SUMMARY || true
