name: Deploy to route.crispygoat.com

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Install dependencies
        run: npm install

      - name: Run migrations
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: |
          set -e
          node scripts/preflight-check.js
          npm run migrate:one
          node scripts/postflight-check.js

      - name: Build
        env:
          NODE_ENV: production
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }}
          NEON_AUTH_BASE_URL: ${{ secrets.NEON_AUTH_BASE_URL }}
          NEON_AUTH_COOKIE_SECRET: ${{ secrets.NEON_AUTH_COOKIE_SECRET }}
          AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
          AUTH_URL: ${{ secrets.AUTH_URL }}
          NEXT_PUBLIC_AUTH_URL: ${{ secrets.NEXT_PUBLIC_AUTH_URL }}
          GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
          GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
          ALLOW_DEV_LOGIN: ${{ secrets.ALLOW_DEV_LOGIN }}
          ADMIN_ALLOWED_EMAILS: ${{ secrets.ADMIN_ALLOWED_EMAILS }}
          NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
          STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
          STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
          STRIPE_PRICE_STARTER: ${{ secrets.STRIPE_PRICE_STARTER }}
          STRIPE_PRICE_FARM: ${{ secrets.STRIPE_PRICE_FARM }}
          STRIPE_PRICE_ENTERPRISE: ${{ secrets.STRIPE_PRICE_ENTERPRISE }}
          STRIPE_PRICE_HARVEST_REACH: ${{ secrets.STRIPE_PRICE_HARVEST_REACH }}
          STRIPE_PRICE_WHOLESALE_PORTAL: ${{ secrets.STRIPE_PRICE_WHOLESALE_PORTAL }}
          STRIPE_PRICE_WATER_LOG: ${{ secrets.STRIPE_PRICE_WATER_LOG }}
          STRIPE_PRICE_AI_TOOLS: ${{ secrets.STRIPE_PRICE_AI_TOOLS }}
          STRIPE_PRICE_SQUARE_SYNC: ${{ secrets.STRIPE_PRICE_SQUARE_SYNC }}
          STRIPE_PRICE_SMS_CAMPAIGNS: ${{ secrets.STRIPE_PRICE_SMS_CAMPAIGNS }}
          RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
          FROM_EMAIL: ${{ secrets.FROM_EMAIL }}
          MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
          MINIO_REGION: ${{ secrets.MINIO_REGION }}
          MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }}
          MINIO_SECRET_KEY: ${{ secrets.MINIO_SECRET_KEY }}
          MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
          MINIO_BUCKET_PRODUCTS: ${{ secrets.MINIO_BUCKET_PRODUCTS }}
          MINIO_BUCKET_BRAND_LOGOS: ${{ secrets.MINIO_BUCKET_BRAND_LOGOS }}
          MINIO_BUCKET_WATER_LOGS: ${{ secrets.MINIO_BUCKET_WATER_LOGS }}
          MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
          MINIMAX_BASE_URL: ${{ secrets.MINIMAX_BASE_URL }}
        run: npm run build

      - name: Deploy
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }}
          NEON_AUTH_BASE_URL: ${{ secrets.NEON_AUTH_BASE_URL }}
          NEON_AUTH_COOKIE_SECRET: ${{ secrets.NEON_AUTH_COOKIE_SECRET }}
          AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
          AUTH_URL: ${{ secrets.AUTH_URL }}
          NEXT_PUBLIC_AUTH_URL: ${{ secrets.NEXT_PUBLIC_AUTH_URL }}
          GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
          GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
          ALLOW_DEV_LOGIN: ${{ secrets.ALLOW_DEV_LOGIN }}
          ADMIN_ALLOWED_EMAILS: ${{ secrets.ADMIN_ALLOWED_EMAILS }}
          NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
          STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
          STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
          STRIPE_PRICE_STARTER: ${{ secrets.STRIPE_PRICE_STARTER }}
          STRIPE_PRICE_FARM: ${{ secrets.STRIPE_PRICE_FARM }}
          STRIPE_PRICE_ENTERPRISE: ${{ secrets.STRIPE_PRICE_ENTERPRISE }}
          STRIPE_PRICE_HARVEST_REACH: ${{ secrets.STRIPE_PRICE_HARVEST_REACH }}
          STRIPE_PRICE_WHOLESALE_PORTAL: ${{ secrets.STRIPE_PRICE_WHOLESALE_PORTAL }}
          STRIPE_PRICE_WATER_LOG: ${{ secrets.STRIPE_PRICE_WATER_LOG }}
          STRIPE_PRICE_AI_TOOLS: ${{ secrets.STRIPE_PRICE_AI_TOOLS }}
          STRIPE_PRICE_SQUARE_SYNC: ${{ secrets.STRIPE_PRICE_SQUARE_SYNC }}
          STRIPE_PRICE_SMS_CAMPAIGNS: ${{ secrets.STRIPE_PRICE_SMS_CAMPAIGNS }}
          RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
          FROM_EMAIL: ${{ secrets.FROM_EMAIL }}
          MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
          MINIO_REGION: ${{ secrets.MINIO_REGION }}
          MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }}
          MINIO_SECRET_KEY: ${{ secrets.MINIO_SECRET_KEY }}
          MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
          MINIO_BUCKET_PRODUCTS: ${{ secrets.MINIO_BUCKET_PRODUCTS }}
          MINIO_BUCKET_BRAND_LOGOS: ${{ secrets.MINIO_BUCKET_BRAND_LOGOS }}
          MINIO_BUCKET_WATER_LOGS: ${{ secrets.MINIO_BUCKET_WATER_LOGS }}
          MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
          MINIMAX_BASE_URL: ${{ secrets.MINIMAX_BASE_URL }}
          CRON_SECRET: ${{ secrets.CRON_SECRET }}
          SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }}
        run: |
          set -e
          APP_DIR=/home/tyler/route-commerce

          # Setup SSH key - write raw (no printf which can corrupt multi-line keys)
          mkdir -p ~/.ssh
          echo "$SERVER_SSH_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519

          # Verify key was written correctly
          if ! grep -q "PRIVATE KEY" ~/.ssh/id_ed25519; then
            echo "ERROR: SSH key not found or malformed. Check SERVER_SSH_KEY secret."
            cat ~/.ssh/id_ed25519 || echo "File is empty"
            exit 1
          fi

          ssh-keyscan -H route.crispygoat.com >> ~/.ssh/known_hosts 2>/dev/null || true

          # Test SSH connection with verbose output for debugging
          echo "Testing SSH connection..."
          ssh -o ConnectTimeout=15 -o StrictHostKeyChecking=no -o LogLevel=VERBOSE tyler@route.crispygoat.com "echo 'SSH OK' && hostname" 2>&1 || { echo "SSH FAILED"; exit 1; }

          # Create app dir on server
          ssh tyler@route.crispygoat.com "mkdir -p $APP_DIR/.next $APP_DIR/public"

          # Write production env file
          ENV_FILE=$(mktemp)
          {
            printf 'DATABASE_URL=%s\n' "$DATABASE_URL"
            printf 'NEXT_PUBLIC_SITE_URL=%s\n' "$NEXT_PUBLIC_SITE_URL"
            printf 'NEON_AUTH_BASE_URL=%s\n' "$NEON_AUTH_BASE_URL"
            printf 'NEON_AUTH_COOKIE_SECRET=%s\n' "$NEON_AUTH_COOKIE_SECRET"
            printf 'AUTH_SECRET=%s\n' "$AUTH_SECRET"
            printf 'AUTH_URL=%s\n' "$AUTH_URL"
            printf 'NEXT_PUBLIC_AUTH_URL=%s\n' "$NEXT_PUBLIC_AUTH_URL"
            printf 'GOOGLE_CLIENT_ID=%s\n' "$GOOGLE_CLIENT_ID"
            printf 'GOOGLE_CLIENT_SECRET=%s\n' "$GOOGLE_CLIENT_SECRET"
            printf 'ALLOW_DEV_LOGIN=%s\n' "$ALLOW_DEV_LOGIN"
            printf 'ADMIN_ALLOWED_EMAILS=%s\n' "$ADMIN_ALLOWED_EMAILS"
            printf 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=%s\n' "$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY"
            printf 'STRIPE_SECRET_KEY=%s\n' "$STRIPE_SECRET_KEY"
            printf 'STRIPE_WEBHOOK_SECRET=%s\n' "$STRIPE_WEBHOOK_SECRET"
            printf 'STRIPE_PRICE_STARTER=%s\n' "$STRIPE_PRICE_STARTER"
            printf 'STRIPE_PRICE_FARM=%s\n' "$STRIPE_PRICE_FARM"
            printf 'STRIPE_PRICE_ENTERPRISE=%s\n' "$STRIPE_PRICE_ENTERPRISE"
            printf 'STRIPE_PRICE_HARVEST_REACH=%s\n' "$STRIPE_PRICE_HARVEST_REACH"
            printf 'STRIPE_PRICE_WHOLESALE_PORTAL=%s\n' "$STRIPE_PRICE_WHOLESALE_PORTAL"
            printf 'STRIPE_PRICE_WATER_LOG=%s\n' "$STRIPE_PRICE_WATER_LOG"
            printf 'STRIPE_PRICE_AI_TOOLS=%s\n' "$STRIPE_PRICE_AI_TOOLS"
            printf 'STRIPE_PRICE_SQUARE_SYNC=%s\n' "$STRIPE_PRICE_SQUARE_SYNC"
            printf 'STRIPE_PRICE_SMS_CAMPAIGNS=%s\n' "$STRIPE_PRICE_SMS_CAMPAIGNS"
            printf 'RESEND_API_KEY=%s\n' "$RESEND_API_KEY"
            printf 'FROM_EMAIL=%s\n' "$FROM_EMAIL"
            printf 'MINIO_ENDPOINT=%s\n' "$MINIO_ENDPOINT"
            printf 'MINIO_REGION=%s\n' "$MINIO_REGION"
            printf 'MINIO_ACCESS_KEY=%s\n' "$MINIO_ACCESS_KEY"
            printf 'MINIO_SECRET_KEY=%s\n' "$MINIO_SECRET_KEY"
            printf 'MINIO_PUBLIC_URL=%s\n' "$MINIO_PUBLIC_URL"
            printf 'MINIO_BUCKET_PRODUCTS=%s\n' "$MINIO_BUCKET_PRODUCTS"
            printf 'MINIO_BUCKET_BRAND_LOGOS=%s\n' "$MINIO_BUCKET_BRAND_LOGOS"
            printf 'MINIO_BUCKET_WATER_LOGS=%s\n' "$MINIO_BUCKET_WATER_LOGS"
            printf 'MINIMAX_API_KEY=%s\n' "$MINIMAX_API_KEY"
            printf 'MINIMAX_BASE_URL=%s\n' "$MINIMAX_BASE_URL"
            printf 'CRON_SECRET=%s\n' "$CRON_SECRET"
          } > "$ENV_FILE"

          # Upload env file and sync build output
          echo "Uploading env file..."
          scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no "$ENV_FILE" tyler@route.crispygoat.com:$APP_DIR/.env

          echo "Copying .next/..."
          scp -o ConnectTimeout=30 -o StrictHostKeyChecking=no -r .next tyler@route.crispygoat.com:$APP_DIR/
          echo "Copying public/..."
          scp -o ConnectTimeout=30 -o StrictHostKeyChecking=no -r public tyler@route.crispygoat.com:$APP_DIR/
          echo "Copying package.json..."
          scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no package.json tyler@route.crispygoat.com:$APP_DIR/
          scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no next.config.ts tyler@route.crispygoat.com:$APP_DIR/ 2>/dev/null || true

          # Ship the migration runner + SQL so the server has a recovery path (scripts/ and db/migrations/ were previously omitted from the artifact).
          # This allows `node scripts/migrate.js` (after sourcing .env.production) to work directly on the target if needed for bootstrap or emergencies.
          # See docs/superpowers/plans/2026-06-prod-db-schema-migration-reliability.md
          echo "Ensuring migration directories on server and copying runner + SQL..."
          ssh -o ConnectTimeout=15 -o StrictHostKeyChecking=no tyler@route.crispygoat.com "mkdir -p $APP_DIR/scripts $APP_DIR/db"
          scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no scripts/migrate.js tyler@route.crispygoat.com:$APP_DIR/scripts/migrate.js 2>/dev/null || true
          scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no -r db/migrations tyler@route.crispygoat.com:$APP_DIR/db/ 2>/dev/null || true

          # Install deps and restart on server
          echo "Installing deps and restarting PM2..."
          ssh -o ConnectTimeout=60 -o StrictHostKeyChecking=no tyler@route.crispygoat.com "cd $APP_DIR && npm install --omit=dev 2>&1 | tail -5 && pm2 restart route-commerce || pm2 start npm --name route-commerce -- start -- -p 3100 && pm2 save && sleep 4 && curl -f -s http://localhost:3100/api/health/db-schema || { echo 'Health check failed after start - schema not applied (see plan)'; exit 1; }"

          echo "Deployed successfully"