<?php
/**
 * modules/turnero/api/get_historial.php
 * GET  Historial paginado de turnos con filtros multi-día.
 *
 * Parámetros (todos opcionales):
 *   fecha_desde  YYYY-MM-DD  (default: hoy; hace 12 meses si se pasa paciente_id)
 *   fecha_hasta  YYYY-MM-DD  (default: hoy)
 *   estado       string      ("finalizado","ausente","cancelado","en_servicio",... o vacío = todos)
 *   lugar_id     int         (0 = todos)
 *   prioridad_id int         (0 = todos)
 *   q            string      búsqueda libre por nombre/código
 *   page         int         (default 1)
 *   per_page     int         (default 50, max 200)
 */
require_once __DIR__ . '/_helpers.php';

requireTurnero();
requireMethod('GET');

$pdo = db();

// ── Parámetros ────────────────────────────────────────────────
$hoy         = date('Y-m-d');

// paciente_id se lee primero: determina el rango de fechas por defecto.
$pacienteId    = (int)($_GET['paciente_id'] ?? 0);

$fechaDesde  = trim($_GET['fecha_desde'] ?? '');
$fechaHasta  = trim($_GET['fecha_hasta'] ?? '');

// Rango por defecto cuando el cliente no manda fechas:
//   - Ficha de paciente (paciente_id): ultimos 12 meses.
//     Antes caia en "hoy", asi que el historial del paciente solo podia mostrar
//     visitas del mismo dia y siempre respondia "sin visitas anteriores".
//   - Listado general del historial: hoy (comportamiento original).
// Para ver el historial completo, el cliente pasa fecha_desde explicita.
$desdePorDefecto = $pacienteId > 0
    ? date('Y-m-d', strtotime('-12 months'))
    : $hoy;

if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $fechaDesde)) $fechaDesde = $desdePorDefecto;
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $fechaHasta)) $fechaHasta = $hoy;
if ($fechaDesde > $fechaHasta)                          $fechaDesde = $fechaHasta;

$estadoFiltro  = trim($_GET['estado']       ?? '');
$lugarId       = (int)($_GET['lugar_id']    ?? 0);
$prioridadId   = (int)($_GET['prioridad_id'] ?? 0);
$q             = trim($_GET['q']            ?? '');

$perPage = min(200, max(10, (int)($_GET['per_page'] ?? 50)));
$page    = max(1, (int)($_GET['page'] ?? 1));
$offset  = ($page - 1) * $perPage;

// ── Base WHERE ───────────────────────────────────────────────
//   Unimos turnos con sesiones para filtrar por fecha de sesión
$where  = ['DATE(s.fecha) BETWEEN ? AND ?'];
$binds  = [$fechaDesde, $fechaHasta];

$estadosValidos = ['espera','en_recepcion','en_espera_lugar','en_servicio','finalizado','ausente','cancelado'];
if ($estadoFiltro && in_array($estadoFiltro, $estadosValidos, true)) {
    $where[] = 't.estado = ?';
    $binds[] = $estadoFiltro;
}
if ($lugarId > 0) {
    $where[] = 't.lugar_destino_id = ?';
    $binds[] = $lugarId;
}
if ($prioridadId > 0) {
    $where[] = 't.prioridad_id = ?';
    $binds[] = $prioridadId;
}
if ($pacienteId > 0) {
    $where[] = 'ts2.paciente_id = ?';
    $binds[] = $pacienteId;
}
if ($q !== '') {
    $where[] = '(t.codigo LIKE ? OR t.paciente_nombre LIKE ? OR s2.nombre_completo LIKE ?)';
    $like     = '%' . $q . '%';
    $binds[]  = $like;
    $binds[]  = $like;
    $binds[]  = $like;
}

$whereStr = 'WHERE ' . implode(' AND ', $where);

// ── Conteo total ──────────────────────────────────────────────
$sqlCount = "
    SELECT COUNT(*) AS total
    FROM   turnero_turnos t
    JOIN   turnero_sesiones s    ON s.id  = t.sesion_id
    LEFT   JOIN turnero_solicitudes ts2 ON ts2.turno_id = t.id
    LEFT   JOIN lab_pacientes s2        ON s2.id = ts2.paciente_id
    $whereStr";

$stmtCount = $pdo->prepare($sqlCount);
$stmtCount->execute($binds);
$totalRows = (int)$stmtCount->fetchColumn();
$totalPages = max(1, (int)ceil($totalRows / $perPage));
if ($page > $totalPages) $page = $totalPages;
$offset = ($page - 1) * $perPage;

// ── Lista paginada ────────────────────────────────────────────
$sqlTurnos = "
    SELECT
        t.id,
        t.codigo,
        t.numero,
        t.estado,
        t.paciente_nombre,
        t.paciente_cel,
        t.creado_at,
        t.inicio_recepcion_at,
        t.fin_recepcion_at,
        t.inicio_lugar_at,
        t.fin_lugar_at,
        s.fecha                           AS fecha_sesion,
        p.codigo  AS prioridad_codigo,
        p.nombre  AS prioridad_nombre,
        p.color   AS prioridad_color,
        l.nombre  AS lugar_nombre,
        s2.nombre_completo                AS paciente_bd,
        s2.tipo_documento                 AS paciente_tipo_doc,
        s2.numero_documento               AS paciente_doc,
        rd.nombre                         AS recepcion_desk_nombre,
        ur.full_name                      AS atendido_recepcion_nombre,
        ul.full_name                      AS atendido_lugar_nombre,
        ts2.observaciones                 AS notas,
        ROUND(TIMESTAMPDIFF(SECOND, t.creado_at,
              COALESCE(t.inicio_recepcion_at, t.fin_recepcion_at)) / 60.0, 1)
                                          AS espera_min,
        ROUND(TIMESTAMPDIFF(SECOND, t.inicio_lugar_at,
              COALESCE(t.fin_lugar_at, NOW())) / 60.0, 1)
                                          AS servicio_min,
        ROUND(TIMESTAMPDIFF(SECOND, t.creado_at, t.fin_lugar_at) / 60.0, 1)
                                          AS total_min
    FROM   turnero_turnos t
    JOIN   turnero_sesiones s    ON s.id  = t.sesion_id
    JOIN   turnero_prioridades p ON p.id  = t.prioridad_id
    LEFT   JOIN turnero_lugares l         ON l.id  = t.lugar_destino_id
    LEFT   JOIN turnero_lugares rd        ON rd.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
    LEFT   JOIN turnero_solicitudes ts2   ON ts2.turno_id = t.id
    LEFT   JOIN lab_pacientes s2          ON s2.id = ts2.paciente_id
    $whereStr
    ORDER  BY t.creado_at DESC
    LIMIT  ? OFFSET ?";

$bindsPage   = array_merge($binds, [$perPage, $offset]);
$stmtTurnos  = $pdo->prepare($sqlTurnos);
$stmtTurnos->execute($bindsPage);
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);

// ── Enriquecer con exámenes, consentimientos, comentarios y tomas (batch) ─
$turnoIds = array_column($turnos, 'id');
$examenes      = [];
$consentimientos = [];
$comentarios   = [];
$relacionados  = [];

if ($turnoIds) {
    $ph = implode(',', array_fill(0, count($turnoIds), '?'));

    // Exámenes — batch
    $stmtExam = $pdo->prepare(
        "SELECT ts.turno_id, et.nombre, et.codigo
           FROM turnero_solicitudes ts
           JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
           JOIN exam_tipos et ON et.id = tei.exam_tipo_id
          WHERE ts.turno_id IN ($ph)
          ORDER BY et.nombre ASC"
    );
    $stmtExam->execute($turnoIds);
    foreach ($stmtExam->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $examenes[(int)$row['turno_id']][] = ['nombre' => $row['nombre'], 'codigo' => $row['codigo']];
    }

    // Consentimientos — batch
    $stmtCons = $pdo->prepare(
        "SELECT tc.turno_id, tc.id, f.nombre, tc.estado, tc.firmado_at
           FROM turnero_consentimientos tc
           LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
          WHERE tc.turno_id IN ($ph)
          ORDER BY tc.estado DESC, tc.firmado_at DESC"
    );
    $stmtCons->execute($turnoIds);
    foreach ($stmtCons->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $tid = (int)$row['turno_id'];
        unset($row['turno_id']);
        $consentimientos[$tid][] = $row;
    }

    // Comentarios — batch (últimos 3 por turno via subquery)
    $stmtCom = $pdo->prepare(
        "SELECT tc.turno_id, tc.usuario_nombre, tc.comentario, tc.tipo, tc.creado_at
           FROM turnero_comentarios tc
          WHERE tc.turno_id IN ($ph)
          ORDER BY tc.turno_id, tc.creado_at ASC"
    );
    $stmtCom->execute($turnoIds);
    foreach ($stmtCom->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $tid = (int)$row['turno_id'];
        if (!isset($comentarios[$tid])) $comentarios[$tid] = [];
        // Se traen todos: cortar en 3 escondía notas —entre ellas el motivo de
        // una ausencia— sin que nada indicara que faltaban.
        if (count($comentarios[$tid]) < 20) {
            unset($row['turno_id']);
            $comentarios[$tid][] = $row;
        }
    }

    // Turnos vinculados por muestras pendientes completadas en otra visita — batch (ambos sentidos)
    // Sentido "seguimiento": este turno tenía una muestra pendiente que se completó en OTRO turno
    $stmtRelFwd = $pdo->prepare(
        "SELECT DISTINCT ts.turno_id AS turno_id, t2.id AS rel_id, t2.codigo AS rel_codigo, s2.fecha AS rel_fecha
           FROM turnero_muestras tm
           JOIN turnero_solicitudes ts ON ts.id = tm.solicitud_id
           JOIN turnero_turnos t2      ON t2.id = tm.recibida_en_turno_id
           JOIN turnero_sesiones s2    ON s2.id = t2.sesion_id
          WHERE ts.turno_id IN ($ph) AND tm.recibida_en_turno_id IS NOT NULL"
    );
    $stmtRelFwd->execute($turnoIds);
    foreach ($stmtRelFwd->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $tid = (int)$row['turno_id'];
        $relacionados[$tid][] = [
            'turno_id' => (int)$row['rel_id'], 'codigo' => $row['rel_codigo'],
            'fecha' => $row['rel_fecha'], 'direccion' => 'seguimiento',
        ];
    }
    // Sentido "origen": este turno completó una muestra pendiente de OTRO turno anterior
    $stmtRelBack = $pdo->prepare(
        "SELECT DISTINCT tm.recibida_en_turno_id AS turno_id, t1.id AS rel_id, t1.codigo AS rel_codigo, s1.fecha AS rel_fecha
           FROM turnero_muestras tm
           JOIN turnero_solicitudes ts ON ts.id = tm.solicitud_id
           JOIN turnero_turnos t1      ON t1.id = ts.turno_id
           JOIN turnero_sesiones s1    ON s1.id = t1.sesion_id
          WHERE tm.recibida_en_turno_id IN ($ph)"
    );
    $stmtRelBack->execute($turnoIds);
    foreach ($stmtRelBack->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $tid = (int)$row['turno_id'];
        $relacionados[$tid][] = [
            'turno_id' => (int)$row['rel_id'], 'codigo' => $row['rel_codigo'],
            'fecha' => $row['rel_fecha'], 'direccion' => 'origen',
        ];
    }
}

foreach ($turnos as &$turno) {
    $tid = (int)$turno['id'];
    $turno['examenes']        = $examenes[$tid]        ?? [];
    $turno['consentimientos'] = $consentimientos[$tid] ?? [];
    $turno['comentarios']     = $comentarios[$tid]     ?? [];
    $turno['relacionados']    = $relacionados[$tid]    ?? [];
}

// ── Resumen por estado (del rango filtrado) ───────────────────
$sqlRes = "
    SELECT t.estado, COUNT(*) AS cnt
    FROM   turnero_turnos t
    JOIN   turnero_sesiones s    ON s.id  = t.sesion_id
    LEFT   JOIN turnero_solicitudes ts2 ON ts2.turno_id = t.id
    LEFT   JOIN lab_pacientes s2        ON s2.id = ts2.paciente_id
    $whereStr
    GROUP  BY t.estado";
$stmtRes = $pdo->prepare($sqlRes);
$stmtRes->execute($binds);
$resumenEstados = [];
foreach ($stmtRes->fetchAll(PDO::FETCH_ASSOC) as $r) {
    $resumenEstados[$r['estado']] = (int)$r['cnt'];
}

// ── Catálogos para los selectores (si pide con ?meta=1) ──────
$meta = [];
if (!empty($_GET['meta'])) {
    $meta['lugares'] = $pdo->query(
        "SELECT id, nombre FROM turnero_lugares WHERE activo=1 ORDER BY sort_order ASC, nombre ASC"
    )->fetchAll(PDO::FETCH_ASSOC);

    $meta['prioridades'] = $pdo->query(
        "SELECT id, nombre, codigo, color FROM turnero_prioridades ORDER BY orden_peso ASC"
    )->fetchAll(PDO::FETCH_ASSOC);
}

jsonOk([
    'fecha_desde'    => $fechaDesde,
    'fecha_hasta'    => $fechaHasta,
    'total'          => $totalRows,
    'page'           => $page,
    'per_page'       => $perPage,
    'total_pages'    => $totalPages,
    'resumen_estados'=> $resumenEstados,
    'turnos'         => $turnos,
    'meta'           => $meta,
]);
