<?php
/**
 * GET /modules/turnero/api/get_traza_turno.php?turno_id=N
 *
 * Bitácora de un turno: qué pasó, cuándo y quién lo hizo.
 *
 * La información ya existía, pero repartida en cinco tablas y sin ninguna
 * pantalla que la juntara: para saber quién retiró un formulario había que
 * consultar la base a mano. Aquí se unifica en una sola línea de tiempo.
 *
 * No inventa nada: cada evento sale de un dato guardado. Lo que el sistema no
 * registró —ver `sinRastro` más abajo— simplemente no aparece.
 */

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

$turnoId = (int)($_GET['turno_id'] ?? 0);
if (!$turnoId) jsonError('turno_id requerido');

$pdo = db();

$t = $pdo->prepare(
    "SELECT t.*, l.nombre AS lugar_nombre, d.nombre AS desk_nombre,
            ur.full_name AS recepcionista, ul.full_name AS profesional
       FROM turnero_turnos t
       LEFT JOIN turnero_lugares l ON l.id = t.lugar_destino_id
       LEFT JOIN turnero_lugares d ON d.id = t.recepcion_desk_id
       LEFT JOIN admin_users ur    ON ur.id = t.atendido_recepcion_por
       LEFT JOIN admin_users ul    ON ul.id = t.atendido_lugar_por
      WHERE t.id = ? LIMIT 1"
);
$t->execute([$turnoId]);
$turno = $t->fetch(PDO::FETCH_ASSOC);
if (!$turno) jsonError('Turno no encontrado', 404);

$ev = [];
$add = function ($cuando, $tipo, $texto, $quien = null, $extra = null) use (&$ev) {
    if (!$cuando) return;
    $ev[] = [
        'cuando' => $cuando,
        'tipo'   => $tipo,      // la vista lo usa para el ícono y el color
        'texto'  => $texto,
        'quien'  => $quien ?: null,
        'extra'  => $extra ?: null,
    ];
};

// ── 1. Recorrido del turno ────────────────────────────────────────────────
$add($turno['creado_at'],            'turno',     'Turno creado');
$add($turno['llamado_recepcion_at'], 'llamado',   'Llamado a ' . ($turno['desk_nombre'] ?: 'recepción'));
$add($turno['inicio_recepcion_at'],  'atencion',  'Inicia atención en recepción', $turno['recepcionista']);
$add($turno['fin_recepcion_at'],     'atencion',  'Termina recepción');
$add($turno['llamado_lugar_at'],     'llamado',   'Llamado a ' . ($turno['lugar_nombre'] ?: 'toma de muestras'));
$add($turno['inicio_lugar_at'],      'atencion',  'Inicia toma de muestras', $turno['profesional']);
$add($turno['muestra_espera_at'],    'muestra',   'Pasa a espera de muestra');
$add($turno['fin_lugar_at'],         'fin',       'Finaliza la atención');

// ── 2. Documentos ─────────────────────────────────────────────────────────
$q = $pdo->prepare(
    "SELECT tc.enviado_at, tc.firmado_at, tc.firmado_profesional_at, tc.estado,
            tc.firma_svg, tc.firma_profesional_svg, tc.datos_respuestas,
            f.nombre AS formulario, f.es_toma_progresiva
       FROM turnero_consentimientos tc
       JOIN lab_formularios f ON f.id = tc.formulario_id
      WHERE tc.turno_id = ?"
);
$q->execute([$turnoId]);
foreach ($q->fetchAll(PDO::FETCH_ASSOC) as $c) {
    $add($c['enviado_at'], 'doc', 'Enviado: ' . $c['formulario']);

    // No todos los formularios los firma el paciente: el F-LAB-08 solo lo firma
    // el profesional y el F-LAB-28 lleva una firma por toma. Se mira qué firma
    // hay guardada en vez de suponer que firmado_at es del paciente, que era lo
    // que antes hacía decir «firmado por el paciente» en documentos que el
    // paciente nunca firmó.
    $firmoPaciente    = !empty($c['firma_svg']);
    $firmoProfesional = !empty($c['firma_profesional_svg']);

    if ($firmoPaciente) {
        $add($c['firmado_at'], 'doc_ok', 'Firmado por el paciente: ' . $c['formulario']);
    }
    if ($firmoProfesional) {
        $add($c['firmado_profesional_at'] ?: $c['firmado_at'], 'doc_ok',
             'Firmado por el profesional: ' . $c['formulario']);
    }

    // Protocolo prolongado: cada toma lleva su hora y su firmante, que es el
    // dato que de verdad interesa. La firma general no dice quién pinchó.
    if (!empty($c['es_toma_progresiva'])) {
        $dr = json_decode($c['datos_respuestas'] ?? '{}', true) ?: [];
        $tomas = [];
        foreach ($dr as $clave => $valor) {
            // Las firmas de toma terminan en _f y traen su hora en _h
            if (!preg_match('/^(_tm[a-z0-9]+)_f$/', $clave, $m)) continue;
            if (!is_string($valor) || strlen($valor) < 10) continue;
            $base = $m[1];
            $tomas[] = [
                'hora'     => $dr[$base . '_h'] ?? null,
                // _tm00 → «Minuto 0», _tm150 → «Minuto 150»
                'etiqueta' => 'Minuto ' . (int) substr($base, 3),
                'firmante' => $dr[$clave . '_pro_nombre'] ?? null,
            ];
        }
        // Se ordenan por hora para que la línea de tiempo quede coherente
        usort($tomas, fn($a, $b) => strcmp((string)$a['hora'], (string)$b['hora']));
        foreach ($tomas as $t) {
            if (!$t['hora']) continue;
            // La hora viene como "HH:MM"; se ancla al día del turno
            $cuando = substr($turno['creado_at'], 0, 10) . ' ' . $t['hora'] . ':00';
            $add($cuando, 'muestra',
                 'Toma tomada y firmada (' . $t['etiqueta'] . ')',
                 $t['firmante']);
        }
    }

    if (!$firmoPaciente && !$firmoProfesional && $c['firmado_at'] && empty($c['es_toma_progresiva'])) {
        $add($c['firmado_at'], 'doc_ok', 'Completado: ' . $c['formulario']);
    }
    if (!empty($c['es_toma_progresiva']) && $c['firmado_at']) {
        $add($c['firmado_at'], 'fin', 'Protocolo cerrado: ' . $c['formulario']);
    }
}

// ── 3. Comentarios del personal ───────────────────────────────────────────
// Aquí caen también las ausencias, que se guardan como comentario con su motivo.
$q = $pdo->prepare(
    "SELECT creado_at, usuario_nombre, comentario, tipo
       FROM turnero_comentarios WHERE turno_id = ? ORDER BY creado_at"
);
$q->execute([$turnoId]);
foreach ($q->fetchAll(PDO::FETCH_ASSOC) as $c) {
    $add($c['creado_at'], 'comentario', $c['comentario'], $c['usuario_nombre'], $c['tipo']);
}

// ── 4. Muestras ───────────────────────────────────────────────────────────
$q = $pdo->prepare(
    "SELECT m.recibida_at, m.tipo_muestra, m.estado, m.motivo_rechazo,
            u.full_name AS quien
       FROM turnero_muestras m
       LEFT JOIN admin_users u ON u.id = m.recibida_por
      WHERE m.recibida_en_turno_id = ?"
);
$q->execute([$turnoId]);
foreach ($q->fetchAll(PDO::FETCH_ASSOC) as $m) {
    $texto = $m['estado'] === 'rechazada'
        ? 'Muestra RECHAZADA (' . $m['tipo_muestra'] . '): ' . ($m['motivo_rechazo'] ?: 'sin motivo')
        : 'Muestra recibida (' . $m['tipo_muestra'] . ')';
    $add($m['recibida_at'], $m['estado'] === 'rechazada' ? 'alerta' : 'muestra', $texto, $m['quien']);
}

// ── 5. Acciones administrativas auditadas ─────────────────────────────────
// El detalle es JSON; se filtra por turno en PHP para no depender de LIKE.
$q = $pdo->prepare(
    "SELECT created_at, admin_nombre, accion, detalle
       FROM lab_actividad_admin
      WHERE modulo IN ('turnero','turnero_config') AND detalle LIKE ?"
);
$q->execute(['%"turno_id":' . $turnoId . '%']);
foreach ($q->fetchAll(PDO::FETCH_ASSOC) as $a) {
    $d = json_decode($a['detalle'], true) ?: [];
    if ((int)($d['turno_id'] ?? 0) !== $turnoId) continue;   // evita coincidencias por prefijo

    // Cada acción se traduce a algo que se entienda leyéndolo, no al nombre
    // técnico del endpoint.
    switch ($a['accion']) {
        case 'quitar_consentimiento':
            $add($a['created_at'], 'alerta',
                'Formulario RETIRADO: ' . ($d['formulario_nombre'] ?? '?'),
                $a['admin_nombre'],
                'Motivo: ' . ($d['motivo'] ?? 'sin motivo')
                    . ' · estaba en «' . ($d['estado_previo'] ?? '?') . '»');
            break;

        case 'cambiar_estado':
            $add($a['created_at'], 'admin',
                'Estado cambiado a mano: ' . ($d['estado_previo'] ?? '?')
                    . ' → ' . ($d['estado_nuevo'] ?? '?'),
                $a['admin_nombre']);
            break;

        case 'resetear_consentimiento':
            $add($a['created_at'], 'alerta',
                'Formulario REINICIADO: ' . ($d['formulario_nombre'] ?? '?'),
                $a['admin_nombre'],
                !empty($d['tenia_firma'])
                    ? 'Se descartó una firma ya hecha'
                    : 'No tenía firma todavía');
            break;

        case 'resetear_toma':
            $n = is_array($d['campos_olvidados'] ?? null) ? count($d['campos_olvidados']) : 0;
            $add($a['created_at'], 'alerta',
                'Toma olvidada en ' . ($d['formulario_nombre'] ?? 'protocolo'),
                $a['admin_nombre'],
                $n ? "Se descartaron $n dato(s) de la toma" : null);
            break;

        case 'cancelar_toma_pendiente':
            $add($a['created_at'], 'alerta',
                'Cancelada la toma pendiente de ' . ($d['turno_origen'] ?? 'otra visita'),
                $a['admin_nombre'],
                $d['formulario_nombre'] ?? null);
            break;

        case 'llamar_turno':
            $add($a['created_at'], 'llamado', 'Llamó al paciente', $a['admin_nombre']);
            break;

        case 'rellamar':
            $add($a['created_at'], 'llamado', 'Volvió a llamar al paciente', $a['admin_nombre']);
            break;

        case 'vincular_paciente':
            $add($a['created_at'], 'admin',
                'Paciente vinculado: ' . ($d['paciente_nombre'] ?? '#' . ($d['paciente_id'] ?? '?')),
                $a['admin_nombre']);
            break;

        default:
            $add($a['created_at'], 'admin', $a['accion'], $a['admin_nombre']);
    }
}

usort($ev, fn($a, $b) => strcmp($a['cuando'], $b['cuando']));

// ── 6. Conversación de WhatsApp ───────────────────────────────────────────
// Solo el conteo del día y el enlace al chat: volcar los mensajes aquí sería
// esparcir datos personales del paciente por una pantalla de consulta.
$chat = null;
if (!empty($turno['paciente_id'])) {
    $q = $pdo->prepare(
        "SELECT u.id AS user_id,
                (SELECT COUNT(*) FROM conversations c
                  WHERE c.user_id = u.id AND DATE(c.created_at) = DATE(?)) AS mensajes
           FROM lab_pacientes p JOIN users u ON u.id = p.user_id
          WHERE p.id = ? LIMIT 1"
    );
    $q->execute([$turno['creado_at'], (int)$turno['paciente_id']]);
    $r = $q->fetch(PDO::FETCH_ASSOC);
    if ($r && (int)$r['mensajes'] > 0) {
        $chat = ['user_id' => (int)$r['user_id'], 'mensajes' => (int)$r['mensajes']];
    }
}

jsonOk([
    'turno'   => [
        'id'       => (int)$turno['id'],
        'codigo'   => $turno['codigo'],
        'estado'   => $turno['estado'],
        'paciente' => $turno['paciente_nombre'],
    ],
    'eventos' => $ev,
    'chat'    => $chat,
    // Se declara lo que el sistema NO registra, para que nadie lea la ausencia
    // de un evento como prueba de que no ocurrió.
    // Lo que el sistema sigue sin registrar. Se declara para que la ausencia de
    // un evento no se lea como prueba de que no ocurrió.
    'sinRastro' => [
        'el llamado original de los turnos anteriores a hoy, que el rellamado sobrescribía',
    ],
]);
