<?php

declare(strict_types=1);

ob_start();
require_once __DIR__ . '/init.php';

if (($_SESSION['admin']['rol'] ?? '') !== 'Superadmin') {
    $_SESSION['flash_message'] = ['type' => 'error', 'text' => 'Acceso denegado. Solo el Superadmin puede ver los reportes.'];
    header('Location: index.php');
    exit;
}

function af_report_date(string $value, string $fallback): string
{
    return preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) ? $value : $fallback;
}

function af_report_month(string $value, string $fallback): string
{
    return preg_match('/^\d{4}-\d{2}$/', $value) ? $value : $fallback;
}

function af_report_export_csv(string $filename, array $headers, array $rows): never
{
    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    header('Content-Type: text/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    echo "\xEF\xBB\xBF";
    $output = fopen('php://output', 'wb');
    fputcsv($output, $headers, ';');
    foreach ($rows as $row) {
        fputcsv($output, array_map(static fn(mixed $value): string => (string) $value, $row), ';');
    }
    fclose($output);
    exit;
}


function af_report_table_exists(PDO $pdo, string $table): bool
{
    static $cache = [];
    if (array_key_exists($table, $cache)) {
        return $cache[$table];
    }
    try {
        $stmt = $pdo->prepare('SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?');
        $stmt->execute([$table]);
        return $cache[$table] = (int) $stmt->fetchColumn() > 0;
    } catch (Throwable) {
        return $cache[$table] = false;
    }
}

function af_report_column_exists(PDO $pdo, string $table, string $column): bool
{
    static $cache = [];
    $key = $table . '.' . $column;
    if (array_key_exists($key, $cache)) {
        return $cache[$key];
    }
    try {
        $stmt = $pdo->prepare('SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?');
        $stmt->execute([$table, $column]);
        return $cache[$key] = (int) $stmt->fetchColumn() > 0;
    } catch (Throwable) {
        return $cache[$key] = false;
    }
}

/** @return array<int,array<string,mixed>> */
function af_report_rows(PDO $pdo, string $section, string $sql, array $params, array &$warnings): array
{
    try {
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (Throwable $e) {
        error_log('gestionar_reportes [' . $section . ']: ' . $e->getMessage());
        $warnings[$section] = 'No se pudo cargar esta sección con la estructura actual de la base de datos.';
        return [];
    }
}

$today = new DateTimeImmutable('today');
$fecha_desde_ingresos = af_report_date((string) ($_GET['fecha_desde_ingresos'] ?? ''), $today->modify('first day of this month')->format('Y-m-d'));
$fecha_hasta_ingresos = af_report_date((string) ($_GET['fecha_hasta_ingresos'] ?? ''), $today->modify('last day of this month')->format('Y-m-d'));
if ($fecha_desde_ingresos > $fecha_hasta_ingresos) {
    [$fecha_desde_ingresos, $fecha_hasta_ingresos] = [$fecha_hasta_ingresos, $fecha_desde_ingresos];
}
$periodo_uso_consultas = af_report_month((string) ($_GET['periodo_uso_consultas'] ?? ''), $today->format('Y-m'));
$dias_inactividad = max(1, min(3650, (int) ($_GET['dias_inactividad'] ?? 90)));
$error_message_db = '';

$reporte_ingresos_planes = [];
$reporte_uso_consultas_data = [];
$reporte_clientes_data = [];
$admins_recursos_data = [];
$admins_gratis_data = [];
$reporte_uso_dominios_admin = [];
$reporte_suscripciones_estado = [];
$reporte_clientes_inactivos_data = [];
$reportWarnings = [];

$paymentStatusFilter = af_report_column_exists($pdo, 'pagos', 'estado_pago')
    ? " AND pa.estado_pago = 'confirmado'"
    : '';

if (af_report_table_exists($pdo, 'planes') && af_report_table_exists($pdo, 'suscripciones')) {
    $incomeSql = "SELECT p.id, p.nombre_plan,
            (SELECT COUNT(*)
             FROM suscripciones s
             WHERE s.id_plan = p.id
               AND s.estado IN ('activa','prueba')
               AND (s.fecha_fin IS NULL OR s.fecha_fin >= NOW())) AS suscripciones_activas,
            COALESCE((SELECT SUM(pa.monto)
                      FROM pagos pa
                      JOIN suscripciones ps ON ps.id = pa.id_suscripcion
                      WHERE ps.id_plan = p.id
                        AND pa.fecha_pago BETWEEN ? AND ?" . $paymentStatusFilter . "), 0) AS total_ingresos
         FROM planes p
         ORDER BY total_ingresos DESC, p.nombre_plan";
    $reporte_ingresos_planes = af_report_rows(
        $pdo,
        'Ingresos por plan',
        $incomeSql,
        [$fecha_desde_ingresos . ' 00:00:00', $fecha_hasta_ingresos . ' 23:59:59'],
        $reportWarnings
    );
}

if (af_report_table_exists($pdo, 'uso_consultas')) {
    $reporte_uso_consultas_data = af_report_rows(
        $pdo,
        'Uso de consultas',
        "SELECT u.nombre_usuario, u.correo,
                COALESCE(uc.consultas_realizadas, 0) AS consultas_realizadas,
                pl.limite_consultas,
                COALESCE(pl.nombre_plan, 'Sin plan') AS nombre_plan
         FROM usuarios u
         JOIN roles r ON r.id = u.id_rol AND r.nombre_rol IN ('Admin','Ayudante de Superadmin')
         LEFT JOIN uso_consultas uc ON uc.id_admin = u.id AND uc.periodo = ?
         LEFT JOIN suscripciones s ON s.id = (
             SELECT sx.id
             FROM suscripciones sx
             WHERE sx.id_admin = u.id
             ORDER BY CASE WHEN sx.estado IN ('activa','prueba') THEN 0 ELSE 1 END,
                      sx.fecha_fin DESC, sx.id DESC
             LIMIT 1
         )
         LEFT JOIN planes pl ON pl.id = s.id_plan
         ORDER BY consultas_realizadas DESC, u.nombre_usuario",
        [$periodo_uso_consultas],
        $reportWarnings
    );
}

$reporte_clientes_data = af_report_rows(
    $pdo,
    'Directorio de usuarios',
    "SELECT u.id, u.nombre_usuario, u.correo, u.telefono,
            r.nombre_rol AS rol_cliente,
            adm.nombre_usuario AS admin_propietario_nombre
     FROM usuarios u
     JOIN roles r ON r.id = u.id_rol
     LEFT JOIN usuarios adm ON adm.id = u.id_admin_propietario
     WHERE r.nombre_rol IN ('Admin','Ayudante de Superadmin','Revendedor','Cliente Final')
     ORDER BY CASE r.nombre_rol
                WHEN 'Admin' THEN 1
                WHEN 'Ayudante de Superadmin' THEN 2
                WHEN 'Revendedor' THEN 3
                WHEN 'Cliente Final' THEN 4
                ELSE 5
              END,
              u.nombre_usuario",
    [],
    $reportWarnings
);

$providerExpression = af_report_column_exists($pdo, 'configuraciones_imap', 'nombre_proveedor')
    ? "COALESCE(ci.nombre_proveedor, 'IMAP')"
    : "'IMAP'";
$admins_recursos_data = af_report_rows(
    $pdo,
    'Administradores y recursos',
    "SELECT u.id AS admin_id, u.nombre_usuario AS admin_nombre, u.correo AS admin_correo,
            COALESCE(p.nombre_plan, 'Sin plan') AS plan_actual,
            p.limite_buzones, p.limite_dominios,
            COUNT(DISTINCT ci.id) AS buzones_usados,
            COUNT(DISTINCT d.id) AS dominios_usados,
            GROUP_CONCAT(DISTINCT CONCAT(ci.imap_usuario, ' · ', {$providerExpression}) SEPARATOR '||') AS buzones_detalle,
            GROUP_CONCAT(DISTINCT d.nombre_dominio SEPARATOR '||') AS dominios_detalle
     FROM usuarios u
     JOIN roles r ON r.id = u.id_rol AND r.nombre_rol IN ('Admin','Ayudante de Superadmin')
     LEFT JOIN suscripciones s ON s.id = (
         SELECT sx.id
         FROM suscripciones sx
         WHERE sx.id_admin = u.id
         ORDER BY CASE WHEN sx.estado IN ('activa','prueba') THEN 0 ELSE 1 END,
                  sx.fecha_fin DESC, sx.id DESC
         LIMIT 1
     )
     LEFT JOIN planes p ON p.id = s.id_plan
     LEFT JOIN configuraciones_imap ci ON ci.id_admin = u.id
     LEFT JOIN dominios d ON d.id_admin_propietario = u.id
     GROUP BY u.id, u.nombre_usuario, u.correo, p.nombre_plan, p.limite_buzones, p.limite_dominios
     ORDER BY u.nombre_usuario",
    [],
    $reportWarnings
);

$admins_gratis_data = af_report_rows(
    $pdo,
    'Oportunidades del plan Gratis',
    "SELECT u.id AS admin_id, u.nombre_usuario AS admin_nombre, u.correo AS admin_correo,
            COALESCE(uc.consultas_realizadas, 0) AS consultas_realizadas,
            pl.limite_consultas
     FROM usuarios u
     JOIN roles r ON r.id = u.id_rol AND r.nombre_rol IN ('Admin','Ayudante de Superadmin')
     JOIN suscripciones s ON s.id = (
         SELECT sx.id
         FROM suscripciones sx
         WHERE sx.id_admin = u.id
         ORDER BY CASE WHEN sx.estado IN ('activa','prueba') THEN 0 ELSE 1 END,
                  sx.fecha_fin DESC, sx.id DESC
         LIMIT 1
     )
     JOIN planes pl ON pl.id = s.id_plan AND LOWER(TRIM(pl.nombre_plan)) = 'gratis'
     LEFT JOIN uso_consultas uc ON uc.id_admin = u.id AND uc.periodo = ?
     ORDER BY consultas_realizadas DESC, u.nombre_usuario",
    [$periodo_uso_consultas],
    $reportWarnings
);

$reporte_uso_dominios_admin = af_report_rows(
    $pdo,
    'Uso de dominios',
    "SELECT u.nombre_usuario AS admin_nombre, u.correo AS admin_correo,
            d.nombre_dominio, COUNT(cs.id) AS total_cuentas_asociadas
     FROM usuarios u
     JOIN roles r ON r.id = u.id_rol AND r.nombre_rol IN ('Admin','Ayudante de Superadmin')
     JOIN dominios d ON d.id_admin_propietario = u.id
     LEFT JOIN correos_servicios cs ON cs.id_dominio = d.id
     GROUP BY u.id, u.nombre_usuario, u.correo, d.id, d.nombre_dominio
     ORDER BY total_cuentas_asociadas DESC, u.nombre_usuario, d.nombre_dominio",
    [],
    $reportWarnings
);

$reporte_suscripciones_estado = af_report_rows(
    $pdo,
    'Suscripciones por estado',
    "SELECT LOWER(s.estado) AS estado, COUNT(*) AS total_suscripciones
     FROM suscripciones s
     GROUP BY LOWER(s.estado)
     ORDER BY total_suscripciones DESC",
    [],
    $reportWarnings
);

$fecha_corte_inactividad = $today->modify('-' . $dias_inactividad . ' days')->format('Y-m-d 00:00:00');
$reporte_clientes_inactivos_data = af_report_rows(
    $pdo,
    'Clientes inactivos',
    "SELECT actividad.nombre_usuario, actividad.correo, actividad.telefono,
            actividad.ultima_consulta,
            CASE WHEN actividad.ultima_consulta IS NULL THEN NULL
                 ELSE DATEDIFF(NOW(), actividad.ultima_consulta)
            END AS dias_sin_consulta
     FROM (
         SELECT u.id, u.nombre_usuario, u.correo, u.telefono,
                MAX(c.fecha_consulta) AS ultima_consulta
         FROM usuarios u
         JOIN roles r ON r.id = u.id_rol AND r.nombre_rol IN ('Revendedor','Cliente Final')
         LEFT JOIN consultas c ON c.id_usuario = u.id
         GROUP BY u.id, u.nombre_usuario, u.correo, u.telefono
     ) actividad
     WHERE actividad.ultima_consulta IS NULL OR actividad.ultima_consulta < ?
     ORDER BY actividad.ultima_consulta IS NULL DESC, actividad.ultima_consulta ASC",
    [$fecha_corte_inactividad],
    $reportWarnings
);

$error_message_db = $reportWarnings
    ? 'Algunas secciones no pudieron cargarse. Las demás permanecen disponibles.'
    : '';

$export = trim((string) ($_GET['export'] ?? ''));
if ($export === 'clientes') {
    af_report_export_csv('clientes-' . date('Ymd-His') . '.csv', ['Nombre','Correo','Teléfono','Rol','Admin propietario'], array_map(static fn(array $r): array => [
        $r['nombre_usuario'] ?? '', $r['correo'] ?? '', $r['telefono'] ?? '', $r['rol_cliente'] ?? '', $r['admin_propietario_nombre'] ?? ''
    ], $reporte_clientes_data));
}
if ($export === 'ingresos') {
    af_report_export_csv('ingresos-por-plan-' . date('Ymd-His') . '.csv', ['Plan','Suscripciones activas','Ingresos'], array_map(static fn(array $r): array => [
        $r['nombre_plan'] ?? '', $r['suscripciones_activas'] ?? 0, number_format((float) ($r['total_ingresos'] ?? 0), 2, '.', '')
    ], $reporte_ingresos_planes));
}
if ($export === 'inactivos') {
    af_report_export_csv('clientes-inactivos-' . date('Ymd-His') . '.csv', ['Nombre','Correo','Teléfono','Última consulta','Días sin consulta'], array_map(static fn(array $r): array => [
        $r['nombre_usuario'] ?? '', $r['correo'] ?? '', $r['telefono'] ?? '', $r['ultima_consulta'] ?? 'Nunca', $r['dias_sin_consulta'] ?? ''
    ], $reporte_clientes_inactivos_data));
}

$totalIngresosReportados = array_sum(array_map(static fn(array $row): float => (float) ($row['total_ingresos'] ?? 0), $reporte_ingresos_planes));
$totalConsultasPeriodo = array_sum(array_map(static fn(array $row): int => (int) ($row['consultas_realizadas'] ?? 0), $reporte_uso_consultas_data));
$totalSuscripciones = array_sum(array_map(static fn(array $row): int => (int) ($row['total_suscripciones'] ?? 0), $reporte_suscripciones_estado));
$subscriptionMap = [];
foreach ($reporte_suscripciones_estado as $row) {
    $subscriptionMap[(string) $row['estado']] = (int) $row['total_suscripciones'];
}
$maxIncome = max(1.0, ...array_map(static fn(array $row): float => (float) ($row['total_ingresos'] ?? 0), $reporte_ingresos_planes ?: [['total_ingresos' => 0]]));
$queryBase = [
    'fecha_desde_ingresos' => $fecha_desde_ingresos,
    'fecha_hasta_ingresos' => $fecha_hasta_ingresos,
    'periodo_uso_consultas' => $periodo_uso_consultas,
    'dias_inactividad' => $dias_inactividad,
];

$titulo_pagina = 'Reportes del Sistema';
require_once __DIR__ . '/admin_header.php';
require_once __DIR__ . '/includes/superadmin_ui_helpers.php';
?>
<style>
.report-premium{width:min(1480px,100%);max-width:1480px;margin:18px auto 0;display:grid;gap:14px}
.report-premium .sa-module-hero,.report-premium .sa-summary-grid{margin:0;width:100%}
.rp-actions{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}.rp-actions a,.rp-actions button{text-decoration:none}
.rp-filter-card{padding:14px 16px;border:1px solid #dfe7f1;border-radius:16px;background:linear-gradient(180deg,#fff,#f8fafc);box-shadow:0 8px 22px rgba(15,23,42,.04)}
.rp-filter-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.rp-filter-head h2{margin:0;color:#172033;font-size:16px;font-weight:900}.rp-filter-head p{margin:3px 0 0;color:#64748b;font-size:11px}
.rp-filter-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr)) minmax(210px,auto);align-items:end;gap:10px}.rp-field label{display:block;margin-bottom:5px;color:#334155;font-size:10px;font-weight:900;text-transform:uppercase;letter-spacing:.055em}.rp-field input,.rp-field select{width:100%;height:40px;padding:0 11px;border:1px solid #cfd9e6;border-radius:10px;background:#fff;color:#172033;font-size:12px;outline:none}.rp-field input:focus,.rp-field select:focus{border-color:#fb7185;box-shadow:0 0 0 3px rgba(239,68,68,.1)}.rp-filter-actions{height:40px;display:flex;align-items:stretch;justify-content:flex-end;gap:8px;align-self:end;white-space:nowrap}.rp-filter-actions .sa-btn{height:40px;min-width:104px;white-space:nowrap;margin:0}
.rp-overview{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(320px,.65fr);gap:14px}.rp-insight{overflow:hidden;border:1px solid #dfe7f1;border-radius:17px;background:#fff;box-shadow:0 9px 24px rgba(15,23,42,.045)}.rp-insight-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:14px 16px;border-bottom:1px solid #e7edf4}.rp-insight-head h2{margin:0;color:#172033;font-size:16px;font-weight:900}.rp-insight-head span{color:#64748b;font-size:10px}.rp-insight-body{padding:15px 16px}
.rp-income-row{display:grid;grid-template-columns:minmax(120px,.35fr) minmax(180px,1fr) 105px;align-items:center;gap:10px;margin-bottom:11px}.rp-income-row:last-child{margin-bottom:0}.rp-income-name strong,.rp-income-name small{display:block}.rp-income-name strong{color:#172033;font-size:11.5px}.rp-income-name small{margin-top:2px;color:#64748b;font-size:9.5px}.rp-bar{height:10px;overflow:hidden;border-radius:999px;background:#eef2f7}.rp-bar span{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#ef3b43,#fb7185)}.rp-income-value{text-align:right;color:#172033;font-size:11px;font-weight:900}
.rp-status-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.rp-status{padding:12px;border:1px solid #e2e8f0;border-radius:13px;background:#f8fafc}.rp-status span,.rp-status strong,.rp-status small{display:block}.rp-status span{color:#64748b;font-size:9px;font-weight:900;text-transform:uppercase}.rp-status strong{margin-top:5px;color:#172033;font-size:22px}.rp-status small{margin-top:3px;color:#94a3b8;font-size:9.5px}
.rp-tabs{display:flex;gap:7px;overflow:auto;padding:5px;border:1px solid #dfe7f1;border-radius:14px;background:#fff}.rp-tab{min-height:38px;padding:0 13px;border:0;border-radius:10px;background:transparent;color:#64748b;font-size:11px;font-weight:900;white-space:nowrap;cursor:pointer}.rp-tab.is-active{background:#feecee;color:#c92832;box-shadow:inset 0 0 0 1px #fecdd3}
.rp-panel{display:none;gap:14px}.rp-panel.is-active{display:grid}.rp-panel.two-col{grid-template-columns:repeat(2,minmax(0,1fr))}.rp-card{min-width:0;overflow:hidden;border:1px solid #dfe7f1;border-radius:17px;background:#fff;box-shadow:0 9px 24px rgba(15,23,42,.045)}.rp-card.is-wide{grid-column:1/-1}.rp-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid #e7edf4}.rp-card-title{display:flex;align-items:center;gap:10px;min-width:0}.rp-card-icon{width:36px;height:36px;display:grid;place-items:center;flex:0 0 auto;border-radius:11px;background:#feecee;color:#dc2633}.rp-card-title h2{margin:0;color:#172033;font-size:15px;font-weight:900}.rp-card-title p{margin:3px 0 0;color:#64748b;font-size:10.5px}.rp-card-tools{display:flex;align-items:flex-end;gap:7px;flex-wrap:nowrap;justify-content:flex-end}.rp-search{position:relative;min-width:190px}.rp-search i{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:#94a3b8;font-size:10px}.rp-search input{width:100%;height:36px;padding:0 10px 0 30px;border:1px solid #d6e0eb;border-radius:9px;font-size:11px}.rp-length-wrap{display:grid;gap:4px;color:#475569;font-size:8.5px;font-weight:900;text-transform:uppercase;letter-spacing:.05em}.rp-length{height:36px;min-width:112px;padding:0 8px;border:1px solid #d6e0eb;border-radius:9px;background:#fff;color:#475569;font-size:10px}.rp-record-summary{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-bottom:1px solid #e7edf4;background:#fff;color:#64748b;font-size:10.5px}.rp-record-summary>span:first-child{font-weight:700;color:#475569}.rp-record-summary [data-rp-summary]{text-align:right}.rp-card-note{color:#64748b;font-size:10px;line-height:1.45}
.rp-table-wrap{overflow:auto}.rp-table{width:100%;min-width:680px;border-collapse:collapse}.rp-table th{padding:10px 12px;border-bottom:1px solid #d5e0eb;background:#edf3f9;color:#30425b;font-size:9.5px;font-weight:900;text-align:left;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}.rp-table td{padding:10px 12px;border-bottom:1px solid #e7edf4;color:#172033;font-size:11px;vertical-align:middle}.rp-table tbody tr:nth-child(even){background:#fbfcfe}.rp-primary{display:block;color:#172033;font-weight:850}.rp-secondary{display:block;margin-top:2px;color:#64748b;font-size:9.5px}.rp-pill{display:inline-flex;align-items:center;gap:5px;padding:4px 8px;border-radius:999px;background:#eef5ff;color:#1d5fbf;font-size:9.5px;font-weight:850}.rp-progress{min-width:135px}.rp-progress-line{height:7px;overflow:hidden;border-radius:999px;background:#eef2f7}.rp-progress-line span{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#f59e0b,#ef4444)}.rp-progress small{display:block;margin-top:4px;color:#64748b;font-size:9px}.rp-details summary{color:#2563eb;font-size:10px;font-weight:850;cursor:pointer}.rp-details div{margin-top:7px;padding:8px;border-radius:9px;background:#f8fafc;color:#475569;font-size:9.5px;line-height:1.55}.rp-card-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px;border-top:1px solid #e7edf4;background:#fff;color:#64748b;font-size:10px}.rp-pagination{display:flex;align-items:center;gap:4px}.rp-page{min-width:30px;height:30px;padding:0 8px;border:1px solid #d8e1ec;border-radius:8px;background:#fff;color:#64748b;font-size:10px;font-weight:800}.rp-page.is-active{border-color:#ef3b43;background:#ef3b43;color:#fff}.rp-page:disabled{opacity:.45;cursor:not-allowed}.rp-empty{padding:25px;text-align:center;color:#64748b;font-size:11px}
@media(max-width:1100px){.rp-filter-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.rp-filter-grid .rp-filter-actions{grid-column:1/-1;justify-content:flex-end}.rp-overview,.rp-panel.two-col{grid-template-columns:1fr}}
@media(max-width:720px){.report-premium{margin-top:10px}.rp-filter-grid{grid-template-columns:1fr}.rp-filter-actions{width:100%;justify-content:stretch}.rp-filter-actions .sa-btn{flex:1}.rp-actions,.rp-card-head{align-items:flex-start;flex-direction:column}.rp-card-tools,.rp-search,.rp-length-wrap{width:100%}.rp-status-grid{grid-template-columns:1fr 1fr}.rp-income-row{grid-template-columns:110px 1fr}.rp-income-value{grid-column:2;text-align:left}.rp-tabs{border-radius:12px}}
@media print{.admin-sidebar,.admin-header,.admin-footer,.rp-actions,.rp-filter-card,.rp-tabs,.rp-card-tools,.rp-pagination{display:none!important}.admin-main{margin:0!important;padding:0!important}.rp-panel{display:grid!important}.report-premium{max-width:none;margin:0}.rp-card{break-inside:avoid;box-shadow:none}}
</style>
<div class="sa-page report-premium sa-admin-cards-4">
<?php
sa_render_module_hero([
    'icon' => 'fa-chart-column',
    'eyebrow' => 'INTELIGENCIA OPERATIVA PREMIUM',
    'title' => 'Reportes globales',
    'description' => '',
]);
sa_render_summary_cards([
    ['label'=>'Ingresos del periodo','value'=>'S/ ' . number_format($totalIngresosReportados, 2),'icon'=>'fa-coins','hint'=>$fecha_desde_ingresos . ' al ' . $fecha_hasta_ingresos],
    ['label'=>'Consultas del mes','value'=>number_format($totalConsultasPeriodo),'icon'=>'fa-magnifying-glass-chart','tone'=>'is-blue','hint'=>$periodo_uso_consultas],
    ['label'=>'Suscripciones','value'=>number_format($totalSuscripciones),'icon'=>'fa-id-card','tone'=>'is-green','hint'=>number_format(($subscriptionMap['activa'] ?? 0) + ($subscriptionMap['prueba'] ?? 0)) . ' operativas'],
    ['label'=>'Clientes inactivos','value'=>number_format(count($reporte_clientes_inactivos_data)),'icon'=>'fa-user-clock','tone'=>'is-amber','hint'=>'Más de ' . $dias_inactividad . ' días'],
]);
?>

<?php if ($reportWarnings): ?>
<div class="sa-alert sa-alert--warning"><i class="fas fa-circle-info"></i><div><strong>Secciones no disponibles</strong><p><?= htmlspecialchars(implode(' · ', array_keys($reportWarnings))) ?>. El resto del reporte continúa operativo.</p></div></div>
<?php endif; ?>

<div class="rp-actions">
    <a class="sa-btn sa-btn--secondary" href="?<?= htmlspecialchars(http_build_query($queryBase + ['export'=>'ingresos'])) ?>"><i class="fas fa-file-csv"></i> Exportar ingresos</a>
    <a class="sa-btn sa-btn--secondary" href="?<?= htmlspecialchars(http_build_query($queryBase + ['export'=>'clientes'])) ?>"><i class="fas fa-users"></i> Exportar clientes</a>
    <button type="button" class="sa-btn sa-btn--primary" onclick="window.print()"><i class="fas fa-print"></i> Imprimir informe</button>
</div>

<section class="rp-filter-card">
    <div class="rp-filter-head"><div><h2>Periodo de análisis</h2><p>Un solo filtro actualiza los reportes financieros, operativos y de actividad.</p></div><span class="sa-badge sa-badge--blue"><i class="fas fa-sliders"></i> Filtros globales</span></div>
    <form method="get" class="rp-filter-grid">
        <div class="rp-field"><label for="fecha_desde_ingresos">Ingresos desde</label><input type="date" id="fecha_desde_ingresos" name="fecha_desde_ingresos" value="<?= htmlspecialchars($fecha_desde_ingresos) ?>"></div>
        <div class="rp-field"><label for="fecha_hasta_ingresos">Ingresos hasta</label><input type="date" id="fecha_hasta_ingresos" name="fecha_hasta_ingresos" value="<?= htmlspecialchars($fecha_hasta_ingresos) ?>"></div>
        <div class="rp-field"><label for="periodo_uso_consultas">Mes de consultas</label><input type="month" id="periodo_uso_consultas" name="periodo_uso_consultas" value="<?= htmlspecialchars($periodo_uso_consultas) ?>"></div>
        <div class="rp-field"><label for="dias_inactividad">Inactividad en días</label><input type="number" min="1" max="3650" id="dias_inactividad" name="dias_inactividad" value="<?= (int) $dias_inactividad ?>"></div>
        <div class="rp-filter-actions"><button class="sa-btn sa-btn--primary" type="submit"><i class="fas fa-filter"></i> Aplicar</button><a class="sa-btn sa-btn--secondary" href="gestionar_reportes.php"><i class="fas fa-rotate-left"></i> Restablecer</a></div>
    </form>
</section>

<section class="rp-overview">
    <article class="rp-insight">
        <header class="rp-insight-head"><h2>Ingresos por plan</h2><span>Distribución del periodo seleccionado</span></header>
        <div class="rp-insight-body">
            <?php if ($reporte_ingresos_planes): foreach ($reporte_ingresos_planes as $row): $income = (float) ($row['total_ingresos'] ?? 0); ?>
            <div class="rp-income-row">
                <div class="rp-income-name"><strong><?= htmlspecialchars((string) $row['nombre_plan']) ?></strong><small><?= number_format((int) $row['suscripciones_activas']) ?> suscripciones operativas</small></div>
                <div class="rp-bar"><span style="width:<?= number_format(min(100, ($income / $maxIncome) * 100), 2, '.', '') ?>%"></span></div>
                <div class="rp-income-value">S/ <?= number_format($income, 2) ?></div>
            </div>
            <?php endforeach; else: ?><div class="rp-empty">Sin ingresos para el periodo seleccionado.</div><?php endif; ?>
        </div>
    </article>
    <article class="rp-insight">
        <header class="rp-insight-head"><h2>Estado de suscripciones</h2><span><?= number_format($totalSuscripciones) ?> registros</span></header>
        <div class="rp-insight-body rp-status-grid">
            <?php foreach ([
                'activa'=>['Activas','Acceso vigente'],
                'prueba'=>['En prueba','Evaluación'],
                'vencida'=>['Vencidas','Requieren gestión'],
                'cancelada'=>['Canceladas','Sin operación'],
            ] as $key=>$meta): ?>
            <div class="rp-status"><span><?= htmlspecialchars($meta[0]) ?></span><strong><?= number_format($subscriptionMap[$key] ?? 0) ?></strong><small><?= htmlspecialchars($meta[1]) ?></small></div>
            <?php endforeach; ?>
        </div>
    </article>
</section>

<nav class="rp-tabs" aria-label="Categorías de reportes">
    <button type="button" class="rp-tab is-active" data-rp-tab="finanzas"><i class="fas fa-coins"></i> Finanzas</button>
    <button type="button" class="rp-tab" data-rp-tab="actividad"><i class="fas fa-chart-line"></i> Actividad</button>
    <button type="button" class="rp-tab" data-rp-tab="operacion"><i class="fas fa-server"></i> Operación</button>
    <button type="button" class="rp-tab" data-rp-tab="clientes"><i class="fas fa-users"></i> Clientes</button>
    <button type="button" class="rp-tab" data-rp-tab="suscripciones"><i class="fas fa-id-card"></i> Suscripciones</button>
</nav>

<section class="rp-panel two-col is-active" data-rp-panel="finanzas">
    <article class="rp-card is-wide" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-money-bill-trend-up"></i></span><div><h2>Detalle financiero por plan</h2><p>Suscripciones operativas e ingresos confirmados.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar plan" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Plan</th><th>Suscripciones operativas</th><th>Ingresos confirmados</th><th>Participación</th></tr></thead><tbody>
        <?php foreach ($reporte_ingresos_planes as $row): $share = $totalIngresosReportados > 0 ? ((float) $row['total_ingresos'] / $totalIngresosReportados) * 100 : 0; ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string) $row['nombre_plan']) ?></span></td><td><?= number_format((int) $row['suscripciones_activas']) ?></td><td><strong>S/ <?= number_format((float) $row['total_ingresos'],2) ?></strong></td><td><span class="rp-pill"><?= number_format($share,1) ?>%</span></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
</section>

<section class="rp-panel two-col" data-rp-panel="actividad">
    <article class="rp-card" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-magnifying-glass-chart"></i></span><div><h2>Uso de consultas</h2><p>Consumo por Admin durante <?= htmlspecialchars($periodo_uso_consultas) ?>.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar Admin" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Admin</th><th>Plan</th><th>Consultas</th><th>Uso</th></tr></thead><tbody>
        <?php foreach ($reporte_uso_consultas_data as $row): $limit=(int)($row['limite_consultas']??0);$used=(int)$row['consultas_realizadas'];$pct=$limit>0?min(100,($used/$limit)*100):0; ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['nombre_usuario']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['correo']) ?></span></td><td><?= htmlspecialchars((string)$row['nombre_plan']) ?></td><td><?= number_format($used) ?> / <?= $limit>0?number_format($limit):'Ilimitado' ?></td><td><div class="rp-progress"><div class="rp-progress-line"><span style="width:<?= number_format($pct,1,'.','') ?>%"></span></div><small><?= $limit>0?number_format($pct,1).'%':'Sin límite' ?></small></div></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
    <article class="rp-card" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-gift"></i></span><div><h2>Oportunidades del plan Gratis</h2><p>Usuarios que pueden requerir una mejora de plan.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar cuenta" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Admin</th><th>Consultas</th><th>Utilización</th></tr></thead><tbody>
        <?php foreach ($admins_gratis_data as $row): $limit=(int)($row['limite_consultas']??0);$used=(int)$row['consultas_realizadas'];$pct=$limit>0?min(100,($used/$limit)*100):0; ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['admin_nombre']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['admin_correo']) ?></span></td><td><?= number_format($used) ?> / <?= $limit>0?number_format($limit):'Ilimitado' ?></td><td><span class="rp-pill"><?= $limit>0?number_format($pct,1).'%':'Sin límite' ?></span></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
</section>

<section class="rp-panel two-col" data-rp-panel="operacion">
    <article class="rp-card is-wide" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-user-shield"></i></span><div><h2>Administradores y recursos</h2><p>Capacidad utilizada en buzones y dominios.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar Admin o plan" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Admin</th><th>Plan</th><th>Buzones</th><th>Dominios</th><th>Detalle</th></tr></thead><tbody>
        <?php foreach ($admins_recursos_data as $row): $b=isset($row['buzones_detalle'])&&$row['buzones_detalle']!==null?explode('||',(string)$row['buzones_detalle']):[];$d=isset($row['dominios_detalle'])&&$row['dominios_detalle']!==null?explode('||',(string)$row['dominios_detalle']):[]; ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['admin_nombre']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['admin_correo']) ?></span></td><td><?= htmlspecialchars((string)$row['plan_actual']) ?></td><td><?= number_format((int)$row['buzones_usados']) ?> / <?= $row['limite_buzones']!==null?number_format((int)$row['limite_buzones']):'Ilimitado' ?></td><td><?= number_format((int)$row['dominios_usados']) ?> / <?= $row['limite_dominios']!==null?number_format((int)$row['limite_dominios']):'Ilimitado' ?></td><td><details class="rp-details"><summary>Ver recursos</summary><div><?php if($b):?><strong>Buzones:</strong><br><?= implode('<br>',array_map('htmlspecialchars',$b)) ?><br><?php endif;?><?php if($d):?><strong>Dominios:</strong><br><?= implode('<br>',array_map('htmlspecialchars',$d)) ?><?php endif;?><?php if(!$b&&!$d):?>Sin recursos configurados.<?php endif;?></div></details></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
    <article class="rp-card is-wide" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-globe"></i></span><div><h2>Uso de dominios</h2><p>Cuentas vinculadas a cada dominio administrado.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar dominio o Admin" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Admin</th><th>Dominio</th><th>Cuentas asociadas</th></tr></thead><tbody>
        <?php foreach ($reporte_uso_dominios_admin as $row): ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['admin_nombre']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['admin_correo']) ?></span></td><td><?= htmlspecialchars((string)$row['nombre_dominio']) ?></td><td><span class="rp-pill"><?= number_format((int)$row['total_cuentas_asociadas']) ?></span></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
</section>

<section class="rp-panel two-col" data-rp-panel="clientes">
    <article class="rp-card" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-users"></i></span><div><h2>Directorio de clientes</h2><p>Admins, revendedores y clientes finales registrados.</p></div></div><div class="rp-card-tools"><a class="sa-btn sa-btn--secondary" href="?<?= htmlspecialchars(http_build_query($queryBase + ['export'=>'clientes'])) ?>"><i class="fas fa-download"></i></a><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar cliente" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Usuario</th><th>Rol</th><th>Teléfono</th><th>Propietario</th></tr></thead><tbody>
        <?php foreach ($reporte_clientes_data as $row): ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['nombre_usuario']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['correo']) ?></span></td><td><span class="rp-pill"><?= htmlspecialchars((string)$row['rol_cliente']) ?></span></td><td><?= htmlspecialchars((string)($row['telefono']?:'Sin teléfono')) ?></td><td><?= htmlspecialchars((string)($row['admin_propietario_nombre']?:'Cuenta principal')) ?></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
    <article class="rp-card" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-user-clock"></i></span><div><h2>Clientes inactivos</h2><p>Sin actividad durante más de <?= (int)$dias_inactividad ?> días.</p></div></div><div class="rp-card-tools"><a class="sa-btn sa-btn--secondary" href="?<?= htmlspecialchars(http_build_query($queryBase + ['export'=>'inactivos'])) ?>"><i class="fas fa-download"></i></a><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar inactivo" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Cliente</th><th>Teléfono</th><th>Última consulta</th><th>Inactividad</th></tr></thead><tbody>
        <?php foreach ($reporte_clientes_inactivos_data as $row): ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars((string)$row['nombre_usuario']) ?></span><span class="rp-secondary"><?= htmlspecialchars((string)$row['correo']) ?></span></td><td><?= htmlspecialchars((string)($row['telefono']?:'Sin teléfono')) ?></td><td><?= $row['ultima_consulta']?date('d/m/Y H:i',strtotime((string)$row['ultima_consulta'])):'Nunca' ?></td><td><span class="rp-pill"><?= $row['dias_sin_consulta']!==null?number_format((int)$row['dias_sin_consulta']).' días':'Sin consultas' ?></span></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
</section>

<section class="rp-panel two-col" data-rp-panel="suscripciones">
    <article class="rp-card is-wide" data-rp-table-card>
        <header class="rp-card-head"><div class="rp-card-title"><span class="rp-card-icon"><i class="fas fa-id-card"></i></span><div><h2>Suscripciones por estado</h2><p>Distribución consolidada del catálogo de suscriptores.</p></div></div><div class="rp-card-tools"><div class="rp-search"><i class="fas fa-search"></i><input type="search" placeholder="Buscar estado" data-rp-search></div><select class="rp-length" data-rp-length><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="all">Todos</option></select></div></header>
        <div class="rp-table-wrap"><table class="rp-table"><thead><tr><th>Estado</th><th>Total</th><th>Participación</th></tr></thead><tbody>
        <?php foreach ($reporte_suscripciones_estado as $row): $pct=$totalSuscripciones>0?((int)$row['total_suscripciones']/$totalSuscripciones)*100:0; ?><tr data-rp-row><td><span class="rp-primary"><?= htmlspecialchars(ucfirst((string)$row['estado'])) ?></span></td><td><?= number_format((int)$row['total_suscripciones']) ?></td><td><div class="rp-progress"><div class="rp-progress-line"><span style="width:<?= number_format($pct,1,'.','') ?>%"></span></div><small><?= number_format($pct,1) ?>%</small></div></td></tr><?php endforeach; ?>
        </tbody></table></div><footer class="rp-card-foot"><span data-rp-summary></span><div class="rp-pagination" data-rp-pagination></div></footer>
    </article>
</section>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
    const tabs = [...document.querySelectorAll('[data-rp-tab]')];
    const panels = [...document.querySelectorAll('[data-rp-panel]')];
    tabs.forEach(tab => tab.addEventListener('click', () => {
        tabs.forEach(item => item.classList.toggle('is-active', item === tab));
        panels.forEach(panel => panel.classList.toggle('is-active', panel.dataset.rpPanel === tab.dataset.rpTab));
        try { localStorage.setItem('afenixx-report-tab', tab.dataset.rpTab); } catch (_) {}
    }));
    try {
        const saved = localStorage.getItem('afenixx-report-tab');
        const savedTab = tabs.find(tab => tab.dataset.rpTab === saved);
        if (savedTab) savedTab.click();
    } catch (_) {}

    const reportCounts = {
        'Detalle financiero por plan': ['plan registrado', 'planes registrados'],
        'Uso de consultas': ['administrador registrado', 'administradores registrados'],
        'Oportunidades del plan Gratis': ['oportunidad registrada', 'oportunidades registradas'],
        'Administradores y recursos': ['administrador registrado', 'administradores registrados'],
        'Uso de dominios': ['dominio registrado', 'dominios registrados'],
        'Directorio de clientes': ['usuario registrado', 'usuarios registrados'],
        'Clientes inactivos': ['cliente inactivo', 'clientes inactivos'],
        'Suscripciones por estado': ['estado registrado', 'estados registrados']
    };

    const reportNotes = {
        'Detalle financiero por plan': 'Los ingresos se agrupan por plan y consideran únicamente pagos confirmados dentro del periodo.',
        'Uso de consultas': 'El consumo mensual se compara con el límite configurado en el plan vigente de cada Admin.',
        'Oportunidades del plan Gratis': 'Estas cuentas pueden requerir seguimiento comercial o una mejora de capacidad.',
        'Administradores y recursos': 'Los recursos muestran buzones y dominios pertenecientes a cada Admin o Ayudante operativo.',
        'Uso de dominios': 'Las cuentas asociadas permiten identificar los dominios con mayor carga operativa.',
        'Directorio de clientes': 'El directorio reúne Admins, Ayudantes, revendedores y clientes finales registrados.',
        'Clientes inactivos': 'La inactividad se calcula usando la última consulta registrada para cada usuario final.',
        'Suscripciones por estado': 'La distribución resume todas las suscripciones registradas en el sistema.'
    };

    document.querySelectorAll('[data-rp-table-card]').forEach(card => {
        const rows = [...card.querySelectorAll('[data-rp-row]')];
        const search = card.querySelector('[data-rp-search]');
        const length = card.querySelector('[data-rp-length]');
        const footer = card.querySelector('.rp-card-foot');
        const existingSummary = card.querySelector('[data-rp-summary]');
        const pagination = card.querySelector('[data-rp-pagination]');
        const title = card.querySelector('.rp-card-title h2')?.textContent.trim() || 'Reporte';
        let page = 1;

        if (length && !length.closest('.rp-length-wrap')) {
            const wrapper = document.createElement('label');
            wrapper.className = 'rp-length-wrap';
            const label = document.createElement('span');
            label.textContent = 'Mostrar';
            length.parentNode.insertBefore(wrapper, length);
            wrapper.append(label, length);
            [...length.options].forEach(option => {
                if (option.value !== 'all' && !/registros/i.test(option.textContent)) {
                    option.textContent = `${option.textContent} registros`;
                }
            });
        }

        const recordSummary = document.createElement('div');
        recordSummary.className = 'rp-record-summary';
        const countLabel = document.createElement('span');
        countLabel.setAttribute('data-rp-count', '');
        const summary = existingSummary || document.createElement('span');
        summary.setAttribute('data-rp-summary', '');
        recordSummary.append(countLabel, summary);
        const tableWrap = card.querySelector('.rp-table-wrap');
        card.insertBefore(recordSummary, tableWrap);

        if (footer) {
            [...footer.querySelectorAll('[data-rp-summary]')].forEach(node => {
                if (node !== summary) node.remove();
            });
            const note = document.createElement('span');
            note.className = 'rp-card-note';
            note.textContent = reportNotes[title] || 'Los datos se actualizan de acuerdo con los filtros seleccionados.';
            footer.prepend(note);
        }

        const render = () => {
            const term = (search?.value || '').trim().toLocaleLowerCase('es');
            const filtered = rows.filter(row => row.textContent.toLocaleLowerCase('es').includes(term));
            const perPage = !length || length.value === 'all' ? Math.max(1, filtered.length) : Math.max(1, Number(length.value));
            const pages = Math.max(1, Math.ceil(filtered.length / perPage));
            page = Math.min(Math.max(1, page), pages);
            rows.forEach(row => row.hidden = true);
            const start = (page - 1) * perPage;
            filtered.slice(start, start + perPage).forEach(row => row.hidden = false);

            const countWords = reportCounts[title] || ['registro', 'registros'];
            countLabel.textContent = `${filtered.length} ${filtered.length === 1 ? countWords[0] : countWords[1]}`;
            summary.textContent = filtered.length
                ? `Mostrando ${start + 1}–${Math.min(start + perPage, filtered.length)} de ${filtered.length} registros`
                : 'Mostrando 0–0 de 0 registros';

            if (pagination) {
                pagination.innerHTML = '';
                const prev = document.createElement('button');
                prev.type = 'button';
                prev.className = 'rp-page';
                prev.innerHTML = '<i class="fas fa-chevron-left"></i>';
                prev.disabled = page === 1;
                prev.title = 'Página anterior';
                prev.onclick = () => { page--; render(); };

                const current = document.createElement('button');
                current.type = 'button';
                current.className = 'rp-page is-active';
                current.textContent = String(page);
                current.title = `Página ${page} de ${pages}`;
                current.disabled = true;

                const next = document.createElement('button');
                next.type = 'button';
                next.className = 'rp-page';
                next.innerHTML = '<i class="fas fa-chevron-right"></i>';
                next.disabled = page === pages;
                next.title = 'Página siguiente';
                next.onclick = () => { page++; render(); };

                pagination.append(prev, current, next);
            }
        };

        search?.addEventListener('input', () => { page = 1; render(); });
        length?.addEventListener('change', () => { page = 1; render(); });
        render();
    });
});
</script>
<?php require_once __DIR__ . '/admin_footer.php'; ob_end_flush(); ?>

<!-- AFENIXX-V12-ASSETS -->
<link rel="stylesheet" href="../assets/css/afenixx_v12.css?v=2026.07.24-v12">
<script src="../assets/js/afenixx_v12.js?v=2026.07.24-v12"></script>
