<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Amministratore;
use App\Services\DistributionService;
use App\Services\MultiDatabaseService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;

class DistributionController extends Controller
{
    /**
     * Health check del server per verifiche distribuzione
     */
    public function health(): JsonResponse
    {
        try {
            $health = [
                'status' => 'ok',
                'timestamp' => now()->toISOString(),
                'version' => config('app.version', '1.0.0'),
                'server' => config('app.url'),
                'database' => [
                    'connection' => config('database.default'),
                    'status' => 'ok'
                ],
                'storage' => [
                    'disk' => config('filesystems.default'),
                    'available' => true
                ],
                'administrators_count' => Amministratore::count(),
                'features' => [
                    'multi_database' => true,
                    'distribution' => true,
                    'migration' => true,
                    'backup' => true
                ]
            ];

            // Test connessione database
            try {
                DB::connection()->getPdo();
            } catch (\Exception $e) {
                $health['database']['status'] = 'error';
                $health['database']['error'] = $e->getMessage();
                $health['status'] = 'degraded';
            }

            // Test storage
            try {
                Storage::disk()->exists('.');
            } catch (\Exception $e) {
                $health['storage']['available'] = false;
                $health['storage']['error'] = $e->getMessage();
                $health['status'] = 'degraded';
            }

            return response()->json($health);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'error' => $e->getMessage(),
                'timestamp' => now()->toISOString()
            ], 500);
        }
    }

    /**
     * Importa archivio amministratore da altro server
     */
    public function importAdministrator(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'codice_amministratore' => 'required|string|size:8',
                'source_server' => 'required|url',
                'migration_token' => 'required|string',
                'archive' => 'required|file|mimes:zip|max:1048576' // Max 1GB
            ]);

            $codiceAmministratore = $request->input('codice_amministratore');
            $sourceServer = $request->input('source_server');
            $migrationToken = $request->input('migration_token');

            Log::info("Inizio importazione amministratore {$codiceAmministratore} da {$sourceServer}");

            // Verifica che l'amministratore non esista già
            if (Amministratore::where('codice_amministratore', $codiceAmministratore)->exists()) {
                return response()->json([
                    'success' => false,
                    'error' => 'Amministratore già presente su questo server'
                ], 409);
            }

            // Salva archivio temporaneo
            $archive = $request->file('archive');
            $tempPath = storage_path("app/temp/import_{$codiceAmministratore}_" . time() . ".zip");
            
            if (!is_dir(dirname($tempPath))) {
                mkdir(dirname($tempPath), 0755, true);
            }
            
            $archive->move(dirname($tempPath), basename($tempPath));

            // Estrae archivio
            $extractPath = storage_path("app/amministratori/{$codiceAmministratore}");
            $zip = new \ZipArchive();
            
            if ($zip->open($tempPath) !== TRUE) {
                throw new \Exception('Impossibile aprire archivio ZIP');
            }
            
            $zip->extractTo($extractPath);
            $zip->close();

            // Rimuove file temporaneo
            unlink($tempPath);

            Log::info("Archivio amministratore {$codiceAmministratore} estratto in {$extractPath}");

            return response()->json([
                'success' => true,
                'message' => 'Archivio importato con successo',
                'transfer_id' => uniqid('transfer_'),
                'extracted_to' => $extractPath,
                'imported_at' => now()->toISOString()
            ]);

        } catch (\Exception $e) {
            Log::error("Errore importazione amministratore: " . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Attiva amministratore dopo importazione
     */
    public function activateAdministrator(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'codice_amministratore' => 'required|string|size:8',
                'activation_token' => 'required|string'
            ]);

            $codiceAmministratore = $request->input('codice_amministratore');
            
            Log::info("Attivazione amministratore {$codiceAmministratore}");

            // Verifica che l'archivio sia stato importato
            $archivePath = storage_path("app/amministratori/{$codiceAmministratore}");
            if (!is_dir($archivePath)) {
                throw new \Exception('Archivio amministratore non trovato. Importare prima l\'archivio.');
            }

            // Cerca metadata
            $metadataPath = storage_path("app/migrations/metadata_{$codiceAmministratore}.json");
            if (!file_exists($metadataPath)) {
                throw new \Exception('Metadata migrazione non trovati');
            }

            $metadata = json_decode(file_get_contents($metadataPath), true);
            
            // Crea record amministratore nel database
            $amministratore = Amministratore::create([
                'nome' => $metadata['amministratore']['nome'],
                'cognome' => $metadata['amministratore']['cognome'],
                'denominazione_studio' => $metadata['amministratore']['denominazione_studio'],
                'codice_amministratore' => $codiceAmministratore,
                'user_id' => 1, // TODO: gestire user associato
                'database_attivo' => $metadata['amministratore']['database_name'],
                'cartella_dati' => "amministratori/{$codiceAmministratore}",
                'stato_sincronizzazione' => 'attivo',
                'attivo' => true
            ]);

            // Ripristina database se presente
            $backupFiles = glob($archivePath . '/backup/database/*.sql');
            if (!empty($backupFiles)) {
                $latestBackup = end($backupFiles);
                $this->restoreDatabase($amministratore, $latestBackup);
            }

            Log::info("Amministratore {$codiceAmministratore} attivato con successo");

            return response()->json([
                'success' => true,
                'message' => 'Amministratore attivato con successo',
                'administrator_id' => $amministratore->id,
                'database_restored' => !empty($backupFiles),
                'activated_at' => now()->toISOString()
            ]);

        } catch (\Exception $e) {
            Log::error("Errore attivazione amministratore: " . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Sincronizza dati amministratore
     */
    public function syncAdministrator(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'codice_amministratore' => 'required|string|size:8',
                'last_sync' => 'nullable|date',
                'sync_token' => 'required|string'
            ]);

            $codiceAmministratore = $request->input('codice_amministratore');
            $lastSync = $request->input('last_sync');

            $amministratore = Amministratore::where('codice_amministratore', $codiceAmministratore)->first();
            
            if (!$amministratore) {
                return response()->json([
                    'success' => false,
                    'error' => 'Amministratore non trovato'
                ], 404);
            }

            // Simula sincronizzazione (da implementare logica specifica)
            $changes = 0;
            
            if ($lastSync) {
                // Conta modifiche dalla data di ultima sincronizzazione
                // TODO: implementare logica di tracking modifiche
            }

            return response()->json([
                'success' => true,
                'changes' => $changes,
                'last_sync' => $amministratore->updated_at,
                'synced_at' => now()->toISOString()
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Esegue backup amministratore
     */
    public function backupAdministrator(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'codice_amministratore' => 'required|string|size:8',
                'backup_token' => 'required|string'
            ]);

            $codiceAmministratore = $request->input('codice_amministratore');
            
            $amministratore = Amministratore::where('codice_amministratore', $codiceAmministratore)->first();
            
            if (!$amministratore) {
                return response()->json([
                    'success' => false,
                    'error' => 'Amministratore non trovato'
                ], 404);
            }

            $backupResult = $amministratore->createDatabaseBackup();

            if ($backupResult['success']) {
                $amministratore->update(['ultimo_backup' => now()]);
            }

            return response()->json($backupResult);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Ottiene informazioni routing per amministratore
     */
    public function getAdministratorRouting(string $codice): JsonResponse
    {
        try {
            $routingInfo = DistributionService::getAdministratorAccessUrl($codice);
            return response()->json($routingInfo);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Ripristina database da backup
     */
    private function restoreDatabase(Amministratore $amministratore, string $backupPath): bool
    {
        try {
            $dbName = $amministratore->getDatabaseName();
            
            // Crea database se non esiste
            DB::statement("CREATE DATABASE IF NOT EXISTS `{$dbName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
            
            // Ripristina da backup
            $command = sprintf(
                'mysql -h %s -u %s -p%s %s < %s',
                env('DB_HOST', '127.0.0.1'),
                env('DB_USERNAME'),
                env('DB_PASSWORD'),
                escapeshellarg($dbName),
                escapeshellarg($backupPath)
            );

            exec($command, $output, $returnCode);

            return $returnCode === 0;

        } catch (\Exception $e) {
            Log::error("Errore ripristino database: " . $e->getMessage());
            return false;
        }
    }
}
