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

param(
    [string]$Mode = "sync",           # sync, deploy, backup, status
    [string]$Target = "remote",       # remote, local, both
    [switch]$Force = $false,          # Forza operazioni senza conferma
    [switch]$Verbose = $false,        # Output dettagliato
    [switch]$DryRun = $false,         # Simulazione senza modifiche
    [switch]$AutoRestart = $false     # Riavvia automaticamente servizi
)

# Configurazione
$CONFIG = @{
    LOCAL_PATH = "U:\home\michele\netgescon\netgescon-laravel"
    REMOTE_HOST = "192.168.0.43"
    REMOTE_USER = "michele"
    REMOTE_PATH = "/var/www/netgescon"
    BACKUP_DIR = "U:\home\michele\netgescon\backup\sync"
    LOG_FILE = "U:\home\michele\netgescon\log\auto-sync.log"
    EXCLUDE_PATTERNS = @(
        "node_modules/",
        "vendor/",
        "storage/logs/",
        "storage/framework/cache/",
        "storage/framework/sessions/",
        "storage/framework/views/",
        ".git/",
        "*.log",
        ".env.local",
        ".env.backup"
    )
}

# Funzioni utility
function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    
    if ($Verbose -or $Level -eq "ERROR") {
        Write-Host $logEntry -ForegroundColor $(
            switch ($Level) {
                "ERROR" { "Red" }
                "WARN" { "Yellow" }
                "SUCCESS" { "Green" }
                default { "White" }
            }
        )
    }
    
    # Crea directory log se non esiste
    $logDir = Split-Path $CONFIG.LOG_FILE -Parent
    if (!(Test-Path $logDir)) {
        New-Item -ItemType Directory -Path $logDir -Force | Out-Null
    }
    
    Add-Content -Path $CONFIG.LOG_FILE -Value $logEntry
}

function Test-RemoteConnection {
    Write-Log "Testando connessione al server remoto..."
    
    $result = & ssh -o ConnectTimeout=10 -o BatchMode=yes "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" "echo 'Connected'"
    
    if ($LASTEXITCODE -eq 0) {
        Write-Log "Connessione remota OK" "SUCCESS"
        return $true
    } else {
        Write-Log "Errore connessione remota" "ERROR"
        return $false
    }
}

function Backup-Local {
    Write-Log "Creando backup locale..."
    
    $backupPath = Join-Path $CONFIG.BACKUP_DIR "local-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
    
    if (!(Test-Path $CONFIG.BACKUP_DIR)) {
        New-Item -ItemType Directory -Path $CONFIG.BACKUP_DIR -Force | Out-Null
    }
    
    if ($DryRun) {
        Write-Log "DRY RUN: Backup locale verso $backupPath" "WARN"
        return $true
    }
    
    try {
        Copy-Item -Path $CONFIG.LOCAL_PATH -Destination $backupPath -Recurse -Force
        Write-Log "Backup locale creato: $backupPath" "SUCCESS"
        return $true
    } catch {
        Write-Log "Errore durante backup locale: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

function Backup-Remote {
    Write-Log "Creando backup remoto..."
    
    $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
    $backupCmd = "sudo cp -r $($CONFIG.REMOTE_PATH) $($CONFIG.REMOTE_PATH)_backup_$timestamp"
    
    if ($DryRun) {
        Write-Log "DRY RUN: $backupCmd" "WARN"
        return $true
    }
    
    $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $backupCmd
    
    if ($LASTEXITCODE -eq 0) {
        Write-Log "Backup remoto creato: $($CONFIG.REMOTE_PATH)_backup_$timestamp" "SUCCESS"
        return $true
    } else {
        Write-Log "Errore durante backup remoto" "ERROR"
        return $false
    }
}

function Sync-ToRemote {
    Write-Log "Sincronizzando verso server remoto..."
    
    # Costruisci exclude pattern per rsync
    $excludeArgs = @()
    foreach ($pattern in $CONFIG.EXCLUDE_PATTERNS) {
        $excludeArgs += "--exclude=$pattern"
    }
    
    $rsyncCmd = @(
        "rsync",
        "-avz",
        "--delete"
    ) + $excludeArgs + @(
        "$($CONFIG.LOCAL_PATH)/",
        "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST):$($CONFIG.REMOTE_PATH)/"
    )
    
    if ($DryRun) {
        Write-Log "DRY RUN: $($rsyncCmd -join ' ')" "WARN"
        return $true
    }
    
    Write-Log "Eseguendo rsync: $($rsyncCmd -join ' ')"
    
    $result = & $rsyncCmd[0] $rsyncCmd[1..($rsyncCmd.Length-1)]
    
    if ($LASTEXITCODE -eq 0) {
        Write-Log "Sincronizzazione completata con successo" "SUCCESS"
        return $true
    } else {
        Write-Log "Errore durante sincronizzazione" "ERROR"
        return $false
    }
}

function Deploy-Remote {
    Write-Log "Eseguendo deploy sul server remoto..."
    
    $deployCommands = @(
        "cd $($CONFIG.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 ($AutoRestart) {
        $deployCommands += @(
            "sudo systemctl restart nginx",
            "sudo systemctl restart php8.3-fpm"
        )
    }
    
    $fullCommand = $deployCommands -join " && "
    
    if ($DryRun) {
        Write-Log "DRY RUN: $fullCommand" "WARN"
        return $true
    }
    
    Write-Log "Eseguendo deploy remoto..."
    $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $fullCommand
    
    if ($LASTEXITCODE -eq 0) {
        Write-Log "Deploy completato con successo" "SUCCESS"
        return $true
    } else {
        Write-Log "Errore durante deploy" "ERROR"
        return $false
    }
}

function Run-Migrations {
    Write-Log "Eseguendo migrazioni sul server remoto..."
    
    $migrationCommands = @(
        "cd $($CONFIG.REMOTE_PATH)",
        "php artisan migrate --force"
    )
    
    $fullCommand = $migrationCommands -join " && "
    
    if ($DryRun) {
        Write-Log "DRY RUN: $fullCommand" "WARN"
        return $true
    }
    
    $result = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" $fullCommand
    
    if ($LASTEXITCODE -eq 0) {
        Write-Log "Migrazioni completate con successo" "SUCCESS"
        return $true
    } else {
        Write-Log "Errore durante migrazioni" "ERROR"
        return $false
    }
}

function Show-Status {
    Write-Log "Controllando stato del sistema..."
    
    # Status locale
    Write-Host "`n=== STATUS LOCALE ===" -ForegroundColor Cyan
    Write-Host "Path: $($CONFIG.LOCAL_PATH)"
    Write-Host "Esistenza: $(Test-Path $CONFIG.LOCAL_PATH)"
    
    if (Test-Path $CONFIG.LOCAL_PATH) {
        $localFiles = Get-ChildItem -Path $CONFIG.LOCAL_PATH -Recurse | Measure-Object
        Write-Host "File totali: $($localFiles.Count)"
        
        $lastModified = Get-ChildItem -Path $CONFIG.LOCAL_PATH -Recurse | 
            Sort-Object LastWriteTime -Descending | 
            Select-Object -First 1
        Write-Host "Ultima modifica: $($lastModified.LastWriteTime) - $($lastModified.Name)"
    }
    
    # Status remoto
    Write-Host "`n=== STATUS REMOTO ===" -ForegroundColor Cyan
    if (Test-RemoteConnection) {
        $remoteStatus = & ssh "$($CONFIG.REMOTE_USER)@$($CONFIG.REMOTE_HOST)" @"
cd $($CONFIG.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')"
"@
        
        if ($LASTEXITCODE -eq 0) {
            Write-Host $remoteStatus
        } else {
            Write-Host "Errore nel recupero status remoto" -ForegroundColor Red
        }
    }
}

# Main execution
function Main {
    Write-Log "=== NetGescon Auto-Sync Started ===" "SUCCESS"
    Write-Log "Modalità: $Mode, Target: $Target, Force: $Force, DryRun: $DryRun"
    
    # Verifica connessione remota
    if ($Target -eq "remote" -or $Target -eq "both") {
        if (!(Test-RemoteConnection)) {
            Write-Log "Impossibile connettersi al server remoto. Uscita." "ERROR"
            exit 1
        }
    }
    
    switch ($Mode) {
        "status" {
            Show-Status
        }
        
        "backup" {
            if ($Target -eq "local" -or $Target -eq "both") {
                if (!(Backup-Local)) { exit 1 }
            }
            if ($Target -eq "remote" -or $Target -eq "both") {
                if (!(Backup-Remote)) { exit 1 }
            }
        }
        
        "sync" {
            # Backup prima della sincronizzazione
            if (!$Force) {
                if (!(Backup-Local)) { 
                    Write-Log "Backup locale fallito. Usa -Force per continuare." "ERROR"
                    exit 1 
                }
                if (!(Backup-Remote)) { 
                    Write-Log "Backup remoto fallito. Usa -Force per continuare." "ERROR"
                    exit 1 
                }
            }
            
            # Sincronizzazione
            if (!(Sync-ToRemote)) { exit 1 }
            
            # Deploy automatico
            if (!(Deploy-Remote)) { exit 1 }
        }
        
        "deploy" {
            if (!(Deploy-Remote)) { exit 1 }
            if (!(Run-Migrations)) { exit 1 }
        }
        
        default {
            Write-Log "Modalità non riconosciuta: $Mode" "ERROR"
            Write-Host @"
Uso: .\auto-sync.ps1 [OPZIONI]

Modalità:
  -Mode sync      Sincronizza e deploya (default)
  -Mode deploy    Solo deploy remoto
  -Mode backup    Solo backup
  -Mode status    Mostra stato sistema

Target:
  -Target remote  Solo server remoto (default)
  -Target local   Solo locale
  -Target both    Entrambi

Opzioni:
  -Force          Forza operazioni senza backup
  -Verbose        Output dettagliato
  -DryRun         Simulazione senza modifiche
  -AutoRestart    Riavvia servizi automaticamente

Esempi:
  .\auto-sync.ps1
  .\auto-sync.ps1 -Mode status -Verbose
  .\auto-sync.ps1 -Mode sync -Force -AutoRestart
  .\auto-sync.ps1 -Mode backup -Target both
"@
            exit 1
        }
    }
    
    Write-Log "=== NetGescon Auto-Sync Completed ===" "SUCCESS"
}

# Esegui main
Main
