<?php
/**
 * API REST para el Sistema de Robot Médico (Versión JSON DB)
 */
// Cabeceras para evitar cache del navegador y permitir peticiones desde el frontend
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');

// Dar tiempo suficiente para peticiones hardware lentas
set_time_limit(300);
ini_set('max_execution_time', 300);

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit;
}

require_once 'config.php';

$method = $_SERVER['REQUEST_METHOD'];

// Validar licencia antes de procesar otras rutas (excepto activar y configuración básica)
$skipLicenseCheck = ['activar', 'licencia', 'configuracion'];

// Detectar ruta actual para el check de licencia (igual que el router)
$currentPath = isset($_SERVER['PATH_INFO']) ? trim($_SERVER['PATH_INFO'], '/') : '';
if ($currentPath == "" && isset($_GET['route'])) {
    $currentPath = trim($_GET['route'], '/');
}

if (!in_array($currentPath, $skipLicenseCheck) && !DB::esLicenciaValida()) {
    // Si la licencia no es válida, devolvemos un 200 con estado false en lugar de un error 401/403
    // para que el frontend maneje la UI de bloqueo sin disparar alertas de red.
    http_response_code(200); 
    echo json_encode(["licencia_invalida" => true, "mensaje" => "Licencia requerida"]);
    exit;
}

// Mejorar detección de ruta para entornos XAMPP/Apache
$path = isset($_SERVER['PATH_INFO']) ? trim($_SERVER['PATH_INFO'], '/') : '';
if ($path == "") {
    // Si PATH_INFO falla, intentar extraer de REQUEST_URI
    $uri = $_SERVER['REQUEST_URI'];
    if (strpos($uri, 'api.php/') !== false) {
        $parts = explode('api.php/', $uri);
        $path = trim(explode('?', $parts[1])[0], '/');
    } elseif (isset($_GET['route'])) {
        $path = $_GET['route'];
    }
}

// Router simple
switch ($path) {
    case 'estudios':
        if ($method == 'GET') {
            echo json_encode(DB::getEstudios());
        }
        break;

    case 'estudio':
        if ($method == 'GET' && isset($_GET['id'])) {
            $estudio = DB::getEstudio($_GET['id']);
            if ($estudio) {
                echo json_encode($estudio);
            } else {
                http_response_code(404);
                echo json_encode(["error" => "Estudio no encontrado"]);
            }
        } elseif ($method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            if (isset($data['id']) && isset($data['estado'])) {
                cambiarEstadoEstudio($data['id'], $data['estado']);
            }
        }
        break;

    case 'configuracion':
        if ($method == 'GET') {
            echo json_encode(DB::getConfig());
        } elseif ($method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            DB::setConfig($data);
            echo json_encode(["mensaje" => "Configuración actualizada"]);
        }
        break;

    case 'licencia':
        if ($method == 'GET') {
            $config = DB::getConfig();
            echo json_encode([
                "licencia" => $config['licencia'] ?? null,
                "valida"   => DB::esLicenciaValida(),
                "hoy"      => date('Y-m-d')
            ]);
        } elseif ($method == 'POST') {
            // Actualizar configuración de licencia (solo activada/vencimiento, no credenciales)
            $data = json_decode(file_get_contents("php://input"), true);
            $config = DB::getConfig();
            
            // Solo permitimos cambiar el estado o la fecha si se desea (modo administración básica)
            // Las credenciales SOLO se pueden cambiar mediante el endpoint 'activar' con validación previa.
            if (isset($data['vencimiento'])) $config['licencia']['vencimiento'] = $data['vencimiento'];
            if (isset($data['activada'])) $config['licencia']['activada'] = (bool)$data['activada'];
            
            DB::setConfig(['licencia' => $config['licencia']]);
            echo json_encode(["mensaje" => "Estado de licencia actualizado", "licencia" => $config['licencia']]);
        }
        break;

    case 'eliminar':
        if ($method == 'POST' || $method == 'DELETE') {
            $data = json_decode(file_get_contents("php://input"), true);
            $id = $data['id'] ?? ($_GET['id'] ?? null);
            if ($id) {
                if (DB::deleteEstudio($id)) {
                    echo json_encode(["mensaje" => "Estudio eliminado", "exito" => true]);
                } else {
                    http_response_code(404);
                    echo json_encode(["error" => "No se pudo eliminar el estudio", "exito" => false]);
                }
            } else {
                http_response_code(400);
                echo json_encode(["error" => "ID de estudio requerido"]);
            }
        }
        break;

    case 'activar':
        if ($method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            $user = $data['usuario'] ?? '';
            $pass = $data['password'] ?? '';
            $user_pass = $user . ':' . $pass;
            
            $config = DB::getConfig();
            $lic = $config['licencia'];
            
            if ($user_pass === $lic['credenciales'] && !empty($user) && !empty($pass)) {
                $dias = isset($data['dias']) ? intval($data['dias']) : 365;
                // Eliminamos la restricción para permitir reducción de licencia

                // Generar clave automáticamente
                $clave = strtoupper(substr(md5($user_pass . time()), 0, 12));

                $lic['activada'] = true;
                $lic['clave_activacion'] = $clave;
                $lic['vencimiento'] = date('Y-m-d', strtotime("+$dias days"));
                
                // Cambio opcional de credenciales maestras
                $msg_extra = "";
                if (!empty($data['nuevo_usuario']) && !empty($data['nuevo_password'])) {
                    $lic['credenciales'] = $data['nuevo_usuario'] . ':' . $data['nuevo_password'];
                    $msg_extra = " y credenciales actualizadas";
                }

                DB::setConfig(['licencia' => $lic]);
                
                // Forzar al Robot a "despertar" si estaba en sleep largo
                @touch(__DIR__ . '/robot.php');

                echo json_encode([
                    "mensaje" => "Sistema activado por $dias días correctamente$msg_extra. Nueva clave: $clave", 
                    "exito" => true,
                    "vencimiento" => $lic['vencimiento'],
                    "clave" => $clave
                ]);
            } else {
                http_response_code(401);
                echo json_encode(["mensaje" => "Usuario o contraseña incorrectos", "exito" => false]);
            }
        }
        break;

    case 'unidades':
        if ($method == 'GET') {
            obtenerEstadoUnidades();
        }
        break;

    case 'expulsar':
        if ($method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            expulsarDisco($data['unidad'] ?? null);
        }
        break;

    case 'grabar':
        if ($method == 'POST') {
            $data = json_decode(file_get_contents("php://input"), true);
            iniciarGrabacion($data['id'], $data['unidad'] ?? null);
        }
        break;

    case 'estadisticas':
        if ($method == 'GET') {
            obtenerEstadisticas();
        }
        break;

    default:
        http_response_code(404);
        echo json_encode(["error" => "Ruta no encontrada: " . $path]);
        break;
}

function obtenerEstadoUnidades() {
    $ahora = time();
    $pulseFile = RUTA_RAIZ . 'backend/robot.pulse';
    $cacheFile = RUTA_RAIZ . 'backend/unidades_cache.json';
    
    // El Robot late cada 2 seg. Si tiene menos de 45seg, está vivo.
    $ultimoPulso = file_exists($pulseFile) ? (int)file_get_contents($pulseFile) : 0;
    $robotActivo = ($ahora - $ultimoPulso < 45);

    if (file_exists($cacheFile)) {
        $mtime = filemtime($cacheFile);
        
        // En Linux, si el robot está activo, PROHIBIDO llamar a hardware desde el API.
        // Siempre usamos el caché si el robot está ahí.
        if ($robotActivo || ($ahora - $mtime < 15)) {
            $fp = fopen($cacheFile, "r");
            if ($fp && flock($fp, LOCK_SH)) {
                $json = stream_get_contents($fp);
                flock($fp, LOCK_UN);
                fclose($fp);
                if ($json) {
                    header('Content-Type: application/json');
                    echo $json;
                    return;
                }
            }
            if ($fp) fclose($fp);
        }
    }

    // Si llegamos aquí, el robot está caído. Solo escaneamos si es estrictamente necesario.
    // En Linux, registramos por qué estamos llamando a hardware (debug)
    if (!ES_WINDOWS) {
        error_log("FALLBACK HARDWARE API: Robot inactivo o sin cache. Pulso: $ultimoPulso, Ahora: $ahora");
    }
    $listaUnidades = getUnidadesOpticas();
    $respuesta = [];

    foreach ($listaUnidades as $unidad) {
        $infoDetalle = getInfoDisco($unidad);
        
        $tipo = 'Bandeja Vac\u00eda';
        if ($infoDetalle['ready']) {
            if ($infoDetalle['blank']) {
                $tipo = 'Disco Blanco \u2713' . ($infoDetalle['capacity'] !== '\u2014' ? " ({$infoDetalle['capacity']})" : '');
            } else {
                $fsLabel = $infoDetalle['fs'] ?: ($infoDetalle['volname'] ?: 'UDF/ISO');
                if ($infoDetalle['rw']) {
                    $tipo = "Disco RW con Datos ($fsLabel)" . ($infoDetalle['volname'] ? " [{$infoDetalle['volname']}]" : '');
                } else {
                    $tipo = "Disco con Datos ($fsLabel)" . ($infoDetalle['volname'] ? " [{$infoDetalle['volname']}]" : '') . " \u26a0 No Regrabable";
                }
            }
        }

        $respuesta[] = [
            'unidad'          => $unidad,
            'disco_insertado' => $infoDetalle['ready'],
            'vacio'           => $infoDetalle['blank'],
            'es_rw'           => $infoDetalle['rw'],
            'tipo'            => $tipo,
            'capacidad'       => $infoDetalle['capacity'],
            'volname'         => $infoDetalle['volname'],
        ];
    }

    $jsonResponse = json_encode($respuesta);
    @file_put_contents($cacheFile, $jsonResponse, LOCK_EX);
    header('Content-Type: application/json');
    echo $jsonResponse;
}

function expulsarDisco($unidad) {
    if (!$unidad) {
        http_response_code(400);
        echo json_encode(["error" => "No se especificó la unidad"]);
        return;
    }

    $exito = expulsarUnidad($unidad);

    // Invalidar el caché de estado de unidades para que el frontend
    // vea el estado actualizado en el próximo polling
    $cacheFile = RUTA_RAIZ . 'backend/unidades_cache.json';
    if (file_exists($cacheFile)) {
        @unlink($cacheFile);
    }

    $plataforma = ES_WINDOWS ? 'Windows (eject_windows.ps1)' : 'Linux (cdrom_helper.sh)';
    echo json_encode([
        "mensaje"     => $exito
            ? "Disco expulsado correctamente de $unidad"
            : "Comando enviado a $unidad (verifique que el disco fue expulsado)",
        "exito"       => $exito,
        "unidad"      => $unidad,
        "plataforma"  => $plataforma,
    ]);
}

function iniciarGrabacion($id, $unidad) {
    if (!$unidad) {
        echo json_encode(["error" => "Debe seleccionar una unidad para grabar"]);
        return;
    }
    DB::updateEstudio($id, [
        'estado' => 'preparando',
        'unidad_asignada' => $unidad
    ]);
    DB::registrarLog($id, 'GRABACION', "Iniciando proceso en la unidad: $unidad");
    echo json_encode(["mensaje" => "Proceso iniciado para el estudio ID: $id en $unidad"]);
}

function cambiarEstadoEstudio($id, $nuevoEstado) {
    if (!$id || !$nuevoEstado) {
        echo json_encode(["error" => "Faltan parámetros"]);
        return;
    }
    DB::updateEstudio($id, ['estado' => $nuevoEstado]);
    DB::registrarLog($id, 'SISTEMA', "Estado cambiado manualmente a: $nuevoEstado");
    echo json_encode(["mensaje" => "Estado actualizado a $nuevoEstado", "id" => $id]);
}

function obtenerEstadisticas() {
    $estudios = DB::getEstudios();
    $config   = DB::getConfig();
    $hoy = date('Y-m-d');
    
    $grabadosHoy = 0;
    $pendientes = 0;
    $errores    = 0;

    foreach ($estudios as $e) {
        if ($e['estado'] === 'finalizado' && isset($e['fecha']) && strpos($e['fecha'], $hoy) !== false) {
            $grabadosHoy++;
        }
        if ($e['estado'] === 'pendiente' || $e['estado'] === 'preparando' || $e['estado'] === 'esperando_disco' || $e['estado'] === 'grabando') {
            $pendientes++;
        }
        if ($e['estado'] === 'error') {
            $errores++;
        }
    }

    $ahora = time();
    $pulseFile = RUTA_RAIZ . 'backend/robot.pulse';
    $ultimoPulso = file_exists($pulseFile) ? (int)file_get_contents($pulseFile) : 0;
    $robotActivo = ($ahora - $ultimoPulso < 45);

    echo json_encode([
        "grabados_hoy" => $grabadosHoy,
        "pendientes"   => $pendientes,
        "errores"      => $errores,
        "robot_activo" => $robotActivo,
        "ultimo_pulso" => $ultimoPulso
    ]);
}
