<?php
/**
 * Script de Prueba para Datos Iniciales
 * Sistema de Inventario Forestal de Guatemala V1.0
 * 
 * Este script valida que todos los datos iniciales se hayan insertado correctamente
 * y verifica la integridad de la base de datos
 */

require_once __DIR__ . '/api/config/database.php';

class InitialDataTester {
    private $pdo;
    private $tests = [];
    private $passed = 0;
    private $failed = 0;
    
    public function __construct() {
        try {
            $database = new Database();
            $this->pdo = $database->getConnection();
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (Exception $e) {
            die("❌ Error de conexión a la base de datos: " . $e->getMessage() . "\n");
        }
    }
    
    /**
     * Ejecutar todas las pruebas
     */
    public function runAllTests() {
        echo "=== INICIANDO PRUEBAS DE DATOS INICIALES ===\n\n";
        
        $this->testDatabaseConnection();
        $this->testTableStructure();
        $this->testSpeciesData();
        $this->testConfigurationData();
        $this->testDataIntegrity();
        $this->testConstraints();
        $this->testIndexes();
        $this->testViews();
        $this->testTriggers();
        
        $this->showResults();
    }
    
    /**
     * Probar conexión a la base de datos
     */
    private function testDatabaseConnection() {
        $this->test("Conexión a base de datos", function() {
            $stmt = $this->pdo->query("SELECT 1");
            return $stmt->fetchColumn() === 1;
        });
    }
    
    /**
     * Probar estructura de tablas
     */
    private function testTableStructure() {
        $expectedTables = [
            'usuarios', 'proyectos', 'rodales', 'especies', 
            'datos_campo', 'configuracion'
        ];
        
        foreach ($expectedTables as $table) {
            $this->test("Tabla '{$table}' existe", function() use ($table) {
                $stmt = $this->pdo->prepare("
                    SELECT COUNT(*) FROM information_schema.TABLES 
                    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?
                ");
                $stmt->execute([$table]);
                return $stmt->fetchColumn() > 0;
            });
        }
        
        // Verificar columnas específicas importantes
        $this->test("Tabla 'usuarios' tiene columna 'rol'", function() {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) FROM information_schema.COLUMNS 
                WHERE TABLE_SCHEMA = DATABASE() 
                AND TABLE_NAME = 'usuarios' 
                AND COLUMN_NAME = 'rol'
            ");
            $stmt->execute();
            return $stmt->fetchColumn() > 0;
        });
        
        $this->test("Tabla 'datos_campo' tiene columna 'estado_sincronizacion'", function() {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) FROM information_schema.COLUMNS 
                WHERE TABLE_SCHEMA = DATABASE() 
                AND TABLE_NAME = 'datos_campo' 
                AND COLUMN_NAME = 'estado_sincronizacion'
            ");
            $stmt->execute();
            return $stmt->fetchColumn() > 0;
        });
    }
    
    /**
     * Probar datos de especies
     */
    private function testSpeciesData() {
        $this->test("Especies forestales insertadas", function() {
            $stmt = $this->pdo->query("SELECT COUNT(*) FROM especies WHERE activa = TRUE");
            $count = $stmt->fetchColumn();
            return $count >= 20; // Esperamos al menos 20 especies
        });
        
        $this->test("Especie 'Pinus maximinoi' existe", function() {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) FROM especies 
                WHERE nombre_cientifico = 'Pinus maximinoi' AND activa = TRUE
            ");
            $stmt->execute();
            return $stmt->fetchColumn() > 0;
        });
        
        $this->test("Especie 'Cupressus lusitanica' existe", function() {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) FROM especies 
                WHERE nombre_cientifico = 'Cupressus lusitanica' AND activa = TRUE
            ");
            $stmt->execute();
            return $stmt->fetchColumn() > 0;
        });
        
        $this->test("Todas las especies tienen nombre común", function() {
            $stmt = $this->pdo->query("
                SELECT COUNT(*) FROM especies 
                WHERE nombre_comun IS NULL OR nombre_comun = '' OR activa = TRUE
            ");
            return $stmt->fetchColumn() === 0;
        });
    }
    
    /**
     * Probar datos de configuración
     */
    private function testConfigurationData() {
        $this->test("Configuraciones del sistema insertadas", function() {
            $stmt = $this->pdo->query("SELECT COUNT(*) FROM configuracion");
            $count = $stmt->fetchColumn();
            return $count >= 25; // Esperamos al menos 25 configuraciones
        });
        
        $requiredConfigs = [
            'sistema_version',
            'max_file_size',
            'session_timeout',
            'gps_precision',
            'dap_max_alert',
            'altura_max_alert',
            'sync_batch_size'
        ];
        
        foreach ($requiredConfigs as $config) {
            $this->test("Configuración '{$config}' existe", function() use ($config) {
                $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM configuracion WHERE clave = ?");
                $stmt->execute([$config]);
                return $stmt->fetchColumn() > 0;
            });
        }
        
        $this->test("Versión del sistema es válida", function() {
            $stmt = $this->pdo->prepare("SELECT valor FROM configuracion WHERE clave = 'sistema_version'");
            $stmt->execute();
            $version = $stmt->fetchColumn();
            return preg_match('/^\d+\.\d+\.\d+$/', $version);
        });
    }
    
    /**
     * Probar integridad de datos
     */
    private function testDataIntegrity() {
        $this->test("No hay registros huérfanos en proyectos", function() {
            $stmt = $this->pdo->query("
                SELECT COUNT(*) FROM proyectos p 
                LEFT JOIN usuarios u ON p.usuario_id = u.id 
                WHERE u.id IS NULL
            ");
            return $stmt->fetchColumn() === 0;
        });
        
        $this->test("No hay registros huérfanos en rodales", function() {
            $stmt = $this->pdo->query("
                SELECT COUNT(*) FROM rodales r 
                LEFT JOIN proyectos p ON r.proyecto_id = p.id 
                WHERE p.id IS NULL
            ");
            return $stmt->fetchColumn() === 0;
        });
        
        $this->test("No hay registros huérfanos en datos_campo", function() {
            $stmt = $this->pdo->query("
                SELECT COUNT(*) FROM datos_campo dc 
                LEFT JOIN rodales r ON dc.rodal_id = r.id 
                WHERE r.id IS NULL
            ");
            return $stmt->fetchColumn() === 0;
        });
        
        $this->test("Todas las especies en datos_campo existen", function() {
            $stmt = $this->pdo->query("
                SELECT COUNT(*) FROM datos_campo dc 
                LEFT JOIN especies e ON dc.especie_id = e.id 
                WHERE e.id IS NULL
            ");
            return $stmt->fetchColumn() === 0;
        });
    }
    
    /**
     * Probar restricciones (constraints)
     */
    private function testConstraints() {
        $this->test("Constraint de área positiva en rodales", function() {
            try {
                $stmt = $this->pdo->prepare("INSERT INTO rodales (proyecto_id, nombre_rodal, area_ha) VALUES (1, 'Test', -1)");
                $stmt->execute();
                return false; // No debería llegar aquí
            } catch (PDOException $e) {
                return strpos($e->getMessage(), 'chk_area_positiva') !== false;
            }
        });
        
        $this->test("Constraint de DAP positivo en datos_campo", function() {
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO datos_campo (rodal_id, numero_parcela, latitud, longitud, especie_id, dap_cm, altura_m, condicion_arbol, usuario_id) 
                    VALUES (1, 1, 14.6349, -90.5069, 1, -5, 10, 'Sano', 1)
                ");
                $stmt->execute();
                return false; // No debería llegar aquí
            } catch (PDOException $e) {
                return strpos($e->getMessage(), 'chk_dap_positivo') !== false;
            }
        });
        
        $this->test("Constraint de altura positiva en datos_campo", function() {
            try {
                $stmt = $this->pdo->prepare("
                    INSERT INTO datos_campo (rodal_id, numero_parcela, latitud, longitud, especie_id, dap_cm, altura_m, condicion_arbol, usuario_id) 
                    VALUES (1, 1, 14.6349, -90.5069, 1, 15, -2, 'Sano', 1)
                ");
                $stmt->execute();
                return false; // No debería llegar aquí
            } catch (PDOException $e) {
                return strpos($e->getMessage(), 'chk_altura_positiva') !== false;
            }
        });
    }
    
    /**
     * Probar índices
     */
    private function testIndexes() {
        $expectedIndexes = [
            ['usuarios', 'email_unique'],
            ['datos_campo', 'idx_rodal_id'],
            ['datos_campo', 'idx_estado_sincronizacion'],
            ['especies', 'idx_nombre_cientifico'],
            ['proyectos', 'idx_departamento']
        ];
        
        foreach ($expectedIndexes as $index) {
            $table = $index[0];
            $indexName = $index[1];
            
            $this->test("Índice '{$indexName}' en tabla '{$table}'", function() use ($table, $indexName) {
                $stmt = $this->pdo->prepare("
                    SELECT COUNT(*) FROM information_schema.STATISTICS 
                    WHERE TABLE_SCHEMA = DATABASE() 
                    AND TABLE_NAME = ? 
                    AND INDEX_NAME = ?
                ");
                $stmt->execute([$table, $indexName]);
                return $stmt->fetchColumn() > 0;
            });
        }
    }
    
    /**
     * Probar vistas
     */
    private function testViews() {
        $expectedViews = [
            'vista_resumen_proyectos',
            'vista_estadisticas_rodal'
        ];
        
        foreach ($expectedViews as $view) {
            $this->test("Vista '{$view}' existe", function() use ($view) {
                $stmt = $this->pdo->prepare("
                    SELECT COUNT(*) FROM information_schema.VIEWS 
                    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?
                ");
                $stmt->execute([$view]);
                return $stmt->fetchColumn() > 0;
            });
            
            $this->test("Vista '{$view}' es consultable", function() use ($view) {
                try {
                    $stmt = $this->pdo->query("SELECT COUNT(*) FROM `{$view}`");
                    $stmt->fetchColumn();
                    return true;
                } catch (Exception $e) {
                    return false;
                }
            });
        }
    }
    
    /**
     * Probar triggers
     */
    private function testTriggers() {
        $this->test("Trigger de sincronización existe", function() {
            $stmt = $this->pdo->prepare("
                SELECT COUNT(*) FROM information_schema.TRIGGERS 
                WHERE TRIGGER_SCHEMA = DATABASE() 
                AND TRIGGER_NAME = 'tr_datos_campo_sync_update'
            ");
            $stmt->execute();
            return $stmt->fetchColumn() > 0;
        });
    }
    
    /**
     * Ejecutar una prueba individual
     */
    private function test($description, $testFunction) {
        try {
            $result = $testFunction();
            if ($result) {
                echo "✅ {$description}\n";
                $this->passed++;
            } else {
                echo "❌ {$description}\n";
                $this->failed++;
            }
            $this->tests[] = ['description' => $description, 'passed' => $result];
        } catch (Exception $e) {
            echo "❌ {$description} - Error: " . $e->getMessage() . "\n";
            $this->failed++;
            $this->tests[] = ['description' => $description, 'passed' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Mostrar resultados finales
     */
    private function showResults() {
        echo "\n=== RESULTADOS DE PRUEBAS ===\n";
        echo "Total de pruebas: " . count($this->tests) . "\n";
        echo "Pasaron: {$this->passed}\n";
        echo "Fallaron: {$this->failed}\n";
        
        $percentage = count($this->tests) > 0 ? round(($this->passed / count($this->tests)) * 100, 2) : 0;
        echo "Porcentaje de éxito: {$percentage}%\n";
        
        if ($this->failed > 0) {
            echo "\n❌ PRUEBAS FALLIDAS:\n";
            foreach ($this->tests as $test) {
                if (!$test['passed']) {
                    echo "  • {$test['description']}";
                    if (isset($test['error'])) {
                        echo " - {$test['error']}";
                    }
                    echo "\n";
                }
            }
        }
        
        if ($this->failed === 0) {
            echo "\n🎉 ¡Todas las pruebas pasaron exitosamente!\n";
            echo "La base de datos está correctamente configurada con datos iniciales.\n";
        } else {
            echo "\n⚠️  Algunas pruebas fallaron. Revise la configuración de la base de datos.\n";
        }
    }
    
    /**
     * Obtener estadísticas detalladas
     */
    public function getDetailedStats() {
        $stats = [];
        
        // Estadísticas de tablas
        $tables = ['usuarios', 'proyectos', 'rodales', 'especies', 'datos_campo', 'configuracion'];
        foreach ($tables as $table) {
            try {
                $stmt = $this->pdo->query("SELECT COUNT(*) FROM `{$table}`");
                $stats['tables'][$table] = $stmt->fetchColumn();
            } catch (Exception $e) {
                $stats['tables'][$table] = 'Error: ' . $e->getMessage();
            }
        }
        
        // Estadísticas de especies por estado
        try {
            $stmt = $this->pdo->query("SELECT activa, COUNT(*) as count FROM especies GROUP BY activa");
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $status = $row['activa'] ? 'activas' : 'inactivas';
                $stats['especies'][$status] = $row['count'];
            }
        } catch (Exception $e) {
            $stats['especies'] = 'Error: ' . $e->getMessage();
        }
        
        // Estadísticas de configuraciones
        try {
            $stmt = $this->pdo->query("SELECT COUNT(*) FROM configuracion");
            $stats['configuraciones']['total'] = $stmt->fetchColumn();
            
            $stmt = $this->pdo->query("SELECT COUNT(*) FROM configuracion WHERE descripcion IS NOT NULL");
            $stats['configuraciones']['con_descripcion'] = $stmt->fetchColumn();
        } catch (Exception $e) {
            $stats['configuraciones'] = 'Error: ' . $e->getMessage();
        }
        
        return $stats;
    }
}

// Ejecutar si se llama directamente
if (basename(__FILE__) == basename($_SERVER['SCRIPT_NAME'])) {
    $tester = new InitialDataTester();
    $tester->runAllTests();
    
    echo "\n=== ESTADÍSTICAS DETALLADAS ===\n";
    $stats = $tester->getDetailedStats();
    
    if (isset($stats['tables'])) {
        echo "\nRegistros por tabla:\n";
        foreach ($stats['tables'] as $table => $count) {
            echo "  {$table}: {$count}\n";
        }
    }
    
    if (isset($stats['especies'])) {
        echo "\nEspecies:\n";
        foreach ($stats['especies'] as $status => $count) {
            echo "  {$status}: {$count}\n";
        }
    }
    
    if (isset($stats['configuraciones'])) {
        echo "\nConfiguraciones:\n";
        foreach ($stats['configuraciones'] as $type => $count) {
            echo "  {$type}: {$count}\n";
        }
    }
}
?>