name: CI/CD Pipeline

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

env:
  GO_VERSION: '1.21'
  PYTHON_VERSION: '3.11'
  NODE_VERSION: '20'
  POSTGRES_USER: breakpilot
  POSTGRES_PASSWORD: breakpilot123
  POSTGRES_DB: breakpilot_test
  REGISTRY: ghcr.io
  IMAGE_PREFIX: ${{ github.repository_owner }}/breakpilot

jobs:
  # ==========================================
  # Go Consent Service Tests
  # ==========================================
  go-tests:
    name: Go Tests
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: ${{ env.POSTGRES_USER }}
          POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
          POSTGRES_DB: ${{ env.POSTGRES_DB }}
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

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

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: ${{ env.GO_VERSION }}
          cache-dependency-path: consent-service/go.sum

      - name: Download dependencies
        working-directory: ./consent-service
        run: go mod download

      - name: Run Go Vet
        working-directory: ./consent-service
        run: go vet ./...

      - name: Run Unit Tests
        working-directory: ./consent-service
        run: go test -v -race -coverprofile=coverage.out ./...
        env:
          DATABASE_URL: postgres://${{ env.POSTGRES_USER }}:${{ env.POSTGRES_PASSWORD }}@localhost:5432/${{ env.POSTGRES_DB }}?sslmode=disable
          JWT_SECRET: test-jwt-secret-for-ci
          JWT_REFRESH_SECRET: test-refresh-secret-for-ci

      - name: Check Coverage
        working-directory: ./consent-service
        run: |
          go tool cover -func=coverage.out
          COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//')
          echo "Total coverage: ${COVERAGE}%"
          if (( $(echo "$COVERAGE < 50" | bc -l) )); then
            echo "::warning::Coverage is below 50%"
          fi

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: ./consent-service/coverage.out
          flags: go
          name: go-coverage
        continue-on-error: true

  # ==========================================
  # Python Backend Tests
  # ==========================================
  python-tests:
    name: Python Tests
    runs-on: ubuntu-latest

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

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
          cache: 'pip'
          cache-dependency-path: backend/requirements.txt

      - name: Install dependencies
        working-directory: ./backend
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install pytest pytest-cov pytest-asyncio httpx

      - name: Run Python Tests
        working-directory: ./backend
        run: pytest -v --cov=. --cov-report=xml --cov-report=term-missing
        continue-on-error: true

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: ./backend/coverage.xml
          flags: python
          name: python-coverage
        continue-on-error: true

  # ==========================================
  # Node.js Website Tests
  # ==========================================
  website-tests:
    name: Website Tests
    runs-on: ubuntu-latest

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

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: website/package-lock.json

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

      - name: Run TypeScript check
        working-directory: ./website
        run: npx tsc --noEmit
        continue-on-error: true

      - name: Run ESLint
        working-directory: ./website
        run: npm run lint
        continue-on-error: true

      - name: Build website
        working-directory: ./website
        run: npm run build
        env:
          NEXT_PUBLIC_BILLING_API_URL: http://localhost:8083
          NEXT_PUBLIC_APP_URL: http://localhost:3000

  # ==========================================
  # Linting
  # ==========================================
  lint:
    name: Linting
    runs-on: ubuntu-latest

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

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: ${{ env.GO_VERSION }}

      - name: Run golangci-lint
        uses: golangci/golangci-lint-action@v4
        with:
          version: latest
          working-directory: ./consent-service
          args: --timeout=5m
        continue-on-error: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: Install Python linters
        run: pip install flake8 black isort

      - name: Run flake8
        working-directory: ./backend
        run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
        continue-on-error: true

      - name: Check Black formatting
        working-directory: ./backend
        run: black --check --diff .
        continue-on-error: true

  # ==========================================
  # Security Scan
  # ==========================================
  security:
    name: Security Scan
    runs-on: ubuntu-latest

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

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'CRITICAL,HIGH'
          exit-code: '0'
        continue-on-error: true

      - name: Run Go security check
        uses: securego/gosec@master
        with:
          args: '-no-fail -fmt sarif -out results.sarif ./consent-service/...'
        continue-on-error: true

  # ==========================================
  # Docker Build & Push
  # ==========================================
  docker-build:
    name: Docker Build & Push
    runs-on: ubuntu-latest
    needs: [go-tests, python-tests, website-tests]
    permissions:
      contents: read
      packages: write

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

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

      - name: Log in to GitHub Container Registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata for consent-service
        id: meta-consent
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-consent-service
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=sha,prefix=
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

      - name: Build and push consent-service
        uses: docker/build-push-action@v5
        with:
          context: ./consent-service
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta-consent.outputs.tags }}
          labels: ${{ steps.meta-consent.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Extract metadata for backend
        id: meta-backend
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-backend
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=sha,prefix=
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

      - name: Build and push backend
        uses: docker/build-push-action@v5
        with:
          context: ./backend
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta-backend.outputs.tags }}
          labels: ${{ steps.meta-backend.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Extract metadata for website
        id: meta-website
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-website
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=sha,prefix=
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

      - name: Build and push website
        uses: docker/build-push-action@v5
        with:
          context: ./website
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta-website.outputs.tags }}
          labels: ${{ steps.meta-website.outputs.labels }}
          build-args: |
            NEXT_PUBLIC_BILLING_API_URL=${{ vars.NEXT_PUBLIC_BILLING_API_URL || 'http://localhost:8083' }}
            NEXT_PUBLIC_APP_URL=${{ vars.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # ==========================================
  # Integration Tests
  # ==========================================
  integration-tests:
    name: Integration Tests
    runs-on: ubuntu-latest
    needs: [docker-build]

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

      - name: Start services with Docker Compose
        run: |
          docker compose up -d postgres mailpit
          sleep 10

      - name: Run consent-service
        working-directory: ./consent-service
        run: |
          go build -o consent-service ./cmd/server
          ./consent-service &
          sleep 5
        env:
          DATABASE_URL: postgres://breakpilot:breakpilot123@localhost:5432/breakpilot_db?sslmode=disable
          JWT_SECRET: test-jwt-secret
          JWT_REFRESH_SECRET: test-refresh-secret
          SMTP_HOST: localhost
          SMTP_PORT: 1025

      - name: Health Check
        run: |
          curl -f http://localhost:8081/health || exit 1

      - name: Run Integration Tests
        run: |
          # Test Auth endpoints
          curl -s http://localhost:8081/api/v1/auth/health

          # Test Document endpoints
          curl -s http://localhost:8081/api/v1/documents
        continue-on-error: true

      - name: Stop services
        if: always()
        run: docker compose down

  # ==========================================
  # Deploy to Staging
  # ==========================================
  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [docker-build, integration-tests]
    if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
    environment:
      name: staging
      url: https://staging.breakpilot.app

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

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Deploy to staging server
        env:
          STAGING_HOST: ${{ secrets.STAGING_HOST }}
          STAGING_USER: ${{ secrets.STAGING_USER }}
          STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
        run: |
          # This is a placeholder for actual deployment
          # Configure based on your staging infrastructure
          echo "Deploying to staging environment..."
          echo "Images to deploy:"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-consent-service:develop"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-backend:develop"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-website:develop"

          # Example: SSH deployment (uncomment when configured)
          # mkdir -p ~/.ssh
          # echo "$STAGING_SSH_KEY" > ~/.ssh/id_rsa
          # chmod 600 ~/.ssh/id_rsa
          # ssh -o StrictHostKeyChecking=no $STAGING_USER@$STAGING_HOST "cd /opt/breakpilot && docker compose pull && docker compose up -d"

      - name: Notify deployment
        run: |
          echo "## Staging Deployment" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Successfully deployed to staging environment" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Deployed images:**" >> $GITHUB_STEP_SUMMARY
          echo "- consent-service: \`develop\`" >> $GITHUB_STEP_SUMMARY
          echo "- backend: \`develop\`" >> $GITHUB_STEP_SUMMARY
          echo "- website: \`develop\`" >> $GITHUB_STEP_SUMMARY

  # ==========================================
  # Deploy to Production
  # ==========================================
  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [docker-build, integration-tests]
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment:
      name: production
      url: https://breakpilot.app

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

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Deploy to production server
        env:
          PROD_HOST: ${{ secrets.PROD_HOST }}
          PROD_USER: ${{ secrets.PROD_USER }}
          PROD_SSH_KEY: ${{ secrets.PROD_SSH_KEY }}
        run: |
          # This is a placeholder for actual deployment
          # Configure based on your production infrastructure
          echo "Deploying to production environment..."
          echo "Images to deploy:"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-consent-service:latest"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-backend:latest"
          echo "  - ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-website:latest"

          # Example: SSH deployment (uncomment when configured)
          # mkdir -p ~/.ssh
          # echo "$PROD_SSH_KEY" > ~/.ssh/id_rsa
          # chmod 600 ~/.ssh/id_rsa
          # ssh -o StrictHostKeyChecking=no $PROD_USER@$PROD_HOST "cd /opt/breakpilot && docker compose pull && docker compose up -d"

      - name: Notify deployment
        run: |
          echo "## Production Deployment" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Successfully deployed to production environment" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Deployed images:**" >> $GITHUB_STEP_SUMMARY
          echo "- consent-service: \`latest\`" >> $GITHUB_STEP_SUMMARY
          echo "- backend: \`latest\`" >> $GITHUB_STEP_SUMMARY
          echo "- website: \`latest\`" >> $GITHUB_STEP_SUMMARY

  # ==========================================
  # Summary
  # ==========================================
  summary:
    name: CI Summary
    runs-on: ubuntu-latest
    needs: [go-tests, python-tests, website-tests, lint, security, docker-build, integration-tests]
    if: always()

    steps:
      - name: Check job results
        run: |
          echo "## CI/CD Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
          echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
          echo "| Go Tests | ${{ needs.go-tests.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Python Tests | ${{ needs.python-tests.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Website Tests | ${{ needs.website-tests.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Linting | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Security | ${{ needs.security.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Docker Build | ${{ needs.docker-build.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Integration Tests | ${{ needs.integration-tests.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "### Docker Images" >> $GITHUB_STEP_SUMMARY
          echo "Images are pushed to: \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-*\`" >> $GITHUB_STEP_SUMMARY
