name: Deploy

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      environment:
        description: Target environment
        required: true
        default: staging
        type: choice
        options:
          - staging
          - production

concurrency:
  group: deploy-${{ inputs.environment || 'staging' }}
  cancel-in-progress: false

env:
  REGISTRY: ghcr.io
  REGISTRY_URL: ghcr.io/${{ github.repository_owner }}

jobs:
  build-api:
    name: Build API Image
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

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

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

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

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

      - name: Build and push API image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: apps/api/Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha,scope=api
          cache-to: type=gha,mode=max,scope=api

  build-web:
    name: Build Web Image
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

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

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

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

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

      - name: Build and push Web image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: apps/web/Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha,scope=web
          cache-to: type=gha,mode=max,scope=web

  build-ai:
    name: Build AI Services Image
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

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

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

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

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

      - name: Build and push AI Services image
        uses: docker/build-push-action@v6
        with:
          context: ./libs/ai-services
          file: libs/ai-services/Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha,scope=ai
          cache-to: type=gha,mode=max,scope=ai

  deploy-staging:
    name: Deploy to Staging
    needs: [build-api, build-web, build-ai]
    if: github.event_name == 'push' || inputs.environment == 'staging'
    runs-on: ubuntu-latest
    environment: staging

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

      - name: Deploy to staging
        env:
          DEPLOY_HOST: ${{ secrets.STAGING_HOST }}
          DEPLOY_USER: ${{ secrets.STAGING_USER }}
          DEPLOY_KEY: ${{ secrets.STAGING_SSH_KEY }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null

          # Copy production compose and deploy
          scp -i ~/.ssh/deploy_key docker-compose.prod.yml "$DEPLOY_USER@$DEPLOY_HOST:~/goodgo/"
          scp -i ~/.ssh/deploy_key -r monitoring/ "$DEPLOY_USER@$DEPLOY_HOST:~/goodgo/monitoring/"

          ssh -i ~/.ssh/deploy_key "$DEPLOY_USER@$DEPLOY_HOST" << DEPLOY_SCRIPT
            cd ~/goodgo
            export IMAGE_TAG="${IMAGE_TAG}"
            export REGISTRY_URL="${REGISTRY_URL}"

            # Login to GHCR
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

            # Pull new images
            docker compose -f docker-compose.prod.yml pull api web ai-services

            # Rolling update — zero downtime
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait api
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait web
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait ai-services

            # Run database migrations
            docker compose -f docker-compose.prod.yml exec api npx prisma migrate deploy

            # Cleanup old images
            docker image prune -f
          DEPLOY_SCRIPT

      - name: Verify staging deployment
        env:
          STAGING_URL: ${{ secrets.STAGING_URL }}
        run: |
          for i in $(seq 1 10); do
            if curl -sf "$STAGING_URL/health" > /dev/null 2>&1; then
              echo "Staging deployment verified successfully"
              exit 0
            fi
            echo "Waiting for staging to be ready... ($i/10)"
            sleep 10
          done
          echo "Staging health check failed"
          exit 1

  smoke-test-staging:
    name: Smoke Test Staging
    needs: [deploy-staging]
    runs-on: ubuntu-latest
    environment: staging

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

      - name: Run smoke tests
        env:
          STAGING_URL: ${{ secrets.STAGING_URL }}
        run: |
          chmod +x scripts/smoke-test.sh
          ./scripts/smoke-test.sh "$STAGING_URL"

      - name: Notify on failure
        if: failure()
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: |
          curl -s -X POST "$SLACK_WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{
              \"text\": \":rotating_light: *Staging smoke tests FAILED* for \`${{ github.sha }}\`\",
              \"blocks\": [{
                \"type\": \"section\",
                \"text\": {
                  \"type\": \"mrkdwn\",
                  \"text\": \":rotating_light: *Staging Smoke Test Failure*\n*Commit:* \`${{ github.sha }}\`\n*Branch:* \`${{ github.ref_name }}\`\n*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"
                }
              }]
            }"

  deploy-production:
    name: Deploy to Production
    needs: [build-api, build-web, build-ai]
    if: inputs.environment == 'production'
    runs-on: ubuntu-latest
    environment: production

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

      - name: Deploy to production
        env:
          DEPLOY_HOST: ${{ secrets.PRODUCTION_HOST }}
          DEPLOY_USER: ${{ secrets.PRODUCTION_USER }}
          DEPLOY_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null

          scp -i ~/.ssh/deploy_key docker-compose.prod.yml "$DEPLOY_USER@$DEPLOY_HOST:~/goodgo/"
          scp -i ~/.ssh/deploy_key -r monitoring/ "$DEPLOY_USER@$DEPLOY_HOST:~/goodgo/monitoring/"

          ssh -i ~/.ssh/deploy_key "$DEPLOY_USER@$DEPLOY_HOST" << DEPLOY_SCRIPT
            cd ~/goodgo
            export IMAGE_TAG="${IMAGE_TAG}"
            export REGISTRY_URL="${REGISTRY_URL}"

            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

            docker compose -f docker-compose.prod.yml pull api web ai-services

            # Rolling update with health checks
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait api
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait web
            docker compose -f docker-compose.prod.yml up -d --no-deps --wait ai-services

            docker compose -f docker-compose.prod.yml exec api npx prisma migrate deploy

            docker image prune -f
          DEPLOY_SCRIPT

      - name: Verify production deployment
        env:
          PRODUCTION_URL: ${{ secrets.PRODUCTION_URL }}
        run: |
          for i in $(seq 1 10); do
            if curl -sf "$PRODUCTION_URL/health" > /dev/null 2>&1; then
              echo "Production deployment verified successfully"
              exit 0
            fi
            echo "Waiting for production to be ready... ($i/10)"
            sleep 10
          done
          echo "Production health check failed"
          exit 1

  smoke-test-production:
    name: Smoke Test Production
    needs: [deploy-production]
    runs-on: ubuntu-latest
    environment: production

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

      - name: Run smoke tests
        env:
          PRODUCTION_URL: ${{ secrets.PRODUCTION_URL }}
        run: |
          chmod +x scripts/smoke-test.sh
          ./scripts/smoke-test.sh "$PRODUCTION_URL"

      - name: Notify on success
        if: success()
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: |
          curl -s -X POST "$SLACK_WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{
              \"text\": \":white_check_mark: *Production deploy successful* for \`${{ github.sha }}\`\",
              \"blocks\": [{
                \"type\": \"section\",
                \"text\": {
                  \"type\": \"mrkdwn\",
                  \"text\": \":white_check_mark: *Production Deploy Successful*\n*Commit:* \`${{ github.sha }}\`\n*Branch:* \`${{ github.ref_name }}\`\n*All smoke tests passed.*\"
                }
              }]
            }"

  rollback-production:
    name: Rollback Production
    needs: [smoke-test-production]
    if: failure()
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Rollback to previous images
        env:
          DEPLOY_HOST: ${{ secrets.PRODUCTION_HOST }}
          DEPLOY_USER: ${{ secrets.PRODUCTION_USER }}
          DEPLOY_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null

          ssh -i ~/.ssh/deploy_key "$DEPLOY_USER@$DEPLOY_HOST" << 'ROLLBACK_SCRIPT'
            cd ~/goodgo

            echo "Rolling back to previous container images..."

            # Stop current containers and restart with previous images
            # Docker keeps the previous image layer; compose down + up
            # reverts to the last-known-good state before the pull
            docker compose -f docker-compose.prod.yml down api web ai-services
            docker compose -f docker-compose.prod.yml up -d --wait api web ai-services

            echo "Rollback complete. Verifying health..."
            sleep 5
            curl -sf http://localhost:3001/health || echo "WARNING: health check failed after rollback"
          ROLLBACK_SCRIPT

      - name: Notify rollback
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: |
          curl -s -X POST "$SLACK_WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{
              \"text\": \":warning: *Production ROLLBACK triggered* for \`${{ github.sha }}\`\",
              \"blocks\": [{
                \"type\": \"section\",
                \"text\": {
                  \"type\": \"mrkdwn\",
                  \"text\": \":warning: *Production Rollback Triggered*\n*Commit:* \`${{ github.sha }}\`\n*Reason:* Smoke tests failed after deploy\n*Action:* Reverted to previous container images\n*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"
                }
              }]
            }"
