#!/bin/bash
# ROA2WEB Quick Rollback Script
# Fast rollback to previous deployment state

set -e

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BACKUP_DIR="$PROJECT_DIR/backups"
LOG_FILE="$PROJECT_DIR/rollback.log"

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

# Logging function
log() {
    local level=$1
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo -e "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}

# Error handling
error_exit() {
    log "ERROR" "$1"
    exit 1
}

# Success message
success() {
    log "SUCCESS" "$1"
}

# Warning message
warning() {
    log "WARNING" "$1"
}

# Info message
info() {
    log "INFO" "$1"
}

# Get last backup
get_last_backup() {
    if [[ -f "$PROJECT_DIR/.last_backup" ]]; then
        cat "$PROJECT_DIR/.last_backup"
    else
        # Find the most recent backup
        find "$BACKUP_DIR" -name "backup_*" -type d -printf '%T+ %p\n' 2>/dev/null | sort -r | head -n1 | cut -d' ' -f2- | xargs basename 2>/dev/null || echo ""
    fi
}

# List available deployments to rollback to
list_rollback_targets() {
    info "Available rollback targets:"
    echo ""
    
    if [[ ! -d "$BACKUP_DIR" ]] || [[ -z "$(ls -A "$BACKUP_DIR" 2>/dev/null)" ]]; then
        warning "No backups found"
        return 1
    fi
    
    local current_backup=$(get_last_backup)
    
    find "$BACKUP_DIR" -name "backup_*" -type d -printf '%T+ %p\n' | sort -r | head -n5 | while read -r line; do
        local date_part=$(echo "$line" | cut -d' ' -f1 | cut -d+ -f1)
        local backup_name=$(basename "$(echo "$line" | cut -d' ' -f2)")
        local backup_path="$(echo "$line" | cut -d' ' -f2)"
        
        local marker=""
        if [[ "$backup_name" == "$current_backup" ]]; then
            marker=" ${GREEN}(current)${NC}"
        fi
        
        echo -e "📦 ${BLUE}$backup_name${NC} ($date_part)$marker"
        
        if [[ -f "$backup_path/backup_info.txt" ]]; then
            grep -E "(Environment|Git)" "$backup_path/backup_info.txt" | sed 's/^/   /' | head -2
        fi
        echo ""
    done
}

# Health check function
health_check() {
    local service=$1
    local url=$2
    local timeout=${3:-30}
    
    info "Performing health check for $service..."
    
    local count=0
    while [[ $count -lt $timeout ]]; do
        if curl -f -s "$url" > /dev/null 2>&1; then
            success "$service health check passed"
            return 0
        fi
        
        sleep 1
        ((count++))
    done
    
    warning "$service health check failed after ${timeout}s"
    return 1
}

# Check service health
check_services_health() {
    info "Checking services health..."
    
    local healthy=true
    
    # Check backend health
    if ! health_check "Backend API" "http://localhost/api/health" 30; then
        healthy=false
    fi
    
    # Check frontend health  
    if ! health_check "Frontend" "http://localhost/health" 30; then
        healthy=false
    fi
    
    # Check gateway health
    if ! health_check "Gateway" "http://localhost/health" 30; then
        healthy=false
    fi
    
    if [[ "$healthy" == "true" ]]; then
        success "All services are healthy"
        return 0
    else
        error_exit "Some services are not healthy"
    fi
}

# Quick rollback without backup restore
quick_rollback() {
    info "Performing quick rollback (restart with previous images)..."
    
    cd "$PROJECT_DIR"
    
    # Stop current services
    info "Stopping current services..."
    docker-compose -f docker-compose.yml -f docker-compose.production.yml down
    
    # Get previous image versions
    local backend_image=$(docker images roa2web/backend --format "{{.ID}}" | sed -n '2p')
    local frontend_image=$(docker images roa2web/frontend --format "{{.ID}}" | sed -n '2p') 
    local gateway_image=$(docker images roa2web/nginx-gateway --format "{{.ID}}" | sed -n '2p')
    
    if [[ -n "$backend_image" ]]; then
        info "Rolling back to previous backend image: $backend_image"
        docker tag "$backend_image" roa2web/backend:rollback
    fi
    
    if [[ -n "$frontend_image" ]]; then
        info "Rolling back to previous frontend image: $frontend_image"
        docker tag "$frontend_image" roa2web/frontend:rollback
    fi
    
    if [[ -n "$gateway_image" ]]; then
        info "Rolling back to previous gateway image: $gateway_image"
        docker tag "$gateway_image" roa2web/nginx-gateway:rollback
    fi
    
    # Start services with rollback images
    info "Starting services with previous images..."
    docker-compose -f docker-compose.yml -f docker-compose.production.yml up -d
    
    # Wait for services to start
    sleep 15
    
    # Check health
    if check_services_health; then
        success "Quick rollback completed successfully!"
    else
        warning "Quick rollback completed but some services may not be healthy"
    fi
}

# Full rollback using backup
full_rollback() {
    local backup_name=$1
    
    if [[ -z "$backup_name" ]]; then
        backup_name=$(get_last_backup)
    fi
    
    if [[ -z "$backup_name" ]]; then
        error_exit "No backup found for rollback"
    fi
    
    local backup_path="$BACKUP_DIR/$backup_name"
    
    if [[ ! -d "$backup_path" ]]; then
        error_exit "Backup not found: $backup_name"
    fi
    
    warning "Performing full rollback to backup: $backup_name"
    warning "This will restore configuration and Docker volumes"
    warning "Press Ctrl+C to cancel or wait 10 seconds to continue..."
    sleep 10
    
    cd "$PROJECT_DIR"
    
    # Stop current services
    info "Stopping current services..."
    docker-compose -f docker-compose.yml -f docker-compose.production.yml down
    
    # Restore Docker images
    if [[ -f "$backup_path/images.tar" ]]; then
        info "Restoring Docker images..."
        docker load -i "$backup_path/images.tar"
    fi
    
    # Restore configuration files
    if [[ -d "$backup_path/config" ]]; then
        info "Restoring configuration files..."
        
        # Backup current config before restore
        local config_backup="config_backup_$(date +%Y%m%d_%H%M%S)"
        mkdir -p "$BACKUP_DIR/$config_backup"
        cp -r .env* "$BACKUP_DIR/$config_backup/" 2>/dev/null || true
        cp docker-compose*.yml "$BACKUP_DIR/$config_backup/"
        
        # Restore from backup
        cp "$backup_path"/.env* . 2>/dev/null || true
        cp "$backup_path"/docker-compose*.yml .
        
        if [[ -d "$backup_path/config/conf" && -d "nginx" ]]; then
            cp -r "$backup_path/config/conf" nginx/
        fi
    fi
    
    # Restore Docker volumes
    if [[ -d "$backup_path/volumes" ]]; then
        info "Restoring Docker volumes..."
        
        for volume_backup in "$backup_path/volumes"/*.tar.gz; do
            if [[ -f "$volume_backup" ]]; then
                local volume_name=$(basename "$volume_backup" .tar.gz)
                local full_volume_name="roa2web_$volume_name"
                
                # Remove current volume
                docker volume rm "$full_volume_name" 2>/dev/null || true
                
                # Create new volume
                docker volume create "$full_volume_name"
                
                # Restore data
                docker run --rm \
                    -v "$full_volume_name":/data \
                    -v "$backup_path/volumes":/backup \
                    alpine tar xzf "/backup/$(basename "$volume_backup")" -C /data
                
                info "Restored volume: $volume_name"
            fi
        done
    fi
    
    # Start services
    info "Starting services..."
    docker-compose -f docker-compose.yml -f docker-compose.production.yml up -d
    
    # Wait for services to start
    sleep 20
    
    # Check health
    if check_services_health; then
        success "Full rollback completed successfully!"
    else
        warning "Full rollback completed but some services may not be healthy"
        warning "You may need to check logs: docker-compose logs"
    fi
}

# Emergency stop
emergency_stop() {
    warning "Performing emergency stop of all ROA2WEB services..."
    
    cd "$PROJECT_DIR"
    
    # Stop all compose services
    docker-compose -f docker-compose.yml -f docker-compose.production.yml down -v 2>/dev/null || true
    docker-compose -f docker-compose.yml down -v 2>/dev/null || true
    
    # Stop any remaining ROA2WEB containers
    docker ps -q --filter "name=roa-" | xargs -r docker stop
    
    success "Emergency stop completed"
}

# Main function
main() {
    local action=${1:-quick}
    
    case $action in
        "quick")
            info "=== ROA2WEB Quick Rollback ==="
            quick_rollback
            ;;
        "full")
            info "=== ROA2WEB Full Rollback ==="
            full_rollback "$2"
            ;;
        "list")
            list_rollback_targets
            ;;
        "emergency")
            emergency_stop
            ;;
        "health")
            check_services_health
            ;;
        *)
            echo "Usage: $0 {quick|full [backup_name]|list|emergency|health}"
            echo ""
            echo "Commands:"
            echo "  quick        - Quick rollback using previous Docker images"
            echo "  full         - Full rollback using backup (restores config + volumes)"
            echo "  list         - List available rollback targets"
            echo "  emergency    - Emergency stop all services"
            echo "  health       - Check current services health"
            echo ""
            echo "Examples:"
            echo "  $0 quick                              # Quick rollback"
            echo "  $0 full                              # Full rollback to last backup"
            echo "  $0 full backup_20240131_143022       # Full rollback to specific backup"
            exit 1
            ;;
    esac
}

# Run main function
main "$@"