<?php
require_once __DIR__ . '/../utils/Cache.php';

class Species {
    private $conn;
    private $table_name = "especies";

    public $id;
    public $nombre_cientifico;
    public $nombre_comun;
    public $activa;
    public $fecha_creacion;

    public function __construct($db) {
        $this->conn = $db;
    }

    // Crear nueva especie
    public function create() {
        $query = "INSERT INTO " . $this->table_name . " 
                  (nombre_cientifico, nombre_comun, activa) 
                  VALUES (:nombre_cientifico, :nombre_comun, :activa)";

        $stmt = $this->conn->prepare($query);

        // Sanitizar datos
        $this->nombre_cientifico = htmlspecialchars(strip_tags($this->nombre_cientifico));
        $this->nombre_comun = htmlspecialchars(strip_tags($this->nombre_comun));
        $this->activa = $this->activa !== null ? $this->activa : true;

        // Bind de parámetros
        $stmt->bindParam(":nombre_cientifico", $this->nombre_cientifico);
        $stmt->bindParam(":nombre_comun", $this->nombre_comun);
        $stmt->bindParam(":activa", $this->activa);

        if ($stmt->execute()) {
            $this->id = $this->conn->lastInsertId();
            // Invalidate species cache
            $this->invalidateSpeciesCache();
            return true;
        }

        return false;
    }

    // Obtener todas las especies activas (con cache)
    public function read() {
        $cacheKey = 'species_active_all';
        
        return Cache::remember($cacheKey, function() {
            $query = "SELECT * FROM " . $this->table_name . " 
                      WHERE activa = 1 
                      ORDER BY nombre_comun ASC";

            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }, 3600); // Cache for 1 hour
    }

    // Obtener todas las especies (incluyendo inactivas) - para administradores
    public function readAll() {
        $query = "SELECT * FROM " . $this->table_name . " 
                  ORDER BY activa DESC, nombre_comun ASC";

        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        return $stmt;
    }

    // Buscar especie por ID
    public function findById($id) {
        $query = "SELECT * FROM " . $this->table_name . " 
                  WHERE id = :id 
                  LIMIT 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $id);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            $this->id = $row['id'];
            $this->nombre_cientifico = $row['nombre_cientifico'];
            $this->nombre_comun = $row['nombre_comun'];
            $this->activa = $row['activa'];
            $this->fecha_creacion = $row['fecha_creacion'];
            
            return true;
        }

        return false;
    }

    // Buscar especie por nombre científico
    public function findByScientificName($nombre) {
        $query = "SELECT * FROM " . $this->table_name . " 
                  WHERE nombre_cientifico = :nombre 
                  LIMIT 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":nombre", $nombre);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            $this->id = $row['id'];
            $this->nombre_cientifico = $row['nombre_cientifico'];
            $this->nombre_comun = $row['nombre_comun'];
            $this->activa = $row['activa'];
            $this->fecha_creacion = $row['fecha_creacion'];
            
            return true;
        }

        return false;
    }

    // Actualizar especie
    public function update() {
        $query = "UPDATE " . $this->table_name . " 
                  SET nombre_cientifico = :nombre_cientifico, 
                      nombre_comun = :nombre_comun, 
                      activa = :activa
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);

        // Sanitizar datos
        $this->nombre_cientifico = htmlspecialchars(strip_tags($this->nombre_cientifico));
        $this->nombre_comun = htmlspecialchars(strip_tags($this->nombre_comun));

        // Bind de parámetros
        $stmt->bindParam(":nombre_cientifico", $this->nombre_cientifico);
        $stmt->bindParam(":nombre_comun", $this->nombre_comun);
        $stmt->bindParam(":activa", $this->activa);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Desactivar especie (soft delete)
    public function deactivate() {
        $query = "UPDATE " . $this->table_name . " 
                  SET activa = 0 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Activar especie
    public function activate() {
        $query = "UPDATE " . $this->table_name . " 
                  SET activa = 1 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Eliminar especie permanentemente (solo si no tiene registros asociados)
    public function delete() {
        // Verificar si tiene registros de campo asociados
        $checkQuery = "SELECT COUNT(*) as count FROM datos_campo WHERE especie_id = :id";
        $checkStmt = $this->conn->prepare($checkQuery);
        $checkStmt->bindParam(":id", $this->id);
        $checkStmt->execute();
        $result = $checkStmt->fetch(PDO::FETCH_ASSOC);

        if ($result['count'] > 0) {
            return ['error' => 'No se puede eliminar la especie porque tiene registros de campo asociados'];
        }

        $query = "DELETE FROM " . $this->table_name . " WHERE id = :id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Validar datos de la especie
    public function validate() {
        $errors = [];

        // Validar nombre científico
        if (empty($this->nombre_cientifico)) {
            $errors[] = "El nombre científico es requerido";
        } elseif (strlen($this->nombre_cientifico) < 3) {
            $errors[] = "El nombre científico debe tener al menos 3 caracteres";
        } elseif (strlen($this->nombre_cientifico) > 200) {
            $errors[] = "El nombre científico no puede exceder 200 caracteres";
        } elseif (!$this->isValidScientificName($this->nombre_cientifico)) {
            $errors[] = "El nombre científico debe seguir la nomenclatura binomial (Género especie)";
        }

        // Validar nombre común
        if (empty($this->nombre_comun)) {
            $errors[] = "El nombre común es requerido";
        } elseif (strlen($this->nombre_comun) < 2) {
            $errors[] = "El nombre común debe tener al menos 2 caracteres";
        } elseif (strlen($this->nombre_comun) > 200) {
            $errors[] = "El nombre común no puede exceder 200 caracteres";
        }

        return $errors;
    }

    // Validar formato de nombre científico
    private function isValidScientificName($name) {
        // Verificar que siga el formato básico de nomenclatura binomial
        // Debe tener al menos dos palabras, la primera con mayúscula
        $pattern = '/^[A-Z][a-z]+ [a-z]+( [a-z]+)*$/';
        return preg_match($pattern, $name);
    }

    // Verificar si el nombre científico ya existe
    public function scientificNameExists($nombre, $excludeId = null) {
        $query = "SELECT id FROM " . $this->table_name . " WHERE nombre_cientifico = :nombre";
        
        if ($excludeId) {
            $query .= " AND id != :exclude_id";
        }

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":nombre", $nombre);
        
        if ($excludeId) {
            $stmt->bindParam(":exclude_id", $excludeId);
        }
        
        $stmt->execute();

        return $stmt->rowCount() > 0;
    }

    // Buscar especies por texto (nombre científico o común)
    public function search($searchTerm) {
        $query = "SELECT * FROM " . $this->table_name . " 
                  WHERE activa = 1 
                  AND (nombre_cientifico LIKE :search OR nombre_comun LIKE :search)
                  ORDER BY nombre_comun ASC";

        $stmt = $this->conn->prepare($query);
        $searchParam = '%' . $searchTerm . '%';
        $stmt->bindParam(":search", $searchParam);
        $stmt->execute();

        return $stmt;
    }

    // Obtener especies más utilizadas
    public function getMostUsedSpecies($limit = 10) {
        $query = "SELECT 
                    e.*,
                    COUNT(dc.id) as uso_count,
                    COUNT(DISTINCT dc.rodal_id) as rodales_count
                  FROM " . $this->table_name . " e
                  LEFT JOIN datos_campo dc ON e.id = dc.especie_id
                  WHERE e.activa = 1
                  GROUP BY e.id
                  ORDER BY uso_count DESC, e.nombre_comun ASC
                  LIMIT :limit";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":limit", $limit, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    // Obtener estadísticas de uso de especies
    public function getUsageStats() {
        $query = "SELECT 
                    COUNT(DISTINCT e.id) as total_especies,
                    COUNT(DISTINCT CASE WHEN e.activa = 1 THEN e.id END) as especies_activas,
                    COUNT(DISTINCT CASE WHEN dc.id IS NOT NULL THEN e.id END) as especies_usadas,
                    COUNT(dc.id) as total_registros
                  FROM " . $this->table_name . " e
                  LEFT JOIN datos_campo dc ON e.id = dc.especie_id";

        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    // Obtener catálogo predefinido de especies de Guatemala
    public static function getGuatemalaSpeciesCatalog() {
        return [
            // Coníferas
            ['nombre_cientifico' => 'Pinus maximinoi', 'nombre_comun' => 'Pino Candelillo'],
            ['nombre_cientifico' => 'Pinus oocarpa', 'nombre_comun' => 'Pino Ocote'],
            ['nombre_cientifico' => 'Pinus pseudostrobus', 'nombre_comun' => 'Pino Blanco'],
            ['nombre_cientifico' => 'Pinus rudis', 'nombre_comun' => 'Pino Colorado'],
            ['nombre_cientifico' => 'Cupressus lusitanica', 'nombre_comun' => 'Ciprés Común'],
            ['nombre_cientifico' => 'Abies guatemalensis', 'nombre_comun' => 'Pinabete'],
            
            // Latifoliadas de bosque nuboso
            ['nombre_cientifico' => 'Quercus sp.', 'nombre_comun' => 'Encino'],
            ['nombre_cientifico' => 'Alnus acuminata', 'nombre_comun' => 'Aliso'],
            ['nombre_cientifico' => 'Liquidambar styraciflua', 'nombre_comun' => 'Liquidámbar'],
            ['nombre_cientifico' => 'Persea americana', 'nombre_comun' => 'Aguacate de Monte'],
            
            // Especies de bosque seco
            ['nombre_cientifico' => 'Cedrela odorata', 'nombre_comun' => 'Cedro'],
            ['nombre_cientifico' => 'Swietenia macrophylla', 'nombre_comun' => 'Caoba'],
            ['nombre_cientifico' => 'Cordia alliodora', 'nombre_comun' => 'Laurel'],
            ['nombre_cientifico' => 'Tabebuia rosea', 'nombre_comun' => 'Matilisguate'],
            ['nombre_cientifico' => 'Dalbergia retusa', 'nombre_comun' => 'Cocobolo'],
            
            // Especies de bosque húmedo tropical
            ['nombre_cientifico' => 'Ceiba pentandra', 'nombre_comun' => 'Ceiba'],
            ['nombre_cientifico' => 'Terminalia amazonia', 'nombre_comun' => 'Volador'],
            ['nombre_cientifico' => 'Vochysia guatemalensis', 'nombre_comun' => 'San Juan'],
            ['nombre_cientifico' => 'Calophyllum brasiliense', 'nombre_comun' => 'Santa María'],
            ['nombre_cientifico' => 'Virola koschnyi', 'nombre_comun' => 'Sangre'],
            
            // Especies de manglares
            ['nombre_cientifico' => 'Rhizophora mangle', 'nombre_comun' => 'Mangle Colorado'],
            ['nombre_cientifico' => 'Avicennia germinans', 'nombre_comun' => 'Mangle Negro'],
            ['nombre_cientifico' => 'Laguncularia racemosa', 'nombre_comun' => 'Mangle Blanco'],
            
            // Especies de plantaciones
            ['nombre_cientifico' => 'Eucalyptus camaldulensis', 'nombre_comun' => 'Eucalipto'],
            ['nombre_cientifico' => 'Tectona grandis', 'nombre_comun' => 'Teca'],
            ['nombre_cientifico' => 'Gmelina arborea', 'nombre_comun' => 'Melina'],
            
            // Especies frutales forestales
            ['nombre_cientifico' => 'Brosimum alicastrum', 'nombre_comun' => 'Ramón'],
            ['nombre_cientifico' => 'Manilkara zapota', 'nombre_comun' => 'Chicozapote'],
            ['nombre_cientifico' => 'Pouteria sapota', 'nombre_comun' => 'Zapote'],
            
            // Otras especies importantes
            ['nombre_cientifico' => 'Ochroma pyramidale', 'nombre_comun' => 'Cecropia'],
            ['nombre_cientifico' => 'Inga sp.', 'nombre_comun' => 'Cujinicuil'],
            ['nombre_cientifico' => 'Erythrina sp.', 'nombre_comun' => 'Pito'],
            ['nombre_cientifico' => 'Gliricidia sepium', 'nombre_comun' => 'Madrecacao'],
            ['nombre_cientifico' => 'Schizolobium parahyba', 'nombre_comun' => 'Gallinazo']
        ];
    }

    // Inicializar catálogo de especies de Guatemala
    public function initializeGuatemalaCatalog() {
        $especies = self::getGuatemalaSpeciesCatalog();
        $insertedCount = 0;
        $errors = [];

        foreach ($especies as $especie) {
            // Verificar si ya existe
            if (!$this->scientificNameExists($especie['nombre_cientifico'])) {
                $this->nombre_cientifico = $especie['nombre_cientifico'];
                $this->nombre_comun = $especie['nombre_comun'];
                $this->activa = true;

                if ($this->create()) {
                    $insertedCount++;
                } else {
                    $errors[] = "Error al insertar: " . $especie['nombre_cientifico'];
                }
            }
        }

        return [
            'inserted' => $insertedCount,
            'total' => count($especies),
            'errors' => $errors
        ];
    }

    // Obtener especies por región ecológica
    public function getSpeciesByEcoregion($ecoregion) {
        $regionSpecies = [
            'bosque_nuboso' => ['Quercus sp.', 'Alnus acuminata', 'Liquidambar styraciflua', 'Abies guatemalensis'],
            'bosque_seco' => ['Cedrela odorata', 'Swietenia macrophylla', 'Tabebuia rosea', 'Cordia alliodora'],
            'bosque_humedo' => ['Ceiba pentandra', 'Terminalia amazonia', 'Vochysia guatemalensis', 'Virola koschnyi'],
            'conífera' => ['Pinus maximinoi', 'Pinus oocarpa', 'Pinus pseudostrobus', 'Cupressus lusitanica'],
            'manglar' => ['Rhizophora mangle', 'Avicennia germinans', 'Laguncularia racemosa']
        ];

        if (!isset($regionSpecies[$ecoregion])) {
            return [];
        }

        $scientificNames = $regionSpecies[$ecoregion];
        $placeholders = str_repeat('?,', count($scientificNames) - 1) . '?';
        
        $query = "SELECT * FROM " . $this->table_name . " 
                  WHERE nombre_cientifico IN ($placeholders) 
                  AND activa = 1 
                  ORDER BY nombre_comun ASC";

        $stmt = $this->conn->prepare($query);
        $stmt->execute($scientificNames);

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    // Obtener especies recomendadas para inventario forestal (con cache)
    public function getRecommendedForInventory() {
        $cacheKey = 'species_recommended_inventory';
        
        return Cache::remember($cacheKey, function() {
            // Especies más comunes en inventarios forestales de Guatemala
            $recommendedSpecies = [
                'Pinus maximinoi', 'Pinus oocarpa', 'Cupressus lusitanica', 
                'Quercus sp.', 'Alnus acuminata', 'Cedrela odorata', 
                'Swietenia macrophylla', 'Cordia alliodora', 'Liquidambar styraciflua',
                'Terminalia amazonia'
            ];

            $placeholders = str_repeat('?,', count($recommendedSpecies) - 1) . '?';
            
            $query = "SELECT * FROM " . $this->table_name . " 
                      WHERE nombre_cientifico IN ($placeholders) 
                      AND activa = 1 
                      ORDER BY nombre_comun ASC";

            $stmt = $this->conn->prepare($query);
            $stmt->execute($recommendedSpecies);

            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }, 7200); // Cache for 2 hours
    }

    // Obtener especies más utilizadas (con cache)
    public function getMostUsedSpeciesCached($limit = 10) {
        $cacheKey = "species_most_used_{$limit}";
        
        return Cache::remember($cacheKey, function() use ($limit) {
            return $this->getMostUsedSpecies($limit);
        }, 1800); // Cache for 30 minutes
    }

    // Invalidar cache de especies
    private function invalidateSpeciesCache() {
        Cache::delete('species_active_all');
        Cache::delete('species_recommended_inventory');
        
        // Invalidate most used species cache for different limits
        for ($i = 5; $i <= 20; $i += 5) {
            Cache::delete("species_most_used_{$i}");
        }
    }

    // Actualizar especie (con invalidación de cache)
    public function updateWithCache() {
        $result = $this->update();
        if ($result) {
            $this->invalidateSpeciesCache();
        }
        return $result;
    }

    // Desactivar especie (con invalidación de cache)
    public function deactivateWithCache() {
        $result = $this->deactivate();
        if ($result) {
            $this->invalidateSpeciesCache();
        }
        return $result;
    }

    // Activar especie (con invalidación de cache)
    public function activateWithCache() {
        $result = $this->activate();
        if ($result) {
            $this->invalidateSpeciesCache();
        }
        return $result;
    }
}
?>