#!/bin/bash
# canary-deploy.sh - Script for canary deployments with automatic rollback
# Usage: ./bin/canary-deploy.sh [--percentage=10] [--wait=5] [--force]

set -e

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

# Default settings
CANARY_PERCENTAGE=10
WAIT_MINUTES=5
FORCE_DEPLOY=false
CURRENT_DATE=$(date +"%Y-%m-%d")
DEPLOY_ID=$(date +"%Y%m%d%H%M%S")

# Parse arguments
for arg in "$@"; do
  case $arg in
    --percentage=*)
      CANARY_PERCENTAGE="${arg#*=}"
      shift
      ;;
    --wait=*)
      WAIT_MINUTES="${arg#*=}"
      shift
      ;;
    --force)
      FORCE_DEPLOY=true
      shift
      ;;
  esac
done

echo -e "${GREEN}=== Canary Deployment System ===${NC}"
echo "Preparing for canary deployment (${CANARY_PERCENTAGE}% of servers, ${WAIT_MINUTES} min wait)..."

# Check if we're in the right directory
if [ ! -d "tests/e2e" ]; then
  echo -e "${RED}Error: Please run this script from the wordpress-dev directory${NC}"
  exit 1
fi

# Create logs directory
mkdir -p logs/deploy
LOG_FILE="logs/deploy/canary-deploy-${DEPLOY_ID}.log"

# Log function
log() {
  echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" >> "$LOG_FILE"
  echo "$1"
}

# Check deployment prerequisites
check_prerequisites() {
  log "Checking deployment prerequisites..."
  
  # Run health check
  if [ -f "bin/health-check.sh" ]; then
    log "Running health check..."
    if ! bash bin/health-check.sh; then
      log "${RED}Health check failed. Aborting deployment.${NC}"
      if [ "$FORCE_DEPLOY" != true ]; then
        return 1
      else
        log "${YELLOW}Forcing deployment despite health check failure.${NC}"
      fi
    fi
  fi
  
  # Verify selectors
  if [ -f "bin/verify-selectors.sh" ]; then
    log "Verifying selectors..."
    if ! bash bin/verify-selectors.sh; then
      log "${RED}Selector verification failed. Aborting deployment.${NC}"
      if [ "$FORCE_DEPLOY" != true ]; then
        return 1
      else
        log "${YELLOW}Forcing deployment despite selector verification failure.${NC}"
      fi
    fi
  fi
  
  # Run pre-deployment validation
  if [ -f "bin/pre-deploy-validation.sh" ]; then
    log "Running pre-deployment validation..."
    if ! bash bin/pre-deploy-validation.sh; then
      log "${RED}Pre-deployment validation failed. Aborting deployment.${NC}"
      if [ "$FORCE_DEPLOY" != true ]; then
        return 1
      else
        log "${YELLOW}Forcing deployment despite validation failure.${NC}"
      fi
    fi
  fi
  
  log "${GREEN}Deployment prerequisites check passed.${NC}"
  return 0
}

# Calculate canary server count
calculate_canary_servers() {
  log "Calculating canary server allocation..."
  
  # In a real environment, this would query your server inventory
  # For this example, we'll assume 10 servers total
  TOTAL_SERVERS=10
  CANARY_SERVERS=$(( TOTAL_SERVERS * CANARY_PERCENTAGE / 100 ))
  
  # Ensure at least one server
  if [ $CANARY_SERVERS -lt 1 ]; then
    CANARY_SERVERS=1
  fi
  
  log "Deploying to ${CANARY_SERVERS} out of ${TOTAL_SERVERS} servers (${CANARY_PERCENTAGE}%)"
  return 0
}

# Deploy to canary servers
deploy_to_canary() {
  log "Deploying to canary servers..."
  
  # In a real environment, this would deploy to specific servers
  # For this example, we'll simulate the deployment
  
  # Create deployment package
  log "Creating deployment package..."
  DEPLOY_DIR="deploy/canary-${DEPLOY_ID}"
  mkdir -p "$DEPLOY_DIR"
  
  # Copy plugin files to deployment directory
  log "Copying plugin files..."
  mkdir -p "$DEPLOY_DIR/hvac-community-events"
  cp -r wordpress/wp-content/plugins/hvac-community-events/* "$DEPLOY_DIR/hvac-community-events/"
  
  # Create deployment metadata
  cat > "$DEPLOY_DIR/deploy-meta.json" << EOF
{
  "deployId": "${DEPLOY_ID}",
  "date": "${CURRENT_DATE}",
  "type": "canary",
  "percentage": ${CANARY_PERCENTAGE},
  "servers": ${CANARY_SERVERS}
}
EOF
  
  log "Deployment package created: ${DEPLOY_DIR}"
  
  # Simulate deployment to canary servers
  log "Deploying to ${CANARY_SERVERS} canary servers..."
  sleep 2
  
  log "${GREEN}Canary deployment completed successfully.${NC}"
  return 0
}

# Run smoke tests on canary
run_canary_tests() {
  log "Running smoke tests on canary servers..."
  
  # Create a canary test file
  CANARY_TEST="tests/e2e/canary-test.spec.ts"
  
  log "Creating canary test..."
  cat > "$CANARY_TEST" << 'EOF'
import { test } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';
import { TEST_USERS } from './data/test-users';

test('Canary deployment smoke test', async ({ page }) => {
  // Login test
  const loginPage = new LoginPage(page);
  await loginPage.navigate();
  await loginPage.login(TEST_USERS.trainer.username, TEST_USERS.trainer.password);
  
  // Verify dashboard loads
  await page.waitForURL(/.*hvac-dashboard/);
  await page.waitForLoadState('networkidle');
  
  // Take screenshot for verification
  await page.screenshot({ path: 'screenshots/canary-dashboard.png' });
  
  // Verify critical element is present
  const eventsTable = await page.isVisible('.hvac-events-table');
  if (!eventsTable) {
    throw new Error('Events table not found on dashboard');
  }
  
  // Check create event button
  const createButton = await page.isVisible('.create-event-button, a:has-text("Create Event")');
  if (!createButton) {
    throw new Error('Create event button not found');
  }
  
  console.log('Canary test passed successfully');
});
EOF
  
  log "Running canary test against canary servers..."
  
  # Run the test
  if npx playwright test "$CANARY_TEST"; then
    log "${GREEN}Canary tests passed successfully.${NC}"
    return 0
  else
    log "${RED}Canary tests failed. Initiating rollback.${NC}"
    return 1
  fi
}

# Monitor canary health
monitor_canary_health() {
  log "Monitoring canary health for ${WAIT_MINUTES} minutes..."
  
  # In a real environment, this would query metrics from the canary servers
  # For this example, we'll simulate monitoring
  
  # Create monitor output file
  MONITOR_FILE="logs/deploy/canary-monitor-${DEPLOY_ID}.txt"
  
  # Start monitoring loop
  local end_time=$(( $(date +%s) + WAIT_MINUTES * 60 ))
  local current_time=$(date +%s)
  local status="healthy"
  
  echo "Canary Health Monitoring - ${CURRENT_DATE}" > "$MONITOR_FILE"
  echo "=================================" >> "$MONITOR_FILE"
  echo "" >> "$MONITOR_FILE"
  
  while [ $current_time -lt $end_time ]; do
    # Simulate health check
    local memory_usage=$((50 + RANDOM % 40))
    local cpu_usage=$((20 + RANDOM % 60))
    local error_rate=$((RANDOM % 10))
    
    # Log metrics
    echo "[$(date +"%H:%M:%S")] Memory: ${memory_usage}%, CPU: ${cpu_usage}%, Error rate: ${error_rate}%" >> "$MONITOR_FILE"
    
    # Check thresholds
    if [ $memory_usage -gt 85 ] || [ $cpu_usage -gt 80 ] || [ $error_rate -gt 5 ]; then
      status="unhealthy"
      echo "[$(date +"%H:%M:%S")] WARNING: Threshold exceeded" >> "$MONITOR_FILE"
    fi
    
    # Sleep for a bit
    sleep 30
    
    # Update current time
    current_time=$(date +%s)
  done
  
  log "Monitoring complete. Results saved to ${MONITOR_FILE}"
  
  # Return status
  if [ "$status" = "healthy" ]; then
    log "${GREEN}Canary is healthy after ${WAIT_MINUTES} minutes.${NC}"
    return 0
  else
    log "${RED}Canary is unhealthy. Initiating rollback.${NC}"
    return 1
  fi
}

# Roll back canary deployment
rollback_canary() {
  log "${RED}Rolling back canary deployment...${NC}"
  
  # In a real environment, this would restore the previous version to canary servers
  # For this example, we'll simulate rollback
  
  log "Restoring previous version to canary servers..."
  sleep 2
  
  log "${GREEN}Rollback completed successfully.${NC}"
  return 0
}

# Deploy to all servers
deploy_to_all() {
  log "Deploying to all servers..."
  
  # In a real environment, this would deploy to all remaining servers
  # For this example, we'll simulate full deployment
  
  log "Deploying to remaining servers..."
  sleep 3
  
  log "${GREEN}Full deployment completed successfully.${NC}"
  return 0
}

# Main deployment logic
log "Starting canary deployment process (ID: ${DEPLOY_ID})..."

# Check prerequisites
if ! check_prerequisites; then
  log "${RED}Deployment prerequisites not met. Aborting deployment.${NC}"
  exit 1
fi

# Calculate canary servers
calculate_canary_servers

# Deploy to canary servers
if ! deploy_to_canary; then
  log "${RED}Canary deployment failed. Aborting deployment.${NC}"
  exit 1
fi

# Run canary tests
if ! run_canary_tests; then
  rollback_canary
  log "${RED}Deployment aborted due to failed canary tests.${NC}"
  exit 1
fi

# Monitor canary health
if ! monitor_canary_health; then
  rollback_canary
  log "${RED}Deployment aborted due to unhealthy canary.${NC}"
  exit 1
fi

# If we get here, canary is healthy, so deploy to all servers
if ! deploy_to_all; then
  log "${RED}Full deployment failed.${NC}"
  exit 1
fi

log "${GREEN}Canary deployment process completed successfully!${NC}"
log "Deployment ID: ${DEPLOY_ID}"
exit 0