<?php
/**
 * GET /modules/turnero/api/get_consentimientos.php
 * Retorna el estado actualizado de los consentimientos de un turno.
 * Usado por lugar.php (polling cada 5 s) y recepcion.php.
 * No requiere autenticación (las pantallas internas ya están protegidas).
 *
 * Query params:
 *   turno_id          int   requerido
 *   incluir_solicitud int   opcional  1 → también retorna solicitud, paciente y exámenes
 */

require_once __DIR__ . '/_helpers.php';
requireMethod('GET');

$turnoId         = isset($_GET['turno_id'])          ? (int) $_GET['turno_id']          : 0;
$incluirSolicitud = isset($_GET['incluir_solicitud']) ? (bool)(int)$_GET['incluir_solicitud'] : false;

if ($turnoId <= 0) jsonError('turno_id inválido.');

$pdo = db();

// ── Verificar que el turno existe ─────────────────────────────
$stmt = $pdo->prepare("SELECT id, estado, lugar_destino_id, paciente_id FROM turnero_turnos WHERE id = ?");
$stmt->execute([$turnoId]);
$turno = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$turno) jsonError('Turno no encontrado.', 404);

// ── Formularios de lugar ──────────────────────────────────────────────────────
// Solo cuando el turno tiene lugar destino asignado. En recepción (NULL),
// fidsDeLugar queda vacío → todos los consentimientos reciben origen_lugar_id=null
// → pasan el filtro !c.origen_lugar_id de recepcion.php.
$lugarDestinoId = (int)($turno['lugar_destino_id'] ?? 0);
$fidsDeLugar    = [];
if ($lugarDestinoId) {
    $stmtL = $pdo->prepare(
        "SELECT formulario_id FROM turnero_lugar_consentimientos WHERE lugar_id = ?"
    );
    $stmtL->execute([$lugarDestinoId]);
    $fidsDeLugar = array_map('intval', $stmtL->fetchAll(PDO::FETCH_COLUMN));
}

// ── Consentimientos ───────────────────────────────────────────
$stmt = $pdo->prepare(
    "SELECT tc.id,
            tc.turno_id,
            tc.formulario_id,
            tc.token,
            tc.estado,
            tc.enviado_at,
            tc.firmado_at,
            (tc.firma_profesional_svg IS NOT NULL) AS tiene_firma_profesional,
            tc.firmado_profesional_at,
            tc.siguiente_toma_at,
            tc.toma_inicio_at,
            tc.datos_respuestas,
            f.nombre               AS formulario_nombre,
            f.esquema              AS formulario_esquema,
            f.es_toma_progresiva   AS formulario_es_toma_prog,
            f.solo_profesional     AS formulario_solo_profesional
       FROM turnero_consentimientos tc
       LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
      WHERE tc.turno_id = ?
      ORDER BY tc.id ASC"
);
$stmt->execute([$turnoId]);
$consentimientos = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Compute flags desde el esquema; origen_lugar_id calculado según config actual
foreach ($consentimientos as &$c) {
    $esquema = $c['formulario_esquema'] ?? null;
    $campos  = [];
    if ($esquema) {
        $decoded = json_decode($esquema, true);
        $campos  = is_array($decoded) ? $decoded : ($decoded['campos'] ?? []);
    }
    $camposFirmaPro = array_values(array_filter($campos, fn($f) => ($f['tipo'] ?? '') === 'firma_profesional'));
    $tieneFirmaPro  = !empty($camposFirmaPro);
    $tieneFirmaPac  = !empty(array_filter($campos, fn($f) => ($f['tipo'] ?? '') === 'firma'));

    // Toma progresiva: override explícito en DB gana; si es NULL, usar heurística (>1 campo firma_profesional)
    $overrideProg = $c['formulario_es_toma_prog'] ?? null;
    $esTomaProg   = $overrideProg !== null ? (bool)(int)$overrideProg : count($camposFirmaPro) > 1;
    $dr = $c['datos_respuestas'] ? (json_decode($c['datos_respuestas'], true) ?? []) : [];
    $tomasTotal   = 0;
    $tomasFirm    = 0;
    $tomasDetalle = []; // reiniciar cada vuelta: si no, un formulario sin tomas hereda las del anterior
    if ($esTomaProg) {

        // Mapear cada firma_profesional a los valores de examen de su sección condicional
        // (y a su etiqueta + campo hora, para poder mostrar el detalle por toma)
        $firmaCondMap = [];
        $curCondCampo = null;
        $curCondVals  = [];
        $curLabel     = null;
        $curHoraId    = null;
        foreach ($campos as $campo) {
            $ft = $campo['tipo'] ?? '';
            if ($ft === 'separador') {
                $cond         = $campo['condicion'] ?? null;
                $curCondCampo = $cond ? ($cond['campo_id'] ?? null) : null;
                $curCondVals  = $cond
                    ? ($cond['valores'] ?? ($cond['valor'] ? [$cond['valor']] : []))
                    : [];
                $curLabel  = $campo['label'] ?? '';
                $curHoraId = null;
            } elseif ($ft === 'hora') {
                $curHoraId = $campo['id'] ?? null;
            } elseif ($ft === 'firma_profesional' && !empty($campo['id'])) {
                $firmaCondMap[$campo['id']] = [
                    'campo' => $curCondCampo, 'valores' => $curCondVals,
                    'label' => $curLabel, 'hora_id' => $curHoraId,
                ];
            }
        }

        // Filtrar por exámenes seleccionados en datos_respuestas
        $relevantIds = [];
        foreach ($firmaCondMap as $fid => $info) {
            if ($info['campo'] === null) {
                $relevantIds[] = $fid; // sin condición → siempre aplica
            } else {
                $ctrlVal = $dr[$info['campo']] ?? null;
                $ctrlArr = is_array($ctrlVal) ? $ctrlVal : ($ctrlVal !== null ? [$ctrlVal] : []);
                if (!empty(array_intersect($info['valores'], $ctrlArr))) {
                    $relevantIds[] = $fid;
                }
            }
        }

        // Si hay config de tomas guardada, restringir al subconjunto seleccionado
        $tomasConfig = is_array($dr['_tomas_config'] ?? null) ? $dr['_tomas_config'] : null;
        if ($tomasConfig !== null) {
            $allowedFids = [];
            foreach ($tomasConfig as $__v) {
                if (!is_array($__v)) continue;
                $__inner = reset($__v);
                // nested: exam => { group => [fids] }; flat: group => [fids]
                if (is_array($__inner)) { foreach ($__v as $__fids) foreach ($__fids as $__f) $allowedFids[] = $__f; }
                else                   { foreach ($__v as $__f) $allowedFids[] = $__f; }
            }
            $allowedFids = array_unique($allowedFids);
            $relevantIds = array_values(array_filter($relevantIds, fn($id) => in_array($id, $allowedFids, true)));
        }

        $tomasTotal = count($relevantIds);
        $tomasDetalle = [];
        foreach ($relevantIds as $fid) {
            $firmado = (!empty($dr[$fid]) && strlen($dr[$fid]) > 10)
                    || (!empty($dr[$fid.'_svg']) && strlen($dr[$fid.'_svg']) > 10);
            if ($firmado) $tomasFirm++;
            $info    = $firmaCondMap[$fid] ?? [];
            $horaId  = $info['hora_id'] ?? null;
            $tomasDetalle[] = [
                'label'    => $info['label'] ?? '',
                'hora'     => $horaId ? ($dr[$horaId] ?? null) : null,
                'firmado'  => $firmado,
                'firmante' => $firmado ? ($dr[$fid . '_pro_nombre'] ?? $dr['_pro_nombre'] ?? null) : null,
            ];
        }
    }

    $soloPro = !empty($c['formulario_solo_profesional']);
    $c['requiere_firma_profesional'] = $tieneFirmaPro;
    $c['requiere_firma_paciente']    = $soloPro ? false : !($tieneFirmaPro && !$tieneFirmaPac);
    $c['origen_lugar_id']            = in_array((int)$c['formulario_id'], $fidsDeLugar, true)
                                       ? ($lugarDestinoId ?: -1) : null;
    $c['es_toma_progresiva']         = $esTomaProg;
    $c['tomas_total']                = $tomasTotal;
    $c['tomas_firmadas']             = $tomasFirm;
    $c['tomas_detalle']              = $tomasDetalle ?? [];
    $c['cierre_anticipado']          = $dr['_cierre_anticipado'] ?? null;
    // Exponer campos firma_profesional (ids) para el frontend
    $c['campos_firma_pro']           = array_column($camposFirmaPro, 'id');
    unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['formulario_solo_profesional'], $c['datos_respuestas']);
}
unset($c);

$respuesta = [
    'turno_id'        => $turnoId,
    'turno_estado'    => $turno['estado'],
    'consentimientos' => $consentimientos,
];

// ── Datos adicionales si solicita solicitud ───────────────────
if ($incluirSolicitud) {
    $stmt = $pdo->prepare(
        "SELECT s.id, s.turno_id, s.paciente_id, s.lugar_id,
                s.numero_orden,
                s.total_cobrado, s.metodo_pago, s.observaciones, s.embarazada, s.solo_muestras, s.medico_id, s.creado_at,
                l.nombre AS lugar_nombre,
                CONCAT(m.nombres, ' ', m.apellidos) AS medico_nombre,
                m.cod_especialidad AS medico_especialidad,
                m.codigo AS medico_codigo
           FROM turnero_solicitudes s
           LEFT JOIN turnero_lugares l ON l.id = s.lugar_id
           LEFT JOIN medicos m ON m.id = s.medico_id
          WHERE s.turno_id = ?
          LIMIT 1"
    );
    $stmt->execute([$turnoId]);
    $solicitud = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;

    $paciente = null;
    $examenes = [];

    if ($solicitud) {
        // Paciente
        $stmt = $pdo->prepare(
            "SELECT id, nombre_completo, tipo_documento, numero_documento,
                    fecha_nacimiento, telefono
               FROM lab_pacientes
              WHERE id = ?"
        );
        $stmt->execute([$solicitud['paciente_id']]);
        $paciente = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;

        // Exámenes
        $stmt = $pdo->prepare(
            "SELECT et.id, et.codigo, et.nombre, et.categoria
               FROM turnero_examen_items tei
               JOIN exam_tipos et ON et.id = tei.exam_tipo_id
              WHERE tei.solicitud_id = ?
              ORDER BY et.categoria, et.nombre"
        );
        $stmt->execute([$solicitud['id']]);
        $examenes = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Nota: en visitas de "solo entrega de muestras" no hay exámenes, así que la
        // Fuente 1 (por examen) no aplica, pero la Fuente 2 (por lugar, ej. F-LAB-08
        // Datos Toma de Muestras) sigue siendo obligatoria — se procesa más abajo igual.

        // Auto-crear consentimientos requeridos desde DOS fuentes:
        // 1. Por examen  → exam_tipo_consentimientos
        // 2. Por lugar   → turnero_lugar_consentimientos
        $requeridos   = [];
        $vistosFIds   = [];

        // Fuente 1: examen
        if (!empty($examenes)) {
            $examIds = array_column($examenes, 'id');
            $ph = implode(',', array_fill(0, count($examIds), '?'));
            $stmtE = $pdo->prepare(
                "SELECT DISTINCT etc.formulario_id, f.nombre AS formulario_nombre
                   FROM exam_tipo_consentimientos etc
                   JOIN lab_formularios f ON f.id = etc.formulario_id
                  WHERE etc.exam_tipo_id IN ($ph) AND f.is_active = 1"
            );
            $stmtE->execute($examIds);
            foreach ($stmtE->fetchAll(PDO::FETCH_ASSOC) as $r) {
                $fid = (int)$r['formulario_id'];
                if (!in_array($fid, $vistosFIds, true)) {
                    $requeridos[] = $r;
                    $vistosFIds[] = $fid;
                }
            }
        }

        // Fuente 2: lugar destino ($lugarDestinoId y $fidsDeLugar ya calculados arriba)
        if ($lugarDestinoId) {
            $stmtL = $pdo->prepare(
                "SELECT DISTINCT tlc.formulario_id, f.nombre AS formulario_nombre
                   FROM turnero_lugar_consentimientos tlc
                   JOIN lab_formularios f ON f.id = tlc.formulario_id
                  WHERE tlc.lugar_id = ? AND f.is_active = 1"
            );
            $stmtL->execute([$lugarDestinoId]);
            foreach ($stmtL->fetchAll(PDO::FETCH_ASSOC) as $r) {
                $fid = (int)$r['formulario_id'];
                if (!in_array($fid, $vistosFIds, true)) {
                    $requeridos[] = $r;
                    $vistosFIds[] = $fid;
                }
            }
        }

        // Auto-crear los registros que falten
        if (!empty($requeridos)) {
            $existFormIds = array_map('intval', array_column($consentimientos, 'formulario_id'));
            $stmtIns = $pdo->prepare(
                "INSERT IGNORE INTO turnero_consentimientos
                    (turno_id, formulario_id, token, estado, creado_por)
                 VALUES (?, ?, ?, 'pendiente', ?)"
            );
            $creados = 0;
            foreach ($requeridos as $r) {
                if (!in_array((int)$r['formulario_id'], $existFormIds, true)) {
                    $token = sprintf(
                        '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
                        mt_rand(0,0xffff), mt_rand(0,0xffff),
                        mt_rand(0,0xffff),
                        mt_rand(0,0x0fff)|0x4000,
                        mt_rand(0,0x3fff)|0x8000,
                        mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0,0xffff)
                    );
                    $stmtIns->execute([$turnoId, (int)$r['formulario_id'], $token, adminId()]);
                    $creados++;
                }
            }

            // Re-leer si se crearon nuevos registros y recalcular flags
            if ($creados > 0) {
                $stmtC = $pdo->prepare(
                    "SELECT tc.id, tc.turno_id, tc.formulario_id, tc.token,
                            tc.estado, tc.enviado_at, tc.firmado_at,
                            (tc.firma_profesional_svg IS NOT NULL) AS tiene_firma_profesional,
                            tc.firmado_profesional_at,
                            tc.siguiente_toma_at,
                            tc.toma_inicio_at,
                            tc.datos_respuestas,
                            f.nombre               AS formulario_nombre,
                            f.esquema              AS formulario_esquema,
                            f.es_toma_progresiva   AS formulario_es_toma_prog,
                            f.solo_profesional     AS formulario_solo_profesional
                       FROM turnero_consentimientos tc
                       LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
                      WHERE tc.turno_id = ?
                      ORDER BY tc.id ASC"
                );
                $stmtC->execute([$turnoId]);
                $consentimientos = $stmtC->fetchAll(PDO::FETCH_ASSOC);
                foreach ($consentimientos as &$c) {
                    $esquema = $c['formulario_esquema'] ?? null;
                    $campos  = [];
                    if ($esquema) {
                        $decoded = json_decode($esquema, true);
                        $campos  = is_array($decoded) ? $decoded : ($decoded['campos'] ?? []);
                    }
                    $camposFirmaPro = array_values(array_filter($campos, fn($f) => ($f['tipo'] ?? '') === 'firma_profesional'));
                    $tieneFirmaPro  = !empty($camposFirmaPro);
                    $tieneFirmaPac  = !empty(array_filter($campos, fn($f) => ($f['tipo'] ?? '') === 'firma'));
                    $overrideProg   = $c['formulario_es_toma_prog'] ?? null;
                    $esTomaProg     = $overrideProg !== null ? (bool)(int)$overrideProg : count($camposFirmaPro) > 1;
                    $dr2 = $c['datos_respuestas'] ? (json_decode($c['datos_respuestas'], true) ?? []) : [];
                    $tomasTotal2 = 0;
                    $tomasFirm   = 0;
                    if ($esTomaProg) {
                        $firmaCondMap2 = [];
                        $curC2 = null; $curV2 = [];
                        foreach ($campos as $campo2) {
                            $ft2 = $campo2['tipo'] ?? '';
                            if ($ft2 === 'separador') {
                                $cond2 = $campo2['condicion'] ?? null;
                                $curC2 = $cond2 ? ($cond2['campo_id'] ?? null) : null;
                                $curV2 = $cond2 ? ($cond2['valores'] ?? ($cond2['valor'] ? [$cond2['valor']] : [])) : [];
                            } elseif ($ft2 === 'firma_profesional' && !empty($campo2['id'])) {
                                $firmaCondMap2[$campo2['id']] = ['campo' => $curC2, 'valores' => $curV2];
                            }
                        }
                        $relevantIds2 = [];
                        foreach ($firmaCondMap2 as $fid2 => $info2) {
                            if ($info2['campo'] === null) {
                                $relevantIds2[] = $fid2;
                            } else {
                                $cv2 = $dr2[$info2['campo']] ?? null;
                                $ca2 = is_array($cv2) ? $cv2 : ($cv2 !== null ? [$cv2] : []);
                                if (!empty(array_intersect($info2['valores'], $ca2))) $relevantIds2[] = $fid2;
                            }
                        }
                        $cfg2 = is_array($dr2['_tomas_config'] ?? null) ? $dr2['_tomas_config'] : null;
                        if ($cfg2 !== null) {
                            $allowed2 = [];
                            foreach ($cfg2 as $__v2) {
                                if (!is_array($__v2)) continue;
                                $__i2 = reset($__v2);
                                if (is_array($__i2)) { foreach ($__v2 as $__fids2) foreach ($__fids2 as $__f2) $allowed2[] = $__f2; }
                                else                 { foreach ($__v2 as $__f2) $allowed2[] = $__f2; }
                            }
                            $allowed2 = array_unique($allowed2);
                            $relevantIds2 = array_values(array_filter($relevantIds2, fn($id) => in_array($id, $allowed2, true)));
                        }
                        $tomasTotal2 = count($relevantIds2);
                        foreach ($relevantIds2 as $fid2) {
                            if (!empty($dr2[$fid2]) && strlen($dr2[$fid2]) > 10) $tomasFirm++;
                        }
                    }
                    $soloPro2 = !empty($c['formulario_solo_profesional']);
                    $c['requiere_firma_profesional'] = $tieneFirmaPro;
                    $c['requiere_firma_paciente']    = $soloPro2 ? false : !($tieneFirmaPro && !$tieneFirmaPac);
                    $c['origen_lugar_id']            = in_array((int)$c['formulario_id'], $fidsDeLugar, true)
                                                       ? $lugarDestinoId : null;
                    $c['es_toma_progresiva']         = $esTomaProg;
                    $c['tomas_total']                = $tomasTotal2;
                    $c['tomas_firmadas']             = $tomasFirm;
                    $c['cierre_anticipado']          = $dr2['_cierre_anticipado'] ?? null;
                    $c['campos_firma_pro']           = array_column($camposFirmaPro, 'id');
                    unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['formulario_solo_profesional'], $c['datos_respuestas']);
                }
                unset($c);
                $respuesta['consentimientos'] = $consentimientos;
            }
        }
    }

    // Muestras pendientes / recibidas del turno
    $muestras = [];
    if ($solicitud) {
        try {
            $stmtM = $pdo->prepare(
                "SELECT tm.id, tm.tipo_muestra, tm.estado, tm.motivo_rechazo, tm.recibida_at,
                        COALESCE(lt.nombre, tm.tipo_muestra) AS label,
                        0 AS es_pendiente_anterior, NULL AS solicitud_orden_anterior
                   FROM turnero_muestras tm
                   LEFT JOIN lab_tipos_muestra lt ON lt.codigo = tm.tipo_muestra
                  WHERE tm.solicitud_id = ?
                  ORDER BY tm.id ASC"
            );
            $stmtM->execute([$solicitud['id']]);
            $muestras = $stmtM->fetchAll(PDO::FETCH_ASSOC);

            // Si es visita de entrega de muestras, agregar pendientes de solicitudes anteriores
            if (!empty($solicitud['solo_muestras']) && !empty($solicitud['paciente_id'])) {
                $stmtPrev = $pdo->prepare(
                    "SELECT tm.id, tm.tipo_muestra, tm.estado, tm.motivo_rechazo, tm.recibida_at,
                            COALESCE(lt.nombre, tm.tipo_muestra) AS label,
                            1 AS es_pendiente_anterior,
                            ts.id AS solicitud_id_anterior,
                            ts.numero_orden AS solicitud_orden_anterior
                       FROM turnero_muestras tm
                       JOIN turnero_solicitudes ts ON ts.id = tm.solicitud_id
                       LEFT JOIN lab_tipos_muestra lt ON lt.codigo = tm.tipo_muestra
                      WHERE ts.paciente_id = ?
                        AND tm.solicitud_id != ?
                        AND tm.estado IN ('pendiente','rechazada')
                      ORDER BY tm.id ASC"
                );
                $stmtPrev->execute([$solicitud['paciente_id'], $solicitud['id']]);
                $previas = $stmtPrev->fetchAll(PDO::FETCH_ASSOC);
                $muestras = array_merge($previas, $muestras);
            }
        } catch (\Throwable $_) {
            // Tabla aún no existe
        }
    }

    // Fallback: sin solicitud pero el turno tiene paciente_id → buscar muestras pendientes igualmente
    if (!$solicitud && !empty($turno['paciente_id'])) {
        $pacId = (int)$turno['paciente_id'];
        $stmt = $pdo->prepare(
            "SELECT id, nombre_completo, tipo_documento, numero_documento,
                    fecha_nacimiento, telefono
               FROM lab_pacientes WHERE id = ?"
        );
        $stmt->execute([$pacId]);
        $paciente = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
        try {
            $stmtPrev = $pdo->prepare(
                "SELECT tm.id, tm.tipo_muestra, tm.estado, tm.motivo_rechazo, tm.recibida_at,
                        COALESCE(lt.nombre, tm.tipo_muestra) AS label,
                        1 AS es_pendiente_anterior,
                        ts.id AS solicitud_id_anterior,
                        ts.numero_orden AS solicitud_orden_anterior
                   FROM turnero_muestras tm
                   JOIN turnero_solicitudes ts ON ts.id = tm.solicitud_id
                   LEFT JOIN lab_tipos_muestra lt ON lt.codigo = tm.tipo_muestra
                  WHERE ts.paciente_id = ?
                    AND tm.estado IN ('pendiente','rechazada')
                  ORDER BY tm.id ASC"
            );
            $stmtPrev->execute([$pacId]);
            $muestras = $stmtPrev->fetchAll(PDO::FETCH_ASSOC);
        } catch (\Throwable $_) {}
    }

    // Cargar exámenes de la solicitud original para cada muestra pendiente de visita anterior,
    // para que al recibirla se vea el contexto completo del servicio (no solo el tipo de muestra)
    $solIdsAnteriores = array_values(array_unique(array_filter(
        array_column($muestras, 'solicitud_id_anterior')
    )));
    if ($solIdsAnteriores) {
        $ph = implode(',', array_fill(0, count($solIdsAnteriores), '?'));
        $stmtExAnt = $pdo->prepare(
            "SELECT tei.solicitud_id, et.nombre, et.codigo
               FROM turnero_examen_items tei
               JOIN exam_tipos et ON et.id = tei.exam_tipo_id
              WHERE tei.solicitud_id IN ($ph)
              ORDER BY et.nombre ASC"
        );
        $stmtExAnt->execute($solIdsAnteriores);
        $examPorSolicitud = [];
        foreach ($stmtExAnt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $examPorSolicitud[(int)$row['solicitud_id']][] = ['nombre' => $row['nombre'], 'codigo' => $row['codigo']];
        }
        foreach ($muestras as &$m) {
            if (!empty($m['solicitud_id_anterior'])) {
                $m['examenes_anteriores'] = $examPorSolicitud[(int)$m['solicitud_id_anterior']] ?? [];
            }
        }
        unset($m);
    }

    $respuesta['solicitud'] = $solicitud;
    $respuesta['paciente']  = $paciente;
    $respuesta['examenes']  = $examenes;
    $respuesta['muestras']  = $muestras;
}

jsonOk($respuesta);
