<?php

namespace App\Services;

use App\Models\Amministratore;
use App\Services\DistributionService;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Log;

class MultiDatabaseService
{
    /**
     * Configura dinamicamente la connessione database per un amministratore.
     */
    public static function setupAdminConnection(Amministratore $amministratore): string
    {
        $connectionName = "admin_{$amministratore->codice_amministratore}";
        
        if ($amministratore->hasDedicatedDatabase()) {
            $config = [
                'driver' => 'mysql',
                'host' => $amministratore->server_database ?? env('DB_HOST', '127.0.0.1'),
                'port' => env('DB_PORT', '3306'),
                'database' => "netgescon_{$amministratore->codice_amministratore}",
                'username' => env('DB_USERNAME', 'forge'),
                'password' => env('DB_PASSWORD', ''),
                'unix_socket' => env('DB_SOCKET', ''),
                'charset' => 'utf8mb4',
                'collation' => 'utf8mb4_unicode_ci',
                'prefix' => '',
                'prefix_indexes' => true,
                'strict' => true,
                'engine' => null,
                'options' => extension_loaded('pdo_mysql') ? array_filter([
                    \PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                ]) : [],
            ];
        } else {
            // Usa database principale con prefisso
            $config = config('database.connections.' . config('database.default'));
            $config['prefix'] = "{$amministratore->codice_amministratore}_";
        }
        
        Config::set("database.connections.{$connectionName}", $config);
        
        return $connectionName;
    }

    /**
     * Crea il database dedicato per un amministratore.
     */
    public static function createAdminDatabase(Amministratore $amministratore): bool
    {
        try {
            $dbName = "netgescon_{$amministratore->codice_amministratore}";
            
            // Connessione root per creare database
            $rootConnection = config('database.default');
            DB::connection($rootConnection)->statement("CREATE DATABASE IF NOT EXISTS `{$dbName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
            
            // Setup connessione specifica
            $connectionName = static::setupAdminConnection($amministratore);
            
            // Esegui migration sul nuovo database
            static::migrateAdminDatabase($connectionName);
            
            // Aggiorna amministratore
            $amministratore->update([
                'database_attivo' => true,
                'database_name' => $amministratore->codice_amministratore
            ]);
            
            return true;
        } catch (\Exception $e) {
            Log::error("Errore creazione database per {$amministratore->codice_amministratore}: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Esegue le migration sul database amministratore.
     */
    private static function migrateAdminDatabase(string $connectionName): void
    {
        // Migration specifiche per database amministratore
        $adminTables = [
            'stabili',
            'movimenti_contabili', 
            'allegati',
            'gestioni',
            'voci_spesa',
            'unita_immobiliari',
            'proprietari',
            'inquilini',
            'fornitori_admin', // Fornitori specifici amministratore
            'bilanci',
            'assemblee',
            'verbali',
            'preventivi',
            'contratti',
        ];
        
        foreach ($adminTables as $table) {
            static::createTableFromMaster($table, $connectionName);
        }
    }

    /**
     * Copia struttura tabella dal database master.
     */
    private static function createTableFromMaster(string $tableName, string $connectionName): void
    {
        try {
            $masterConnection = config('database.default');
            $createSql = DB::connection($masterConnection)
                ->select("SHOW CREATE TABLE `{$tableName}`")[0]->{'Create Table'};
            
            DB::connection($connectionName)->statement($createSql);
        } catch (\Exception $e) {
            Log::warning("Tabella {$tableName} non copiata: " . $e->getMessage());
        }
    }

    /**
     * Ottiene la connessione per un amministratore specifico.
     */
    public static function getAdminConnection(Amministratore $amministratore): string
    {
        $connectionName = "admin_{$amministratore->codice_amministratore}";
        
        // Se non esiste la configurazione, creala
        if (!config("database.connections.{$connectionName}")) {
            return static::setupAdminConnection($amministratore);
        }
        
        return $connectionName;
    }

    /**
     * Sincronizza schema tra database master e amministratori.
     */
    public static function syncSchemaToAllAdmins(): array
    {
        $results = [];
        
        $adminsWithDb = Amministratore::where('database_attivo', true)->get();
        
        foreach ($adminsWithDb as $admin) {
            try {
                $connectionName = static::getAdminConnection($admin);
                static::migrateAdminDatabase($connectionName);
                $results[$admin->codice_amministratore] = 'success';
            } catch (\Exception $e) {
                $results[$admin->codice_amministratore] = 'error: ' . $e->getMessage();
            }
        }
        
        return $results;
    }

    /**
     * Verifica integrità database amministratore.
     */
    public static function checkAdminDatabase(Amministratore $amministratore): array
    {
        try {
            $connectionName = static::getAdminConnection($amministratore);
            $tables = Schema::connection($connectionName)->getTables();
            
            return [
                'status' => 'ok',
                'tables_count' => count($tables),
                'tables' => array_column($tables, 'name'),
                'size' => static::getDatabaseSize($connectionName)
            ];
        } catch (\Exception $e) {
            return [
                'status' => 'error',
                'message' => $e->getMessage()
            ];
        }
    }

    /**
     * Calcola dimensione database.
     */
    private static function getDatabaseSize(string $connectionName): string
    {
        try {
            $config = config("database.connections.{$connectionName}");
            $dbName = $config['database'];
            
            $size = DB::connection($connectionName)
                ->select("SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'DB Size in MB' FROM information_schema.tables WHERE table_schema='{$dbName}'")[0]->{'DB Size in MB'};
            
            return $size . ' MB';
        } catch (\Exception $e) {
            return 'N/A';
        }
    }
}
