name: CI

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

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

env:
  NODE_VERSION: "20"
  PNPM_VERSION: "9"

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "pnpm"
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      - name: Run linter
        run: pnpm lint

  typecheck:
    name: Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "pnpm"
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      - name: Build all packages
        run: pnpm build

  test:
    name: Test Suite
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_DB: shieldai
          POSTGRES_USER: shieldai
          POSTGRES_PASSWORD: shieldai_dev
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U shieldai"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 5
      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "pnpm"
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      - name: Run tests with coverage
        run: pnpm test:coverage
        env:
          DATABASE_URL: "postgresql://shieldai:shieldai_dev@localhost:5432/shieldai"
          REDIS_URL: "redis://localhost:6379"
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          file: ./coverage/lcov.info
          flags: unittests
          name: shieldai-coverage
          fail_on_empty: false

  docker-build:
    name: Docker Build
    runs-on: ubuntu-latest
    needs: [lint, typecheck, test]
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: api
            context: .
            dockerfile: packages/api/Dockerfile
          - name: darkwatch
            context: .
            dockerfile: services/darkwatch/Dockerfile
          - name: spamshield
            context: .
            dockerfile: services/spamshield/Dockerfile
          - name: voiceprint
            context: .
            dockerfile: services/voiceprint/Dockerfile
    steps:
      - uses: actions/checkout@v4
      - name: Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build Docker image
        uses: docker/build-push-action@v5
        with:
          context: ${{ matrix.context }}
          file: ${{ matrix.dockerfile }}
          push: false
          tags: shieldai-${{ matrix.name }}:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  security-scan:
    name: Security Scan
    runs-on: ubuntu-latest
    needs: [lint]
    steps:
      - uses: actions/checkout@v4
      - name: Run pnpm audit
        run: pnpm audit --prod
      - name: Trivy filesystem scan
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: fs
          scan-ref: "."
          format: table
          exit-code: 1
          ignore-unfixed: true
          severity: CRITICAL,HIGH

  terraform-plan:
    name: Terraform Plan
    runs-on: ubuntu-latest
    needs: [lint]
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Terraform Format
        working-directory: infra
        run: terraform fmt -check -diff
      - name: Terraform Init
        working-directory: infra
        run: terraform init
      - name: Terraform Validate
        working-directory: infra
        run: terraform validate
      - name: Terraform Plan
        working-directory: infra
        run: terraform plan -var-file=environments/staging/terraform.tfvars.example -no-color
        env:
          TF_VAR_hibp_api_key: ${{ secrets.HIBP_API_KEY }}
          TF_VAR_resend_api_key: ${{ secrets.RESEND_API_KEY }}

  load-test:
    name: Load Test
    runs-on: ubuntu-latest
    needs: [lint, typecheck, test, docker-build]
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    environment: staging
    steps:
      - uses: actions/checkout@v4

      - name: Install k6
        run: |
          K6_VERSION="v0.50.0"
          K6_URL="https://github.com/grafana/k6/releases/download/${K6_VERSION}/k6-linux-amd64.tar.gz"
          K6_SHA256="d950a2408d0be2dc81aef397a7c984a1d84271d7ae94ff7a47d08371904f0800"
          curl -sSL "${K6_URL}" -o k6.tar.gz
          echo "${K6_SHA256}  k6.tar.gz" | sha256sum --check --strict -
          tar xzf k6.tar.gz
          sudo mv k6 /usr/local/bin/
          k6 version

      - name: Validate required secrets
        run: |
          if [ -z "$API_TOKEN" ]; then
            echo "❌ LOAD_TEST_API_TOKEN secret is not set"
            exit 1
          fi

      - name: Run combined load tests
        run: |
          chmod +x scripts/load-test/run-all.sh
          ./scripts/load-test/run-all.sh
        env:
          LOAD_TEST_BASE_URL: ${{ secrets.LOAD_TEST_BASE_URL || 'http://localhost:3000' }}
          API_TOKEN: ${{ secrets.LOAD_TEST_API_TOKEN }}
          TARGET_RPS: ${{ vars.LOAD_TEST_TARGET_RPS || '500' }}
          DURATION: ${{ vars.LOAD_TEST_DURATION || '300s' }}
          K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN || '' }}
          K6_CLOUD_PROJECT_ID: ${{ vars.K6_CLOUD_PROJECT_ID || '' }}

      - name: Upload load test report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: load-test-report-${{ github.sha }}
          path: scripts/load-test/reports/
          retention-days: 30

      - name: Check P99 thresholds
        if: always()
        run: |
          if [ -f scripts/load-test/reports/threshold-results.json ]; then
            FAILURES=$(jq -r '[.services | to_entries[] | select(.value.exitCode != 0) | .key] | join(", ")' scripts/load-test/reports/threshold-results.json 2>/dev/null || echo "")
            if [ -n "$FAILURES" ] && [ "$FAILURES" != "" ]; then
              echo "❌ Load test failures: $FAILURES"
              exit 1
            else
              echo "✅ All load tests passed"
            fi
          else
            echo "⚠️ No threshold results file found"
            exit 1
          fi

      - name: Validate auto-scaling
        if: always()
        run: |
          SUMMARY_FILE=$(ls scripts/load-test/reports/*-summary-*.json 2>/dev/null | head -1)
          if [ -n "$SUMMARY_FILE" ]; then
            MAX_VUS=$(jq -r '.metrics.vus.max // 0' "$SUMMARY_FILE")
            TARGET_VUS=20
            if [ "$(echo "$MAX_VUS >= $TARGET_VUS" | bc -l)" -eq 1 ]; then
              echo "✅ Auto-scaling validated: max VUs ($MAX_VUS) >= target ($TARGET_VUS)"
            else
              echo "⚠️ Auto-scaling below target: max VUs ($MAX_VUS) < target ($TARGET_VUS)"
            fi
          else
            echo "⚠️ No summary file for auto-scaling validation"
          fi
