<?php
require_once __DIR__ . '/../models/Rodal.php';
require_once __DIR__ . '/../models/Project.php';
require_once __DIR__ . '/../middleware/AuthMiddleware.php';
require_once __DIR__ . '/../middleware/RoleMiddleware.php';
require_once __DIR__ . '/../utils/Cache.php';

class RodalController {
    private $db;
    private $rodal;
    private $project;
    
    public function __construct($database) {
        $this->db = $database;
        $this->rodal = new Rodal($this->db);
        $this->project = new Project($this->db);
    }

    // GET /api/projects/{projectId}/rodales - Obtener rodales por proyecto
    public function getByProject($projectId) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente', 'Técnico de Campo']);
            
            // Verificar que el proyecto existe
            if (!$this->project->findById($projectId)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden ver rodales de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para ver los rodales de este proyecto'
                ]);
            }
            
            // Try to get from cache first (5 minutes TTL)
            $cacheKey = "rodales_project_{$projectId}_user_{$user['user_id']}";
            $rodales = Cache::get($cacheKey);
            
            if ($rodales === null) {
                // Obtener rodales del proyecto
                $stmt = $this->rodal->readByProject($projectId);
                $rodales = [];
                
                while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                    $rodales[] = [
                        'id' => (int)$row['id'],
                        'proyecto_id' => (int)$row['proyecto_id'],
                        'nombre_rodal' => $row['nombre_rodal'],
                        'area_ha' => (float)$row['area_ha'],
                        'fecha_creacion' => $row['fecha_creacion'],
                        'nombre_proyecto' => $row['nombre_proyecto']
                    ];
                }
                
                // Cache with tags for easy invalidation (5 minutes TTL)
                Cache::tag(['rodales', 'project_' . $projectId], $cacheKey, $rodales, 300);
            }
            
            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => $rodales,
                'total' => count($rodales),
                'proyecto_id' => (int)$projectId
            ]);
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener rodales: ' . $e->getMessage()
            ]);
        }
    }

    // POST /api/projects/{projectId}/rodales - Crear nuevo rodal
    public function store($projectId) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente']);
            
            // Verificar que el proyecto existe
            if (!$this->project->findById($projectId)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden crear rodales en sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para crear rodales en este proyecto'
                ]);
            }
            
            // Obtener datos del request
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!$input) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Datos de entrada inválidos'
                ]);
            }
            
            // Asignar datos al modelo
            $this->rodal->proyecto_id = $projectId;
            $this->rodal->nombre_rodal = $input['nombre_rodal'] ?? '';
            $this->rodal->area_ha = $input['area_ha'] ?? 0;
            
            // Validar datos
            $errors = $this->rodal->validate();
            if (!empty($errors)) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Errores de validación',
                    'errors' => $errors
                ]);
            }
            
            // Verificar que el nombre del rodal no exista en el proyecto
            if ($this->rodal->rodalNameExistsInProject($this->rodal->nombre_rodal, $projectId)) {
                http_response_code(409);
                return json_encode([
                    'success' => false,
                    'message' => 'Ya existe un rodal con este nombre en el proyecto'
                ]);
            }
            
            // Validar área según estándares forestales
            $areaValidation = $this->rodal->validateAreaForestry($this->rodal->area_ha);
            if (!$areaValidation['valid']) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Área inválida',
                    'errors' => $areaValidation['errors']
                ]);
            }
            
            // Crear rodal
            if ($this->rodal->create()) {
                // Invalidate rodales cache
                Cache::invalidateTag('rodales');
                Cache::invalidateTag('project_' . $projectId);
                
                $response = [
                    'success' => true,
                    'message' => 'Rodal creado exitosamente',
                    'data' => [
                        'id' => (int)$this->rodal->id,
                        'proyecto_id' => (int)$this->rodal->proyecto_id,
                        'nombre_rodal' => $this->rodal->nombre_rodal,
                        'area_ha' => (float)$this->rodal->area_ha
                    ]
                ];
                
                // Agregar advertencias si las hay
                if (!empty($areaValidation['warnings'])) {
                    $response['warnings'] = $areaValidation['warnings'];
                }
                
                http_response_code(201);
                return json_encode($response);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al crear el rodal'
                ]);
            }
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al crear rodal: ' . $e->getMessage()
            ]);
        }
    }

    // GET /api/rodales/{id} - Obtener rodal específico
    public function show($id) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente', 'Técnico de Campo']);
            
            if (!$this->rodal->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Rodal no encontrado'
                ]);
            }
            
            // Verificar permisos del proyecto asociado
            if (!$this->project->findById($this->rodal->proyecto_id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto asociado no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden ver rodales de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para ver este rodal'
                ]);
            }
            
            // Obtener estadísticas completas del rodal
            $calculations = $this->rodal->getForestCalculations($id);
            
            if (!$calculations) {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al obtener datos del rodal'
                ]);
            }
            
            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => $calculations
            ]);
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener rodal: ' . $e->getMessage()
            ]);
        }
    }

    // PUT /api/rodales/{id} - Actualizar rodal
    public function update($id) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente']);
            
            // Buscar rodal
            if (!$this->rodal->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Rodal no encontrado'
                ]);
            }
            
            // Verificar permisos del proyecto asociado
            if (!$this->project->findById($this->rodal->proyecto_id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto asociado no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden editar rodales de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para editar este rodal'
                ]);
            }
            
            // Obtener datos del request
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!$input) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Datos de entrada inválidos'
                ]);
            }
            
            // Actualizar solo los campos proporcionados
            if (isset($input['nombre_rodal'])) {
                $this->rodal->nombre_rodal = $input['nombre_rodal'];
            }
            if (isset($input['area_ha'])) {
                $this->rodal->area_ha = $input['area_ha'];
            }
            
            // Validar datos
            $errors = $this->rodal->validate();
            if (!empty($errors)) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Errores de validación',
                    'errors' => $errors
                ]);
            }
            
            // Verificar que el nombre del rodal no exista en el proyecto (excluyendo el actual)
            if (isset($input['nombre_rodal']) && 
                $this->rodal->rodalNameExistsInProject($this->rodal->nombre_rodal, $this->rodal->proyecto_id, $id)) {
                http_response_code(409);
                return json_encode([
                    'success' => false,
                    'message' => 'Ya existe un rodal con este nombre en el proyecto'
                ]);
            }
            
            // Validar área según estándares forestales si se está actualizando
            $warnings = [];
            if (isset($input['area_ha'])) {
                $areaValidation = $this->rodal->validateAreaForestry($this->rodal->area_ha);
                if (!$areaValidation['valid']) {
                    http_response_code(400);
                    return json_encode([
                        'success' => false,
                        'message' => 'Área inválida',
                        'errors' => $areaValidation['errors']
                    ]);
                }
                $warnings = $areaValidation['warnings'];
            }
            
            // Actualizar rodal
            if ($this->rodal->update()) {
                // Invalidate rodales cache
                Cache::invalidateTag('rodales');
                Cache::invalidateTag('project_' . $this->rodal->proyecto_id);
                Cache::invalidateTag('rodal_' . $id);
                
                $response = [
                    'success' => true,
                    'message' => 'Rodal actualizado exitosamente'
                ];
                
                // Agregar advertencias si las hay
                if (!empty($warnings)) {
                    $response['warnings'] = $warnings;
                }
                
                http_response_code(200);
                return json_encode($response);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al actualizar el rodal'
                ]);
            }
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al actualizar rodal: ' . $e->getMessage()
            ]);
        }
    }

    // DELETE /api/rodales/{id} - Eliminar rodal
    public function destroy($id) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente']);
            
            // Buscar rodal
            if (!$this->rodal->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Rodal no encontrado'
                ]);
            }
            
            // Verificar permisos del proyecto asociado
            if (!$this->project->findById($this->rodal->proyecto_id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto asociado no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden eliminar rodales de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para eliminar este rodal'
                ]);
            }
            
            // Store project ID before deletion
            $projectId = $this->rodal->proyecto_id;
            
            // Eliminar rodal
            $result = $this->rodal->delete();
            
            if ($result === true) {
                // Invalidate rodales cache
                Cache::invalidateTag('rodales');
                Cache::invalidateTag('project_' . $projectId);
                Cache::invalidateTag('rodal_' . $id);
                Cache::invalidateTag('calculations');
                
                http_response_code(200);
                return json_encode([
                    'success' => true,
                    'message' => 'Rodal eliminado exitosamente'
                ]);
            } elseif (is_array($result) && isset($result['error'])) {
                http_response_code(409);
                return json_encode([
                    'success' => false,
                    'message' => $result['error']
                ]);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al eliminar el rodal'
                ]);
            }
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al eliminar rodal: ' . $e->getMessage()
            ]);
        }
    }

    // GET /api/rodales/{id}/field-data - Obtener datos de campo por rodal
    public function getFieldData($id) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente', 'Técnico de Campo']);
            
            // Verificar que el rodal existe
            if (!$this->rodal->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Rodal no encontrado'
                ]);
            }
            
            // Verificar permisos del proyecto asociado
            if (!$this->project->findById($this->rodal->proyecto_id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto asociado no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden ver datos de campo de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para ver los datos de campo de este rodal'
                ]);
            }
            
            // Obtener parámetros de filtro
            $filters = [];
            if (isset($_GET['especie_id'])) {
                $filters['especie_id'] = $_GET['especie_id'];
            }
            if (isset($_GET['numero_parcela'])) {
                $filters['numero_parcela'] = $_GET['numero_parcela'];
            }
            if (isset($_GET['condicion_arbol'])) {
                $filters['condicion_arbol'] = $_GET['condicion_arbol'];
            }
            if (isset($_GET['estado_sincronizacion'])) {
                $filters['estado_sincronizacion'] = $_GET['estado_sincronizacion'];
            }
            
            // Parámetros de paginación
            $page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
            $limit = isset($_GET['limit']) ? min(100, max(10, intval($_GET['limit']))) : 50;
            $offset = ($page - 1) * $limit;
            
            // Consulta para obtener datos de campo
            $query = "SELECT 
                        dc.*,
                        e.nombre_cientifico,
                        e.nombre_comun,
                        u.nombre as usuario_nombre
                      FROM datos_campo dc
                      LEFT JOIN especies e ON dc.especie_id = e.id
                      LEFT JOIN usuarios u ON dc.usuario_id = u.id
                      WHERE dc.rodal_id = :rodal_id";
            
            $params = [':rodal_id' => $id];
            
            // Aplicar filtros
            if (!empty($filters['especie_id'])) {
                $query .= " AND dc.especie_id = :especie_id";
                $params[':especie_id'] = $filters['especie_id'];
            }
            if (!empty($filters['numero_parcela'])) {
                $query .= " AND dc.numero_parcela = :numero_parcela";
                $params[':numero_parcela'] = $filters['numero_parcela'];
            }
            if (!empty($filters['condicion_arbol'])) {
                $query .= " AND dc.condicion_arbol = :condicion_arbol";
                $params[':condicion_arbol'] = $filters['condicion_arbol'];
            }
            if (!empty($filters['estado_sincronizacion'])) {
                $query .= " AND dc.estado_sincronizacion = :estado_sincronizacion";
                $params[':estado_sincronizacion'] = $filters['estado_sincronizacion'];
            }
            
            // Ordenar por fecha de captura descendente
            $query .= " ORDER BY dc.fecha_captura DESC";
            
            // Contar total de registros
            $countQuery = str_replace('SELECT dc.*, e.nombre_cientifico, e.nombre_comun, u.nombre as usuario_nombre', 'SELECT COUNT(*)', $query);
            $countStmt = $this->db->prepare($countQuery);
            $countStmt->execute($params);
            $totalRecords = $countStmt->fetchColumn();
            
            // Aplicar paginación
            $query .= " LIMIT :limit OFFSET :offset";
            $params[':limit'] = $limit;
            $params[':offset'] = $offset;
            
            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            
            $fieldData = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $fieldData[] = [
                    'id' => (int)$row['id'],
                    'rodal_id' => (int)$row['rodal_id'],
                    'numero_parcela' => (int)$row['numero_parcela'],
                    'fecha_captura' => $row['fecha_captura'],
                    'latitud' => (float)$row['latitud'],
                    'longitud' => (float)$row['longitud'],
                    'especie' => [
                        'id' => (int)$row['especie_id'],
                        'nombre_cientifico' => $row['nombre_cientifico'],
                        'nombre_comun' => $row['nombre_comun']
                    ],
                    'dap_cm' => (float)$row['dap_cm'],
                    'altura_m' => (float)$row['altura_m'],
                    'condicion_arbol' => $row['condicion_arbol'],
                    'estado_sincronizacion' => $row['estado_sincronizacion'],
                    'usuario_nombre' => $row['usuario_nombre']
                ];
            }
            
            // Obtener especies más comunes en el rodal
            $topSpecies = $this->rodal->getTopSpecies($id, 5);
            
            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => $fieldData,
                'pagination' => [
                    'current_page' => $page,
                    'per_page' => $limit,
                    'total_records' => (int)$totalRecords,
                    'total_pages' => ceil($totalRecords / $limit)
                ],
                'summary' => [
                    'rodal_id' => (int)$id,
                    'nombre_rodal' => $this->rodal->nombre_rodal,
                    'area_ha' => (float)$this->rodal->area_ha,
                    'total_registros' => (int)$totalRecords,
                    'especies_principales' => $topSpecies
                ]
            ]);
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener datos de campo: ' . $e->getMessage()
            ]);
        }
    }

    // GET /api/rodales/{id}/calculations - Obtener cálculos forestales del rodal
    public function getCalculations($id) {
        try {
            // Verificar autenticación
            $user = AuthMiddleware::authenticate();
            RoleMiddleware::checkRole(['Administrador', 'Regente']);
            
            // Verificar que el rodal existe
            if (!$this->rodal->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Rodal no encontrado'
                ]);
            }
            
            // Verificar permisos del proyecto asociado
            if (!$this->project->findById($this->rodal->proyecto_id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Proyecto asociado no encontrado'
                ]);
            }
            
            // Verificar permisos: regentes solo pueden ver cálculos de sus propios proyectos
            if ($user['rol'] === 'Regente' && $this->project->usuario_id != $user['user_id']) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para ver los cálculos de este rodal'
                ]);
            }
            
            // Obtener cálculos forestales completos
            $calculations = $this->rodal->getForestCalculations($id);
            
            if (!$calculations) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'No se pudieron obtener los cálculos del rodal'
                ]);
            }
            
            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => $calculations
            ]);
            
        } catch (Exception $e) {
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener cálculos: ' . $e->getMessage()
            ]);
        }
    }
}
?>