# .gitea/workflows/manual-deploy-major.yml
#
# This workflow provides a MANUAL trigger to perform a MAJOR version bump
# and deploy the application to the PRODUCTION environment.
name: Manual - Deploy Major Version to Production

on:
  workflow_dispatch:
    inputs:
      confirmation:
        description: 'Type "deploy-major-to-prod" to confirm you want to deploy a new major version.'
        required: true
        default: 'do-not-run'
      force_reload:
        description: 'Force PM2 reload even if version matches (true/false).'
        required: false
        type: boolean
        default: false

jobs:
  deploy-production-major:
    runs-on: projectium.com

    steps:
      - name: Verify Confirmation Phrase
        run: |
          if [ "${{ gitea.event.inputs.confirmation }}" != "deploy-major-to-prod" ]; then
            echo "ERROR: Confirmation phrase did not match. Aborting deployment."
            exit 1
          fi
          echo "✅ Confirmation accepted. Proceeding with major version production deployment."

      - name: Checkout Code from 'main' branch
        uses: actions/checkout@v3
        with:
          ref: 'main' # Explicitly check out the main branch for production deployment
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: '**/package-lock.json'

      - name: Install Dependencies
        run: npm ci

      - name: Bump Major Version and Push
        run: |
          # Configure git for the commit.
          git config --global user.name 'Gitea Actions'
          git config --global user.email 'actions@gitea.projectium.com'

          # Bump the major version number. This creates a new commit and a new tag.
          # The commit message includes [skip ci] to prevent this push from triggering another workflow run.
          npm version major -m "ci: Bump version to %s for major release [skip ci]"

          # Push the new commit and the new tag back to the main branch.
          git push --follow-tags

      - name: Check for Production Database Schema Changes
        env:
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_USER: ${{ secrets.DB_USER_PROD }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD_PROD }}
          DB_NAME: ${{ secrets.DB_DATABASE_PROD }}
        run: |
          if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ] || [ -z "$DB_NAME" ]; then
            echo "ERROR: One or more production database secrets (DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE_PROD) are not set."
            exit 1
          fi
          echo "--- Checking for production schema changes ---"
          CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
          echo "Current Git Schema Hash: $CURRENT_HASH"
          # The psql command will now fail the step if the query errors (e.g., column missing), preventing deployment on a bad schema.
          DEPLOYED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c "SELECT schema_hash FROM public.schema_info WHERE environment = 'production';" -t -A)
          echo "Deployed DB Schema Hash: $DEPLOYED_HASH"
          if [ -z "$DEPLOYED_HASH" ]; then
            echo "WARNING: No schema hash found in the production database. This is expected for a first-time deployment."
          elif [ "$CURRENT_HASH" != "$DEPLOYED_HASH" ]; then
            echo "ERROR: Database schema mismatch detected! A manual database migration is required."
            exit 1
          else
            echo "✅ Schema is up to date. No changes detected."
          fi

      - name: Build React Application for Production
        run: |
          if [ -z "${{ secrets.VITE_GOOGLE_GENAI_API_KEY }}" ]; then
            echo "ERROR: The VITE_GOOGLE_GENAI_API_KEY secret is not set."
            exit 1
          fi
          GITEA_SERVER_URL="https://gitea.projectium.com"
          COMMIT_MESSAGE=$(git log -1 --grep="\[skip ci\]" --invert-grep --pretty=%s)
          PACKAGE_VERSION=$(node -p "require('./package.json').version")
          VITE_APP_VERSION="$(date +'%Y%m%d-%H%M'):$(git rev-parse --short HEAD):$PACKAGE_VERSION" \
          VITE_APP_COMMIT_URL="$GITEA_SERVER_URL/${{ gitea.repository }}/commit/${{ gitea.sha }}" \
          VITE_APP_COMMIT_MESSAGE="$COMMIT_MESSAGE" \
          VITE_API_BASE_URL=/api VITE_API_KEY=${{ secrets.VITE_GOOGLE_GENAI_API_KEY }} npm run build

      - name: Deploy Application to Production Server
        run: |
          echo "Deploying application files to /var/www/flyer-crawler.projectium.com..."
          APP_PATH="/var/www/flyer-crawler.projectium.com"
          mkdir -p "$APP_PATH"
          mkdir -p "$APP_PATH/flyer-images/icons" "$APP_PATH/flyer-images/archive"
          rsync -avz --delete --exclude 'node_modules' --exclude '.git' --exclude 'dist' --exclude 'flyer-images' ./ "$APP_PATH/"
          rsync -avz dist/ "$APP_PATH"
          echo "Application deployment complete."

      - name: Install Backend Dependencies and Restart Production Server
        env:
          # --- Production Secrets Injection ---
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_USER: ${{ secrets.DB_USER_PROD }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD_PROD }}
          DB_NAME: ${{ secrets.DB_DATABASE_PROD }}
          # Explicitly use database 0 for production (test uses database 1)
          REDIS_URL: 'redis://localhost:6379/0'
          REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD_PROD }}
          FRONTEND_URL: 'https://flyer-crawler.projectium.com'
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
          GEMINI_API_KEY: ${{ secrets.VITE_GOOGLE_GENAI_API_KEY }}
          GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
          SMTP_HOST: 'localhost'
          SMTP_PORT: '1025'
          SMTP_SECURE: 'false'
          SMTP_USER: ''
          SMTP_PASS: ''
          SMTP_FROM_EMAIL: 'noreply@flyer-crawler.projectium.com'
        run: |
          if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ] || [ -z "$DB_NAME" ]; then
            echo "ERROR: One or more production database secrets (DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE_PROD) are not set."
            exit 1
          fi
          echo "Installing production dependencies and restarting server..."
          cd /var/www/flyer-crawler.projectium.com
          npm install --omit=dev

          # --- Cleanup Errored Processes ---
          echo "Cleaning up errored or stopped PM2 processes..."
          node -e "const exec = require('child_process').execSync; try { const list = JSON.parse(exec('pm2 jlist').toString()); list.forEach(p => { if (p.pm2_env.status === 'errored' || p.pm2_env.status === 'stopped') { console.log('Deleting ' + p.pm2_env.status + ' process: ' + p.name + ' (' + p.pm2_env.pm_id + ')'); try { exec('pm2 delete ' + p.pm2_env.pm_id); } catch(e) { console.error('Failed to delete ' + p.pm2_env.pm_id); } } }); } catch (e) { console.error('Error cleaning up processes:', e); }"

          # --- Version Check Logic ---
          # Get the version from the newly deployed package.json
          NEW_VERSION=$(node -p "require('./package.json').version")
          echo "Deployed Package Version: $NEW_VERSION"

          # Get the running version from PM2 for the main API process
          # We use a small node script to parse the JSON output from pm2 jlist
          RUNNING_VERSION=$(pm2 jlist | node -e "try { const list = JSON.parse(require('fs').readFileSync(0, 'utf-8')); const app = list.find(p => p.name === 'flyer-crawler-api'); console.log(app ? app.pm2_env.version : ''); } catch(e) { console.log(''); }")
          echo "Running PM2 Version: $RUNNING_VERSION"

          if [ "${{ gitea.event.inputs.force_reload }}" == "true" ] || [ "$NEW_VERSION" != "$RUNNING_VERSION" ] || [ -z "$RUNNING_VERSION" ]; then
            if [ "${{ gitea.event.inputs.force_reload }}" == "true" ]; then
              echo "Force reload triggered by manual input. Reloading PM2..."
            else
              echo "Version mismatch (Running: $RUNNING_VERSION -> Deployed: $NEW_VERSION) or app not running. Reloading PM2..."
            fi
            pm2 startOrReload ecosystem.config.cjs --env production --update-env && pm2 save
            echo "Production backend server reloaded successfully."
          else
            echo "Version $NEW_VERSION is already running. Skipping PM2 reload."
          fi

          echo "Updating schema hash in production database..."
          CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
          PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c \
          "INSERT INTO public.schema_info (environment, schema_hash, deployed_at) VALUES ('production', '$CURRENT_HASH', NOW())
           ON CONFLICT (environment) DO UPDATE SET schema_hash = EXCLUDED.schema_hash, deployed_at = NOW();"

          UPDATED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c "SELECT schema_hash FROM public.schema_info WHERE environment = 'production';" -t -A)
          if [ "$CURRENT_HASH" = "$UPDATED_HASH" ]; then
            echo "✅ Schema hash successfully updated in the database to: $UPDATED_HASH"
          else
            echo "ERROR: Failed to update schema hash in the database."
          fi

      - name: Show PM2 Environment for Production
        run: |
          echo "--- Displaying recent PM2 logs for flyer-crawler-api ---"
          sleep 5
          pm2 describe flyer-crawler-api || echo "Could not find production pm2 process."
          pm2 logs flyer-crawler-api --lines 20 --nostream || echo "Could not find production pm2 process."
          pm2 env flyer-crawler-api || echo "Could not find production pm2 process."