#!/bin/bash

# NetGescon Auto-Sync Bash Script
# Sincronizzazione automatica tra WSL/Linux e server remoto
# Versione: 2.0
# Data: 2025-01-17

set -euo pipefail

# Configurazione
LOCAL_PATH="$HOME/netgescon/netgescon-laravel"
REMOTE_HOST="192.168.0.43"
REMOTE_USER="michele"
REMOTE_PATH="/var/www/netgescon"
BACKUP_DIR="$HOME/netgescon/backup/sync"
LOG_FILE="$HOME/netgescon/log/auto-sync.log"

# Opzioni default
MODE="sync"
TARGET="remote"
FORCE=false
VERBOSE=false
DRY_RUN=false
AUTO_RESTART=false

# Colori per 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

# Funzioni utility
log() {
    local message="$1"
    local level="${2:-INFO}"
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    local log_entry="[$timestamp] [$level] $message"
    
    # Crea directory log se non esiste
    mkdir -p "$(dirname "$LOG_FILE")"
    
    # Scrivi nel log
    echo "$log_entry" >> "$LOG_FILE"
    
    # Output colorato se verbose o errore
    if [[ "$VERBOSE" == "true" || "$level" == "ERROR" ]]; then
        case "$level" in
            "ERROR")
                echo -e "${RED}$log_entry${NC}" >&2
                ;;
            "WARN")
                echo -e "${YELLOW}$log_entry${NC}"
                ;;
            "SUCCESS")
                echo -e "${GREEN}$log_entry${NC}"
                ;;
            *)
                echo -e "${NC}$log_entry${NC}"
                ;;
        esac
    fi
}

show_usage() {
    cat << EOF
NetGescon Auto-Sync Script

Uso: $0 [OPZIONI]

Modalità:
  -m, --mode MODE     Modalità operazione (sync|deploy|backup|status) [default: sync]
  -t, --target TARGET Target operazione (remote|local|both) [default: remote]

Opzioni:
  -f, --force         Forza operazioni senza backup
  -v, --verbose       Output dettagliato
  -d, --dry-run       Simulazione senza modifiche
  -r, --auto-restart  Riavvia servizi automaticamente
  -h, --help          Mostra questo aiuto

Esempi:
  $0                                    # Sync completo
  $0 -m status -v                       # Mostra stato dettagliato
  $0 -m sync -f -r                      # Sync forzato con riavvio
  $0 -m backup -t both                  # Backup locale e remoto
  $0 -d -m sync                         # Simula sync senza modifiche

EOF
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -m|--mode)
                MODE="$2"
                shift 2
                ;;
            -t|--target)
                TARGET="$2"
                shift 2
                ;;
            -f|--force)
                FORCE=true
                shift
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -d|--dry-run)
                DRY_RUN=true
                shift
                ;;
            -r|--auto-restart)
                AUTO_RESTART=true
                shift
                ;;
            -h|--help)
                show_usage
                exit 0
                ;;
            *)
                echo "Opzione sconosciuta: $1" >&2
                show_usage
                exit 1
                ;;
        esac
    done
}

test_remote_connection() {
    log "Testando connessione al server remoto..."
    
    if ssh -o ConnectTimeout=10 -o BatchMode=yes "$REMOTE_USER@$REMOTE_HOST" "echo 'Connected'" >/dev/null 2>&1; then
        log "Connessione remota OK" "SUCCESS"
        return 0
    else
        log "Errore connessione remota" "ERROR"
        return 1
    fi
}

backup_local() {
    log "Creando backup locale..."
    
    local backup_path="$BACKUP_DIR/local-$(date +%Y%m%d-%H%M%S)"
    
    mkdir -p "$BACKUP_DIR"
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log "DRY RUN: Backup locale verso $backup_path" "WARN"
        return 0
    fi
    
    if cp -r "$LOCAL_PATH" "$backup_path" 2>/dev/null; then
        log "Backup locale creato: $backup_path" "SUCCESS"
        return 0
    else
        log "Errore durante backup locale" "ERROR"
        return 1
    fi
}

backup_remote() {
    log "Creando backup remoto..."
    
    local timestamp=$(date +%Y%m%d-%H%M%S)
    local backup_cmd="sudo cp -r $REMOTE_PATH ${REMOTE_PATH}_backup_$timestamp"
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log "DRY RUN: $backup_cmd" "WARN"
        return 0
    fi
    
    if ssh "$REMOTE_USER@$REMOTE_HOST" "$backup_cmd" 2>/dev/null; then
        log "Backup remoto creato: ${REMOTE_PATH}_backup_$timestamp" "SUCCESS"
        return 0
    else
        log "Errore durante backup remoto" "ERROR"
        return 1
    fi
}

sync_to_remote() {
    log "Sincronizzando verso server remoto..."
    
    # Costruisci exclude pattern per rsync
    local exclude_args=(
        "--exclude=node_modules/"
        "--exclude=vendor/"
        "--exclude=storage/logs/"
        "--exclude=storage/framework/cache/"
        "--exclude=storage/framework/sessions/"
        "--exclude=storage/framework/views/"
        "--exclude=.git/"
        "--exclude=*.log"
        "--exclude=.env.local"
        "--exclude=.env.backup"
    )
    
    local rsync_cmd=(
        "rsync"
        "-avz"
        "--delete"
        "${exclude_args[@]}"
        "$LOCAL_PATH/"
        "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/"
    )
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log "DRY RUN: ${rsync_cmd[*]}" "WARN"
        return 0
    fi
    
    log "Eseguendo rsync: ${rsync_cmd[*]}"
    
    if "${rsync_cmd[@]}" 2>/dev/null; then
        log "Sincronizzazione completata con successo" "SUCCESS"
        return 0
    else
        log "Errore durante sincronizzazione" "ERROR"
        return 1
    fi
}

deploy_remote() {
    log "Eseguendo deploy sul server remoto..."
    
    local deploy_commands=(
        "cd $REMOTE_PATH"
        "sudo chown -R www-data:www-data ."
        "sudo chmod -R 755 ."
        "sudo chmod -R 777 storage/"
        "sudo chmod -R 777 bootstrap/cache/"
        "composer install --no-dev --optimize-autoloader"
        "php artisan config:cache"
        "php artisan route:cache"
        "php artisan view:cache"
    )
    
    if [[ "$AUTO_RESTART" == "true" ]]; then
        deploy_commands+=(
            "sudo systemctl restart nginx"
            "sudo systemctl restart php8.3-fpm"
        )
    fi
    
    local full_command
    IFS=' && ' eval 'full_command="${deploy_commands[*]}"'
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log "DRY RUN: $full_command" "WARN"
        return 0
    fi
    
    log "Eseguendo deploy remoto..."
    if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then
        log "Deploy completato con successo" "SUCCESS"
        return 0
    else
        log "Errore durante deploy" "ERROR"
        return 1
    fi
}

run_migrations() {
    log "Eseguendo migrazioni sul server remoto..."
    
    local migration_commands=(
        "cd $REMOTE_PATH"
        "php artisan migrate --force"
    )
    
    local full_command
    IFS=' && ' eval 'full_command="${migration_commands[*]}"'
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log "DRY RUN: $full_command" "WARN"
        return 0
    fi
    
    if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then
        log "Migrazioni completate con successo" "SUCCESS"
        return 0
    else
        log "Errore durante migrazioni" "ERROR"
        return 1
    fi
}

show_status() {
    log "Controllando stato del sistema..."
    
    # Status locale
    echo -e "\n${CYAN}=== STATUS LOCALE ===${NC}"
    echo "Path: $LOCAL_PATH"
    echo "Esistenza: $(test -d "$LOCAL_PATH" && echo "true" || echo "false")"
    
    if [[ -d "$LOCAL_PATH" ]]; then
        local file_count=$(find "$LOCAL_PATH" -type f | wc -l)
        echo "File totali: $file_count"
        
        local last_modified=$(find "$LOCAL_PATH" -type f -exec stat -c '%Y %n' {} \; 2>/dev/null | sort -nr | head -1)
        echo "Ultima modifica: $last_modified"
        
        local disk_usage=$(du -sh "$LOCAL_PATH" 2>/dev/null | cut -f1)
        echo "Spazio disco: $disk_usage"
    fi
    
    # Status remoto
    echo -e "\n${CYAN}=== STATUS REMOTO ===${NC}"
    if test_remote_connection; then
        local remote_status
        remote_status=$(ssh "$REMOTE_USER@$REMOTE_HOST" "
cd $REMOTE_PATH 2>/dev/null || exit 1
echo 'Path exists: true'
echo 'Files count: \$(find . -type f | wc -l)'
echo 'Last modified: \$(find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | head -1)'
echo 'Disk usage: \$(du -sh . | cut -f1)'
echo 'Laravel version: \$(php artisan --version 2>/dev/null || echo \"N/A\")'
echo 'Database status:'
php artisan migrate:status 2>/dev/null | tail -5 || echo 'N/A'
" 2>/dev/null)
        
        if [[ $? -eq 0 ]]; then
            echo "$remote_status"
        else
            echo -e "${RED}Errore nel recupero status remoto${NC}"
        fi
    fi
}

main() {
    log "=== NetGescon Auto-Sync Started ===" "SUCCESS"
    log "Modalità: $MODE, Target: $TARGET, Force: $FORCE, DryRun: $DRY_RUN"
    
    # Verifica connessione remota se necessario
    if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then
        if ! test_remote_connection; then
            log "Impossibile connettersi al server remoto. Uscita." "ERROR"
            exit 1
        fi
    fi
    
    case "$MODE" in
        "status")
            show_status
            ;;
        
        "backup")
            if [[ "$TARGET" == "local" || "$TARGET" == "both" ]]; then
                backup_local || exit 1
            fi
            if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then
                backup_remote || exit 1
            fi
            ;;
        
        "sync")
            # Backup prima della sincronizzazione
            if [[ "$FORCE" != "true" ]]; then
                backup_local || {
                    log "Backup locale fallito. Usa -f per continuare." "ERROR"
                    exit 1
                }
                backup_remote || {
                    log "Backup remoto fallito. Usa -f per continuare." "ERROR"
                    exit 1
                }
            fi
            
            # Sincronizzazione
            sync_to_remote || exit 1
            
            # Deploy automatico
            deploy_remote || exit 1
            ;;
        
        "deploy")
            deploy_remote || exit 1
            run_migrations || exit 1
            ;;
        
        *)
            log "Modalità non riconosciuta: $MODE" "ERROR"
            show_usage
            exit 1
            ;;
    esac
    
    log "=== NetGescon Auto-Sync Completed ===" "SUCCESS"
}

# Parse arguments and run main
parse_args "$@"
main
