#!/bin/bash
# ========================================
# MATH PLATFORM - PRODUCTION DEPLOYMENT
# Enterprise Grade Deployment Script
# ========================================

set -euo pipefail

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

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BACKUP_DIR="$PROJECT_DIR/backups"
LOG_DIR="$PROJECT_DIR/logs"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Error handler
error_handler() {
    log_error "Deployment failed at line $1"
    log_info "Rolling back to previous state..."
    rollback_deployment
    exit 1
}

trap 'error_handler $LINENO' ERR

# ========================================
# PRE-DEPLOYMENT CHECKS
# ========================================

check_prerequisites() {
    log_info "Checking prerequisites..."
    
    # Check if running as root (should NOT)
    if [[ $EUID -eq 0 ]]; then
        log_error "Do not run this script as root"
        exit 1
    fi
    
    # Check required commands
    local required_commands=("docker" "docker-compose" "curl" "wget")
    for cmd in "${required_commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            log_error "$cmd is required but not installed"
            exit 1
        fi
    done
    
    # Check Docker is running
    if ! docker info &> /dev/null; then
        log_error "Docker daemon is not running"
        exit 1
    fi
    
    log_success "Prerequisites check passed"
}

check_environment() {
    log_info "Checking environment variables..."
    
    local required_vars=(
        "DATABASE_URL"
        "REDIS_PASSWORD"
        "JWT_SECRET"
    )
    
    local missing_vars=()
    for var in "${required_vars[@]}"; do
        if [[ -z "${!var:-}" ]]; then
            missing_vars+=("$var")
        fi
    done
    
    if [[ ${#missing_vars[@]} -gt 0 ]]; then
        log_error "Missing required environment variables:"
        printf '%s\n' "${missing_vars[@]}"
        exit 1
    fi
    
    log_success "Environment variables check passed"
}

# ========================================
# DATABASE OPERATIONS
# ========================================

create_backup() {
    log_info "Creating database backup..."
    
    mkdir -p "$BACKUP_DIR"
    local backup_file="$BACKUP_DIR/backup_$TIMESTAMP.sql"
    
    # Extract database info from DATABASE_URL
    local db_container="math-postgres-prod"
    
    if docker ps | grep -q "$db_container"; then
        if docker exec "$db_container" pg_dump -U mathuser mathdb > "$backup_file"; then
            log_success "Database backup created: $backup_file"
            
            # Compress backup
            gzip "$backup_file"
            log_success "Backup compressed: ${backup_file}.gz"
            
            # Keep only last 7 backups
            ls -t "$BACKUP_DIR"/backup_*.sql.gz | tail -n +8 | xargs -r rm
        else
            log_warning "Failed to create database backup, continuing anyway..."
        fi
    else
        log_warning "Database container not running, skipping backup"
    fi
}

run_migrations() {
    log_info "Running database migrations..."
    
    cd "$PROJECT_DIR"
    
    # Create temporary migration container
    docker-compose -f docker-compose.prod.yml run --rm backend npx prisma migrate deploy
    
    log_success "Database migrations completed"
}

# ========================================
# DEPLOYMENT OPERATIONS
# ========================================

build_images() {
    log_info "Building Docker images..."
    
    cd "$PROJECT_DIR"
    
    # Export version for builds
    export VERSION=${VERSION:-1.0.0}
    
    # Build all images
    docker-compose -f docker-compose.prod.yml build --no-cache
    
    log_success "Docker images built successfully"
}

zero_downtime_deploy() {
    log_info "Starting zero-downtime deployment..."
    
    cd "$PROJECT_DIR"
    
    # Scale up new instances
    log_info "Scaling up backend instances..."
    docker-compose -f docker-compose.prod.yml up -d --no-deps --scale backend=3 backend
    
    # Wait for health checks
    log_info "Waiting for health checks (30s)..."
    sleep 30
    
    # Check health
    if ! check_service_health "backend"; then
        log_error "Backend health check failed after scaling"
        return 1
    fi
    
    # Scale down to normal
    log_info "Scaling down to normal capacity..."
    docker-compose -f docker-compose.prod.yml up -d --no-deps --scale backend=2 backend
    
    log_success "Zero-downtime deployment completed"
}

deploy_services() {
    log_info "Deploying services..."
    
    cd "$PROJECT_DIR"
    
    # Pull latest images if using registry
    if [[ "${PULL_IMAGES:-false}" == "true" ]]; then
        log_info "Pulling latest images from registry..."
        docker-compose -f docker-compose.prod.yml pull
    fi
    
    # Deploy all services
    docker-compose -f docker-compose.prod.yml up -d --remove-orphans
    
    log_success "Services deployed successfully"
}

# ========================================
# HEALTH CHECKS
# ========================================

check_service_health() {
    local service=$1
    local max_attempts=${2:-10}
    local attempt=1
    
    log_info "Checking health for service: $service"
    
    while [[ $attempt -le $max_attempts ]]; do
        if docker-compose -f docker-compose.prod.yml ps "$service" | grep -q "healthy"; then
            log_success "$service is healthy"
            return 0
        fi
        
        log_info "Health check attempt $attempt/$max_attempts..."
        sleep 5
        ((attempt++))
    done
    
    log_error "$service failed health check after $max_attempts attempts"
    return 1
}

run_health_checks() {
    log_info "Running comprehensive health checks..."
    
    local services=("postgres" "redis" "backend" "frontend" "nginx")
    local failed_services=()
    
    for service in "${services[@]}"; do
        if ! check_service_health "$service"; then
            failed_services+=("$service")
        fi
    done
    
    if [[ ${#failed_services[@]} -gt 0 ]]; then
        log_error "Health checks failed for services:"
        printf '%s\n' "${failed_services[@]}"
        return 1
    fi
    
    # Check main health endpoint
    local health_url="http://localhost/health"
    if curl -sf "$health_url" &> /dev/null; then
        log_success "Main health endpoint is responding"
    else
        log_warning "Main health endpoint not responding (might need SSL)"
    fi
    
    log_success "All health checks passed"
}

# ========================================
# ROLLBACK
# ========================================

rollback_deployment() {
    log_warning "Initiating rollback..."
    
    cd "$PROJECT_DIR"
    
    # Get last successful version (if available)
    local last_version=${LAST_VERSION:-"latest"}
    
    # Revert to previous images
    export VERSION="$last_version"
    docker-compose -f docker-compose.prod.yml up -d
    
    log_warning "Rollback completed"
}

# ========================================
# CLEANUP
# ========================================

cleanup() {
    log_info "Running cleanup..."
    
    # Remove old images
    docker image prune -af --filter "until=24h" || true
    
    # Remove unused volumes
    docker volume prune -f || true
    
    # Clean old logs
    find "$LOG_DIR" -name "*.log" -type f -mtime +7 -delete 2>/dev/null || true
    
    log_success "Cleanup completed"
}

# ========================================
# MAIN
# ========================================

main() {
    log_info "🚀 Starting Math Platform Production Deployment"
    log_info "Timestamp: $(date)"
    log_info "Version: ${VERSION:-1.0.0}"
    
    # Pre-deployment
    check_prerequisites
    check_environment
    
    # Backup
    create_backup
    
    # Database
    run_migrations
    
    # Build and deploy
    build_images
    deploy_services
    
    # Zero-downtime for backend
    zero_downtime_deploy
    
    # Verification
    run_health_checks
    
    # Cleanup
    cleanup
    
    log_success "✅ Deployment completed successfully!"
    log_info "Services are running at:"
    log_info "  - Frontend: https://localhost"
    log_info "  - API: https://localhost/api"
    log_info "  - Grafana: http://localhost:3001 (if monitoring enabled)"
}

# Parse command line arguments
case "${1:-deploy}" in
    "backup")
        create_backup
        ;;
    "migrate")
        check_environment
        run_migrations
        ;;
    "rollback")
        rollback_deployment
        ;;
    "health")
        run_health_checks
        ;;
    "deploy"|*)
        main
        ;;
esac
