#!/bin/bash
# =============================================================================
# Production Deployment Script
# =============================================================================
# Usage: ./scripts/deploy-production.sh [OPTIONS]
#
# Options:
#   --skip-backup       Skip database backup (not recommended)
#   --skip-migrations   Skip database migrations
#   --skip-build        Skip build (only restart services)
#   --rollback          Rollback to previous deployment
#   --dry-run           Show what would be done without executing
#   -y, --yes           Skip confirmation prompt
#
# This script deploys the main branch to the production server (Hetzner 3).
# It should be run ON the production server (cms.c2sgmbh.de).
#
# IMPORTANT: Always ensure develop is merged to main before deploying!
# =============================================================================

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Configuration
PROJECT_DIR="${PROJECT_DIR:-/home/payload/payload-cms}"
BRANCH="main"
BACKUP_DIR="$HOME/backups/pre-deploy"
ROLLBACK_FILE="/tmp/previous_deploy_sha"
LOG_DIR="$HOME/logs"
LOG_FILE="$LOG_DIR/deploy-production-$(date +%Y%m%d).log"
HEALTH_CHECK_URL="http://localhost:3001/admin"
PRODUCTION_URL="https://cms.c2sgmbh.de"

# Parse arguments
SKIP_BACKUP=false
SKIP_MIGRATIONS=false
SKIP_BUILD=false
DO_ROLLBACK=false
DRY_RUN=false
AUTO_YES=false

for arg in "$@"; do
  case $arg in
    --skip-backup)
      SKIP_BACKUP=true
      shift
      ;;
    --skip-migrations)
      SKIP_MIGRATIONS=true
      shift
      ;;
    --skip-build)
      SKIP_BUILD=true
      shift
      ;;
    --rollback)
      DO_ROLLBACK=true
      shift
      ;;
    --dry-run)
      DRY_RUN=true
      shift
      ;;
    -y|--yes)
      AUTO_YES=true
      shift
      ;;
    -h|--help)
      head -30 "$0" | tail -25
      exit 0
      ;;
  esac
done

# Functions
log() {
  local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $1"
  echo -e "${BLUE}${msg}${NC}" | tee -a "$LOG_FILE"
}

success() {
  local msg="[SUCCESS] $1"
  echo -e "${GREEN}${msg}${NC}" | tee -a "$LOG_FILE"
}

warn() {
  local msg="[WARNING] $1"
  echo -e "${YELLOW}${msg}${NC}" | tee -a "$LOG_FILE"
}

error() {
  local msg="[ERROR] $1"
  echo -e "${RED}${msg}${NC}" | tee -a "$LOG_FILE"
  exit 1
}

info() {
  local msg="[INFO] $1"
  echo -e "${CYAN}${msg}${NC}" | tee -a "$LOG_FILE"
}

# Ensure directories exist
mkdir -p "$BACKUP_DIR" "$LOG_DIR"

# Header
echo ""
echo -e "${CYAN}=============================================="
echo -e "  PRODUCTION DEPLOYMENT - Hetzner 3"
echo -e "  URL: $PRODUCTION_URL"
echo -e "==============================================${NC}"
echo ""

# Check if we're on the right server
if [ ! -d "$PROJECT_DIR" ]; then
  error "Project directory not found: $PROJECT_DIR. Are you on the production server?"
fi

cd "$PROJECT_DIR"

# Rollback mode
if [ "$DO_ROLLBACK" = true ]; then
  echo -e "${YELLOW}=== ROLLBACK MODE ===${NC}"

  if [ ! -f "$ROLLBACK_FILE" ]; then
    error "No rollback point found. Cannot rollback."
  fi

  PREVIOUS_SHA=$(cat "$ROLLBACK_FILE")
  log "Rolling back to: $PREVIOUS_SHA"

  if [ "$DRY_RUN" = true ]; then
    info "[DRY RUN] Would rollback to $PREVIOUS_SHA"
    exit 0
  fi

  git fetch origin main
  git checkout main
  git reset --hard "$PREVIOUS_SHA"

  pnpm install --frozen-lockfile
  pm2 stop payload 2>/dev/null || true
  NODE_OPTIONS="--max-old-space-size=2048" pnpm build
  pm2 restart payload --update-env
  pm2 restart queue-worker --update-env

  success "Rollback complete to $PREVIOUS_SHA"
  pm2 status
  exit 0
fi

# Show current state
log "Checking current state..."
CURRENT_SHA=$(git rev-parse HEAD)
CURRENT_BRANCH=$(git branch --show-current)
info "Current branch: $CURRENT_BRANCH"
info "Current commit: $CURRENT_SHA"

# Fetch latest
log "Fetching latest from origin..."
git fetch origin main

LATEST_SHA=$(git rev-parse origin/main)
info "Latest main: $LATEST_SHA"

if [ "$CURRENT_SHA" = "$LATEST_SHA" ]; then
  warn "Already at latest version. Nothing to deploy."
  if [ "$AUTO_YES" != true ]; then
    read -p "Continue anyway? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
      exit 0
    fi
  fi
fi

# Show changes
echo ""
log "Changes to be deployed:"
git log --oneline "$CURRENT_SHA".."$LATEST_SHA" 2>/dev/null || echo "  (fresh deployment)"
echo ""

# Confirmation
if [ "$AUTO_YES" != true ] && [ "$DRY_RUN" != true ]; then
  echo -e "${YELLOW}PRODUCTION DEPLOYMENT${NC}"
  echo ""
  echo "Options:"
  echo "  Skip backup: $SKIP_BACKUP"
  echo "  Skip migrations: $SKIP_MIGRATIONS"
  echo "  Skip build: $SKIP_BUILD"
  echo ""
  read -p "Deploy to PRODUCTION? (yes/no) " CONFIRM
  if [ "$CONFIRM" != "yes" ]; then
    echo "Deployment cancelled."
    exit 0
  fi
fi

# Dry run check
if [ "$DRY_RUN" = true ]; then
  info "[DRY RUN] Would deploy $LATEST_SHA"
  info "[DRY RUN] Would create backup in $BACKUP_DIR"
  info "[DRY RUN] Would run migrations: $([[ $SKIP_MIGRATIONS = true ]] && echo 'NO' || echo 'YES')"
  info "[DRY RUN] Would run build: $([[ $SKIP_BUILD = true ]] && echo 'NO' || echo 'YES')"
  exit 0
fi

# Step 1: Create backup
if [ "$SKIP_BACKUP" = false ]; then
  log "Creating database backup..."
  BACKUP_FILE="$BACKUP_DIR/payload_db_$(date +%Y-%m-%d_%H-%M-%S).sql.gz"

  if [ -f "$HOME/.pgpass" ]; then
    # Read password from .pgpass (format: host:port:db:user:password)
    export PGPASSWORD
    PGPASSWORD=$(grep 'payload_db' "$HOME/.pgpass" | cut -d: -f5)
    pg_dump -h localhost -U payload payload_db | gzip > "$BACKUP_FILE"
    unset PGPASSWORD
    success "Backup created: $BACKUP_FILE"

    # Keep only last 5 pre-deploy backups
    ls -t "$BACKUP_DIR"/payload_db_*.sql.gz 2>/dev/null | tail -n +6 | xargs rm -f 2>/dev/null || true
  else
    warn "No .pgpass found, skipping backup"
  fi
else
  warn "Skipping backup (--skip-backup)"
fi

# Step 2: Save rollback point
log "Saving rollback point..."
echo "$CURRENT_SHA" > "$ROLLBACK_FILE"
info "Rollback SHA saved: $CURRENT_SHA"

# Step 3: Pull latest code
log "Pulling latest code..."
git stash --include-untracked 2>/dev/null || true
git checkout main
git reset --hard origin/main
success "Code updated to: $(git rev-parse --short HEAD)"

# Step 4: Install dependencies
log "Installing dependencies..."
pnpm install --frozen-lockfile
success "Dependencies installed"

# Step 5: Run migrations and schema sync
if [ "$SKIP_MIGRATIONS" = false ]; then
  log "Running database migrations..."
  pnpm payload migrate || warn "No migrations to run or migration failed"

  # WICHTIG: drizzle-kit push wurde aus dem automatischen Deployment entfernt
  # um Datenverlust zu verhindern. Nur Payload-Migrationen sind sicher.
  # Für manuelle Schema-Erweiterungen: ./scripts/sync-schema.sh --dry-run
else
  warn "Skipping migrations (--skip-migrations)"
fi

# Step 6: Build
if [ "$SKIP_BUILD" = false ]; then
  log "Stopping services for build..."
  pm2 stop payload 2>/dev/null || true
  pm2 stop queue-worker 2>/dev/null || true

  log "Building application..."
  NODE_OPTIONS="--max-old-space-size=2048" pnpm build
  success "Build completed"
else
  warn "Skipping build (--skip-build)"
fi

# Step 7: Restart services
log "Restarting services..."
pm2 restart payload --update-env 2>/dev/null || pm2 start ecosystem.config.cjs --only payload
pm2 restart queue-worker --update-env 2>/dev/null || pm2 start ecosystem.config.cjs --only queue-worker
success "Services restarted"

# Step 8: Health check
log "Waiting for service to start..."
sleep 10

log "Running health check..."
MAX_RETRIES=5
RETRY_COUNT=0
HEALTH_OK=false

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
  HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")

  if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 400 ]; then
    success "Health check passed (HTTP $HTTP_STATUS)"
    HEALTH_OK=true
    break
  fi

  RETRY_COUNT=$((RETRY_COUNT + 1))
  warn "Health check attempt $RETRY_COUNT failed (HTTP $HTTP_STATUS), retrying in 5s..."
  sleep 5
done

if [ "$HEALTH_OK" = false ]; then
  error "Health check failed after $MAX_RETRIES attempts. Consider rolling back with --rollback"
fi

# Show PM2 status
echo ""
log "PM2 Status:"
pm2 status

# Summary
echo ""
echo -e "${GREEN}=============================================="
echo -e "  PRODUCTION DEPLOYMENT COMPLETE!"
echo -e "==============================================${NC}"
echo ""
echo "  URL: $PRODUCTION_URL"
echo "  Admin: $PRODUCTION_URL/admin"
echo "  Commit: $(git rev-parse --short HEAD)"
echo "  Previous: $(cat $ROLLBACK_FILE | cut -c1-7)"
echo "  Time: $(date)"
echo ""
echo "  To rollback: ./scripts/deploy-production.sh --rollback"
echo ""

log "Deployment finished successfully"
