<?php
ob_start();
/**
 * Endpoint API para recepción de datos de telemetría
 * Recibe datos CSV del equipo Arduino con hasta 14 sensores independientes
 */

require_once '../config.php';

ob_clean();
header('Content-Type: application/json; charset=utf-8');


// Solo permitir método POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    jsonResponse(false, 'Método no permitido. Use POST.', null, 405);
}

// Leer el body crudo del request
$rawData = file_get_contents('php://input');

if (empty($rawData)) {
    jsonResponse(false, 'Body vacío. Se requiere datos CSV.', null, 400);
}

// Limpiar datos
$rawData = trim($rawData);

// ============================================
// MODO PRUEBA: Si recibe "hola", guardarlo como mensaje de prueba
// ============================================
if (strtolower($rawData) === 'hola') {
    $pdo = getDBConnection();
    if (!$pdo) {
        jsonResponse(false, 'Error de conexión a la base de datos', null, 500);
    }

    try {
        // Crear tabla de mensajes de prueba si no existe
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS mensajes_prueba (
                id INT AUTO_INCREMENT PRIMARY KEY,
                mensaje TEXT NOT NULL,
                fecha TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                ip VARCHAR(45),
                INDEX idx_fecha (fecha)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ");

        // Guardar mensaje de prueba
        $stmt = $pdo->prepare("
            INSERT INTO mensajes_prueba (mensaje, ip) 
            VALUES (:mensaje, :ip)
        ");

        $stmt->execute([
            ':mensaje' => $rawData,
            ':ip' => $_SERVER['REMOTE_ADDR'] ?? 'desconocida'
        ]);

        jsonResponse(true, 'Mensaje de prueba recibido: "hola"', [
            'id' => $pdo->lastInsertId(),
            'mensaje' => $rawData,
            'tipo' => 'prueba',
            'fecha' => date('Y-m-d H:i:s')
        ], 200);

    } catch (PDOException $e) {
        error_log("Error al guardar mensaje de prueba: " . $e->getMessage());
        jsonResponse(false, 'Error al guardar mensaje de prueba', null, 500);
    }
}

// PARSE CSV (Esperado: temp, idZona, fechaRecibida, apiKey, [buque_id])
$values = array_map('trim', explode(',', $rawData));
if (count($values) < 4) {
    log_simple("ERROR: Formato CSV inválido (" . count($values) . " valores)");
    jsonResponse(false, 'Formato inválido', null, 400);
}

$temperatura = $values[0];
$idZona = $values[1];
$fechaRecibida = $values[2];
$apiKey = $values[3];
$buqueId = $values[4] ?? 'BOUCIÑA-01'; // Soporte dinámico

// Validar API KEY
if ($apiKey !== API_KEY) {
    error_log("Intento de acceso con API KEY inválida desde IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'desconocida'));
    jsonResponse(false, 'API KEY inválida', null, 401);
}

// Validar temperatura
if (!is_numeric($temperatura)) {
    jsonResponse(false, 'Temperatura inválida. Debe ser un número.', null, 400);
}
// Forzar a float pero manteniendo precisión si es necesario (el DB hará truncate a 2 decimales)
// USAR number_format PARA EVITAR ERRORES DE FLOTANTE (ej: 2.88 -> 2.879999 -> 2.87 en DB)
$temperatura = number_format((float) $temperatura, 2, '.', '');

// Validar ID de zona (1-14)
$MAX_SENSORS = 14;
if (!is_numeric($idZona) || (int) $idZona < 1 || (int) $idZona > $MAX_SENSORS) {
    jsonResponse(false, "ID de zona inválido. Debe ser un número entre 1 y $MAX_SENSORS.", null, 400);
}
$idZona = (int) $idZona;

// Usar la fecha/hora actual del SERVIDOR (Argentina) en lugar de la que envía el dispositivo
// Esto garantiza sincronización total con el Dashboard ignorando desajustes del reloj del ESP32
$fechaFinal = date('Y-m-d H:i:s');

// Conectar a la base de datos
$pdo = getDBConnection();
if (!$pdo) {
    jsonResponse(false, 'Error interno del servidor', null, 500);
}

// LIMPIEZA AUTOMÁTICA DE BASE DE DATOS (Una vez al día)
// Elimina completamente registros de meses anteriores para mantener solo el mes corriente
$cleanupFile = '../config/last_cleanup.txt';
if (!file_exists($cleanupFile) || (time() - filemtime($cleanupFile) > 86400)) {
    try {
        $pdo->exec("DELETE FROM mediciones WHERE fecha < DATE_FORMAT(NOW(), '%Y-%m-01')");
        @touch($cleanupFile); // Actualizar fecha de limpieza
    } catch (PDOException $e) { /* Silencioso */
    }
}

try {
    // Obtener última medición del buque para mantener otros valores de sensores
    $buqueId = 'BOUCIÑA-01';

    // Obtener configuración de Max/Min Temp para este buque
    $stmtConfig = $pdo->prepare("SELECT max_temp, min_temp FROM ships WHERE ship_id = :buque");
    $stmtConfig->execute([':buque' => $buqueId]);
    $config = $stmtConfig->fetch(PDO::FETCH_ASSOC);
    $maxThreshold = $config ? (float) $config['max_temp'] : 25.0;

    // Construir lista de columnas temp1..temp14
    $tempCols = [];
    for ($i = 1; $i <= $MAX_SENSORS; $i++)
        $tempCols[] = "temp$i";
    $colsStr = implode(', ', $tempCols);

    $stmtLast = $pdo->prepare("
        SELECT $colsStr
        FROM mediciones 
        WHERE buque_id = :buque_id
        ORDER BY fecha DESC 
        LIMIT 1
    ");
    $stmtLast->execute([':buque_id' => $buqueId]);
    $ultimaMedicion = $stmtLast->fetch(PDO::FETCH_ASSOC);

    // --- DATA INSIGHTS LOGIC ---
    $timeNow = time();
    $lastTime = $ultimaMedicion ? strtotime($ultimaMedicion['fecha']) : 0;
    $timeSinceLast = $timeNow - $lastTime;

    $prevValue = $ultimaMedicion ? (float) $ultimaMedicion["temp$idZona"] : null;
    $currentValue = (float) $temperatura;

    // Obtener Min Threshold (si existe en DB, sino default 0.0)
    $minThreshold = $config ? (float) $config['min_temp'] : 0.0;

    // Decision Logic for Insertion:
    $isFirst = (!$ultimaMedicion);
    $isHeartbeat = ($timeSinceLast > 3600); // 1 hour heartbeat

    $isTransitionHigh = false;
    if ($prevValue !== null) {
        // Crossing Max Threshold
        if (
            ($prevValue <= $maxThreshold && $currentValue > $maxThreshold) ||
            ($prevValue > $maxThreshold && $currentValue <= $maxThreshold)
        ) {
            $isTransitionHigh = true;
        }
        // Crossing Min Threshold
        if (
            ($prevValue >= $minThreshold && $currentValue < $minThreshold) ||
            ($prevValue < $minThreshold && $currentValue >= $minThreshold)
        ) {
            $isTransitionHigh = true;
        }
    }

    $isSignificantChange = ($prevValue !== null && abs($currentValue - $prevValue) >= 2.0);

    // Prepare array of temperatures for the database row
    $temps = [];
    for ($i = 1; $i <= $MAX_SENSORS; $i++) {
        if ($i === $idZona) {
            $temps[$i] = $temperatura;
        } else {
            $temps[$i] = $ultimaMedicion ? $ultimaMedicion["temp$i"] : null;
        }
    }

    // ----------------------------------------------------
    // ACTUALIZACIÓN LIVE (Always on, for Dashboard)
    // ----------------------------------------------------
    try {
        $livePayload = [
            'unica' => true,
            'fecha' => $fechaFinal,
            'ip' => $_SERVER['REMOTE_ADDR'] ?? 'desconocida',
        ];
        for ($i = 1; $i <= $MAX_SENSORS; $i++) {
            $livePayload["temp$i"] = $temps[$i];
        }

        $stmtUpdateShip = $pdo->prepare("
            UPDATE ships 
            SET last_contact = NOW(), 
                last_payload = :payload 
            WHERE ship_id = :buque
        ");
        $stmtUpdateShip->execute([
            ':payload' => json_encode($livePayload),
            ':buque' => $buqueId
        ]);
    } catch (Exception $e) {
        error_log("Error live update: " . $e->getMessage());
    }

    // Determine final Decision
    $shouldInsert = ($isFirst || $isHeartbeat || $isTransitionHigh || $isSignificantChange);

    // ----------------------------------------------------
    // DEDUPLICACIÓN (Solo si NO es un cambio importante)
    // ----------------------------------------------------
    if (!$shouldInsert) {
        $isIdenticalToLast = true;
        if ($ultimaMedicion) {
            for ($i = 1; $i <= $MAX_SENSORS; $i++) {
                $valActual = (float) $temps[$i];
                $valAnterior = (float) ($ultimaMedicion["temp$i"] ?? 0);
                if (abs($valActual - $valAnterior) > 0.001) {
                    $isIdenticalToLast = false;
                    break;
                }
            }
        } else {
            $isIdenticalToLast = false;
        }

        // Si es idéntico Y fue hace poco, saltar
        if ($isIdenticalToLast && $timeSinceLast < 600) { // 10 min window for identical data
            jsonResponse(true, 'OK (Deduplicación activa)', [
                'id' => 0,
                'info' => 'Registro idéntico omitido',
                'skipped' => true
            ], 200);
            exit;
        }
    }

    // Si aún decidimos no insertar (ej: es igual pero pasó el tiempo de deduplicación 
    // pero no el latido de 1 hora), podemos forzar o saltar.
    // Seguimos la orden del usuario: solo cambios o latido.
    if (!$shouldInsert) {
        jsonResponse(true, 'OK (Sin cambios significativos para historial)', [
            'id' => 0,
            'sensor' => $idZona,
            'temp' => $temperatura,
            'skipped' => true
        ], 200);
        exit;
    }

    // Insertar nueva medición con temperatura, fecha e IP de origen
    $ipOrigen = $_SERVER['REMOTE_ADDR'] ?? 'desconocida';

    // Construir query dinámica
    $paramNames = [];
    for ($i = 1; $i <= $MAX_SENSORS; $i++)
        $paramNames[] = ":t$i";
    $paramsStr = implode(', ', $paramNames);

    $sql = "INSERT INTO mediciones (buque_id, $colsStr, fecha, ip) 
            VALUES (:buque_id, $paramsStr, :fecha, :ip)";

    $params = [
        ':buque_id' => $buqueId,
        ':fecha' => $fechaFinal,
        ':ip' => $ipOrigen
    ];

    for ($i = 1; $i <= $MAX_SENSORS; $i++) {
        $params[":t$i"] = $temps[$i];
    }

    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $insertId = $pdo->lastInsertId();

    jsonResponse(true, 'OK', [
        'id' => $insertId,
        'sensor_id' => $idZona,
        'temperatura' => number_format($temperatura, 2, '.', ''), // Asegurar formato en respuesta
        'fecha' => $fechaFinal
    ], 200);

} catch (PDOException $e) {
    error_log("Error al insertar medición: " . $e->getMessage());
    jsonResponse(false, 'Error al guardar medición: ' . $e->getMessage(), null, 500);
}

