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

class FieldDataController {
    private $db;
    private $fieldData;
    private $rodal;
    
    public function __construct($database) {
        $this->db = $database;
        $this->fieldData = new FieldData($this->db);
        $this->rodal = new Rodal($this->db);
    }

    // POST /api/field-data/sync - Sincronización masiva de datos de campo
    public function syncBatch() {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            // Obtener datos del request
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!$input || !isset($input['records']) || !is_array($input['records'])) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Se requiere un array de registros para sincronizar',
                    'expected_format' => [
                        'records' => [
                            [
                                'rodal_id' => 'int',
                                'numero_parcela' => 'int',
                                'latitud' => 'float',
                                'longitud' => 'float',
                                'especie_id' => 'int',
                                'dap_cm' => 'float',
                                'altura_m' => 'float',
                                'condicion_arbol' => 'string',
                                'fecha_captura' => 'datetime (optional)'
                            ]
                        ]
                    ]
                ]);
            }

            $records = $input['records'];
            
            // Validar que no esté vacío
            if (empty($records)) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'No se proporcionaron registros para sincronizar'
                ]);
            }

            // Validar límite de registros por lote
            $maxBatchSize = 100; // Configurable desde base de datos
            if (count($records) > $maxBatchSize) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => "Máximo $maxBatchSize registros por lote. Recibidos: " . count($records)
                ]);
            }

            // Preparar registros para inserción
            $processedRecords = [];
            $validationErrors = [];
            
            foreach ($records as $index => $record) {
                // Agregar datos del usuario y estado de sincronización
                $record['usuario_id'] = $user['user_id'];
                $record['estado_sincronizacion'] = 'Sincronizado';
                
                // Si no se proporciona fecha_captura, usar timestamp actual
                if (!isset($record['fecha_captura']) || empty($record['fecha_captura'])) {
                    $record['fecha_captura'] = date('Y-m-d H:i:s');
                }

                // Validar permisos del usuario sobre el rodal
                if (!$this->validateUserRodalAccess($user, $record['rodal_id'])) {
                    $validationErrors[] = "Registro " . ($index + 1) . ": No tiene permisos para este rodal";
                    continue;
                }

                $processedRecords[] = $record;
            }

            // Si hay errores de permisos, rechazar todo el lote
            if (!empty($validationErrors)) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'Errores de permisos en el lote',
                    'errors' => $validationErrors
                ]);
            }

            // Procesar lote con transacción
            $result = $this->fieldData->createBatch($processedRecords);
            
            if ($result['success']) {
                // Invalidate calculation caches for affected rodales
                $affectedRodales = array_unique(array_column($processedRecords, 'rodal_id'));
                foreach ($affectedRodales as $rodalId) {
                    Cache::invalidateTag('rodal_' . $rodalId);
                    Cache::invalidateTag('calculations');
                }
                
                // Obtener IDs de registros insertados para respuesta
                $insertedIds = $this->getLastInsertedIds($result['inserted']);
                
                http_response_code(201);
                return json_encode([
                    'success' => true,
                    'message' => 'Sincronización completada exitosamente',
                    'data' => [
                        'total_records' => count($records),
                        'inserted' => $result['inserted'],
                        'failed' => count($records) - $result['inserted'],
                        'inserted_ids' => $insertedIds
                    ]
                ]);
            } else {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Error en la sincronización',
                    'errors' => $result['errors'],
                    'data' => [
                        'total_records' => count($records),
                        'inserted' => $result['inserted'],
                        'failed' => count($records) - $result['inserted']
                    ]
                ]);
            }
            
        } catch (Exception $e) {
            error_log("Error en syncBatch: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error interno del servidor durante la sincronización'
            ]);
        }
    }

    // PUT /api/field-data/mark-synced - Marcar registros como sincronizados
    public function markAsSynced() {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            // Obtener datos del request
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!$input || !isset($input['ids']) || !is_array($input['ids'])) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Se requiere un array de IDs para marcar como sincronizados'
                ]);
            }

            $ids = array_filter($input['ids'], 'is_numeric');
            
            if (empty($ids)) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'No se proporcionaron IDs válidos'
                ]);
            }

            // Validar que el usuario tenga permisos sobre todos los registros
            if (!$this->validateUserRecordsAccess($user, $ids)) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para marcar algunos de estos registros'
                ]);
            }

            // Marcar como sincronizados
            if ($this->fieldData->markAsSynced($ids)) {
                http_response_code(200);
                return json_encode([
                    'success' => true,
                    'message' => 'Registros marcados como sincronizados exitosamente',
                    'data' => [
                        'updated_count' => count($ids)
                    ]
                ]);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al marcar registros como sincronizados'
                ]);
            }
            
        } catch (Exception $e) {
            error_log("Error en markAsSynced: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error interno del servidor'
            ]);
        }
    }

    // GET /api/rodales/{id}/field-data - Obtener datos de campo por rodal
    public function getByRodal($rodalId) {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            // Validar que el rodal existe y el usuario tiene permisos
            if (!$this->validateUserRodalAccess($user, $rodalId)) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para acceder a este rodal'
                ]);
            }

            // Obtener parámetros de consulta
            $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 100;
            $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
            $estado = isset($_GET['estado']) ? $_GET['estado'] : null;

            // Validar parámetros
            if ($limit > 500) $limit = 500; // Máximo 500 registros
            if ($limit < 1) $limit = 100;
            if ($offset < 0) $offset = 0;

            $stmt = $this->fieldData->readByRodal($rodalId);
            $records = [];
            $totalCount = 0;
            
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                // Filtrar por estado si se especifica
                if ($estado && $row['estado_sincronizacion'] !== $estado) {
                    continue;
                }
                
                $totalCount++;
                
                // Aplicar paginación
                if ($totalCount <= $offset) {
                    continue;
                }
                if (count($records) >= $limit) {
                    break;
                }
                
                $records[] = [
                    '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'],
                    'especie_nombre_cientifico' => $row['nombre_cientifico'],
                    'especie_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_id' => (int)$row['usuario_id'],
                    'usuario_nombre' => $row['usuario_nombre'],
                    'fecha_sincronizacion' => $row['fecha_sincronizacion']
                ];
            }

            // Obtener estadísticas del rodal
            $stats = $this->fieldData->getDataQualityStats($rodalId);

            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => [
                    'records' => $records,
                    'pagination' => [
                        'total' => $totalCount,
                        'limit' => $limit,
                        'offset' => $offset,
                        'returned' => count($records)
                    ],
                    'statistics' => [
                        'total_registros' => (int)$stats['total_registros'],
                        'dap_promedio' => round((float)$stats['dap_promedio'], 2),
                        'altura_promedio' => round((float)$stats['altura_promedio'], 2),
                        'dap_outliers' => (int)$stats['dap_outliers'],
                        'altura_outliers' => (int)$stats['altura_outliers']
                    ]
                ]
            ]);
            
        } catch (Exception $e) {
            error_log("Error en getByRodal: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener datos de campo'
            ]);
        }
    }

    // GET /api/field-data/{id} - Obtener registro específico
    public function show($id) {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            if (!$this->fieldData->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Registro no encontrado'
                ]);
            }

            // Validar permisos del usuario sobre el registro
            if (!$this->validateUserRecordsAccess($user, [$id])) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para acceder a este registro'
                ]);
            }

            // Obtener alertas de valores atípicos
            $recordData = [
                'dap_cm' => $this->fieldData->dap_cm,
                'altura_m' => $this->fieldData->altura_m
            ];
            $alerts = $this->fieldData->getOutlierAlerts($recordData);

            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => [
                    'id' => (int)$this->fieldData->id,
                    'rodal_id' => (int)$this->fieldData->rodal_id,
                    'numero_parcela' => (int)$this->fieldData->numero_parcela,
                    'fecha_captura' => $this->fieldData->fecha_captura,
                    'latitud' => (float)$this->fieldData->latitud,
                    'longitud' => (float)$this->fieldData->longitud,
                    'especie_id' => (int)$this->fieldData->especie_id,
                    'dap_cm' => (float)$this->fieldData->dap_cm,
                    'altura_m' => (float)$this->fieldData->altura_m,
                    'condicion_arbol' => $this->fieldData->condicion_arbol,
                    'estado_sincronizacion' => $this->fieldData->estado_sincronizacion,
                    'usuario_id' => (int)$this->fieldData->usuario_id,
                    'fecha_sincronizacion' => $this->fieldData->fecha_sincronizacion,
                    'alerts' => $alerts
                ]
            ]);
            
        } catch (Exception $e) {
            error_log("Error en show: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener registro'
            ]);
        }
    }

    // PUT /api/field-data/{id} - Actualizar registro
    public function update($id) {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            if (!RoleMiddleware::checkRole(['Administrador', 'Regente', 'Técnico de Campo'])) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para realizar esta acción'
                ]);
            }
            
            if (!$this->fieldData->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Registro no encontrado'
                ]);
            }

            // Validar permisos del usuario sobre el registro
            if (!$this->validateUserRecordsAccess($user, [$id])) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para editar este registro'
                ]);
            }

            // 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['numero_parcela'])) {
                $this->fieldData->numero_parcela = $input['numero_parcela'];
            }
            if (isset($input['latitud'])) {
                $this->fieldData->latitud = $input['latitud'];
            }
            if (isset($input['longitud'])) {
                $this->fieldData->longitud = $input['longitud'];
            }
            if (isset($input['especie_id'])) {
                $this->fieldData->especie_id = $input['especie_id'];
            }
            if (isset($input['dap_cm'])) {
                $this->fieldData->dap_cm = $input['dap_cm'];
            }
            if (isset($input['altura_m'])) {
                $this->fieldData->altura_m = $input['altura_m'];
            }
            if (isset($input['condicion_arbol'])) {
                $this->fieldData->condicion_arbol = $input['condicion_arbol'];
            }

            // Validar datos
            $errors = $this->fieldData->validate();
            if (!empty($errors)) {
                http_response_code(400);
                return json_encode([
                    'success' => false,
                    'message' => 'Errores de validación',
                    'errors' => $errors
                ]);
            }

            // Actualizar registro
            if ($this->fieldData->update()) {
                http_response_code(200);
                return json_encode([
                    'success' => true,
                    'message' => 'Registro actualizado exitosamente'
                ]);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al actualizar el registro'
                ]);
            }
            
        } catch (Exception $e) {
            error_log("Error en update: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al actualizar registro'
            ]);
        }
    }

    // DELETE /api/field-data/{id} - Eliminar registro
    public function destroy($id) {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            if (!RoleMiddleware::checkRole(['Administrador', 'Regente'])) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para realizar esta acción'
                ]);
            }
            
            if (!$this->fieldData->findById($id)) {
                http_response_code(404);
                return json_encode([
                    'success' => false,
                    'message' => 'Registro no encontrado'
                ]);
            }

            // Validar permisos del usuario sobre el registro
            if (!$this->validateUserRecordsAccess($user, [$id])) {
                http_response_code(403);
                return json_encode([
                    'success' => false,
                    'message' => 'No tiene permisos para eliminar este registro'
                ]);
            }

            // Eliminar registro
            if ($this->fieldData->delete()) {
                http_response_code(200);
                return json_encode([
                    'success' => true,
                    'message' => 'Registro eliminado exitosamente'
                ]);
            } else {
                http_response_code(500);
                return json_encode([
                    'success' => false,
                    'message' => 'Error al eliminar el registro'
                ]);
            }
            
        } catch (Exception $e) {
            error_log("Error en destroy: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al eliminar registro'
            ]);
        }
    }

    // GET /api/field-data/pending-sync - Obtener registros pendientes de sincronización
    public function getPendingSync() {
        try {
            // Verificar autenticación
            if (!AuthMiddleware::authenticate()) {
                http_response_code(401);
                return json_encode([
                    'success' => false,
                    'message' => 'Token de autenticación requerido'
                ]);
            }
            
            $user = AuthMiddleware::getCurrentUser();
            
            // Los técnicos de campo solo pueden ver sus propios registros pendientes
            $userId = ($user['rol'] === 'Técnico de Campo') ? $user['user_id'] : null;
            
            $stmt = $this->fieldData->getPendingSync($userId);
            $records = [];
            
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $records[] = [
                    'id' => (int)$row['id'],
                    'rodal_id' => (int)$row['rodal_id'],
                    'rodal_nombre' => $row['nombre_rodal'],
                    'proyecto_nombre' => $row['nombre_proyecto'],
                    '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'],
                    'especie_nombre_cientifico' => $row['nombre_cientifico'],
                    'especie_nombre_comun' => $row['nombre_comun'],
                    'dap_cm' => (float)$row['dap_cm'],
                    'altura_m' => (float)$row['altura_m'],
                    'condicion_arbol' => $row['condicion_arbol']
                ];
            }

            http_response_code(200);
            return json_encode([
                'success' => true,
                'data' => [
                    'records' => $records,
                    'total' => count($records)
                ]
            ]);
            
        } catch (Exception $e) {
            error_log("Error en getPendingSync: " . $e->getMessage());
            http_response_code(500);
            return json_encode([
                'success' => false,
                'message' => 'Error al obtener registros pendientes'
            ]);
        }
    }

    // Validar acceso del usuario a un rodal específico
    private function validateUserRodalAccess($user, $rodalId) {
        try {
            // Los administradores tienen acceso a todo
            if ($user['rol'] === 'Administrador') {
                return true;
            }

            // Verificar que el rodal existe y obtener el proyecto
            if (!$this->rodal->findById($rodalId)) {
                return false;
            }

            // Para regentes y técnicos, verificar que el proyecto les pertenece
            $query = "SELECT p.usuario_id 
                      FROM proyectos p 
                      INNER JOIN rodales r ON p.id = r.proyecto_id 
                      WHERE r.id = :rodal_id";
            
            $stmt = $this->db->prepare($query);
            $stmt->bindParam(":rodal_id", $rodalId);
            $stmt->execute();
            
            if ($stmt->rowCount() === 0) {
                return false;
            }
            
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            return $row['usuario_id'] == $user['user_id'];
            
        } catch (Exception $e) {
            error_log("Error en validateUserRodalAccess: " . $e->getMessage());
            return false;
        }
    }

    // Validar acceso del usuario a registros específicos
    private function validateUserRecordsAccess($user, $recordIds) {
        try {
            // Los administradores tienen acceso a todo
            if ($user['rol'] === 'Administrador') {
                return true;
            }

            if (empty($recordIds)) {
                return false;
            }

            $placeholders = str_repeat('?,', count($recordIds) - 1) . '?';
            
            $query = "SELECT COUNT(*) as count
                      FROM datos_campo dc
                      INNER JOIN rodales r ON dc.rodal_id = r.id
                      INNER JOIN proyectos p ON r.proyecto_id = p.id
                      WHERE dc.id IN ($placeholders) AND p.usuario_id = ?";
            
            $params = array_merge($recordIds, [$user['user_id']]);
            
            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            return $row['count'] == count($recordIds);
            
        } catch (Exception $e) {
            error_log("Error en validateUserRecordsAccess: " . $e->getMessage());
            return false;
        }
    }

    // Obtener IDs de los últimos registros insertados
    private function getLastInsertedIds($count) {
        try {
            $query = "SELECT id FROM datos_campo ORDER BY id DESC LIMIT :count";
            $stmt = $this->db->prepare($query);
            $stmt->bindParam(":count", $count, PDO::PARAM_INT);
            $stmt->execute();
            
            $ids = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $ids[] = (int)$row['id'];
            }
            
            return array_reverse($ids); // Devolver en orden ascendente
            
        } catch (Exception $e) {
            error_log("Error en getLastInsertedIds: " . $e->getMessage());
            return [];
        }
    }
}
?>