name: Deploy to Production

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        required: true
        default: 'production'
        type: choice
        options:
          - production
          - staging
      skip_tests:
        description: 'Skip E2E tests (emergency deploy only)'
        required: false
        default: false
        type: boolean

# Prevent concurrent deployments
concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: false  # Never cancel a deployment in progress

env:
  NODE_VERSION: '20'
  PORT: 10000

jobs:
  # ============================================================
  # Job 1: Build & Verify
  # ============================================================
  build:
    name: Build & Verify
    runs-on: ubuntu-latest
    timeout-minutes: 15

    outputs:
      build-artifact: ${{ steps.artifact-name.outputs.name }}

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

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci --prefer-offline

      - name: Type check
        run: npx tsc --noEmit
        continue-on-error: true  # Warn but don't block on type errors

      - name: Build production bundle
        run: npm run build
        env:
          NODE_ENV: production

      - name: Verify build output
        run: |
          echo "Verifying build output..."
          test -d dist/ || (echo "ERROR: dist/ directory not found" && exit 1)
          test -f dist/server/entry.mjs || (echo "ERROR: Server entry point missing" && exit 1)
          test -d dist/client/ || (echo "ERROR: Client assets missing" && exit 1)
          echo "Build verification passed"
          echo "Build size:"
          du -sh dist/

      - name: Generate artifact name
        id: artifact-name
        run: echo "name=build-${{ github.sha }}" >> $GITHUB_OUTPUT

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ steps.artifact-name.outputs.name }}
          path: |
            dist/
            package.json
            package-lock.json
            server.mjs
            ecosystem.config.cjs
            .env.example
          retention-days: 3

  # ============================================================
  # Job 2: Smoke Tests (Pre-Deploy Gate)
  # ============================================================
  pre-deploy-tests:
    name: Pre-Deploy Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: build
    if: inputs.skip_tests != true

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

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci --prefer-offline

      - name: Install Playwright (Chromium only for speed)
        run: npx playwright install chromium --with-deps

      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ needs.build.outputs.build-artifact }}
          path: .

      - name: Start server
        run: npm run start &
        env:
          NODE_ENV: production
          PORT: ${{ env.PORT }}

      - name: Wait for server
        run: npx wait-on http://localhost:${{ env.PORT }}/api/health.json --timeout 60000

      - name: Run smoke tests
        run: npx playwright test tests/e2e-smoke-suite.spec.ts --project=chromium --reporter=list
        env:
          BASE_URL: http://localhost:${{ env.PORT }}

      - name: Run critical API tests
        run: npx playwright test tests/api-integration.spec.ts --project=chromium --reporter=list
        env:
          BASE_URL: http://localhost:${{ env.PORT }}

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: pre-deploy-test-failures-${{ github.run_number }}
          path: |
            playwright-report/
            test-results/
          retention-days: 7

  # ============================================================
  # Job 3a: Deploy to Railway
  # Activate by setting DEPLOY_TARGET=railway secret
  # ============================================================
  deploy-railway:
    name: Deploy to Railway
    runs-on: ubuntu-latest
    timeout-minutes: 10
    needs: [build, pre-deploy-tests]
    if: |
      always() &&
      needs.build.result == 'success' &&
      (needs.pre-deploy-tests.result == 'success' || needs.pre-deploy-tests.result == 'skipped') &&
      vars.DEPLOY_TARGET == 'railway'
    environment:
      name: ${{ inputs.environment || 'production' }}
      url: https://workroot.in

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

      - name: Install Railway CLI
        run: npm install -g @railway/cli

      - name: Deploy to Railway
        run: railway up --service workroot-website
        env:
          RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}

      - name: Verify Railway deployment
        run: |
          echo "Waiting for Railway deployment to propagate..."
          sleep 30
          curl --fail --silent --max-time 30 https://workroot.in/api/health.json \
            || (echo "Health check failed after Railway deploy" && exit 1)
          echo "Railway deployment verified"

  # ============================================================
  # Job 3b: Deploy to Render
  # Activate by setting DEPLOY_TARGET=render secret
  # ============================================================
  deploy-render:
    name: Deploy to Render
    runs-on: ubuntu-latest
    timeout-minutes: 10
    needs: [build, pre-deploy-tests]
    if: |
      always() &&
      needs.build.result == 'success' &&
      (needs.pre-deploy-tests.result == 'success' || needs.pre-deploy-tests.result == 'skipped') &&
      vars.DEPLOY_TARGET == 'render'
    environment:
      name: ${{ inputs.environment || 'production' }}
      url: https://workroot.in

    steps:
      - name: Trigger Render deploy hook
        run: |
          curl --fail --silent --show-error \
            -X POST "${{ secrets.RENDER_DEPLOY_HOOK_URL }}" \
            || (echo "Failed to trigger Render deploy hook" && exit 1)
          echo "Render deployment triggered"

      - name: Wait for Render deployment
        run: |
          echo "Waiting for Render to deploy (up to 5 minutes)..."
          for i in $(seq 1 30); do
            sleep 10
            STATUS=$(curl --silent --max-time 10 https://workroot.in/api/health.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('status',''))" 2>/dev/null || echo "error")
            if [ "$STATUS" = "ok" ]; then
              echo "Render deployment verified after ${i}0 seconds"
              exit 0
            fi
            echo "Attempt $i/30: status=$STATUS, retrying..."
          done
          echo "ERROR: Render deployment health check timed out"
          exit 1

  # ============================================================
  # Job 3c: Deploy to VPS (SSH + PM2)
  # Activate by setting DEPLOY_TARGET=vps secret
  # ============================================================
  deploy-vps:
    name: Deploy to VPS (PM2)
    runs-on: ubuntu-latest
    timeout-minutes: 20
    needs: [build, pre-deploy-tests]
    if: |
      always() &&
      needs.build.result == 'success' &&
      (needs.pre-deploy-tests.result == 'success' || needs.pre-deploy-tests.result == 'skipped') &&
      vars.DEPLOY_TARGET == 'vps'
    environment:
      name: ${{ inputs.environment || 'production' }}
      url: https://workroot.in

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

      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: ${{ needs.build.outputs.build-artifact }}
          path: build-output/

      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.VPS_SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          echo "${{ secrets.VPS_HOST_KEY }}" >> ~/.ssh/known_hosts

      - name: Create deployment package
        run: |
          tar -czf deploy-package.tar.gz -C build-output .
          echo "Deployment package created: $(du -sh deploy-package.tar.gz | cut -f1)"

      - name: Upload package to VPS
        run: |
          scp -i ~/.ssh/deploy_key \
            -o StrictHostKeyChecking=yes \
            deploy-package.tar.gz \
            ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}:/tmp/workroot-deploy-${{ github.sha }}.tar.gz

      - name: Deploy on VPS
        run: |
          ssh -i ~/.ssh/deploy_key \
            -o StrictHostKeyChecking=yes \
            ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} \
            'bash -s' << 'DEPLOY_SCRIPT'
            set -e

            DEPLOY_DIR="/var/www/workroot"
            BACKUP_DIR="/var/www/workroot-backup-$(date +%Y%m%d-%H%M%S)"
            DEPLOY_PKG="/tmp/workroot-deploy-${{ github.sha }}.tar.gz"

            echo "=== Starting deployment ==="
            echo "Deploy time: $(date)"
            echo "Commit: ${{ github.sha }}"

            # Step 1: Backup current deployment
            if [ -d "$DEPLOY_DIR" ]; then
              echo "Backing up current deployment to $BACKUP_DIR..."
              cp -r "$DEPLOY_DIR" "$BACKUP_DIR"
            fi

            # Step 2: Extract new deployment
            echo "Extracting deployment package..."
            mkdir -p "$DEPLOY_DIR"
            tar -xzf "$DEPLOY_PKG" -C "$DEPLOY_DIR"

            # Step 3: Install production dependencies
            echo "Installing production dependencies..."
            cd "$DEPLOY_DIR"
            npm ci --omit=dev --prefer-offline

            # Step 4: Ensure logs directory exists
            mkdir -p logs

            # Step 5: Reload PM2 (zero-downtime restart)
            echo "Reloading PM2..."
            if pm2 list | grep -q "workroot-website"; then
              pm2 reload ecosystem.config.cjs --update-env
            else
              pm2 start ecosystem.config.cjs --env production
              pm2 save
            fi

            # Step 6: Health check
            echo "Running health check..."
            sleep 5
            for i in $(seq 1 12); do
              STATUS=$(curl --silent --max-time 5 http://localhost:10000/api/health.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('status',''))" 2>/dev/null || echo "error")
              if [ "$STATUS" = "ok" ]; then
                echo "Health check passed after ${i}0 seconds"
                break
              fi
              if [ $i -eq 12 ]; then
                echo "ERROR: Health check failed after 2 minutes"
                echo "=== Rolling back ==="
                cp -r "$BACKUP_DIR/." "$DEPLOY_DIR/"
                cd "$DEPLOY_DIR"
                npm ci --omit=dev --prefer-offline
                pm2 reload ecosystem.config.cjs --update-env
                exit 1
              fi
              echo "Attempt $i/12: status=$STATUS, retrying..."
              sleep 10
            done

            # Step 7: Cleanup
            rm -f "$DEPLOY_PKG"
            rm -rf "$BACKUP_DIR"

            echo "=== Deployment complete ==="
            pm2 status
          DEPLOY_SCRIPT

  # ============================================================
  # Job 3d: Deploy to Fly.io
  # Activate by setting DEPLOY_TARGET=fly secret
  # ============================================================
  deploy-fly:
    name: Deploy to Fly.io
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: [build, pre-deploy-tests]
    if: |
      always() &&
      needs.build.result == 'success' &&
      (needs.pre-deploy-tests.result == 'success' || needs.pre-deploy-tests.result == 'skipped') &&
      vars.DEPLOY_TARGET == 'fly'
    environment:
      name: ${{ inputs.environment || 'production' }}
      url: https://workroot.in

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

      - name: Setup Fly CLI
        uses: superfly/flyctl-actions/setup-flyctl@master

      - name: Deploy to Fly.io
        run: flyctl deploy --remote-only --wait-timeout 300
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

      - name: Verify Fly.io deployment
        run: |
          sleep 15
          flyctl status
          curl --fail --silent --max-time 30 https://workroot.in/api/health.json \
            || (echo "Health check failed after Fly.io deploy" && exit 1)
          echo "Fly.io deployment verified"
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

  # ============================================================
  # Job 4: Post-Deploy Verification
  # ============================================================
  post-deploy-verify:
    name: Post-Deploy Verification
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: [deploy-railway, deploy-render, deploy-vps, deploy-fly]
    if: |
      always() &&
      (
        needs.deploy-railway.result == 'success' ||
        needs.deploy-render.result == 'success' ||
        needs.deploy-vps.result == 'success' ||
        needs.deploy-fly.result == 'success'
      )

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

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci --prefer-offline

      - name: Install Playwright
        run: npx playwright install chromium --with-deps

      - name: Run production smoke tests
        run: |
          npx playwright test tests/e2e-smoke-suite.spec.ts \
            --project=chromium \
            --reporter=list
        env:
          BASE_URL: https://workroot.in

      - name: Verify critical endpoints
        run: |
          echo "Checking production endpoints..."

          # Health check
          HEALTH=$(curl --silent --max-time 10 https://workroot.in/api/health.json)
          echo "Health: $HEALTH"

          # Homepage
          HTTP_STATUS=$(curl --silent --max-time 10 -o /dev/null -w "%{http_code}" https://workroot.in/)
          echo "Homepage: HTTP $HTTP_STATUS"
          [ "$HTTP_STATUS" = "200" ] || (echo "Homepage returned $HTTP_STATUS" && exit 1)

          # Contact page
          HTTP_STATUS=$(curl --silent --max-time 10 -o /dev/null -w "%{http_code}" https://workroot.in/contact)
          echo "Contact page: HTTP $HTTP_STATUS"
          [ "$HTTP_STATUS" = "200" ] || (echo "Contact page returned $HTTP_STATUS" && exit 1)

          # Sitemap
          HTTP_STATUS=$(curl --silent --max-time 10 -o /dev/null -w "%{http_code}" https://workroot.in/sitemap.xml)
          echo "Sitemap: HTTP $HTTP_STATUS"
          [ "$HTTP_STATUS" = "200" ] || (echo "Sitemap returned $HTTP_STATUS" && exit 1)

          echo "All critical endpoints verified"

      - name: Upload post-deploy results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: post-deploy-results-${{ github.run_number }}
          path: |
            playwright-report/
            test-results/
          retention-days: 14

  # ============================================================
  # Job 5: Notify on Failure
  # ============================================================
  notify-failure:
    name: Notify on Failure
    runs-on: ubuntu-latest
    needs: [build, pre-deploy-tests, post-deploy-verify]
    if: |
      always() &&
      (
        needs.build.result == 'failure' ||
        needs.pre-deploy-tests.result == 'failure' ||
        needs.post-deploy-verify.result == 'failure'
      )

    steps:
      - name: Create failure summary
        run: |
          echo "## Deployment Failed" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| Stage | Status |" >> $GITHUB_STEP_SUMMARY
          echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
          echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Pre-Deploy Tests | ${{ needs.pre-deploy-tests.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Post-Deploy Verify | ${{ needs.post-deploy-verify.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
          echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
          echo "**Author:** ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "Check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details." >> $GITHUB_STEP_SUMMARY

      # Uncomment and configure one notification method:

      # Slack notification
      # - name: Notify Slack
      #   uses: slackapi/slack-github-action@v1.27.0
      #   with:
      #     payload: |
      #       {
      #         "text": "Deployment failed on ${{ github.ref_name }} by ${{ github.actor }}",
      #         "attachments": [{
      #           "color": "danger",
      #           "text": "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
      #         }]
      #       }
      #   env:
      #     SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      #     SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
