name: Deploy Backend to Cloud Run

on:
  push:
    branches: [main]
    paths:
      - 'backend/**'
      - '.github/workflows/deploy-backend.yml'
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy to'
        type: choice
        required: true
        default: 'production'
        options:
          - production
          - staging

env:
  PROJECT_ID: mana-core-453821
  REGION: europe-west3
  ARTIFACT_REGISTRY: europe-west3-docker.pkg.dev
  SERVICE_NAME: manadeck-backend
  REPOSITORY_NAME: manadeck-backend
  WORKING_DIR: backend

jobs:
  test:
    name: Test & Build Verification
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: read
    defaults:
      run:
        working-directory: ${{ env.WORKING_DIR }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Configure git for private packages
        env:
          GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
        run: |
          git config --global url."https://${GH_TOKEN}@github.com/".insteadOf ssh://git@github.com/
          git config --global url."https://${GH_TOKEN}@github.com/".insteadOf git@github.com:

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
          cache-dependency-path: ${{ env.WORKING_DIR }}/package-lock.json

      - name: Patch package-lock.json with authenticated URLs
        env:
          GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
        working-directory: ${{ env.WORKING_DIR }}
        run: |
          # Handle both SSH and HTTPS URLs
          if grep -q "git+ssh://git@github.com" package-lock.json; then
            echo "⚠️  SSH URLs found - patching to HTTPS with token..."
            sed -i "s|git+ssh://git@github.com/Memo-2023/|git+https://${GH_TOKEN}@github.com/Memo-2023/|g" package-lock.json
            echo "✓ Lockfile patched successfully"
          else
            echo "⚠️  HTTPS URLs found - injecting token..."
            sed -i "s|git+https://github.com/Memo-2023/|git+https://${GH_TOKEN}@github.com/Memo-2023/|g" package-lock.json
            echo "✓ Token injected successfully"
          fi

      - name: Install dependencies
        working-directory: ${{ env.WORKING_DIR }}
        run: npm ci --legacy-peer-deps

      - name: Type check & build
        working-directory: ${{ env.WORKING_DIR }}
        run: npm run build

      - name: Run tests
        working-directory: ${{ env.WORKING_DIR }}
        run: npm test
        continue-on-error: true

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: ${{ env.WORKING_DIR }}/dist
          retention-days: 1

  build-and-deploy:
    name: Build & Deploy to Cloud Run
    needs: test
    runs-on: ubuntu-latest

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

      - name: Google Cloud Auth
        uses: google-github-actions/auth@v2
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY_PROD }}

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2
        with:
          version: 'latest'

      - name: Configure Docker for Artifact Registry
        run: |
          gcloud auth configure-docker ${{ env.ARTIFACT_REGISTRY }}

      - name: Generate version tag
        id: version
        run: |
          SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
          TIMESTAMP=$(date +%Y%m%d-%H%M%S)
          VERSION="v${TIMESTAMP}-${SHORT_SHA}"
          echo "version=${VERSION}" >> $GITHUB_OUTPUT
          echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT

      - name: Build and Push Docker Image
        env:
          DOCKER_BUILDKIT: 1
          GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
        working-directory: ${{ env.WORKING_DIR }}
        run: |
          IMAGE_NAME="${{ env.ARTIFACT_REGISTRY }}/${{ env.PROJECT_ID }}/${{ env.REPOSITORY_NAME }}/${{ env.SERVICE_NAME }}"
          IMAGE_TAG="${IMAGE_NAME}:${{ steps.version.outputs.version }}"
          LATEST_TAG="${IMAGE_NAME}:latest"
          SHA_TAG="${IMAGE_NAME}:${{ steps.version.outputs.short_sha }}"

          echo "Building image: ${IMAGE_TAG}"

          docker build \
            -t ${IMAGE_TAG} \
            -t ${LATEST_TAG} \
            -t ${SHA_TAG} \
            --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
            --build-arg VCS_REF=${{ github.sha }} \
            --build-arg VERSION=${{ steps.version.outputs.version }} \
            --secret id=github_token,env=GH_TOKEN \
            .

          echo "Pushing images..."
          docker push ${IMAGE_TAG}
          docker push ${LATEST_TAG}
          docker push ${SHA_TAG}

          echo "image_tag=${IMAGE_TAG}" >> $GITHUB_ENV
          echo "version=${{ steps.version.outputs.version }}" >> $GITHUB_ENV

      - name: Deploy to Cloud Run
        id: deploy
        run: |
          echo "Deploying to Cloud Run..."
          echo "Service account: ${{ secrets.CLOUD_RUN_SERVICE_ACCOUNT }}"
          gcloud run deploy ${{ env.SERVICE_NAME }} \
            --image="${{ env.image_tag }}" \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }} \
            --platform=managed \
            --allow-unauthenticated \
            --min-instances=0 \
            --max-instances=10 \
            --memory=512Mi \
            --cpu=1 \
            --timeout=300 \
            --concurrency=80 \
            --port=8080 \
            --service-account=${{ secrets.CLOUD_RUN_SERVICE_ACCOUNT }} \
            --set-env-vars="NODE_ENV=production" \
            --set-secrets="MANA_SERVICE_URL=MANA_SERVICE_URL:latest,APP_ID=MANADECK_APP_ID:latest,MANA_SUPABASE_SECRET_KEY=MANA_SUPABASE_SECRET_KEY:latest,SUPABASE_URL=MANADECK_SUPABASE_URL:latest,SUPABASE_ANON_KEY=MANADECK_SUPABASE_ANON_KEY:latest,SUPABASE_SERVICE_KEY=MANADECK_SUPABASE_SERVICE_KEY:latest" \
            --labels="environment=production,commit=${{ steps.version.outputs.short_sha }},version=${{ env.version }}"

          # Ensure 100% traffic goes to the new revision
          echo "Routing traffic to latest revision..."
          gcloud run services update-traffic ${{ env.SERVICE_NAME }} \
            --to-latest \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }} \
            --platform=managed

          echo "✅ Traffic routed to latest revision"

      - name: Get Service URL
        id: service-url
        run: |
          SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }} \
            --format='value(status.url)')

          echo "service_url=${SERVICE_URL}" >> $GITHUB_OUTPUT

          echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "- **Service**: \`${{ env.SERVICE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
          echo "- **URL**: ${SERVICE_URL}" >> $GITHUB_STEP_SUMMARY
          echo "- **Version**: \`${{ env.version }}\`" >> $GITHUB_STEP_SUMMARY
          echo "- **Image**: \`${{ env.image_tag }}\`" >> $GITHUB_STEP_SUMMARY
          echo "- **Region**: \`${{ env.REGION }}\`" >> $GITHUB_STEP_SUMMARY
          echo "- **Commit**: \`${{ steps.version.outputs.short_sha }}\`" >> $GITHUB_STEP_SUMMARY

      - name: Wait for deployment
        run: sleep 15

      - name: Health Check
        id: health-check
        run: |
          SERVICE_URL="${{ steps.service-url.outputs.service_url }}"

          echo "Testing health endpoint: ${SERVICE_URL}/health/live"

          MAX_RETRIES=5
          RETRY_COUNT=0
          SUCCESS=false

          while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
            HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${SERVICE_URL}/health/live || echo "000")

            if [ "$HTTP_CODE" = "200" ]; then
              echo "✅ Health check passed (HTTP $HTTP_CODE)"
              SUCCESS=true
              break
            else
              echo "⚠️  Health check attempt $((RETRY_COUNT + 1))/$MAX_RETRIES failed (HTTP $HTTP_CODE)"
              RETRY_COUNT=$((RETRY_COUNT + 1))
              if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
                echo "Retrying in 10 seconds..."
                sleep 10
              fi
            fi
          done

          if [ "$SUCCESS" = false ]; then
            echo "❌ Health check failed after $MAX_RETRIES attempts"
            exit 1
          fi

      - name: Liveness Check
        run: |
          SERVICE_URL="${{ steps.service-url.outputs.service_url }}"

          echo "Testing liveness endpoint: ${SERVICE_URL}/health/live"
          RESPONSE=$(curl -s ${SERVICE_URL}/health/live)
          echo "Response: $RESPONSE"

          STATUS=$(echo $RESPONSE | jq -r '.status')
          if [ "$STATUS" = "ok" ]; then
            echo "✅ Liveness check passed"
          else
            echo "❌ Liveness check failed"
            exit 1
          fi

      - name: Deployment Notification
        if: success()
        run: |
          echo "## ✅ Deployment Successful" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Service is healthy and ready to receive traffic." >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "### Quick Links" >> $GITHUB_STEP_SUMMARY
          echo "- [Service URL](${{ steps.service-url.outputs.service_url }})" >> $GITHUB_STEP_SUMMARY
          echo "- [Health Check](${{ steps.service-url.outputs.service_url }}/health)" >> $GITHUB_STEP_SUMMARY
          echo "- [Cloud Run Console](https://console.cloud.google.com/run/detail/${{ env.REGION }}/${{ env.SERVICE_NAME }}/metrics?project=${{ env.PROJECT_ID }})" >> $GITHUB_STEP_SUMMARY

  rollback:
    name: Rollback on Failure
    runs-on: ubuntu-latest
    if: failure() && needs.build-and-deploy.result == 'failure'
    needs: build-and-deploy

    steps:
      - name: Google Cloud Auth
        uses: google-github-actions/auth@v2
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY_PROD }}

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2
        with:
          version: 'latest'

      - name: Get Previous Revision
        id: get-revision
        run: |
          REVISIONS=$(gcloud run revisions list \
            --service=${{ env.SERVICE_NAME }} \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }} \
            --format="value(name)" \
            --limit=2)

          PREV_REVISION=$(echo "$REVISIONS" | tail -n 1)

          if [ -z "$PREV_REVISION" ]; then
            echo "❌ No previous revision found for rollback"
            exit 1
          fi

          echo "prev_revision=${PREV_REVISION}" >> $GITHUB_OUTPUT
          echo "Found previous revision: ${PREV_REVISION}"

      - name: Rollback to Previous Revision
        run: |
          echo "Rolling back to revision: ${{ steps.get-revision.outputs.prev_revision }}"

          gcloud run services update-traffic ${{ env.SERVICE_NAME }} \
            --to-revisions=${{ steps.get-revision.outputs.prev_revision }}=100 \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }}

          echo "## ⚠️ Deployment Failed - Rollback Executed" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Service has been rolled back to revision: \`${{ steps.get-revision.outputs.prev_revision }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Please check the logs and fix the issues before redeploying." >> $GITHUB_STEP_SUMMARY

      - name: Verify Rollback
        run: |
          sleep 10

          SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} \
            --project=${{ env.PROJECT_ID }} \
            --region=${{ env.REGION }} \
            --format='value(status.url)')

          HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${SERVICE_URL}/health/live)

          if [ $HTTP_CODE -eq 200 ]; then
            echo "✅ Rollback successful - service is healthy"
          else
            echo "❌ Rollback verification failed - service may be unhealthy"
            exit 1
          fi
