name: Deploy to Production

on:
  push:
    branches:
      - production-deployment
  workflow_dispatch:

jobs:
  deploy:
    name: Build and Deploy
    runs-on: ubuntu-24.04
    steps:
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan -H 192.168.1.151 >> ~/.ssh/known_hosts

      - name: Deploy via SSH
        run: |
          ssh root@192.168.1.151 << 'ENDSSH'
            set -e
            cd /opt/wordly

            # ──────────────────────────────────────────────
            # 1. GIT PULL
            # ──────────────────────────────────────────────
            echo "=== [1/8] Git pull ==="
            git config --global --add safe.directory /opt/wordly
            git fetch origin production-deployment
            git reset --hard origin/production-deployment

            # ──────────────────────────────────────────────
            # 2. DATABASE BACKUP (before anything else)
            # ──────────────────────────────────────────────
            echo "=== [2/8] Database backup ==="
            BACKUP_DIR="/opt/backups/postgres"
            BACKUP_FILE="${BACKUP_DIR}/translate_db_$(date +%Y%m%d_%H%M%S).sql.gz"
            mkdir -p "$BACKUP_DIR"

            docker compose exec -T postgres pg_dumpall -U translate </dev/null | gzip > "$BACKUP_FILE"
            BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
            echo "  Backup saved: ${BACKUP_FILE} (${BACKUP_SIZE})"

            # Keep only last 10 backups
            ls -t "${BACKUP_DIR}"/translate_db_*.sql.gz | tail -n +11 | xargs -r rm --
            echo "  Retained last 10 backups"

            # ──────────────────────────────────────────────
            # 3. BUILD IMAGES (--no-cache for fresh deps)
            # ──────────────────────────────────────────────
            echo "=== [3/8] Building images ==="
            docker compose build --no-cache backend frontend

            # ──────────────────────────────────────────────
            # 4. START INFRASTRUCTURE ONLY (postgres + redis)
            # ──────────────────────────────────────────────
            echo "=== [4/8] Starting postgres and redis ==="
            docker compose up -d postgres redis

            # ──────────────────────────────────────────────
            # 5. WAIT FOR POSTGRES
            # ──────────────────────────────────────────────
            echo "=== [5/8] Waiting for postgres ==="
            for i in $(seq 1 30); do
              if docker compose exec -T postgres pg_isready -U translate </dev/null >/dev/null 2>&1; then
                echo "  Postgres ready after $((i * 2))s"
                break
              fi
              if [ "$i" -eq 30 ]; then
                echo "  FATAL: Postgres not ready after 60s"
                docker compose logs postgres --tail=30
                exit 1
              fi
              sleep 2
            done

            # ──────────────────────────────────────────────
            # 6. RUN MIGRATIONS (BEFORE starting backend)
            #    entrypoint passes through args via exec "$@"
            # ──────────────────────────────────────────────
            echo "=== [6/8] Running database migrations ==="
            if ! docker compose run -T --rm backend alembic upgrade head </dev/null; then
              echo "  FATAL: Migration FAILED!"
              echo "  Restoring database from backup..."
              gunzip -c "$BACKUP_FILE" | docker compose exec -T postgres psql -U translate -d translate_db >/dev/null 2>&1 || true
              echo "  Database restored."
              echo "  Deploy ABORTED."
              exit 1
            fi
            echo "  Migrations applied successfully"

            # ──────────────────────────────────────────────
            # 7. START ALL SERVICES (backend + frontend)
            #    backend entrypoint will see alembic is already at head → no-op
            # ──────────────────────────────────────────────
            echo "=== [7/8] Starting all services ==="
            docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d --remove-orphans

            # Wait for backend healthy
            echo "  Waiting for backend healthy..."
            for i in $(seq 1 20); do
              if curl -sf http://localhost:8001/health >/dev/null 2>&1; then
                echo "  Backend healthy after $((i * 5))s"
                break
              fi
              if [ "$i" -eq 20 ]; then
                echo "  FATAL: Backend not healthy after 100s"
                echo "  Rolling back database..."
                gunzip -c "$BACKUP_FILE" | docker compose exec -T postgres psql -U translate -d translate_db </dev/null >/dev/null 2>&1 || true
                docker compose restart backend
                echo "  Deploy FAILED. Database restored."
                docker compose logs backend --tail=50
                exit 1
              fi
              sleep 5
            done

            # ──────────────────────────────────────────────
            # 8. SUMMARY
            # ──────────────────────────────────────────────
            echo "=== [8/8] Deploy summary ==="
            docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
            echo ""
            echo "Health: $(curl -sf http://localhost:8001/health 2>/dev/null || echo 'FAILED')"
            echo "Backup: ${BACKUP_FILE} (${BACKUP_SIZE})"
          ENDSSH

      - name: Wait for frontend
        run: |
          echo "Waiting for frontend..."
          for i in $(seq 1 20); do
            CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://192.168.1.151:3000/ || echo "000")
            if [ "$CODE" != "000" ] && [ "$CODE" -lt 500 ]; then
              echo "Frontend OK (HTTP $CODE) after $((i * 5))s"
              exit 0
            fi
            echo "  [$((i * 5))s] HTTP $CODE"
            sleep 5
          done
          echo "Timeout!"
          exit 1

      - name: Cleanup
        if: always()
        run: ssh root@192.168.1.151 "docker image prune -f" || true
