name: CD Preprod

# Full pipeline triggered on every push to preprod.
# Flow: lint → unit tests → integration tests → docker build → deploy → notify
#
# Secrets required:
#   REGISTRY_TOKEN            — Scaleway registry (read/write)
#   NEXT_PUBLIC_API_URL       — https://api.preprod.xpeditis.com
#   NEXT_PUBLIC_APP_URL       — https://preprod.xpeditis.com
#   PORTAINER_WEBHOOK_BACKEND — Portainer webhook (preprod backend)
#   PORTAINER_WEBHOOK_FRONTEND— Portainer webhook (preprod frontend)
#   PREPROD_BACKEND_URL       — https://api.preprod.xpeditis.com
#   PREPROD_FRONTEND_URL      — https://preprod.xpeditis.com
#   DISCORD_WEBHOOK_URL

on:
  push:
    branches: [preprod]

concurrency:
  group: cd-preprod
  cancel-in-progress: false

env:
  REGISTRY: rg.fr-par.scw.cloud/weworkstudio
  NODE_VERSION: '20'

jobs:
  # ── 1. Lint ─────────────────────────────────────────────────────────
  backend-quality:
    name: Backend — Lint
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: apps/backend
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: apps/backend/package-lock.json
      - run: npm install --legacy-peer-deps
      - run: npm run lint

  frontend-quality:
    name: Frontend — Lint & Type-check
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: apps/frontend
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: apps/frontend/package-lock.json
      - run: npm ci --legacy-peer-deps
      - run: npm run lint
      - run: npm run type-check

  # ── 2. Unit Tests ────────────────────────────────────────────────────
  backend-tests:
    name: Backend — Unit Tests
    runs-on: ubuntu-latest
    needs: backend-quality
    defaults:
      run:
        working-directory: apps/backend
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: apps/backend/package-lock.json
      - run: npm install --legacy-peer-deps
      - run: npm test -- --passWithNoTests

  frontend-tests:
    name: Frontend — Unit Tests
    runs-on: ubuntu-latest
    needs: frontend-quality
    defaults:
      run:
        working-directory: apps/frontend
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: apps/frontend/package-lock.json
      - run: npm ci --legacy-peer-deps
      - run: npm test -- --passWithNoTests

  # ── 3. Integration Tests ─────────────────────────────────────────────
  integration-tests:
    name: Backend — Integration Tests
    runs-on: ubuntu-latest
    needs: [backend-tests, frontend-tests]
    defaults:
      run:
        working-directory: apps/backend

    services:
      postgres:
        image: postgres:15-alpine
        env:
          POSTGRES_USER: xpeditis_test
          POSTGRES_PASSWORD: xpeditis_test_password
          POSTGRES_DB: xpeditis_test
        options: >-
          --health-cmd pg_isready
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10
        ports:
          - 5432:5432
      redis:
        image: redis:7-alpine
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10
        ports:
          - 6379:6379

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: apps/backend/package-lock.json
      - run: npm install --legacy-peer-deps
      - name: Run integration tests
        env:
          NODE_ENV: test
          DATABASE_HOST: localhost
          DATABASE_PORT: 5432
          DATABASE_USER: xpeditis_test
          DATABASE_PASSWORD: xpeditis_test_password
          DATABASE_NAME: xpeditis_test
          DATABASE_SYNCHRONIZE: 'false'
          REDIS_HOST: localhost
          REDIS_PORT: 6379
          REDIS_PASSWORD: ''
          JWT_SECRET: test-secret-key-ci
          SMTP_HOST: localhost
          SMTP_PORT: 1025
          SMTP_FROM: test@xpeditis.com
        run: npm run test:integration -- --passWithNoTests

  # ── 4. Docker Build & Push ───────────────────────────────────────────
  # Tags: preprod (latest for this env) + preprod-SHA (used by prod for exact promotion)
  build-backend:
    name: Build Backend
    runs-on: ubuntu-latest
    needs: integration-tests
    outputs:
      sha: ${{ steps.sha.outputs.short }}
    steps:
      - uses: actions/checkout@v4
      - name: Short SHA
        id: sha
        run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: nologin
          password: ${{ secrets.REGISTRY_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          context: ./apps/backend
          file: ./apps/backend/Dockerfile
          push: true
          tags: |
            ${{ env.REGISTRY }}/xpeditis-backend:preprod
            ${{ env.REGISTRY }}/xpeditis-backend:preprod-${{ steps.sha.outputs.short }}
          cache-from: type=registry,ref=${{ env.REGISTRY }}/xpeditis-backend:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}/xpeditis-backend:buildcache,mode=max
          platforms: linux/amd64,linux/arm64

  build-frontend:
    name: Build Frontend
    runs-on: ubuntu-latest
    needs: integration-tests
    outputs:
      sha: ${{ steps.sha.outputs.short }}
    steps:
      - uses: actions/checkout@v4
      - name: Short SHA
        id: sha
        run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: nologin
          password: ${{ secrets.REGISTRY_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          context: ./apps/frontend
          file: ./apps/frontend/Dockerfile
          push: true
          tags: |
            ${{ env.REGISTRY }}/xpeditis-frontend:preprod
            ${{ env.REGISTRY }}/xpeditis-frontend:preprod-${{ steps.sha.outputs.short }}
          cache-from: type=registry,ref=${{ env.REGISTRY }}/xpeditis-frontend:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}/xpeditis-frontend:buildcache,mode=max
          platforms: linux/amd64,linux/arm64
          build-args: |
            NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}
            NEXT_PUBLIC_APP_URL=${{ secrets.NEXT_PUBLIC_APP_URL }}

  build-log-exporter:
    name: Build Log Exporter
    runs-on: ubuntu-latest
    needs: integration-tests
    outputs:
      sha: ${{ steps.sha.outputs.short }}
    steps:
      - uses: actions/checkout@v4
      - name: Short SHA
        id: sha
        run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: nologin
          password: ${{ secrets.REGISTRY_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          context: ./apps/log-exporter
          file: ./apps/log-exporter/Dockerfile
          push: true
          tags: |
            ${{ env.REGISTRY }}/xpeditis-log-exporter:preprod
            ${{ env.REGISTRY }}/xpeditis-log-exporter:preprod-${{ steps.sha.outputs.short }}
          cache-from: type=registry,ref=${{ env.REGISTRY }}/xpeditis-log-exporter:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}/xpeditis-log-exporter:buildcache,mode=max
          platforms: linux/amd64,linux/arm64

  # ── 5. Deploy via Portainer ──────────────────────────────────────────
  deploy:
    name: Deploy to Preprod
    runs-on: ubuntu-latest
    needs: [build-backend, build-frontend, build-log-exporter]
    environment: preprod
    steps:
      - name: Deploy backend
        run: |
          HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.PORTAINER_WEBHOOK_BACKEND }}")
          echo "Portainer response: HTTP $HTTP_CODE"
          if [[ "$HTTP_CODE" != "2"* ]]; then
            echo "ERROR: Portainer webhook failed with HTTP $HTTP_CODE"
            exit 1
          fi
          echo "Backend webhook triggered."
      - name: Wait for backend startup
        run: sleep 20
      - name: Deploy frontend
        run: |
          HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.PORTAINER_WEBHOOK_FRONTEND }}")
          echo "Portainer response: HTTP $HTTP_CODE"
          if [[ "$HTTP_CODE" != "2"* ]]; then
            echo "ERROR: Portainer webhook failed with HTTP $HTTP_CODE"
            exit 1
          fi
          echo "Frontend webhook triggered."

  # ── Notifications ────────────────────────────────────────────────────
  notify-success:
    name: Notify Success
    runs-on: ubuntu-latest
    needs: [build-backend, build-frontend, deploy]
    if: success()
    steps:
      - run: |
          curl -s -H "Content-Type: application/json" -d '{
            "embeds": [{
              "title": "✅ Preprod Deployed & Healthy",
              "color": 3066993,
              "fields": [
                {"name": "Author", "value": "${{ github.actor }}", "inline": true},
                {"name": "SHA", "value": "`${{ needs.build-backend.outputs.sha }}`", "inline": true},
                {"name": "Workflow", "value": "[${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": false}
              ],
              "footer": {"text": "Xpeditis CI/CD • Preprod"}
            }]
          }' ${{ secrets.DISCORD_WEBHOOK_URL }}

  notify-failure:
    name: Notify Failure
    runs-on: ubuntu-latest
    needs: [backend-quality, frontend-quality, backend-tests, frontend-tests, integration-tests, build-backend, build-frontend, deploy]
    if: failure()
    steps:
      - run: |
          curl -s -H "Content-Type: application/json" -d '{
            "embeds": [{
              "title": "❌ Preprod Pipeline Failed",
              "description": "Preprod was NOT deployed.",
              "color": 15158332,
              "fields": [
                {"name": "Author", "value": "${{ github.actor }}", "inline": true},
                {"name": "Workflow", "value": "[${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": false}
              ],
              "footer": {"text": "Xpeditis CI/CD • Preprod"}
            }]
          }' ${{ secrets.DISCORD_WEBHOOK_URL }}
