<?php
/**
 * GET /api/lab/get_metricas.php
 * Estadísticas de período para el módulo de reportes.
 * Parámetros: desde (Y-m-d), hasta (Y-m-d)
 */
require_once __DIR__ . '/_helpers.php';
requireMethod('GET');

try {
    $db    = Database::getInstance();
    $desde = $_GET['desde'] ?? date('Y-m-01');
    $hasta = $_GET['hasta'] ?? date('Y-m-d');

    // ── 1. Domicilios por día ────────────────────────────────────────────────
    $porDia = $db->fetchAll(
        "SELECT DATE(fecha_programada) AS dia,
                COUNT(*)                        AS total,
                SUM(estado = 'completado')       AS completados,
                SUM(estado = 'cancelado')        AS cancelados,
                SUM(estado = 'reprogramado')     AS reprogramados
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
         GROUP BY DATE(fecha_programada)
         ORDER BY dia ASC",
        [$desde, $hasta]
    );

    // ── 2. KPIs de tasa de éxito ────────────────────────────────────────────
    $kpi = $db->fetch(
        "SELECT COUNT(*)                              AS total,
                SUM(estado = 'completado')             AS completados,
                SUM(estado = 'cancelado')              AS cancelados,
                SUM(estado = 'reprogramado')           AS reprogramados,
                SUM(estado NOT IN ('completado','cancelado','reprogramado')) AS en_curso
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?",
        [$desde, $hasta]
    ) ?: [];

    // ── 3. Tiempo promedio en domicilio ──────────────────────────────────────
    $tiempos = $db->fetch(
        "SELECT ROUND(AVG(TIMESTAMPDIFF(MINUTE, hora_llegada, hora_salida)), 1) AS promedio_min,
                MIN(TIMESTAMPDIFF(MINUTE, hora_llegada, hora_salida))           AS min_min,
                MAX(TIMESTAMPDIFF(MINUTE, hora_llegada, hora_salida))           AS max_min,
                COUNT(*)                                                         AS con_tiempos
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
           AND hora_llegada IS NOT NULL AND hora_salida IS NOT NULL
           AND hora_salida > hora_llegada",
        [$desde, $hasta]
    ) ?: [];

    // ── 4. Tiempo promedio desde agendamiento hasta realización ─────────────
    $tiempoAgen = $db->fetch(
        "SELECT ROUND(AVG(DATEDIFF(fecha_programada, DATE(created_at))), 1) AS dias_promedio,
                MIN(DATEDIFF(fecha_programada, DATE(created_at)))            AS dias_min,
                MAX(DATEDIFF(fecha_programada, DATE(created_at)))            AS dias_max
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
           AND estado = 'completado'",
        [$desde, $hasta]
    ) ?: [];

    // ── 5. Ranking de enfermeras ────────────────────────────────────────────
    $rankingEnf = $db->fetchAll(
        "SELECT e.id, e.nombre_completo,
                COUNT(a.id)                         AS asignados,
                SUM(d.estado = 'completado')        AS completados,
                SUM(d.estado = 'cancelado')         AS cancelados,
                ROUND(SUM(d.estado='completado') / NULLIF(COUNT(a.id),0) * 100, 1) AS tasa_pct
         FROM lab_asignaciones a
         JOIN lab_enfermeras e ON e.id = a.enfermera_id
         JOIN lab_domicilios d ON d.id = a.domicilio_id
         WHERE d.fecha_programada BETWEEN ? AND ?
         GROUP BY e.id, e.nombre_completo
         ORDER BY completados DESC, asignados DESC",
        [$desde, $hasta]
    );

    // ── 6. Financiero ────────────────────────────────────────────────────────
    $financiero = $db->fetch(
        "SELECT SUM(COALESCE(valor_domicilio,0) + COALESCE(valor_copago,0))  AS total_bruto,
                SUM(CASE WHEN pago_estado='pagado'   THEN COALESCE(valor_domicilio,0)+COALESCE(valor_copago,0) ELSE 0 END) AS cobrado,
                SUM(CASE WHEN pago_estado='pendiente' THEN COALESCE(valor_domicilio,0)+COALESCE(valor_copago,0) ELSE 0 END) AS pendiente,
                SUM(CASE WHEN pago_estado='exento'    THEN COALESCE(valor_domicilio,0)+COALESCE(valor_copago,0) ELSE 0 END) AS exento,
                COUNT(CASE WHEN pago_estado='pagado'   THEN 1 END) AS n_pagados,
                COUNT(CASE WHEN pago_estado='pendiente' THEN 1 END) AS n_pendientes,
                COUNT(CASE WHEN pago_estado='exento'    THEN 1 END) AS n_exentos
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?",
        [$desde, $hasta]
    ) ?: [];

    // ── 7. Por modo de pago ─────────────────────────────────────────────────
    $porModoPago = $db->fetchAll(
        "SELECT COALESCE(pago_modo, 'no_especificado') AS modo,
                COUNT(*) AS n,
                SUM(COALESCE(valor_domicilio,0)+COALESCE(valor_copago,0)) AS total
         FROM lab_domicilios
         WHERE pago_estado = 'pagado'
           AND fecha_programada BETWEEN ? AND ?
         GROUP BY pago_modo
         ORDER BY n DESC",
        [$desde, $hasta]
    );

    // ── 8. Top zonas (barrio / ciudad) ──────────────────────────────────────
    $topZonas = $db->fetchAll(
        "SELECT COALESCE(NULLIF(TRIM(barrio),''), NULLIF(TRIM(ciudad),''), 'Sin datos') AS zona,
                COUNT(*) AS n
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
         GROUP BY zona
         ORDER BY n DESC
         LIMIT 10",
        [$desde, $hasta]
    );

    // ── 9. Domicilios por tipo de cliente ────────────────────────────────────
    $porTipoCliente = $db->fetchAll(
        "SELECT COALESCE(tipo_cliente,'particular') AS tipo,
                COALESCE(seguro_nombre,'')           AS seguro,
                COUNT(*) AS n
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
         GROUP BY tipo, seguro
         ORDER BY n DESC",
        [$desde, $hasta]
    );

    // ── 10. Top exámenes solicitados (simple word-frequency) ─────────────────
    // Traemos todos los valores y hacemos el conteo en PHP para no depender de
    // funciones de texto avanzadas de MySQL que podrían variar según servidor.
    $examRows = $db->fetchAll(
        "SELECT examenes_solicitados FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
           AND examenes_solicitados IS NOT NULL AND examenes_solicitados != ''",
        [$desde, $hasta]
    );
    $examConteo = [];
    foreach ($examRows as $row) {
        // Dividir por coma, punto y coma o salto de línea
        $items = preg_split('/[,;\n]+/', $row['examenes_solicitados'] ?? '');
        foreach ($items as $item) {
            $item = trim($item);
            if (strlen($item) > 2) {
                $k = mb_strtolower($item);
                $examConteo[$k] = ($examConteo[$k] ?? 0) + 1;
            }
        }
    }
    arsort($examConteo);
    $topExamenes = array_slice(
        array_map(fn($k, $v) => ['examen' => $k, 'n' => $v], array_keys($examConteo), $examConteo),
        0, 10
    );

    // ── 11. Horas del día con más agendamientos ─────────────────────────────
    $porHora = $db->fetchAll(
        "SELECT HOUR(hora_programada) AS hora, COUNT(*) AS n
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
           AND hora_programada IS NOT NULL
         GROUP BY HOUR(hora_programada)
         ORDER BY hora ASC",
        [$desde, $hasta]
    );

    // ── 12. Tiempo de traslado: desde 'en_camino' hasta 'en_domicilio' ────────
    // Fuente: columnas hora_en_camino y hora_llegada de lab_domicilios.
    // hora_en_camino se guarda cuando el enfermero marca 'En camino'.
    // hora_llegada   se guarda cuando el enfermero marca 'En domicilio'.
    // Se excluyen filas donde la llegada sea anterior a la salida (datos corruptos).
    $traslado = $db->fetch(
        "SELECT
                ROUND(AVG(TIMESTAMPDIFF(MINUTE,
                    CONCAT(fecha_programada,' ',hora_en_camino),
                    CONCAT(fecha_programada,' ',hora_llegada))), 1) AS promedio_min,
                MIN(TIMESTAMPDIFF(MINUTE,
                    CONCAT(fecha_programada,' ',hora_en_camino),
                    CONCAT(fecha_programada,' ',hora_llegada)))     AS min_min,
                MAX(TIMESTAMPDIFF(MINUTE,
                    CONCAT(fecha_programada,' ',hora_en_camino),
                    CONCAT(fecha_programada,' ',hora_llegada)))     AS max_min,
                COUNT(*)                                             AS con_datos,
                SUM(TIMESTAMPDIFF(MINUTE,
                    CONCAT(fecha_programada,' ',hora_en_camino),
                    CONCAT(fecha_programada,' ',hora_llegada)) <= 15) AS dentro_15min,
                SUM(TIMESTAMPDIFF(MINUTE,
                    CONCAT(fecha_programada,' ',hora_en_camino),
                    CONCAT(fecha_programada,' ',hora_llegada)) <= 30) AS dentro_30min
         FROM lab_domicilios
         WHERE fecha_programada BETWEEN ? AND ?
           AND hora_en_camino IS NOT NULL
           AND hora_llegada   IS NOT NULL
           AND hora_llegada   > hora_en_camino",
        [$desde, $hasta]
    ) ?: [];

    // ── 13. Tiempo de traslado por enfermera (top 10 más rápidas) ─────────────
    $trasladoPorEnfermera = $db->fetchAll(
        "SELECT e.nombre_completo,
                ROUND(AVG(TIMESTAMPDIFF(MINUTE,
                    CONCAT(d.fecha_programada,' ',d.hora_en_camino),
                    CONCAT(d.fecha_programada,' ',d.hora_llegada))), 1) AS promedio_min,
                COUNT(*) AS viajes
         FROM lab_domicilios d
         JOIN lab_asignaciones a ON a.domicilio_id = d.id
              AND a.estado NOT IN ('liberada')
         JOIN lab_enfermeras e ON e.id = a.enfermera_id
         WHERE d.fecha_programada BETWEEN ? AND ?
           AND d.hora_en_camino IS NOT NULL
           AND d.hora_llegada   IS NOT NULL
           AND d.hora_llegada   > d.hora_en_camino
         GROUP BY e.id, e.nombre_completo
         ORDER BY promedio_min ASC
         LIMIT 10",
        [$desde, $hasta]
    );

    jsonOk([
        'por_dia'                  => $porDia,
        'kpi'                      => $kpi,
        'tiempos'                  => $tiempos,
        'tiempo_agendamiento'      => $tiempoAgen,
        'ranking_enfermeras'       => $rankingEnf,
        'financiero'               => $financiero,
        'por_modo_pago'            => $porModoPago,
        'top_zonas'                => $topZonas,
        'por_tipo_cliente'         => $porTipoCliente,
        'top_examenes'             => $topExamenes,
        'por_hora'                 => $porHora,
        'traslado'                 => $traslado,
        'traslado_por_enfermera'   => $trasladoPorEnfermera,
    ]);

} catch (Exception $e) {
    error_log('[get_metricas] ' . $e->getMessage());
    jsonError($e->getMessage(), 500);
}
