<?php
/**
 * Helpers compartidos para los endpoints del módulo de laboratorio.
 * Incluido automáticamente por cada endpoint de /api/lab/.
 */

// Capturar cualquier salida accidental (warnings, notices) antes del JSON
ob_start();

require_once __DIR__ . '/../../config/config.php';
require_once __DIR__ . '/../../classes/lab/ActividadAdmin.php';
require_once __DIR__ . '/../../classes/lab/Paciente.php';
require_once __DIR__ . '/../../classes/lab/Enfermera.php';
require_once __DIR__ . '/../../classes/lab/OrdenMedica.php';
require_once __DIR__ . '/../../classes/lab/Domicilio.php';
require_once __DIR__ . '/../../classes/lab/Asignacion.php';
require_once __DIR__ . '/../../classes/lab/Formulario.php';

// Los endpoints API nunca deben mostrar errores PHP en HTML — enviar como JSON
error_reporting(E_ERROR | E_PARSE);
ini_set('display_errors', '0');
ini_set('html_errors', '0');

// Interceptar errores fatales y devolverlos como JSON en lugar de HTML
register_shutdown_function(function () {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        ob_clean();
        http_response_code(500);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode([
            'ok'    => false,
            'error' => 'Error interno del servidor: ' . $err['message'],
        ]);
    }
});

// Cabeceras JSON estándar
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

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

requireAuthentication();

/**
 * Shorthand para obtener la conexión PDO.
 */
function db(): \PDO {
    return Database::getInstance()->getConnection();
}

/**
 * ID del admin autenticado actualmente.
 */
function adminId(): ?int {
    return isset($_SESSION['admin_user']['id'])
        ? (int)$_SESSION['admin_user']['id']
        : null;
}

/**
 * Rol del usuario autenticado ('admin' | 'enfermero').
 */
function userRole(): string {
    return $_SESSION['admin_user']['role'] ?? 'admin';
}

/**
 * Detiene la ejecución con 403 JSON si el usuario no es admin ni superadmin.
 */
function requireAdmin(): void {
    $role = userRole();
    if (!in_array($role, ['admin', 'superadmin'], true)) {
        jsonError('Acceso restringido a administradores', 403);
    }
}

/**
 * Detiene la ejecución con 403 JSON si el usuario no tiene permiso 'write' sobre el módulo dado.
 * Los admins sin role_id tienen acceso total (retrocompat.).
 */
function requireModuleWrite(string $moduleSlug): void {
    $role    = userRole();
    $modules = $_SESSION['admin_user']['modules'] ?? null;

    // Enfermero nunca tiene write en módulos de diseño
    if ($role === 'enfermero') {
        jsonError('Solo permite­o a administradores', 403);
    }

    // Admin sin modules cargados = acceso total (sistema legacy)
    if ($modules === null || ($role === 'admin' && empty($_SESSION['admin_user']['role_id']))) {
        return;
    }

    $perms = $_SESSION['admin_user']['module_permissions'] ?? [];
    if (($perms[$moduleSlug] ?? '') !== 'write') {
        jsonError('No tienes permiso de escritura en este módulo', 403);
    }
}

/**
 * Detiene la ejecución si no se puede actuar como enfermero.
 * Acepta tanto admins (que pueden actuar en nombre de cualquier enfermera)
 * como el propio enfermero autenticado.
 */
function requireEnfermeroAccess(int $enfermeraIdSolicitado): void {
    if (userRole() === 'admin') return;
    $propio = enfermeraId();
    if (!$propio || $propio !== $enfermeraIdSolicitado) {
        jsonError('Solo puedes gestionar tus propios domicilios', 403);
    }
}

/**
 * Lee el body JSON del request.
 */
function inputJson(): array {
    static $parsed = null;
    if ($parsed === null) {
        $raw    = file_get_contents('php://input');
        $parsed = json_decode($raw, true) ?? [];
    }
    return $parsed;
}

/**
 * Devuelve una respuesta de éxito.
 */
function jsonOk(array $payload = [], string $mensaje = ''): void {
    ob_clean();
    $resp = ['ok' => true, 'success' => true];
    if ($mensaje) {
        $resp['message'] = $mensaje;
    }
    echo json_encode(array_merge($resp, $payload), JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * Devuelve un error JSON con código HTTP.
 */
function jsonError(string $mensaje, int $code = 400): void {
    ob_clean();
    http_response_code($code);
    echo json_encode(['ok' => false, 'success' => false, 'error' => $mensaje], JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * Valida que el método HTTP sea el esperado.
 */
function requireMethod(string $method): void {
    if ($_SERVER['REQUEST_METHOD'] !== strtoupper($method)) {
        jsonError('Método no permitido', 405);
    }
}
