#!/bin/bash
# Desk-Moloni v3.0 Maintenance Script
# 
# Automated maintenance tasks including log cleanup, optimization,
# health checks, and system maintenance operations.

set -euo pipefail

# Script configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_DIR="$(dirname "$SCRIPT_DIR")"
CLI_DIR="$MODULE_DIR/cli"
LOG_DIR="$MODULE_DIR/logs"
LOCK_DIR="$MODULE_DIR/locks"
CACHE_DIR="$MODULE_DIR/cache"
TEMP_DIR="$MODULE_DIR/temp"

# Maintenance configuration
DEFAULT_LOG_RETENTION_DAYS=30
DEFAULT_QUEUE_CLEANUP_DAYS=7
DEFAULT_TEMP_CLEANUP_HOURS=24
DEFAULT_OPTIMIZATION_INTERVAL=7  # days

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

# Logging functions
log_info() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local message="[$timestamp] [INFO] $1"
    echo -e "${BLUE}$message${NC}"
    echo "$message" >> "$LOG_DIR/maintenance.log" 2>/dev/null || true
}

log_success() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local message="[$timestamp] [SUCCESS] $1"
    echo -e "${GREEN}$message${NC}"
    echo "$message" >> "$LOG_DIR/maintenance.log" 2>/dev/null || true
}

log_warning() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local message="[$timestamp] [WARNING] $1"
    echo -e "${YELLOW}$message${NC}"
    echo "$message" >> "$LOG_DIR/maintenance.log" 2>/dev/null || true
}

log_error() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local message="[$timestamp] [ERROR] $1"
    echo -e "${RED}$message${NC}"
    echo "$message" >> "$LOG_DIR/maintenance.log" 2>/dev/null || true
}

# Help function
show_help() {
    cat << EOF
Desk-Moloni v3.0 Maintenance Script

Usage: $0 [OPTIONS] [TASKS]

Tasks:
    all                   Run all maintenance tasks (default)
    cleanup               Clean up old logs and temporary files
    optimize              Optimize database tables and indexes
    health-check          Perform comprehensive health check
    queue-maintenance     Clean up and optimize queue
    cache-cleanup         Clear expired cache files
    log-rotation          Rotate and compress log files
    backup-cleanup        Clean up old backup files
    token-refresh         Refresh OAuth tokens if needed
    stats-update          Update performance statistics

Options:
    -h, --help                    Show this help message
    --log-retention DAYS          Log retention period (default: $DEFAULT_LOG_RETENTION_DAYS)
    --queue-cleanup DAYS          Queue cleanup period (default: $DEFAULT_QUEUE_CLEANUP_DAYS)
    --temp-cleanup HOURS          Temp file cleanup period (default: $DEFAULT_TEMP_CLEANUP_HOURS)
    --dry-run                     Show what would be done without changes
    --verbose                     Verbose output
    --force                       Force operations without prompts

Examples:
    $0                           # Run all maintenance tasks
    $0 cleanup optimize          # Run specific tasks
    $0 --dry-run                # Preview maintenance actions
    $0 health-check --verbose    # Detailed health check

EOF
}

# Parse command line arguments
TASKS=()
LOG_RETENTION_DAYS=$DEFAULT_LOG_RETENTION_DAYS
QUEUE_CLEANUP_DAYS=$DEFAULT_QUEUE_CLEANUP_DAYS
TEMP_CLEANUP_HOURS=$DEFAULT_TEMP_CLEANUP_HOURS
DRY_RUN=false
VERBOSE=false
FORCE=false

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        --log-retention)
            LOG_RETENTION_DAYS="$2"
            shift 2
            ;;
        --queue-cleanup)
            QUEUE_CLEANUP_DAYS="$2"
            shift 2
            ;;
        --temp-cleanup)
            TEMP_CLEANUP_HOURS="$2"
            shift 2
            ;;
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --verbose)
            VERBOSE=true
            shift
            ;;
        --force)
            FORCE=true
            shift
            ;;
        all|cleanup|optimize|health-check|queue-maintenance|cache-cleanup|log-rotation|backup-cleanup|token-refresh|stats-update)
            TASKS+=("$1")
            shift
            ;;
        *)
            log_error "Unknown option: $1"
            show_help
            exit 1
            ;;
    esac
done

# Default to all tasks if none specified
if [[ ${#TASKS[@]} -eq 0 ]]; then
    TASKS=("all")
fi

# Create required directories
ensure_directories() {
    local dirs=("$LOG_DIR" "$LOCK_DIR" "$CACHE_DIR" "$TEMP_DIR")
    
    for dir in "${dirs[@]}"; do
        if [[ ! -d "$dir" ]]; then
            if [[ "$DRY_RUN" == true ]]; then
                log_info "Would create directory: $dir"
            else
                mkdir -p "$dir"
                log_info "Created directory: $dir"
            fi
        fi
    done
}

# Log cleanup task
task_cleanup() {
    log_info "Starting cleanup task"
    
    local files_removed=0
    local space_freed=0
    
    # Clean up old log files
    if [[ -d "$LOG_DIR" ]]; then
        log_info "Cleaning up log files older than $LOG_RETENTION_DAYS days"
        
        if [[ "$DRY_RUN" == true ]]; then
            local old_logs
            old_logs=$(find "$LOG_DIR" -name "*.log" -type f -mtime +$LOG_RETENTION_DAYS 2>/dev/null | wc -l)
            log_info "Would remove $old_logs old log files"
        else
            while IFS= read -r -d '' file; do
                local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                ((files_removed++))
                ((space_freed += size))
                [[ "$VERBOSE" == true ]] && log_info "Removed: $(basename "$file")"
            done < <(find "$LOG_DIR" -name "*.log" -type f -mtime +$LOG_RETENTION_DAYS -print0 2>/dev/null)
        fi
    fi
    
    # Clean up temporary files
    if [[ -d "$TEMP_DIR" ]]; then
        log_info "Cleaning up temporary files older than $TEMP_CLEANUP_HOURS hours"
        
        if [[ "$DRY_RUN" == true ]]; then
            local old_temps
            old_temps=$(find "$TEMP_DIR" -type f -mmin +$((TEMP_CLEANUP_HOURS * 60)) 2>/dev/null | wc -l)
            log_info "Would remove $old_temps temporary files"
        else
            while IFS= read -r -d '' file; do
                local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                ((files_removed++))
                ((space_freed += size))
                [[ "$VERBOSE" == true ]] && log_info "Removed: $(basename "$file")"
            done < <(find "$TEMP_DIR" -type f -mmin +$((TEMP_CLEANUP_HOURS * 60)) -print0 2>/dev/null)
        fi
    fi
    
    # Clean up orphaned lock files
    if [[ -d "$LOCK_DIR" ]]; then
        log_info "Cleaning up orphaned lock files"
        
        for lock_file in "$LOCK_DIR"/*.lock; do
            if [[ -f "$lock_file" ]]; then
                # Check if process is still running (basic check)
                local lock_name=$(basename "$lock_file" .lock)
                if ! pgrep -f "$lock_name" > /dev/null; then
                    if [[ "$DRY_RUN" == true ]]; then
                        log_info "Would remove orphaned lock: $(basename "$lock_file")"
                    else
                        rm "$lock_file"
                        log_info "Removed orphaned lock: $(basename "$lock_file")"
                    fi
                fi
            fi
        done
    fi
    
    if [[ "$DRY_RUN" == false ]]; then
        local space_mb=$((space_freed / 1024 / 1024))
        log_success "Cleanup completed: $files_removed files removed, ${space_mb}MB freed"
    fi
}

# Database optimization task
task_optimize() {
    log_info "Starting database optimization task"
    
    local tables=("desk_moloni_config" "desk_moloni_mapping" "desk_moloni_sync_queue" "desk_moloni_sync_log")
    
    if [[ "$DRY_RUN" == true ]]; then
        log_info "Would optimize ${#tables[@]} database tables"
        return
    fi
    
    # Get database connection details from PHP config
    local db_config
    if ! db_config=$(php -r "
        require_once '$MODULE_DIR/config/bootstrap.php';
        \$config = include '$MODULE_DIR/config/config.php';
        echo \$config['database']['host'] . '|' . \$config['database']['database'] . '|' . \$config['database']['username'];
    " 2>/dev/null); then
        log_error "Failed to get database configuration"
        return 1
    fi
    
    IFS='|' read -r db_host db_name db_user <<< "$db_config"
    
    # Read password securely (this is a simplified approach)
    log_info "Enter database password for optimization:"
    read -s db_password
    
    local mysql_cmd="mysql -h$db_host -u$db_user -p$db_password $db_name"
    
    for table in "${tables[@]}"; do
        log_info "Optimizing table: $table"
        
        # Check if table exists
        if ! echo "SHOW TABLES LIKE '$table';" | $mysql_cmd 2>/dev/null | grep -q "$table"; then
            log_warning "Table not found: $table"
            continue
        fi
        
        # Optimize table
        if echo "OPTIMIZE TABLE $table;" | $mysql_cmd &>/dev/null; then
            log_success "Optimized: $table"
        else
            log_error "Failed to optimize: $table"
        fi
        
        # Analyze table for better query planning
        if echo "ANALYZE TABLE $table;" | $mysql_cmd &>/dev/null; then
            [[ "$VERBOSE" == true ]] && log_info "Analyzed: $table"
        fi
    done
    
    log_success "Database optimization completed"
}

# Health check task
task_health_check() {
    log_info "Starting comprehensive health check"
    
    local issues=0
    
    # Check CLI commands
    local cli_commands=("queue_processor.php" "sync_commands.php")
    for cmd in "${cli_commands[@]}"; do
        local cmd_path="$CLI_DIR/$cmd"
        if [[ -f "$cmd_path" && -x "$cmd_path" ]]; then
            log_success "✓ CLI command available: $cmd"
        else
            log_error "✗ CLI command missing or not executable: $cmd"
            ((issues++))
        fi
    done
    
    # Check directory permissions
    local required_dirs=("$LOG_DIR" "$LOCK_DIR" "$CACHE_DIR" "$TEMP_DIR")
    for dir in "${required_dirs[@]}"; do
        if [[ -d "$dir" && -w "$dir" ]]; then
            log_success "✓ Directory writable: $(basename "$dir")"
        else
            log_error "✗ Directory not writable: $(basename "$dir")"
            ((issues++))
        fi
    done
    
    # Check disk space
    local disk_usage
    disk_usage=$(df "$MODULE_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
    if [[ "$disk_usage" -lt 90 ]]; then
        log_success "✓ Disk usage OK: ${disk_usage}%"
    else
        log_warning "⚠ Disk usage high: ${disk_usage}%"
    fi
    
    # Check memory usage (if possible)
    if command -v free &> /dev/null; then
        local mem_usage
        mem_usage=$(free | awk 'NR==2{printf "%.0f", $3*100/$2}')
        if [[ "$mem_usage" -lt 80 ]]; then
            log_success "✓ Memory usage OK: ${mem_usage}%"
        else
            log_warning "⚠ Memory usage high: ${mem_usage}%"
        fi
    fi
    
    # Check recent errors in logs
    if [[ -f "$LOG_DIR/queue_processor.log" ]]; then
        local recent_errors
        recent_errors=$(tail -n 100 "$LOG_DIR/queue_processor.log" | grep -c "ERROR" || true)
        if [[ "$recent_errors" -eq 0 ]]; then
            log_success "✓ No recent errors in queue processor"
        else
            log_warning "⚠ $recent_errors recent errors in queue processor"
        fi
    fi
    
    # Test basic CLI functionality
    if [[ "$DRY_RUN" == false ]]; then
        if php "$CLI_DIR/sync_commands.php" test-connection &>/dev/null; then
            log_success "✓ API connection test passed"
        else
            log_warning "⚠ API connection test failed (may be expected)"
        fi
    fi
    
    if [[ "$issues" -eq 0 ]]; then
        log_success "Health check completed - no critical issues found"
    else
        log_error "Health check found $issues critical issues"
        return 1
    fi
}

# Queue maintenance task
task_queue_maintenance() {
    log_info "Starting queue maintenance task"
    
    if [[ "$DRY_RUN" == true ]]; then
        log_info "Would clean up completed queue entries older than $QUEUE_CLEANUP_DAYS days"
        log_info "Would reset stuck processing tasks"
        return
    fi
    
    # Clean up old completed tasks
    php "$CLI_DIR/sync_commands.php" queue-cleanup --days="$QUEUE_CLEANUP_DAYS" || true
    
    # Reset stuck processing tasks (running for more than 1 hour)
    php "$CLI_DIR/sync_commands.php" queue-reset-stuck || true
    
    log_success "Queue maintenance completed"
}

# Cache cleanup task
task_cache_cleanup() {
    log_info "Starting cache cleanup task"
    
    if [[ ! -d "$CACHE_DIR" ]]; then
        log_info "Cache directory not found, skipping"
        return
    fi
    
    local cache_files=0
    local cache_size=0
    
    if [[ "$DRY_RUN" == true ]]; then
        cache_files=$(find "$CACHE_DIR" -type f 2>/dev/null | wc -l)
        log_info "Would clear $cache_files cache files"
    else
        # Clear all cache files
        for cache_file in "$CACHE_DIR"/*; do
            if [[ -f "$cache_file" ]]; then
                local size=$(stat -f%z "$cache_file" 2>/dev/null || stat -c%s "$cache_file" 2>/dev/null || echo 0)
                rm "$cache_file"
                ((cache_files++))
                ((cache_size += size))
            fi
        done
        
        local size_mb=$((cache_size / 1024 / 1024))
        log_success "Cache cleanup completed: $cache_files files, ${size_mb}MB cleared"
    fi
}

# Log rotation task
task_log_rotation() {
    log_info "Starting log rotation task"
    
    if [[ ! -d "$LOG_DIR" ]]; then
        return
    fi
    
    local rotated=0
    
    # Rotate large log files
    for log_file in "$LOG_DIR"/*.log; do
        if [[ -f "$log_file" ]]; then
            local size=$(stat -f%z "$log_file" 2>/dev/null || stat -c%s "$log_file" 2>/dev/null || echo 0)
            local size_mb=$((size / 1024 / 1024))
            
            # Rotate files larger than 10MB
            if [[ "$size_mb" -gt 10 ]]; then
                local base_name=$(basename "$log_file" .log)
                local timestamp=$(date +%Y%m%d_%H%M%S)
                local rotated_name="$LOG_DIR/${base_name}_${timestamp}.log"
                
                if [[ "$DRY_RUN" == true ]]; then
                    log_info "Would rotate large log file: $(basename "$log_file") (${size_mb}MB)"
                else
                    cp "$log_file" "$rotated_name"
                    > "$log_file"  # Truncate original file
                    
                    # Compress rotated file
                    if command -v gzip &> /dev/null; then
                        gzip "$rotated_name"
                        log_info "Rotated and compressed: $(basename "$log_file")"
                    else
                        log_info "Rotated: $(basename "$log_file")"
                    fi
                    
                    ((rotated++))
                fi
            fi
        fi
    done
    
    if [[ "$DRY_RUN" == false ]]; then
        log_success "Log rotation completed: $rotated files rotated"
    fi
}

# Backup cleanup task
task_backup_cleanup() {
    log_info "Starting backup cleanup task"
    
    local backup_dir="$MODULE_DIR/backups"
    
    if [[ ! -d "$backup_dir" ]]; then
        log_info "No backup directory found, skipping"
        return
    fi
    
    local retention_days=90  # Keep backups for 90 days
    local removed=0
    
    if [[ "$DRY_RUN" == true ]]; then
        local old_backups
        old_backups=$(find "$backup_dir" -type d -mtime +$retention_days 2>/dev/null | wc -l)
        log_info "Would remove $old_backups old backup directories"
    else
        while IFS= read -r -d '' backup; do
            rm -rf "$backup"
            ((removed++))
            [[ "$VERBOSE" == true ]] && log_info "Removed backup: $(basename "$backup")"
        done < <(find "$backup_dir" -type d -mtime +$retention_days -print0 2>/dev/null)
        
        log_success "Backup cleanup completed: $removed old backups removed"
    fi
}

# Token refresh task
task_token_refresh() {
    log_info "Starting token refresh task"
    
    if [[ "$DRY_RUN" == true ]]; then
        log_info "Would check and refresh OAuth tokens if needed"
        return
    fi
    
    # Run token refresh command
    if php "$CLI_DIR/sync_commands.php" token-refresh &>/dev/null; then
        log_success "Token refresh completed"
    else
        log_warning "Token refresh failed or not needed"
    fi
}

# Statistics update task
task_stats_update() {
    log_info "Starting statistics update task"
    
    if [[ "$DRY_RUN" == true ]]; then
        log_info "Would update performance and usage statistics"
        return
    fi
    
    # Update statistics
    if php "$CLI_DIR/sync_commands.php" stats-update &>/dev/null; then
        log_success "Statistics update completed"
    else
        log_warning "Statistics update failed"
    fi
}

# Execute maintenance tasks
run_tasks() {
    local start_time=$(date +%s)
    
    log_info "Starting maintenance run with tasks: ${TASKS[*]}"
    
    if [[ "$DRY_RUN" == true ]]; then
        log_warning "DRY RUN MODE - No changes will be made"
    fi
    
    for task in "${TASKS[@]}"; do
        case "$task" in
            all)
                task_cleanup
                task_optimize
                task_health_check
                task_queue_maintenance
                task_cache_cleanup
                task_log_rotation
                task_backup_cleanup
                task_token_refresh
                task_stats_update
                ;;
            cleanup)
                task_cleanup
                ;;
            optimize)
                task_optimize
                ;;
            health-check)
                task_health_check
                ;;
            queue-maintenance)
                task_queue_maintenance
                ;;
            cache-cleanup)
                task_cache_cleanup
                ;;
            log-rotation)
                task_log_rotation
                ;;
            backup-cleanup)
                task_backup_cleanup
                ;;
            token-refresh)
                task_token_refresh
                ;;
            stats-update)
                task_stats_update
                ;;
            *)
                log_error "Unknown task: $task"
                ;;
        esac
    done
    
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))
    
    log_success "Maintenance completed in ${duration} seconds"
}

# Main execution
main() {
    # Ensure required directories exist
    ensure_directories
    
    # Run maintenance tasks
    run_tasks
}

# Error handling
trap 'log_error "Maintenance script failed on line $LINENO"' ERR

# Execute if called directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi