<?php
class Rodal {
    private $conn;
    private $table_name = "rodales";

    public $id;
    public $proyecto_id;
    public $nombre_rodal;
    public $area_ha;
    public $fecha_creacion;

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

    // Crear nuevo rodal
    public function create() {
        $query = "INSERT INTO " . $this->table_name . " 
                  (proyecto_id, nombre_rodal, area_ha) 
                  VALUES (:proyecto_id, :nombre_rodal, :area_ha)";

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

        // Sanitizar datos
        $this->nombre_rodal = htmlspecialchars(strip_tags($this->nombre_rodal));
        $this->area_ha = floatval($this->area_ha);

        // Bind de parámetros
        $stmt->bindParam(":proyecto_id", $this->proyecto_id);
        $stmt->bindParam(":nombre_rodal", $this->nombre_rodal);
        $stmt->bindParam(":area_ha", $this->area_ha);

        if ($stmt->execute()) {
            $this->id = $this->conn->lastInsertId();
            return true;
        }

        return false;
    }

    // Obtener todos los rodales
    public function read() {
        $query = "SELECT r.*, p.nombre_proyecto 
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  ORDER BY r.fecha_creacion DESC";

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

        return $stmt;
    }

    // Obtener rodales por proyecto
    public function readByProject($projectId) {
        $query = "SELECT r.*, p.nombre_proyecto 
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  WHERE r.proyecto_id = :proyecto_id
                  ORDER BY r.nombre_rodal ASC";

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

        return $stmt;
    }

    // Buscar rodal por ID
    public function findById($id) {
        $query = "SELECT r.*, p.nombre_proyecto 
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  WHERE r.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->proyecto_id = $row['proyecto_id'];
            $this->nombre_rodal = $row['nombre_rodal'];
            $this->area_ha = $row['area_ha'];
            $this->fecha_creacion = $row['fecha_creacion'];
            
            return true;
        }

        return false;
    }

    // Obtener rodal por ID como array
    public function getById($id) {
        $query = "SELECT r.*, p.nombre_proyecto 
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  WHERE r.id = :id 
                  LIMIT 1";

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

        if ($stmt->rowCount() > 0) {
            return $stmt->fetch(PDO::FETCH_ASSOC);
        }

        return null;
    }

    // Obtener rodales por proyecto como array
    public function getByProjectId($projectId) {
        $query = "SELECT r.*, p.nombre_proyecto 
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  WHERE r.proyecto_id = :proyecto_id
                  ORDER BY r.nombre_rodal ASC";

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

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

    // Actualizar rodal
    public function update() {
        $query = "UPDATE " . $this->table_name . " 
                  SET nombre_rodal = :nombre_rodal, area_ha = :area_ha
                  WHERE id = :id";

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

        // Sanitizar datos
        $this->nombre_rodal = htmlspecialchars(strip_tags($this->nombre_rodal));
        $this->area_ha = floatval($this->area_ha);

        // Bind de parámetros
        $stmt->bindParam(":nombre_rodal", $this->nombre_rodal);
        $stmt->bindParam(":area_ha", $this->area_ha);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Eliminar rodal
    public function delete() {
        // Verificar si tiene datos de campo asociados
        $checkQuery = "SELECT COUNT(*) as count FROM datos_campo WHERE rodal_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 el rodal porque tiene datos 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 del rodal
    public function validate() {
        $errors = [];

        // Validar proyecto_id
        if (empty($this->proyecto_id)) {
            $errors[] = "El ID del proyecto es requerido";
        } else {
            // Verificar que el proyecto existe
            $checkQuery = "SELECT id FROM proyectos WHERE id = :proyecto_id";
            $checkStmt = $this->conn->prepare($checkQuery);
            $checkStmt->bindParam(":proyecto_id", $this->proyecto_id);
            $checkStmt->execute();
            
            if ($checkStmt->rowCount() === 0) {
                $errors[] = "El proyecto especificado no existe";
            }
        }

        // Validar nombre del rodal
        if (empty($this->nombre_rodal)) {
            $errors[] = "El nombre del rodal es requerido";
        } elseif (strlen($this->nombre_rodal) < 2) {
            $errors[] = "El nombre del rodal debe tener al menos 2 caracteres";
        } elseif (strlen($this->nombre_rodal) > 100) {
            $errors[] = "El nombre del rodal no puede exceder 100 caracteres";
        }

        // Validar área en hectáreas
        if (empty($this->area_ha) || $this->area_ha <= 0) {
            $errors[] = "El área debe ser mayor a 0 hectáreas";
        } elseif ($this->area_ha > 10000) {
            $errors[] = "El área no puede exceder 10,000 hectáreas";
        } elseif (!is_numeric($this->area_ha)) {
            $errors[] = "El área debe ser un valor numérico";
        }

        return $errors;
    }

    // Verificar si el nombre del rodal ya existe en el proyecto
    public function rodalNameExistsInProject($nombre, $projectId, $excludeId = null) {
        $query = "SELECT id FROM " . $this->table_name . " 
                  WHERE nombre_rodal = :nombre AND proyecto_id = :proyecto_id";
        
        if ($excludeId) {
            $query .= " AND id != :exclude_id";
        }

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

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

    // Obtener estadísticas del rodal
    public function getRodalStatistics($rodalId) {
        $query = "SELECT 
                    r.*,
                    p.nombre_proyecto,
                    COUNT(dc.id) as total_arboles,
                    COALESCE(AVG(dc.dap_cm), 0) as dap_promedio,
                    COALESCE(AVG(dc.altura_m), 0) as altura_promedio,
                    COALESCE(MAX(dc.dap_cm), 0) as dap_maximo,
                    COALESCE(MAX(dc.altura_m), 0) as altura_maxima,
                    COALESCE(MIN(dc.dap_cm), 0) as dap_minimo,
                    COALESCE(MIN(dc.altura_m), 0) as altura_minima,
                    COUNT(DISTINCT dc.numero_parcela) as total_parcelas,
                    COUNT(DISTINCT dc.especie_id) as total_especies,
                    SUM(CASE WHEN dc.estado_sincronizacion = 'Sincronizado' THEN 1 ELSE 0 END) as registros_sincronizados,
                    SUM(CASE WHEN dc.estado_sincronizacion = 'Pendiente' THEN 1 ELSE 0 END) as registros_pendientes,
                    SUM(CASE WHEN dc.condicion_arbol = 'Sano' THEN 1 ELSE 0 END) as arboles_sanos,
                    SUM(CASE WHEN dc.condicion_arbol = 'Bifurcado' THEN 1 ELSE 0 END) as arboles_bifurcados,
                    SUM(CASE WHEN dc.condicion_arbol = 'Plagado' THEN 1 ELSE 0 END) as arboles_plagados,
                    SUM(CASE WHEN dc.condicion_arbol = 'Muerto en Pie' THEN 1 ELSE 0 END) as arboles_muertos
                  FROM " . $this->table_name . " r
                  LEFT JOIN proyectos p ON r.proyecto_id = p.id
                  LEFT JOIN datos_campo dc ON r.id = dc.rodal_id
                  WHERE r.id = :rodal_id
                  GROUP BY r.id";

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

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

    // Calcular área basal del rodal (m²/ha)
    public function calculateAreaBasal($rodalId) {
        $query = "SELECT dap_cm FROM datos_campo WHERE rodal_id = :rodal_id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":rodal_id", $rodalId);
        $stmt->execute();

        $registros = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        if (empty($registros)) {
            return 0;
        }

        // Obtener área del rodal
        $rodalQuery = "SELECT area_ha FROM " . $this->table_name . " WHERE id = :rodal_id";
        $rodalStmt = $this->conn->prepare($rodalQuery);
        $rodalStmt->bindParam(":rodal_id", $rodalId);
        $rodalStmt->execute();
        $rodalData = $rodalStmt->fetch(PDO::FETCH_ASSOC);

        if (!$rodalData) {
            return 0;
        }

        $areaRodal = $rodalData['area_ha'];
        $sumaAreaBasal = 0;

        foreach ($registros as $registro) {
            $radio = $registro['dap_cm'] / 2 / 100; // convertir a metros
            $areaBasalArbol = pi() * pow($radio, 2);
            $sumaAreaBasal += $areaBasalArbol;
        }

        return round($sumaAreaBasal / $areaRodal, 2);
    }

    // Calcular volumen del rodal (m³/ha)
    public function calculateVolume($rodalId) {
        $query = "SELECT dap_cm, altura_m FROM datos_campo WHERE rodal_id = :rodal_id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":rodal_id", $rodalId);
        $stmt->execute();

        $registros = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        if (empty($registros)) {
            return 0;
        }

        // Obtener área del rodal
        $rodalQuery = "SELECT area_ha FROM " . $this->table_name . " WHERE id = :rodal_id";
        $rodalStmt = $this->conn->prepare($rodalQuery);
        $rodalStmt->bindParam(":rodal_id", $rodalId);
        $rodalStmt->execute();
        $rodalData = $rodalStmt->fetch(PDO::FETCH_ASSOC);

        if (!$rodalData) {
            return 0;
        }

        $areaRodal = $rodalData['area_ha'];
        $volumenTotal = 0;

        foreach ($registros as $registro) {
            $radio = $registro['dap_cm'] / 2 / 100; // convertir a metros
            $areaBasalArbol = pi() * pow($radio, 2);
            $volumenArbol = $areaBasalArbol * $registro['altura_m'] * 0.7; // Factor de forma típico
            $volumenTotal += $volumenArbol;
        }

        return round($volumenTotal / $areaRodal, 2);
    }

    // Calcular densidad de árboles por hectárea
    public function calculateTreeDensity($rodalId) {
        $query = "SELECT COUNT(*) as total_arboles FROM datos_campo WHERE rodal_id = :rodal_id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":rodal_id", $rodalId);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        // Obtener área del rodal
        $rodalQuery = "SELECT area_ha FROM " . $this->table_name . " WHERE id = :rodal_id";
        $rodalStmt = $this->conn->prepare($rodalQuery);
        $rodalStmt->bindParam(":rodal_id", $rodalId);
        $rodalStmt->execute();
        $rodalData = $rodalStmt->fetch(PDO::FETCH_ASSOC);

        if (!$rodalData || $rodalData['area_ha'] == 0) {
            return 0;
        }

        return round($result['total_arboles'] / $rodalData['area_ha'], 0);
    }

    // Obtener resumen completo de cálculos forestales
    public function getForestCalculations($rodalId) {
        $stats = $this->getRodalStatistics($rodalId);
        
        if (!$stats) {
            return null;
        }

        return [
            'rodal_info' => [
                'id' => $stats['id'],
                'nombre_rodal' => $stats['nombre_rodal'],
                'area_ha' => $stats['area_ha'],
                'proyecto' => $stats['nombre_proyecto']
            ],
            'conteos' => [
                'total_arboles' => $stats['total_arboles'],
                'total_parcelas' => $stats['total_parcelas'],
                'total_especies' => $stats['total_especies'],
                'densidad_por_ha' => $this->calculateTreeDensity($rodalId)
            ],
            'promedios' => [
                'dap_promedio' => round($stats['dap_promedio'], 2),
                'altura_promedio' => round($stats['altura_promedio'], 2)
            ],
            'rangos' => [
                'dap_minimo' => $stats['dap_minimo'],
                'dap_maximo' => $stats['dap_maximo'],
                'altura_minima' => $stats['altura_minima'],
                'altura_maxima' => $stats['altura_maxima']
            ],
            'calculos_forestales' => [
                'area_basal_m2_ha' => $this->calculateAreaBasal($rodalId),
                'volumen_m3_ha' => $this->calculateVolume($rodalId)
            ],
            'condicion_arboles' => [
                'sanos' => $stats['arboles_sanos'],
                'bifurcados' => $stats['arboles_bifurcados'],
                'plagados' => $stats['arboles_plagados'],
                'muertos' => $stats['arboles_muertos']
            ],
            'sincronizacion' => [
                'sincronizados' => $stats['registros_sincronizados'],
                'pendientes' => $stats['registros_pendientes']
            ]
        ];
    }

    // Validar área según estándares forestales
    public function validateAreaForestry($area) {
        $warnings = [];
        $errors = [];

        if ($area < 0.1) {
            $warnings[] = "Área muy pequeña para inventario forestal (< 0.1 ha)";
        }

        if ($area > 1000) {
            $warnings[] = "Área muy grande, considere dividir en rodales más pequeños";
        }

        if ($area <= 0) {
            $errors[] = "El área debe ser mayor a 0";
        }

        return [
            'errors' => $errors,
            'warnings' => $warnings,
            'valid' => empty($errors)
        ];
    }

    // Obtener especies más comunes en el rodal
    public function getTopSpecies($rodalId, $limit = 5) {
        $query = "SELECT 
                    e.nombre_cientifico,
                    e.nombre_comun,
                    COUNT(dc.id) as cantidad,
                    ROUND((COUNT(dc.id) * 100.0 / (SELECT COUNT(*) FROM datos_campo WHERE rodal_id = :rodal_id)), 2) as porcentaje
                  FROM datos_campo dc
                  JOIN especies e ON dc.especie_id = e.id
                  WHERE dc.rodal_id = :rodal_id
                  GROUP BY e.id, e.nombre_cientifico, e.nombre_comun
                  ORDER BY cantidad DESC
                  LIMIT :limit";

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

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