<?php
/**
 * POST /modules/turnero/api/guardar_toma.php
 * Guarda una firma parcial en formularios de tomas prolongadas.
 * Calcula el próximo intervalo y actualiza estado + siguiente_toma_at.
 *
 * Body JSON:
 *   turno_id       int     requerido
 *   formulario_id  int     requerido
 *   campo_id       string  requerido  (id del campo firma_profesional firmado)
 *   svg            string  requerido  (data URI)
 *   datos_respuestas object requerido (todos los valores actuales del form)
 */
require_once __DIR__ . '/_helpers.php';
requireMethod('POST');
requireTurnero();

$body         = inputJson();
$turnoId      = (int)($body['turno_id']      ?? 0);
$formularioId = (int)($body['formulario_id'] ?? 0);
$campoId      = trim($body['campo_id']       ?? '');
$svg          = $body['svg']                 ?? '';
$datosInput   = is_array($body['datos_respuestas'] ?? null) ? $body['datos_respuestas'] : [];

if (!$turnoId)      jsonError('turno_id requerido.');
if (!$formularioId) jsonError('formulario_id requerido.');
if (!$campoId)      jsonError('campo_id requerido.');
if (strlen($svg) < 100) jsonError('Firma requerida.');
if (!preg_match('/^data:image\/(svg\+xml|png|jpeg|webp);base64,/i', $svg)) {
    jsonError('Formato de firma no válido.');
}

$pdo = db();

// ── Cargar consentimiento y esquema ──────────────────────────
$stmt = $pdo->prepare(
    "SELECT tc.id, tc.estado, tc.datos_respuestas, tc.toma_inicio_at, t.sesion_id,
            f.esquema
       FROM turnero_consentimientos tc
       JOIN turnero_turnos t ON t.id = tc.turno_id
       JOIN lab_formularios f ON f.id = tc.formulario_id
      WHERE tc.turno_id = ? AND tc.formulario_id = ?"
);
$stmt->execute([$turnoId, $formularioId]);
$tc = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$tc) jsonError('Consentimiento no encontrado.', 404);

$esquema = json_decode($tc['esquema'] ?? '[]', true);
if (!is_array($esquema)) $esquema = [];

// ── Merge datos_respuestas existentes + nuevos ───────────────
$datosActuales = [];
if ($tc['datos_respuestas']) {
    $d = json_decode($tc['datos_respuestas'], true);
    if (is_array($d)) $datosActuales = $d;
}
// Guardar svg en el campo firmado
$datosInput[$campoId] = $svg;

// Identidad del firmante — resuelta en el servidor desde la sesión, no desde el
// cliente: cada toma puede firmarla un profesional distinto y esta es la única
// fuente confiable de quién la hizo.
$__uid = adminId();
if ($__uid) {
    $stmtPro = $pdo->prepare(
        "SELECT au.full_name, au.cedula AS au_cedula,
                le.nombre_completo AS pro_nombre, le.numero_documento AS pro_documento
           FROM admin_users au
           LEFT JOIN lab_enfermeras le ON le.id = au.enfermera_id
          WHERE au.id = ? LIMIT 1"
    );
    $stmtPro->execute([$__uid]);
    $pro = $stmtPro->fetch(PDO::FETCH_ASSOC) ?: [];
    $proNombre = ($pro['pro_nombre'] ?? null) ?: ($pro['full_name'] ?? null);
    $proCedula = ($pro['au_cedula'] ?? null) ?: ($pro['pro_documento'] ?? null);
    if ($proNombre) {
        $datosInput[$campoId . '_pro_nombre'] = $proNombre;
        $datosInput['_pro_nombre']            = $proNombre; // respaldo global
    }
    if ($proCedula) {
        $datosInput[$campoId . '_pro_cedula'] = $proCedula;
        $datosInput['_pro_cedula']            = $proCedula;
    }
    $datosInput[$campoId . '_pro_id'] = $__uid;
}

$datosMerge = array_merge($datosActuales, $datosInput);

// ── Analizar esquema: campos firma_profesional en orden ──────
// Solo incluye firmas cuya sección condicional coincide con el examen seleccionado.
$firmasCampos   = [];
$separadorLabel = null;
$curCondField   = null;
$curCondVals    = [];

foreach ($esquema as $campo) {
    $tipo = $campo['tipo'] ?? '';
    if ($tipo === 'separador') {
        $separadorLabel = $campo['label'] ?? '';
        $cond = $campo['condicion'] ?? null;
        if ($cond) {
            $curCondField = $cond['campo_id'] ?? null;
            $curCondVals  = $cond['valores'] ?? ($cond['valor'] ? [$cond['valor']] : []);
        } else {
            $curCondField = null;
            $curCondVals  = [];
        }
    }
    if ($tipo === 'firma_profesional') {
        // Filtrar por condición del separador padre
        if ($curCondField !== null && !empty($curCondVals)) {
            $ctrlVal = $datosMerge[$curCondField] ?? null;
            $ctrlArr = is_array($ctrlVal) ? $ctrlVal : ($ctrlVal !== null ? [$ctrlVal] : []);
            if (empty(array_intersect($curCondVals, $ctrlArr))) continue;
        }
        $minutos  = null;
        $horaFija = null;
        if ($separadorLabel !== null) {
            if (preg_match('/Minuto\s+(\d+)/i', $separadorLabel, $m)) {
                $minutos = (int)$m[1];
            } elseif (preg_match('/(\d+):(\d+)\s*(a\.?m\.?|p\.?m\.?)/i', $separadorLabel, $m)) {
                $h = (int)$m[1]; $min = (int)$m[2];
                $pm = strtolower(preg_replace('/[^apm]/i', '', $m[3])) === 'pm';
                if ($pm && $h < 12) $h += 12;
                $horaFija = sprintf('%02d:%02d:00', $h, $min);
            } elseif (stripos($separadorLabel, 'Otro') !== false) {
                $otroVal = trim((string)($datosMerge['_otro_hora'] ?? ''));
                $minutos = is_numeric($otroVal) ? (int)$otroVal : PHP_INT_MAX;
            }
        }
        $firmasCampos[] = ['id' => $campo['id'], 'minutos' => $minutos, 'hora_fija' => $horaFija];
    }
}

// ── Aplicar filtro de ciclos configurados (tomas_config) ────
$__tcFirmas = $datosMerge['_tomas_config'] ?? null;
if (is_array($__tcFirmas)) {
    $__allowed = [];
    foreach ($__tcFirmas as $__v) {
        if (!is_array($__v)) continue;
        $__inner = reset($__v);
        if (is_array($__inner)) {
            // nested: { examName: { groupKey: [fids] } }
            foreach ($__v as $__fids) foreach ($__fids as $__f) $__allowed[$__f] = true;
        } else {
            // flat: { groupKey: [fids] }
            foreach ($__v as $__f) $__allowed[$__f] = true;
        }
    }
    $firmasCampos = array_values(array_filter($firmasCampos, fn($f) => isset($__allowed[$f['id']])));
}

// Ordenar cronológicamente para que el siguiente pendiente sea el más próximo
usort($firmasCampos, fn($a, $b) => ($a['minutos'] ?? PHP_INT_MAX) <=> ($b['minutos'] ?? PHP_INT_MAX));

// ── Determinar estado y siguiente_toma_at ────────────────────
// Acepta firma guardada con clave campo_id O campo_id_svg (compatibilidad registros históricos)
$hasFirma   = fn($f) => (isset($datosMerge[$f['id']]) && strlen($datosMerge[$f['id']]) > 10)
                      || (isset($datosMerge[$f['id'].'_svg']) && strlen($datosMerge[$f['id'].'_svg']) > 10);
$firmados   = array_filter($firmasCampos, $hasFirma);
$pendientes = array_values(array_filter($firmasCampos, fn($f) => !$hasFirma($f)));

$todasFirmadas    = empty($pendientes);
$siguienteToma    = null;
$nuevoEstado      = 'en_progreso';
$tomaInicioAt     = $tc['toma_inicio_at'];

if (empty($tc['toma_inicio_at'])) {
    $tomaInicioAt = date('Y-m-d H:i:s');
}

if ($todasFirmadas) {
    $nuevoEstado = 'firmado';
} else {
    $next = $pendientes[0];
    if ($next['hora_fija'] !== null) {
        $siguienteToma = date('Y-m-d') . ' ' . $next['hora_fija'];
    } elseif ($next['minutos'] !== null && $tomaInicioAt) {
        $siguienteToma = date('Y-m-d H:i:s', strtotime($tomaInicioAt) + $next['minutos'] * 60);
    }
    // Si la siguiente toma ya pasó o es ahora (minuto 0), no enviar countdown
    if ($siguienteToma !== null && $siguienteToma <= date('Y-m-d H:i:s')) {
        $siguienteToma = null;
    }
}

// ── Persistir ────────────────────────────────────────────────
$pdo->prepare(
    "UPDATE turnero_consentimientos
        SET datos_respuestas  = ?,
            estado            = ?,
            siguiente_toma_at = ?,
            toma_inicio_at    = COALESCE(toma_inicio_at, ?),
            firmado_at        = IF(? = 'firmado', NOW(), firmado_at),
            firmado_profesional_at = IF(? = 'firmado', NOW(), firmado_profesional_at)
      WHERE turno_id = ? AND formulario_id = ?"
)->execute([
    json_encode($datosMerge, JSON_UNESCAPED_UNICODE),
    $nuevoEstado,
    $siguienteToma,
    date('Y-m-d H:i:s'),
    $nuevoEstado,
    $nuevoEstado,
    $turnoId,
    $formularioId,
]);

notificarSSE((int)$tc['sesion_id']);

$totalFirmas   = count($firmasCampos);
$firmadasCount = count($firmados) + ($todasFirmadas ? 0 : 1); // incluye la recién guardada

jsonOk([
    'estado'           => $nuevoEstado,
    'siguiente_toma_at'=> $siguienteToma,
    'tomas_firmadas'   => min($firmadasCount, $totalFirmas),
    'tomas_total'      => $totalFirmas,
    'completado'       => $todasFirmadas,
], $todasFirmadas ? 'Formulario completado.' : 'Toma guardada. Próxima: ' . ($siguienteToma ?? 'pendiente'));
