<?php
ob_start();

require_once '../auth.php';
require_once '../config.php';

checkApiLogin();

if (ob_get_level() > 0)
    ob_clean();
header('Content-Type: application/json; charset=utf-8');
date_default_timezone_set('America/Argentina/Buenos_Aires');

// Conectar a la base de datos
$pdo = getDBConnection();

if (!$pdo) {
    jsonResponse(false, 'Error de conexión a la base de datos', null, 500);
}

try {
    // Obtener buque_id de la URL o usar el por defecto
    $buque_id = isset($_GET['buque_id']) ? $_GET['buque_id'] : 'BOUCINA-01';

    // 1. Obtener última medición guardada en el HISTORIAL (Tabla mediciones)
    $cols = [];
    for ($i = 1; $i <= 16; $i++)
        $cols[] = "temp$i";
    $colsStr = implode(', ', $cols);

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

    // 2. Obtener historial de últimas 48 horas para el Chart
    $stmtHist = $pdo->prepare("
        SELECT $colsStr, 
               fecha 
        FROM mediciones 
        WHERE buque_id = :buque_id 
        AND fecha >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
        ORDER BY fecha DESC
        LIMIT 10000
    ");
    $stmtHist->execute(['buque_id' => $buque_id]);
    $historial = $stmtHist->fetchAll(PDO::FETCH_ASSOC);
    $historial = array_reverse($historial);

    // --- DECIMACIÓN DE DATOS (Optimización de Rendimiento) ---
    // Si hay demasiados puntos (> 1500), tomamos una muestra para no saturar el navegador.
    // Esto mantiene la línea suave pero con mucho menos carga de CPU.
    $maxChartPoints = 1500;
    if (count($historial) > $maxChartPoints) {
        $step = ceil(count($historial) / $maxChartPoints);
        $decimated = [];
        for ($i = 0; $i < count($historial); $i += $step) {
            $decimated[] = $historial[$i];
        }
        $historial = $decimated;
    }

    // -------------------------------------------------------------------------
    // 3. INYECTAR DATOS EN VIVO (Prioridad absoluta sobre el historial)
    // -------------------------------------------------------------------------
    try {
        // --- NUEVO: INTEGRACIÓN CON CACHÉ DE THROTTLING ---
        $safeBuqueId = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $buque_id);
        $cacheFile = __DIR__ . "/../cache/ship_$safeBuqueId.json";
        $cacheData = null;
        if (file_exists($cacheFile)) {
            $fp = fopen($cacheFile, 'r');
            if ($fp) {
                if (flock($fp, LOCK_SH)) {
                    $content = stream_get_contents($fp);
                    if (!empty($content)) {
                        $cacheData = json_decode($content, true);
                    }
                    flock($fp, LOCK_UN);
                }
                fclose($fp);
            }
        }

        $stmtLive = $pdo->prepare("SELECT last_payload FROM ships WHERE ship_id = :buque_id");
        $stmtLive->execute(['buque_id' => $buque_id]);
        $rowLive = $stmtLive->fetch(PDO::FETCH_ASSOC);

        $liveData = null;
        if ($rowLive && !empty($rowLive['last_payload'])) {
            $liveData = json_decode($rowLive['last_payload'], true);
        }

        // Si el caché es más reciente que la DB, usar caché
        if ($cacheData && isset($cacheData['last_contact'])) {
            $cacheTime = strtotime($cacheData['last_contact']);
            $dbTime = ($liveData && isset($liveData['fecha'])) ? strtotime($liveData['fecha']) : 0;

            if ($cacheTime > $dbTime) {
                $liveData = [
                    'fecha' => $cacheData['last_contact'],
                    'ip' => $cacheData['ip'] ?? '---',
                    'sensor_timestamps' => $cacheData['timestamps'] ?? []
                ];
                for ($i = 1; $i <= 16; $i++) {
                    $liveData["temp$i"] = $cacheData['temps'][$i] ?? null;
                }
            }
        }

        if ($liveData && isset($liveData['fecha'])) {

            // LÓGICA DE VALIDACIÓN DE TIEMPO REFORZADA
            // Si el ESP32 manda "now" o la hora está reseteada (00:00), forzamos la inyección.
            $esDatoNuevo = false;
            if ($liveData['fecha'] === 'now' || strpos($liveData['fecha'], '00:00') !== false) {
                $esDatoNuevo = true;
            } else {
                $lastDbTime = $ultima ? strtotime($ultima['fecha']) : 0;
                $liveTime = strtotime($liveData['fecha']);
                $esDatoNuevo = ($liveTime >= $lastDbTime);
            }

            if ($esDatoNuevo) {
                // Inicializar si el historial estaba vacío
                if (!$ultima)
                    $ultima = [];

                // Sobreescritura directa de sensores (Capa Live)
                // VALIDACIÓN DE TIMEOUT POR SENSOR (10 minutos = 600 segundos)
                // Si un sensor específico no se actualizó en X tiempo, se marca como NULL ("--")
                $now = time();
                $timeout = 600; // 10 minutos (ESP32 envía cada 5 min + buffer)

                $sensorTimestamps = isset($liveData['sensor_timestamps']) ? $liveData['sensor_timestamps'] : [];

                for ($i = 1; $i <= 16; $i++) {
                    $val = null;

                    // Determinar valor crudo y filtrar inválidos (0.00, 85.00)
                    if (isset($liveData["temp$i"])) {
                        $valRaw = $liveData["temp$i"];
                        if ($valRaw !== null && ((float) $valRaw == 0.00 || (float) $valRaw == 85.00)) {
                            $val = null;
                        } else {
                            $val = $valRaw;
                        }
                    }

                    // Aplicar timeout si tenemos timestamp para este sensor
                    if (isset($sensorTimestamps[$i])) {
                        $ts = (int) $sensorTimestamps[$i];
                        if ($ts > 0 && ($now - $ts) > $timeout) {
                            $val = null; // Sensor expirado
                        }
                    }

                    $ultima["temp$i"] = $val;
                }

                // Actualizar metadatos del Card
                $ultima['fecha'] = $liveData['fecha'];
                $ultima['ip'] = $liveData['ip'] ?? ($ultima['ip'] ?? '---');
                $ultima['buque_id'] = $buque_id;

                // Inyectar el punto en el historial del Chart para ver cambios menores a 1°C
                $chartPoint = ['fecha' => $liveData['fecha']];
                for ($i = 1; $i <= 16; $i++) {
                    if (isset($ultima["temp$i"])) {
                        $chartPoint["temp$i"] = $ultima["temp$i"];
                    }
                }
                $historial[] = $chartPoint;
            }
        }
    } catch (Exception $e) { /* Error silencioso en live data */
    }

    // 4. Preparación de datos para el Dashboard (Lista de buques según rol)
    $listaBuques = [];
    $role = $_SESSION['role'] ?? '';
    $userId = $_SESSION['user_id'] ?? 0;

    if ($role === 'admin') {
        // Global admin ve todos
        $stmtBuques = $pdo->query("SELECT ship_id, name FROM ships ORDER BY name ASC");
        $listaBuques = $stmtBuques->fetchAll(PDO::FETCH_ASSOC);
    } else {
        // Sub-adm o usuario común solo ve los suyos
        $stmtBuques = $pdo->prepare("SELECT s.ship_id, s.name 
                                    FROM ships s 
                                    JOIN user_ships us ON s.ship_id = us.ship_id 
                                    WHERE us.user_id = :user_id 
                                    ORDER BY s.name ASC");
        $stmtBuques->execute([':user_id' => $userId]);
        $listaBuques = $stmtBuques->fetchAll(PDO::FETCH_ASSOC);

        // Fallback porsia (migración)
        if (empty($listaBuques) && !empty($_SESSION['ship_id'])) {
            $stmtBuques = $pdo->prepare("SELECT ship_id, name FROM ships WHERE ship_id = :id");
            $stmtBuques->execute([':id' => $_SESSION['ship_id']]);
            $listaBuques = $stmtBuques->fetchAll(PDO::FETCH_ASSOC);
        }
    }

    // Normalización de tipos y Validación Global de Antigüedad
    // Si la última medición (sea de DB o Live) tiene más de 10 minutos, 
    // consideramos que el sistema está OFFLINE y mostramos "--"
    $MAX_SENSORS = 16;

    if ($ultima && isset($ultima['fecha'])) {
        $lastTime = strtotime($ultima['fecha']);
        // 600 segundos = 10 minutos
        // Si no hay datos recientes, forzamos NULL en todos los sensores
        if ((time() - $lastTime) > 600) {
            for ($i = 1; $i <= $MAX_SENSORS; $i++) {
                $ultima["temp$i"] = null;
            }
        } else {
            // Si es reciente, asegurar tipos float y filtrar valores inválidos (0.00, 85.00)
            for ($i = 1; $i <= $MAX_SENSORS; $i++) {
                if (isset($ultima["temp$i"]) && $ultima["temp$i"] !== null) {
                    $fVal = (float) $ultima["temp$i"];
                    if ($fVal == 0.00 || $fVal == 85.00) {
                        $ultima["temp$i"] = null;
                    } else {
                        $ultima["temp$i"] = $fVal;
                    }
                }
            }
        }
    }

    foreach ($historial as &$h) {
        for ($i = 1; $i <= $MAX_SENSORS; $i++) {
            if (isset($h["temp$i"]) && $h["temp$i"] !== null) {
                $fVal = (float) $h["temp$i"];
                if ($fVal == 0.00 || $fVal == 85.00) {
                    $h["temp$i"] = null;
                } else {
                    $h["temp$i"] = $fVal;
                }
            }
        }
    }

    // Respuesta JSON estandarizada
    jsonResponse(true, 'Datos sincronizados correctamente', [
        'ultima' => $ultima,
        'historial' => $historial,
        'lista_buques' => $listaBuques,
        'buque_id' => $buque_id
    ], 200);

} catch (PDOException $e) {
    jsonResponse(false, 'Error crítico: ' . $e->getMessage(), null, 500);
}