<?php

declare(strict_types=1);

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

require_once __DIR__ . '/config.php';

if (is_file(__DIR__ . '/config_ui.php')) {
    require_once __DIR__ . '/config_ui.php';
}

function af_user_e(
    mixed $value
): string {
    return htmlspecialchars(
        (string) $value,
        ENT_QUOTES,
        'UTF-8'
    );
}

function af_user_lower(
    mixed $value
): string {
    $value = trim((string) $value);

    return function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);
}

function af_user_phone(
    mixed $value
): string {
    return preg_replace(
        '/\D+/',
        '',
        (string) $value
    ) ?: '';
}

function af_user_column_exists(
    PDO $pdo,
    string $table,
    string $column
): bool {
    static $cache = [];

    $cacheKey = $table . '.' . $column;

    if (array_key_exists($cacheKey, $cache)) {
        return $cache[$cacheKey];
    }

    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[$cacheKey] =
            (int) $stmt->fetchColumn() > 0;
    } catch (Throwable $error) {
        return $cache[$cacheKey] = false;
    }
}

function af_user_message(
    PDO $pdo,
    string $key,
    string $fallback
): string {
    try {
        $stmt = $pdo->prepare(
            'SELECT contenido
             FROM mensajes_sistema
             WHERE clave = ?
             LIMIT 1'
        );

        $stmt->execute([$key]);

        $value = trim(
            (string) $stmt->fetchColumn()
        );

        return $value !== ''
            ? $value
            : $fallback;
    } catch (Throwable $error) {
        return $fallback;
    }
}

function af_user_template(
    PDO $pdo
): string {
    try {
        $stmt = $pdo->query(
            "SELECT mensaje
             FROM plantillas_whatsapp
             WHERE modulo_uso IN (
                 'revendedor_renovar',
                 'vencimiento',
                 'cliente_general'
             )
             ORDER BY CASE modulo_uso
                 WHEN 'revendedor_renovar' THEN 1
                 WHEN 'vencimiento' THEN 2
                 ELSE 3
             END,
             id ASC
             LIMIT 1"
        );

        $template = trim(
            (string) $stmt->fetchColumn()
        );

        if ($template !== '') {
            return $template;
        }
    } catch (Throwable $error) {
        // Se utiliza la plantilla segura inferior.
    }

    return
        "Hola, soy {nombre_cliente}.\n\n"
        . "Deseo renovar mi servicio:\n"
        . "📺 Plataforma: {plataforma}\n"
        . "🏷️ Tipo: {tipo_servicio}\n"
        . "📧 Correo: {correo}\n"
        . "🔑 ID de acceso: {codigo_cuenta}\n"
        . "📅 Vencimiento: {fecha_vencimiento}\n\n"
        . "Quedo atento a la confirmación.";
}

function af_user_replace(
    string $template,
    array $values
): string {
    return str_replace(
        array_keys($values),
        array_values($values),
        $template
    );
}

function af_user_professional_whatsapp(
    string $template,
    array $values,
    string $brand,
    string $mode = 'renewal'
): string {
    $message = trim($template);

    foreach ($values as $key => $value) {
        $clean = trim(str_replace('*', '', (string) $value));
        $clean = $clean !== '' ? $clean : 'Sin dato';
        $message = str_replace('*' . $key . '*', '*' . $clean . '*', $message);
        $message = str_replace($key, '*' . $clean . '*', $message);
    }

    // Evita que una plantilla antigua muestre llaves sin reemplazar.
    $message = preg_replace('/\\{[a-zA-Z0-9_]+\\}/u', 'Sin dato', $message) ?? $message;
    $message = preg_replace('/\\*{2,}/u', '*', $message) ?? $message;
    $message = preg_replace('/\\n{3,}/u', "\n\n", $message) ?? $message;
    $message = trim($message);

    $heading = match ($mode) {
        'expired' => '🚨 *SOLICITUD DE REACTIVACIÓN*',
        'active' => '🔄 *SOLICITUD DE RENOVACIÓN ANTICIPADA*',
        'support' => '💬 *SOLICITUD DE ATENCIÓN*',
        default => '⏰ *SOLICITUD DE RENOVACIÓN*',
    };

    $firstLine = trim((string) strtok($message, "\n"));
    if (!preg_match('/^[^\\n]{0,8}\\*[^*\\n]{4,90}\\*$/u', $firstLine)) {
        $message = $heading . "\n\n" . $message;
    }

    $details = [
        '👤 *Cliente:* ' . ($values['{nombre_cliente}'] ?? 'Sin dato'),
        '📺 *Plataforma:* ' . ($values['{plataforma}'] ?? 'Sin dato'),
        '🏷️ *Servicio:* ' . ($values['{tipo_servicio}'] ?? 'Sin dato'),
        '📧 *Cuenta:* ' . ($values['{correo}'] ?? 'Sin dato'),
        '🔑 *ID de acceso:* ' . ($values['{codigo_cuenta}'] ?? 'Sin dato'),
        '📅 *Vencimiento:* ' . ($values['{fecha_vencimiento}'] ?? 'Sin dato'),
    ];

    $normalized = function_exists('mb_strtolower')
        ? mb_strtolower($message, 'UTF-8')
        : strtolower($message);

    $missingDetails = [];
    foreach ($details as $line) {
        $position = strrpos($line, ':');
        $value = $position === false ? '' : trim(str_replace('*', '', substr($line, $position + 1)));
        $valueNormalized = function_exists('mb_strtolower')
            ? mb_strtolower($value, 'UTF-8')
            : strtolower($value);
        if ($value !== '' && $value !== 'Sin dato' && !str_contains($normalized, $valueNormalized)) {
            $missingDetails[] = $line;
        }
    }

    if ($missingDetails !== []) {
        $message .= "\n\n📋 *DETALLE DEL SERVICIO*\n" . implode("\n", $missingDetails);
    }

    if (!preg_match('/responde|confirma|confirmar|ayuda|atento|atenta/iu', $message)) {
        $message .= "\n\n✅ *Siguiente paso:* confirma la renovación o indícame cómo deseas continuar.";
    }

    $brand = trim(str_replace('*', '', $brand));
    $messageNormalized = function_exists('mb_strtolower')
        ? mb_strtolower($message, 'UTF-8')
        : strtolower($message);
    $brandNormalized = function_exists('mb_strtolower')
        ? mb_strtolower($brand, 'UTF-8')
        : strtolower($brand);

    if ($brand !== '' && !str_contains($messageNormalized, $brandNormalized)) {
        $message .= "\n\n✨ *{$brand}* · Atención y acceso seguro";
    }

    return trim(preg_replace('/\\n{3,}/u', "\n\n", $message) ?? $message);
}

function af_user_status(
    mixed $dateValue
): array {
    $dateValue = trim(
        (string) $dateValue
    );

    if (
        $dateValue === ''
        || strtotime($dateValue) === false
    ) {
        return [
            'key' => 'without-date',
            'label' => 'Sin fecha',
            'days' => null,
        ];
    }

    $today = new DateTimeImmutable('today');

    $end = new DateTimeImmutable(
        date('Y-m-d', strtotime($dateValue))
    );

    $days = (int) $today
        ->diff($end)
        ->format('%r%a');

    if ($days < 0) {
        return [
            'key' => 'expired',
            'label' => 'Vencida',
            'days' => $days,
        ];
    }

    if ($days === 0) {
        return [
            'key' => 'soon',
            'label' => 'Vence hoy',
            'days' => 0,
        ];
    }

    if ($days <= 7) {
        return [
            'key' => 'soon',
            'label' =>
                'Próxima · '
                . $days
                . ' día'
                . ($days === 1 ? '' : 's'),
            'days' => $days,
        ];
    }

    return [
        'key' => 'active',
        'label' => 'Activa',
        'days' => $days,
    ];
}

/*
|--------------------------------------------------------------------------
| Validación de sesión
|--------------------------------------------------------------------------
*/

$role = af_user_lower(
    $_SESSION['rol']
    ?? $_SESSION['consulta']['rol']
    ?? $_SESSION['consulta']['tipo_acceso']
    ?? ''
);

$sessionUserId = (int) (
    $_SESSION['uid']
    ?? $_SESSION['usuario_id']
    ?? $_SESSION['consulta']['uid']
    ?? 0
);

$sessionIdentifier = trim(
    (string) (
        $_SESSION['usuario']
        ?? $_SESSION['nombre_usuario']
        ?? $_SESSION['consulta']['usuario']
        ?? $_SESSION['consulta']['correo']
        ?? ''
    )
);

$allowedRoles = [
    'usuario',
    'cliente',
];

$consultaAccess = !empty(
    $_SESSION['consulta']['uid']
);

$manualUrl = $role === 'revendedor'
    ? 'manual_revendedor.php'
    : 'manual_usuario.php';

if (
    !in_array(
        $role,
        $allowedRoles,
        true
    )
    && !$consultaAccess
) {
    header(
        'Location: login_consulta.php?error=2'
    );

    exit;
}

/*
|--------------------------------------------------------------------------
| Resolver usuario conectado
|--------------------------------------------------------------------------
*/

$user = [];

try {
    if ($sessionUserId > 0) {
        $stmtUser = $pdo->prepare(
            "SELECT
                id,
                nombre_usuario,
                correo,
                telefono,
                codigo_consulta,
                id_admin_propietario
             FROM usuarios
             WHERE id = ?
             LIMIT 1"
        );

        $stmtUser->execute([
            $sessionUserId,
        ]);

        $user = $stmtUser->fetch(
            PDO::FETCH_ASSOC
        ) ?: [];
    }

    if (
        !$user
        && $sessionIdentifier !== ''
    ) {
        $stmtUser = $pdo->prepare(
            "SELECT
                id,
                nombre_usuario,
                correo,
                telefono,
                codigo_consulta,
                id_admin_propietario
             FROM usuarios
             WHERE nombre_usuario = ?
                OR correo = ?
             LIMIT 1"
        );

        $stmtUser->execute([
            $sessionIdentifier,
            $sessionIdentifier,
        ]);

        $user = $stmtUser->fetch(
            PDO::FETCH_ASSOC
        ) ?: [];
    }
} catch (Throwable $error) {
    error_log(
        'Dashboard usuario: '
        . $error->getMessage()
    );
}

$userId = (int) (
    $user['id']
    ?? $sessionUserId
);

if ($userId <= 0) {
    session_destroy();

    header(
        'Location: login_consulta.php?error=2'
    );

    exit;
}

/*
|--------------------------------------------------------------------------
| Acciones seguras del usuario
|--------------------------------------------------------------------------
*/

if (
    $_SERVER['REQUEST_METHOD'] === 'POST'
    && (string) ($_POST['action'] ?? '') === 'regenerate_assigned_account_id'
) {
    Security::headers(true);
    Security::requireCsrf();

    try {
        $accountId = filter_input(
            INPUT_POST,
            'account_id',
            FILTER_VALIDATE_INT
        ) ?: 0;

        if ($accountId <= 0) {
            throw new InvalidArgumentException(
                'La cuenta seleccionada no es válida.'
            );
        }

        $pdo->beginTransaction();

        $check = $pdo->prepare(
            "SELECT cs.id
             FROM asociaciones a
             INNER JOIN correos_servicios cs
                ON cs.id = a.id_correo_servicio
             WHERE a.id_usuario = ?
               AND cs.id = ?
             LIMIT 1
             FOR UPDATE"
        );

        $check->execute([
            $userId,
            $accountId,
        ]);

        if (!$check->fetchColumn()) {
            throw new RuntimeException(
                'La cuenta no está asignada a tu usuario.'
            );
        }

        do {
            $newCode = strtoupper(
                substr(
                    bin2hex(random_bytes(8)),
                    0,
                    10
                )
            );

            $duplicate = $pdo->prepare(
                'SELECT COUNT(*)
                 FROM correos_servicios
                 WHERE codigo_acceso_cuenta = ?'
            );

            $duplicate->execute([
                $newCode,
            ]);
        } while ((int) $duplicate->fetchColumn() > 0);

        $update = $pdo->prepare(
            'UPDATE correos_servicios
             SET codigo_acceso_cuenta = ?
             WHERE id = ?'
        );

        $update->execute([
            $newCode,
            $accountId,
        ]);

        $pdo->commit();

        Security::json([
            'success' => true,
            'message' => 'El ID de acceso fue regenerado.',
            'codigo' => $newCode,
        ]);
    } catch (Throwable $error) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }

        error_log(
            'Dashboard usuario, regenerar ID: '
            . $error->getMessage()
        );

        Security::json([
            'success' => false,
            'message' => $error->getMessage(),
        ], 422);
    }
}

$userName = trim(
    (string) (
        $user['nombre_usuario']
        ?? $_SESSION['nombre_usuario']
        ?? $_SESSION['usuario']
        ?? 'Usuario'
    )
) ?: 'Usuario';

$userEmail = trim(
    (string) (
        $user['correo']
        ?? ''
    )
);

$consultationCode = trim(
    (string) (
        $user['codigo_consulta']
        ?? $_SESSION['consulta']['codigo_consulta']
        ?? ''
    )
);

/*
|--------------------------------------------------------------------------
| Administrador propietario
|--------------------------------------------------------------------------
*/

$administrator = [];

$ownerId = (int) (
    $user['id_admin_propietario']
    ?? 0
);

if ($ownerId > 0) {
    try {
        $stmtAdmin = $pdo->prepare(
            "SELECT
                id,
                nombre_usuario,
                correo,
                telefono
             FROM usuarios
             WHERE id = ?
             LIMIT 1"
        );

        $stmtAdmin->execute([
            $ownerId,
        ]);

        $administrator = $stmtAdmin->fetch(
            PDO::FETCH_ASSOC
        ) ?: [];
    } catch (Throwable $error) {
        error_log(
            'Dashboard usuario, administrador: '
            . $error->getMessage()
        );
    }
}

$administratorName = trim(
    (string) (
        $administrator['nombre_usuario']
        ?? 'Administrador'
    )
) ?: 'Administrador';

$administratorPhone = af_user_phone(
    $administrator['telefono']
    ?? $ui_support_whatsapp_number
    ?? ''
);

$administratorEmail = trim(
    (string) (
        $administrator['correo']
        ?? ''
    )
);

/*
|--------------------------------------------------------------------------
| Cuentas asignadas
|--------------------------------------------------------------------------
*/

$accounts = [];

try {
    $hasServiceProfileFlag = af_user_column_exists(
        $pdo,
        'correos_servicios',
        'es_perfil'
    );

    $hasAssociationProfilePin = af_user_column_exists(
        $pdo,
        'asociaciones',
        'pin_perfil'
    );

    $hasAssociationProfileName = af_user_column_exists(
        $pdo,
        'asociaciones',
        'nombre_perfil'
    );

    $hasAssociationRenewal = af_user_column_exists(
        $pdo,
        'asociaciones',
        'fecha_vencimiento'
    );

    $profileFlagExpression = $hasServiceProfileFlag
        ? 'COALESCE(cs.es_perfil, 0)'
        : '0';

    $profilePinExpression = $hasAssociationProfilePin
        ? 'a.pin_perfil'
        : 'NULL';

    $profileNameExpression = $hasAssociationProfileName
        ? 'a.nombre_perfil'
        : 'NULL';

    /*
     * La fecha oficial de la cuenta está en correos_servicios.fecha_renovacion.
     * Algunas instalaciones antiguas guardaron fecha_vencimiento en asociaciones,
     * por eso se conserva como respaldo.
     */
    $renewalExpression = $hasAssociationRenewal
        ? 'COALESCE(cs.fecha_renovacion, a.fecha_vencimiento)'
        : 'cs.fecha_renovacion';

    $stmtAccounts = $pdo->prepare(
        "SELECT
            cs.id AS id_correo_servicio,
            cs.correo,
            cs.codigo_acceso_cuenta,
            cs.id_plataforma,
            cs.fecha_creacion AS fecha_registro_cuenta,
            {$renewalExpression} AS fecha_vencimiento,
            {$profileFlagExpression} AS es_perfil,
            {$profilePinExpression} AS pin_perfil,
            {$profileNameExpression} AS nombre_perfil,
            p.nombre AS plataforma,
            p.imagen_url
         FROM asociaciones a
         INNER JOIN correos_servicios cs
            ON cs.id = a.id_correo_servicio
         INNER JOIN plataformas p
            ON p.id = cs.id_plataforma
         WHERE a.id_usuario = ?
         ORDER BY
            CASE
                WHEN {$renewalExpression} IS NULL THEN 1
                ELSE 0
            END,
            {$renewalExpression} ASC,
            p.nombre ASC,
            cs.correo ASC"
    );

    $stmtAccounts->execute([
        $userId,
    ]);

    $accounts = $stmtAccounts->fetchAll(
        PDO::FETCH_ASSOC
    );
} catch (Throwable $accountsError) {
    error_log(
        'Dashboard usuario, cuentas: '
        . $accountsError->getMessage()
    );

    $accounts = [];
}

/*
|--------------------------------------------------------------------------
| Resumen y plataformas
|--------------------------------------------------------------------------
*/

$platforms = [];
$activeCount = 0;
$soonCount = 0;
$expiredCount = 0;

foreach ($accounts as &$account) {
    $status = af_user_status(
        $account['fecha_vencimiento']
        ?? ''
    );

    $account['_status'] = $status;

    $platformId = (int) (
        $account['id_plataforma']
        ?? 0
    );

    if ($platformId > 0) {
        $platforms[$platformId] = (string) (
            $account['plataforma']
            ?? 'Plataforma'
        );
    }

    if ($status['key'] === 'active') {
        $activeCount++;
    } elseif ($status['key'] === 'soon') {
        $soonCount++;
    } elseif ($status['key'] === 'expired') {
        $expiredCount++;
    }
}

unset($account);

asort(
    $platforms,
    SORT_NATURAL | SORT_FLAG_CASE
);

/*
|--------------------------------------------------------------------------
| Mensajes configurables
|--------------------------------------------------------------------------
*/

$dashboardNotice = af_user_message(
    $pdo,
    'DASHBOARD_USUARIO_COMUNICADO',
    "Hola {nombre_cliente}. Tienes {total_servicios} servicio(s) vinculados a tu cuenta.\nRevisa las fechas de renovación, utiliza Consultar para localizar tus códigos y comunícate con {administrador} cuando necesites renovar o recibir soporte."
);

$dashboardNotice = af_user_replace(
    $dashboardNotice,
    [
        '{nombre_cliente}' => $userName,
        '{administrador}' => $administratorName,
        '{total_servicios}' => (string) count($accounts),
        '{codigo_cliente}' => $consultationCode,
    ]
);

$renewTemplate = af_user_template(
    $pdo
);

$messageBrand = trim((string) ($ui_title_system ?? 'Ave Fénix')) ?: 'Ave Fénix';

$contactMessage =
    "💬 *SOLICITUD DE ATENCIÓN*\n\n"
    . "Hola *{$administratorName}*, soy *{$userName}*.\n\n"
    . "Necesito ayuda con los servicios vinculados a mi cuenta.\n"
    . (
        $consultationCode !== ''
            ? "🔑 *ID de consulta:* {$consultationCode}\n"
            : ''
    )
    . "📦 *Servicios registrados:* " . count($accounts) . "\n\n"
    . "✅ *Siguiente paso:* por favor, revisa mi cuenta y confírmame cómo continuar.\n\n"
    . "✨ *{$messageBrand}* · Atención y acceso seguro";

/*
|--------------------------------------------------------------------------
| Marca blanca
|--------------------------------------------------------------------------
*/

$brandPrimary = (string) (
    $ui_color_button_hex
    ?? $ui_color_primary_bg_hex
    ?? '#dc2626'
);

$brandSecondary = (string) (
    $ui_color_secondary_hex
    ?? '#7f1d1d'
);

$brandAccent = (string) (
    $ui_color_accent_hex
    ?? '#f59e0b'
);

if (
    !preg_match(
        '/^#[0-9a-fA-F]{6}$/',
        $brandPrimary
    )
) {
    $brandPrimary = '#dc2626';
}

if (
    !preg_match(
        '/^#[0-9a-fA-F]{6}$/',
        $brandSecondary
    )
) {
    $brandSecondary = '#7f1d1d';
}

if (
    !preg_match(
        '/^#[0-9a-fA-F]{6}$/',
        $brandAccent
    )
) {
    $brandAccent = '#f59e0b';
}

$systemTitle = trim(
    (string) (
        $ui_title_system
        ?? 'Ave Fénix'
    )
) ?: 'Ave Fénix';

$logoPath = trim(
    (string) (
        $ui_logo_login_path
        ?? 'assets/img/logo.png'
    )
);

$renewMessages = [];

foreach ($accounts as $index => $account) {
    $isProfile = (int) (
        $account['es_perfil']
        ?? 0
    ) === 1;

    $typeLabel = $isProfile
        ? 'Perfil/Pantalla'
        : 'Cuenta completa';

    $expiration = !empty(
        $account['fecha_vencimiento']
    )
        ? date(
            'd/m/Y',
            strtotime(
                (string) $account['fecha_vencimiento']
            )
        )
        : 'Sin fecha';

    $renewValues = [
        '{nombre_cliente}' => $userName,
        '{cliente}' => $userName,
        '{nombre}' => $userName,
        '{plataforma}' => (string) ($account['plataforma'] ?? 'Servicio'),
        '{servicio}' => $typeLabel,
        '{tipo_servicio}' => $typeLabel,
        '{correo}' => (string) ($account['correo'] ?? ''),
        '{cuenta}' => (string) ($account['correo'] ?? ''),
        '{email}' => (string) ($account['correo'] ?? ''),
        '{fecha_vencimiento}' => $expiration,
        '{fecha_renovacion}' => $expiration,
        '{vencimiento}' => $expiration,
        '{codigo_cliente}' => $consultationCode,
        '{id_cliente}' => $consultationCode,
        '{codigo_cuenta}' => (string) ($account['codigo_acceso_cuenta'] ?? ''),
        '{codigo_acceso}' => (string) ($account['codigo_acceso_cuenta'] ?? ''),
        '{id_cuenta}' => (string) ($account['codigo_acceso_cuenta'] ?? ''),
        '{nombre_perfil}' => (string) ($account['nombre_perfil'] ?? $typeLabel),
        '{perfil}' => (string) ($account['nombre_perfil'] ?? $typeLabel),
        '{pin_perfil}' => (string) ($account['pin_perfil'] ?? ''),
        '{link_login}' =>
            ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://')
            . ($_SERVER['HTTP_HOST'] ?? '')
            . '/login_consulta.php',
    ];

    $messageMode = match ((string) ($account['_status']['key'] ?? 'soon')) {
        'expired' => 'expired',
        'active' => 'active',
        default => 'renewal',
    };

    $renewMessages[$index] = af_user_professional_whatsapp(
        $renewTemplate,
        $renewValues,
        $systemTitle,
        $messageMode
    );
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">

    <meta
        name="viewport"
        content="width=device-width, initial-scale=1"
    >

    <meta
        name="theme-color"
        content="<?= af_user_e($brandPrimary) ?>"
    >

    <title>
        Mi panel | <?= af_user_e($systemTitle) ?>
    </title>

    <link
        rel="preconnect"
        href="https://fonts.googleapis.com"
    >

    <link
        rel="preconnect"
        href="https://fonts.gstatic.com"
        crossorigin
    >

    <link
        href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
        rel="stylesheet"
    >

    <link
        href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
        rel="stylesheet"
    >

    <link
        rel="stylesheet"
        href="assets/css/public-shared.css?v=2026.07.25-v16"
    >

    <script
        src="https://cdn.jsdelivr.net/npm/sweetalert2@11"
    ></script>

    <style>
        :root {
            --brand:
                <?= af_user_e($brandPrimary) ?>;

            --brand-dark:
                <?= af_user_e($brandSecondary) ?>;

            --public-red:
                <?= af_user_e($brandPrimary) ?>;

            --public-red-dark:
                <?= af_user_e($brandSecondary) ?>;

            --public-footer-height: 66px;

            --accent:
                <?= af_user_e($brandAccent) ?>;

            --ink: #0f172a;
            --muted: #64748b;
            --line: #e2e8f0;
            --soft: #f4f7fb;
            --surface: #ffffff;
            --success: #16a34a;
            --warning: #d97706;
            --danger: #dc2626;
            --blue: #2563eb;
        }

        * {
            box-sizing: border-box;
        }

        html {
            scroll-behavior: smooth;
        }

        body {
            margin: 0;
            min-height: 100vh;
            padding-bottom: var(--public-footer-height, 66px);
            font-family:
                Inter,
                system-ui,
                sans-serif;
            color: var(--ink);
            background:
                radial-gradient(
                    circle at 0 0,
                    color-mix(
                        in srgb,
                        var(--brand) 8%,
                        transparent
                    ),
                    transparent 28%
                ),
                radial-gradient(
                    circle at 100% 100%,
                    color-mix(
                        in srgb,
                        var(--accent) 8%,
                        transparent
                    ),
                    transparent 30%
                ),
                var(--soft);
        }

        button,
        input,
        select,
        textarea {
            font: inherit;
        }

        button,
        a {
            -webkit-tap-highlight-color:
                transparent;
        }

        .topbar {
            position: sticky;
            z-index: 100;
            top: 0;
            border-bottom:
                1px solid rgba(226,232,240,.9);
            background:
                rgba(255,255,255,.93);
            box-shadow:
                0 8px 30px rgba(15,23,42,.05);
            backdrop-filter:
                blur(15px);
        }

        .topbar-inner {
            width:
                min(
                    1450px,
                    calc(100% - 32px)
                );
            min-height: 76px;
            margin: 0 auto;
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 20px;
        }

        .brand {
            display: flex;
            align-items: center;
            gap: 12px;
            min-width: 0;
        }

        .brand-logo {
            width: 46px;
            height: 46px;
            display: grid;
            flex: 0 0 46px;
            place-items: center;
            overflow: hidden;
            border: 1px solid var(--line);
            border-radius: 15px;
            background: #fff;
            color: var(--brand);
            box-shadow:
                0 9px 20px rgba(15,23,42,.08);
        }

        .brand-logo img {
            width: 100%;
            height: 100%;
            padding: 4px;
            object-fit: contain;
        }

        .brand-title,
        .brand-subtitle {
            display: block;
        }

        .brand-title {
            font-size: 15px;
            font-weight: 900;
        }

        .brand-subtitle {
            margin-top: 3px;
            color: var(--muted);
            font-size: 9px;
            font-weight: 800;
            letter-spacing: .09em;
            text-transform: uppercase;
        }

        .topbar-actions {
            display: flex;
            align-items: center;
            gap: 9px;
        }

        .topbar-nav-link {
            min-height: 42px;
            display: inline-flex;
            align-items: center;
            gap: 8px;
            padding: 0 13px;
            border: 1px solid #dbe4ef;
            border-radius: 13px;
            background: #ffffff;
            color: #334155;
            text-decoration: none;
            font-size: 10.5px;
            font-weight: 900;
            white-space: nowrap;
            transition: .18s ease;
        }
        .topbar-nav-link i { color: var(--brand); }
        .topbar-nav-link:hover {
            transform: translateY(-2px);
            border-color: color-mix(in srgb, var(--brand) 35%, #dbe4ef);
            box-shadow: 0 9px 22px rgba(15,23,42,.08);
        }

        .topbar-user {
            min-width: 0;
            text-align: right;
        }

        .topbar-user strong,
        .topbar-user span {
            display: block;
        }

        .topbar-user strong {
            max-width: 220px;
            overflow: hidden;
            font-size: 12px;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .topbar-user span {
            margin-top: 2px;
            color: var(--muted);
            font-size: 9px;
            font-weight: 700;
        }

        .icon-button {
            width: 42px;
            height: 42px;
            display: grid;
            place-items: center;
            border: 1px solid var(--line);
            border-radius: 13px;
            background: #fff;
            color: var(--ink);
            text-decoration: none;
            transition: .2s ease;
        }

        .icon-button:hover {
            color: #fff;
            border-color: var(--brand);
            background: var(--brand);
            transform: translateY(-2px);
        }

        .page {
            width:
                min(
                    1450px,
                    calc(100% - 32px)
                );
            margin: 0 auto;
            padding: 28px 0 90px;
        }

        .hero {
            position: relative;
            isolation: isolate;
            display: grid;
            grid-template-columns:
                minmax(0, 1fr) auto;
            align-items: center;
            gap: 24px;
            padding: 32px;
            overflow: hidden;
            border-radius: 28px;
            color: #fff;
            background:
                radial-gradient(
                    circle at 88% 10%,
                    rgba(255,255,255,.18),
                    transparent 32%
                ),
                linear-gradient(
                    135deg,
                    var(--brand),
                    var(--brand-dark)
                );
            box-shadow:
                0 28px 65px
                color-mix(
                    in srgb,
                    var(--brand) 24%,
                    transparent
                );
        }

        .hero::after {
            content: "";
            position: absolute;
            z-index: -1;
            top: -120px;
            right: -90px;
            width: 330px;
            height: 330px;
            border:
                1px solid rgba(255,255,255,.16);
            border-radius: 50%;
            box-shadow:
                0 0 0 48px rgba(255,255,255,.05),
                0 0 0 95px rgba(255,255,255,.025);
        }

        .hero-eyebrow {
            color: #fee2e2;
            font-size: 10px;
            font-weight: 900;
            letter-spacing: .15em;
            text-transform: uppercase;
        }

        .hero h1 {
            max-width: 850px;
            margin: 10px 0 0;
            font-size:
                clamp(
                    29px,
                    4vw,
                    47px
                );
            line-height: 1.02;
            letter-spacing: -.045em;
        }

        .hero p {
            max-width: 760px;
            margin: 14px 0 0;
            color: #fee2e2;
            font-size: 14px;
            line-height: 1.7;
        }

        .hero-id {
            min-width: 195px;
            padding: 17px;
            border: 1px solid rgba(255,255,255,.16);
            border-radius: 19px;
            background: rgba(255,255,255,.10);
            backdrop-filter: blur(10px);
        }

        .hero-id small,
        .hero-id strong {
            display: block;
        }

        .hero-id small {
            color: #fee2e2;
            font-size: 9px;
            font-weight: 900;
            letter-spacing: .1em;
            text-transform: uppercase;
        }

        .hero-id strong {
            margin-top: 7px;
            font-family: monospace;
            font-size: 20px;
            letter-spacing: .08em;
        }

        .stats {
            display: grid;
            grid-template-columns:
                repeat(4, minmax(0, 1fr));
            gap: 15px;
            margin-top: 20px;
        }

        .stat {
            display: grid;
            grid-template-columns:
                52px 1fr;
            gap: 13px;
            align-items: center;
            padding: 17px;
            border: 1px solid var(--line);
            border-radius: 19px;
            background: #fff;
            box-shadow:
                0 12px 28px rgba(15,23,42,.05);
        }

        .stat-icon {
            width: 52px;
            height: 52px;
            display: grid;
            place-items: center;
            border-radius: 16px;
            background:
                color-mix(
                    in srgb,
                    var(--brand) 10%,
                    #fff
                );
            color: var(--brand);
            font-size: 19px;
        }

        .stat.is-green .stat-icon {
            color: var(--success);
            background: #ecfdf5;
        }

        .stat.is-orange .stat-icon {
            color: var(--warning);
            background: #fff7ed;
        }

        .stat.is-red .stat-icon {
            color: var(--danger);
            background: #fff1f2;
        }

        .stat small,
        .stat strong {
            display: block;
        }

        .stat small {
            color: var(--muted);
            font-size: 9px;
            font-weight: 850;
            letter-spacing: .08em;
            text-transform: uppercase;
        }

        .stat strong {
            margin-top: 4px;
            font-size: 25px;
            line-height: 1;
        }

        .communication {
            display: grid;
            grid-template-columns:
                minmax(0, 1fr) auto;
            align-items: center;
            gap: 22px;
            margin-top: 20px;
            padding: 24px;
            border:
                1px solid
                color-mix(
                    in srgb,
                    var(--blue) 17%,
                    var(--line)
                );
            border-radius: 23px;
            background:
                linear-gradient(
                    145deg,
                    #fff,
                    #f5f9ff
                );
            box-shadow:
                0 15px 35px rgba(15,23,42,.05);
        }

        .communication-main {
            display: grid;
            grid-template-columns:
                60px 1fr;
            gap: 16px;
            align-items: start;
        }

        .communication-icon {
            width: 60px;
            height: 60px;
            display: grid;
            place-items: center;
            border-radius: 18px;
            background:
                linear-gradient(
                    145deg,
                    #2563eb,
                    #1d4ed8
                );
            color: #fff;
            font-size: 23px;
            box-shadow:
                0 14px 28px rgba(37,99,235,.22);
        }

        .communication small {
            color: var(--blue);
            font-size: 9px;
            font-weight: 900;
            letter-spacing: .12em;
            text-transform: uppercase;
        }

        .communication h2 {
            margin: 5px 0 0;
            font-size: 20px;
        }

        .communication p {
            max-width: 900px;
            margin: 8px 0 0;
            color: var(--muted);
            font-size: 12px;
            line-height: 1.7;
            white-space: pre-line;
        }

        .communication-contact {
            margin-top: 10px;
            color: #334155;
            font-size: 10px;
            font-weight: 750;
        }

        .communication-actions {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-end;
            gap: 9px;
        }

        .button {
            min-height: 43px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            padding: 0 15px;
            border: 0;
            border-radius: 13px;
            cursor: pointer;
            font-size: 10px;
            font-weight: 900;
            letter-spacing: .035em;
            text-decoration: none;
            text-transform: uppercase;
            transition: .2s ease;
        }

        .button:hover {
            transform: translateY(-2px);
        }

        .button-primary {
            color: #fff;
            background:
                linear-gradient(
                    135deg,
                    var(--brand),
                    var(--brand-dark)
                );
            box-shadow:
                0 12px 25px
                color-mix(
                    in srgb,
                    var(--brand) 22%,
                    transparent
                );
        }

        .button-blue {
            color: #fff;
            background: var(--blue);
        }

        .button-green {
            color: #fff;
            background: #16a34a;
        }

        .button-light {
            border: 1px solid var(--line);
            color: #334155;
            background: #fff;
        }

        .panel {
            margin-top: 20px;
            overflow: hidden;
            border: 1px solid var(--line);
            border-radius: 24px;
            background: #fff;
            box-shadow:
                0 17px 40px rgba(15,23,42,.055);
        }

        .panel-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 18px;
            padding: 21px 22px;
            border-bottom: 1px solid #eef2f7;
        }

        .panel-title {
            display: flex;
            align-items: center;
            gap: 13px;
        }

        .panel-title-icon {
            width: 43px;
            height: 43px;
            display: grid;
            place-items: center;
            border-radius: 14px;
            color: var(--brand);
            background:
                color-mix(
                    in srgb,
                    var(--brand) 9%,
                    #fff
                );
        }

        .panel-title h2,
        .panel-title p {
            margin: 0;
        }

        .panel-title h2 {
            font-size: 18px;
        }

        .panel-title p {
            margin-top: 4px;
            color: var(--muted);
            font-size: 10px;
        }

        .toolbar {
            display: grid;
            grid-template-columns:
                minmax(190px, 1fr)
                minmax(240px, 1.3fr)
                auto;
            gap: 11px;
            padding: 17px 22px;
            border-bottom: 1px solid #eef2f7;
            background: #fbfcfe;
        }

        .field {
            position: relative;
        }

        .field i {
            position: absolute;
            top: 50%;
            left: 14px;
            color: #94a3b8;
            transform: translateY(-50%);
            pointer-events: none;
        }

        .field input,
        .field select {
            width: 100%;
            height: 44px;
            padding: 0 14px 0 39px;
            border: 1px solid #dbe4ef;
            border-radius: 13px;
            outline: none;
            color: #334155;
            background: #fff;
            font-size: 11px;
            font-weight: 750;
            transition: .18s ease;
        }

        .field input:focus,
        .field select:focus {
            border-color: var(--brand);
            box-shadow:
                0 0 0 4px
                color-mix(
                    in srgb,
                    var(--brand) 9%,
                    transparent
                );
        }

        .table-wrap {
            overflow-x: auto;
        }

        .services-table {
            width: 100%;
            min-width: 1050px;
            border-collapse: collapse;
        }

        .services-table th {
            padding: 13px 15px;
            color: #64748b;
            background: #f8fafc;
            font-size: 9px;
            font-weight: 900;
            letter-spacing: .075em;
            text-align: left;
            text-transform: uppercase;
        }

        .services-table td {
            padding: 14px 15px;
            border-top: 1px solid #eef2f7;
            color: #475569;
            font-size: 11px;
            vertical-align: middle;
        }

        .services-table tbody tr {
            transition: .18s ease;
        }

        .services-table tbody tr:hover {
            background: #fbfdff;
        }

        .service {
            display: flex;
            align-items: center;
            gap: 11px;
        }

        .service-logo {
            width: 43px;
            height: 43px;
            display: grid;
            flex: 0 0 43px;
            place-items: center;
            overflow: hidden;
            border: 1px solid var(--line);
            border-radius: 13px;
            color: var(--brand);
            background: #fff;
        }

        .service-logo img {
            width: 100%;
            height: 100%;
            padding: 4px;
            object-fit: contain;
        }

        .service strong,
        .service small {
            display: block;
        }

        .service strong {
            color: var(--ink);
            font-size: 12px;
        }

        .service small {
            margin-top: 4px;
            color: var(--muted);
            font-size: 8px;
            font-weight: 850;
            text-transform: uppercase;
        }

        .code {
            display: inline-block;
            padding: 7px 9px;
            border: 1px solid #dbe4ef;
            border-radius: 9px;
            color: #334155;
            background: #f8fafc;
            font-family: monospace;
            font-size: 11px;
            font-weight: 900;
            letter-spacing: .04em;
            user-select: all;
        }

        .status {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 7px 9px;
            border-radius: 999px;
            font-size: 8px;
            font-weight: 900;
            text-transform: uppercase;
        }

        .status::before {
            content: "";
            width: 6px;
            height: 6px;
            border-radius: 50%;
            background: currentColor;
        }

        .status-active {
            color: #15803d;
            background: #ecfdf5;
        }

        .status-soon {
            color: #b45309;
            background: #fff7ed;
        }

        .status-expired {
            color: #be123c;
            background: #fff1f2;
        }

        .status-without-date {
            color: #64748b;
            background: #f1f5f9;
        }

        .actions {
            display: flex;
            justify-content: flex-end;
            gap: 7px;
        }

        .action {
            width: 36px;
            height: 36px;
            display: grid;
            place-items: center;
            border: 1px solid var(--line);
            border-radius: 11px;
            cursor: pointer;
            color: #475569;
            background: #fff;
            text-decoration: none;
            transition: .18s ease;
        }

        .action:hover {
            color: #fff;
            border-color: var(--brand);
            background: var(--brand);
            transform: translateY(-2px);
        }

        .action.is-blue:hover {
            border-color: var(--blue);
            background: var(--blue);
        }

        .action.is-green:hover {
            border-color: #16a34a;
            background: #16a34a;
        }

        .action.is-amber:hover {
            border-color: #d97706;
            background: #d97706;
        }

        .account-dates {
            min-width: 132px;
        }

        .account-dates strong,
        .account-dates small {
            display: block;
        }

        .account-dates strong {
            color: #0f172a;
            white-space: nowrap;
        }

        .account-dates strong i {
            margin-right: 5px;
            color: var(--brand);
        }

        .account-dates small {
            margin-top: 4px;
            color: #64748b;
            font-size: 10px;
            white-space: nowrap;
        }

        .empty {
            padding: 65px 25px;
            text-align: center;
        }

        .empty i {
            color: #cbd5e1;
            font-size: 48px;
        }

        .empty strong,
        .empty span {
            display: block;
        }

        .empty strong {
            margin-top: 14px;
            font-size: 17px;
        }

        .empty span {
            max-width: 500px;
            margin: 7px auto 0;
            color: var(--muted);
            font-size: 11px;
            line-height: 1.6;
        }

        .panel-footer {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 15px;
            padding: 15px 22px;
            border-top: 1px solid #eef2f7;
            color: var(--muted);
            background: #fbfcfe;
            font-size: 10px;
            font-weight: 750;
        }

        .modal {
            position: fixed;
            z-index: 9999;
            inset: 0;
            display: none;
            align-items: center;
            justify-content: center;
            padding: 16px;
            background: rgba(2,6,23,.77);
            backdrop-filter: blur(7px);
        }

        .modal.is-open {
            display: flex;
        }

        .modal-box {
            width:
                min(
                    680px,
                    100%
                );
            max-height:
                calc(100vh - 30px);
            display: flex;
            flex-direction: column;
            overflow: hidden;
            border-radius: 25px;
            background: #fff;
            box-shadow:
                0 35px 90px rgba(2,6,23,.36);
        }

        .modal-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 14px;
            padding: 19px 21px;
            color: #fff;
            background:
                linear-gradient(
                    135deg,
                    var(--brand),
                    var(--brand-dark)
                );
        }

        .modal-title {
            display: flex;
            align-items: center;
            gap: 11px;
        }

        .modal-title i {
            width: 41px;
            height: 41px;
            display: grid;
            place-items: center;
            border-radius: 13px;
            background: rgba(255,255,255,.14);
        }

        .modal-title h3,
        .modal-title p {
            margin: 0;
        }

        .modal-title h3 {
            font-size: 16px;
        }

        .modal-title p {
            margin-top: 3px;
            color: #fee2e2;
            font-size: 9px;
        }

        .modal-close {
            width: 39px;
            height: 39px;
            display: grid;
            place-items: center;
            border: 0;
            border-radius: 12px;
            cursor: pointer;
            color: #fff;
            background: rgba(255,255,255,.12);
            font-size: 20px;
        }

        .modal-body {
            overflow-y: auto;
            padding: 21px;
        }

        .modal-body label {
            display: block;
            margin-bottom: 8px;
            color: #475569;
            font-size: 9px;
            font-weight: 900;
            letter-spacing: .08em;
            text-transform: uppercase;
        }

        .modal-body textarea {
            width: 100%;
            min-height: 240px;
            padding: 15px;
            resize: vertical;
            border: 1px solid #dbe4ef;
            border-radius: 15px;
            outline: none;
            color: #334155;
            background: #f8fafc;
            font-size: 12px;
            line-height: 1.65;
        }

        .modal-body textarea:focus {
            border-color: var(--brand);
            background: #fff;
        }

        .modal-footer {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-end;
            gap: 9px;
            padding: 16px 21px;
            border-top: 1px solid #eef2f7;
            background: #f8fafc;
        }

        .footer {
            padding: 18px 16px;
            border-top: 3px solid var(--brand);
            color: #cbd5e1;
            background: #08111f;
            text-align: center;
            font-size: 9px;
        }

        [hidden] {
            display: none !important;
        }

        /* V16: el dashboard usa exactamente el pie público compartido. */
        body.af-user-dashboard .public-footer {
            position: fixed !important;
            right: 0 !important;
            bottom: 0 !important;
            left: 0 !important;
            z-index: 1200 !important;
        }

        body.af-user-dashboard .public-footer-inner {
            width: min(1200px, calc(100% - 32px));
            margin: 0 auto;
        }

        @media (max-width: 760px) {
            body.af-user-dashboard { padding-bottom: 0; }
            body.af-user-dashboard .public-footer { position: relative !important; }
        }

        @media (max-width: 1050px) {
            .stats {
                grid-template-columns:
                    repeat(2, minmax(0, 1fr));
            }

            .communication {
                grid-template-columns: 1fr;
            }

            .communication-actions {
                justify-content: flex-start;
            }
        }

        @media (max-width: 760px) {
            .topbar-user {
                display: none;
            }

            .topbar-nav-link {
                width: 42px;
                min-width: 42px;
                padding: 0;
                justify-content: center;
            }
            .topbar-nav-link span { display: none; }

            .topbar-inner,
            .page {
                width:
                    min(
                        100% - 22px,
                        1450px
                    );
            }

            .hero {
                grid-template-columns: 1fr;
                padding: 25px;
            }

            .hero-id {
                min-width: 0;
            }

            .stats {
                grid-template-columns: 1fr 1fr;
                gap: 10px;
            }

            .stat {
                grid-template-columns:
                    42px 1fr;
                padding: 13px;
            }

            .stat-icon {
                width: 42px;
                height: 42px;
            }

            .communication {
                padding: 19px;
            }

            .communication-main {
                grid-template-columns:
                    48px 1fr;
            }

            .communication-icon {
                width: 48px;
                height: 48px;
                border-radius: 15px;
                font-size: 19px;
            }

            .toolbar {
                grid-template-columns: 1fr;
            }

            .panel-header {
                align-items: flex-start;
                flex-direction: column;
            }

            .panel-footer {
                align-items: flex-start;
                flex-direction: column;
            }

            .modal-footer .button {
                width: 100%;
            }
        }

        @media (max-width: 480px) {
            .stats {
                grid-template-columns: 1fr;
            }

            .brand-subtitle {
                display: none;
            }

            .communication-actions .button,
            .toolbar .button {
                width: 100%;
            }
        }
    </style>
</head>

<body class="af-user-dashboard">
<header class="topbar">
    <div class="topbar-inner">
        <a
            href="dashboard_usuario.php"
            class="brand"
            style="color:inherit;text-decoration:none"
        >
            <span class="brand-logo">
                <?php if ($logoPath !== ''): ?>
                    <img
                        src="<?= af_user_e($logoPath) ?>"
                        alt="<?= af_user_e($systemTitle) ?>"
                        onerror="this.style.display='none';this.nextElementSibling.style.display='block'"
                    >
                    <i
                        class="fas fa-fire-flame-curved"
                        style="display:none"
                    ></i>
                <?php else: ?>
                    <i class="fas fa-fire-flame-curved"></i>
                <?php endif; ?>
            </span>

            <span>
                <span class="brand-title">
                    <?= af_user_e($systemTitle) ?>
                </span>

                <span class="brand-subtitle">
                    Panel privado de servicios
                </span>
            </span>
        </a>

        <div class="topbar-actions">
            <a class="topbar-nav-link" href="consulta.php" title="Consultar códigos">
                <i class="fas fa-magnifying-glass"></i><span>Consultar</span>
            </a>
            <a class="topbar-nav-link" href="<?= af_user_e($manualUrl) ?>" title="Manual de uso">
                <i class="fas fa-book-open"></i><span>Manual de uso</span>
            </a>
            <div class="topbar-user">
                <strong>
                    <?= af_user_e($userName) ?>
                </strong>

                <span>
                    Sesión de usuario segura
                </span>
            </div>

            <a
                class="icon-button"
                href="index.php"
                title="Página principal"
                aria-label="Página principal"
            >
                <i class="fas fa-house"></i>
            </a>

            <a
                class="icon-button"
                href="logout.php"
                title="Cerrar sesión"
                aria-label="Cerrar sesión"
            >
                <i class="fas fa-arrow-right-from-bracket"></i>
            </a>
        </div>
    </div>
</header>

<main class="page">
    <section class="hero">
        <div>
            <div class="hero-eyebrow">
                Resumen de mi cuenta
            </div>

            <h1>
                Bienvenido, <?= af_user_e($userName) ?>
            </h1>

            <p>
                Revisa tus servicios asignados, consulta accesos,
                controla tus fechas de vencimiento y comunícate con
                tu administrador desde un solo lugar.
            </p>
        </div>

        <div class="hero-id">
            <small>ID general de consulta</small>

            <strong>
                <?= af_user_e(
                    $consultationCode !== ''
                        ? $consultationCode
                        : 'NO ASIGNADO'
                ) ?>
            </strong>
        </div>
    </section>

    <section class="stats">
        <article class="stat">
            <span class="stat-icon">
                <i class="fas fa-layer-group"></i>
            </span>

            <span>
                <small>Servicios asignados</small>
                <strong><?= count($accounts) ?></strong>
            </span>
        </article>

        <article class="stat is-green">
            <span class="stat-icon">
                <i class="fas fa-circle-check"></i>
            </span>

            <span>
                <small>Servicios activos</small>
                <strong><?= $activeCount ?></strong>
            </span>
        </article>

        <article class="stat is-orange">
            <span class="stat-icon">
                <i class="fas fa-clock"></i>
            </span>

            <span>
                <small>Próximos a vencer</small>
                <strong><?= $soonCount ?></strong>
            </span>
        </article>

        <article class="stat is-red">
            <span class="stat-icon">
                <i class="fas fa-triangle-exclamation"></i>
            </span>

            <span>
                <small>Servicios vencidos</small>
                <strong><?= $expiredCount ?></strong>
            </span>
        </article>
    </section>

    <section class="communication">
        <div class="communication-main">
            <span class="communication-icon">
                <i class="fas fa-message"></i>
            </span>

            <div>
                <small>Comunicación administrativa</small>

                <h2>
                    Centro de atención y renovaciones
                </h2>

                <p><?= nl2br(af_user_e($dashboardNotice)) ?></p>

                <div class="communication-contact">
                    <i class="fas fa-user-shield"></i>
                    <?= af_user_e($administratorName) ?>

                    <?php if ($administratorEmail !== ''): ?>
                        · <?= af_user_e($administratorEmail) ?>
                    <?php endif; ?>
                </div>
            </div>
        </div>

        <div class="communication-actions">
            <button
                type="button"
                class="button button-green"
                id="contactAdminButton"
            >
                <i class="fab fa-whatsapp"></i>
                Escribir al Admin
            </button>
        </div>
    </section>

    <section class="panel">
        <header class="panel-header">
            <div class="panel-title">
                <span class="panel-title-icon">
                    <i class="fas fa-tv"></i>
                </span>

                <div>
                    <h2>Mis servicios</h2>

                    <p>
                        Consulta, copia o solicita la renovación de
                        cada servicio asignado.
                    </p>
                </div>
            </div>

            <button
                type="button"
                class="button button-primary"
                id="prepareSelectedButton"
            >
                <i class="fas fa-clipboard-list"></i>
                Preparar seleccionados
            </button>
        </header>

        <div class="toolbar">
            <div class="field">
                <i class="fas fa-layer-group"></i>

                <select id="platformFilter">
                    <option value="">
                        Todas las plataformas
                    </option>

                    <?php foreach ($platforms as $platformId => $platformName): ?>
                        <option value="<?= (int) $platformId ?>">
                            <?= af_user_e($platformName) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="field">
                <i class="fas fa-magnifying-glass"></i>

                <input
                    type="search"
                    id="serviceSearch"
                    placeholder="Buscar plataforma, correo, ID o perfil..."
                >
            </div>

            <button
                type="button"
                class="button button-light"
                id="clearFiltersButton"
            >
                <i class="fas fa-rotate-left"></i>
                Limpiar
            </button>
        </div>

        <?php if (!$accounts): ?>
            <div class="empty">
                <i class="fas fa-box-open"></i>

                <strong>
                    Todavía no tienes servicios asignados
                </strong>

                <span>
                    Cuando tu administrador vincule una cuenta,
                    aparecerá automáticamente en esta sección.
                </span>
            </div>
        <?php else: ?>
            <div class="table-wrap">
                <table class="services-table">
                    <thead>
                        <tr>
                            <th style="width:45px">
                                <input
                                    type="checkbox"
                                    id="selectAllAccounts"
                                >
                            </th>

                            <th>Servicio</th>
                            <th>Correo vinculado</th>
                            <th>ID de acceso</th>
                            <th>Fechas</th>
                            <th>Estado</th>
                            <th style="text-align:right">
                                Opciones
                            </th>
                        </tr>
                    </thead>

                    <tbody id="servicesBody">
                    <?php foreach ($accounts as $index => $account): ?>
                        <?php
                        $isProfile = (int) (
                            $account['es_perfil']
                            ?? 0
                        ) === 1;

                        $typeLabel = $isProfile
                            ? 'Perfil/Pantalla'
                            : 'Cuenta completa';

                        $profileLabel = trim(
                            (string) (
                                $account['nombre_perfil']
                                ?? ''
                            )
                        );

                        if ($profileLabel === '') {
                            $profileLabel = $typeLabel;
                        }

                        $expiration = !empty(
                            $account['fecha_vencimiento']
                        )
                            ? date(
                                'd/m/Y',
                                strtotime(
                                    (string) $account['fecha_vencimiento']
                                )
                            )
                            : 'Sin fecha';

                        $registeredDate = !empty(
                            $account['fecha_registro_cuenta']
                        )
                            ? date(
                                'd/m/Y',
                                strtotime(
                                    (string) $account['fecha_registro_cuenta']
                                )
                            )
                            : 'Sin registro';

                        $status = $account['_status'];

                        $copyMessage =
                            "📺 Servicio: "
                            . (
                                $account['plataforma']
                                ?? 'Servicio'
                            )
                            . "\n"
                            . "🏷️ Tipo: "
                            . $typeLabel
                            . "\n"
                            . "📧 Correo: "
                            . (
                                $account['correo']
                                ?? ''
                            )
                            . "\n"
                            . "🔑 ID de acceso: "
                            . (
                                $account['codigo_acceso_cuenta']
                                ?? ''
                            )
                            . "\n"
                            . "📅 Renovación: "
                            . $expiration
                            . "\n"
                            . "🗓️ Cuenta registrada: "
                            . $registeredDate;

                        if (
                            $isProfile
                            && $profileLabel !== ''
                        ) {
                            $copyMessage .=
                                "\n👤 Perfil: "
                                . $profileLabel;
                        }

                        if (
                            $isProfile
                            && !empty($account['pin_perfil'])
                        ) {
                            $copyMessage .=
                                "\n🔐 PIN: "
                                . $account['pin_perfil'];
                        }

                        $searchText = af_user_lower(
                            implode(
                                ' ',
                                [
                                    $account['plataforma']
                                        ?? '',
                                    $account['correo']
                                        ?? '',
                                    $account['codigo_acceso_cuenta']
                                        ?? '',
                                    $profileLabel,
                                    $typeLabel,
                                ]
                            )
                        );
                        ?>

                        <tr
                            data-service-row
                            data-platform="<?= (int) (
                                $account['id_plataforma']
                                ?? 0
                            ) ?>"
                            data-search="<?= af_user_e($searchText) ?>"
                        >
                            <td>
                                <input
                                    type="checkbox"
                                    class="service-checkbox"
                                    data-summary="<?= af_user_e($copyMessage) ?>"
                                >
                            </td>

                            <td>
                                <div class="service">
                                    <span class="service-logo">
                                        <?php if (!empty($account['imagen_url'])): ?>
                                            <img
                                                src="<?= af_user_e($account['imagen_url']) ?>"
                                                alt="<?= af_user_e($account['plataforma']) ?>"
                                                onerror="this.style.display='none';this.nextElementSibling.style.display='block'"
                                            >

                                            <i
                                                class="fas fa-tv"
                                                style="display:none"
                                            ></i>
                                        <?php else: ?>
                                            <i class="fas fa-tv"></i>
                                        <?php endif; ?>
                                    </span>

                                    <span>
                                        <strong>
                                            <?= af_user_e(
                                                $account['plataforma']
                                                ?? 'Servicio'
                                            ) ?>
                                        </strong>

                                        <small>
                                            <?= af_user_e($typeLabel) ?>
                                        </small>

                                        <?php if (
                                            $isProfile
                                            && $profileLabel !== $typeLabel
                                        ): ?>
                                            <small>
                                                <?= af_user_e($profileLabel) ?>
                                            </small>
                                        <?php endif; ?>
                                    </span>
                                </div>
                            </td>

                            <td>
                                <?= af_user_e(
                                    $account['correo']
                                    ?? ''
                                ) ?>
                            </td>

                            <td>
                                <code class="code">
                                    <?= af_user_e(
                                        $account['codigo_acceso_cuenta']
                                        ?? 'SIN ID'
                                    ) ?>
                                </code>
                            </td>

                            <td>
                                <div class="account-dates">
                                    <strong>
                                        <i class="fas fa-calendar-check"></i>
                                        <?= af_user_e($expiration) ?>
                                    </strong>
                                    <small>
                                        Registrada:
                                        <?= af_user_e($registeredDate) ?>
                                    </small>
                                </div>
                            </td>

                            <td>
                                <span
                                    class="status status-<?= af_user_e($status['key']) ?>"
                                >
                                    <?= af_user_e($status['label']) ?>
                                </span>
                            </td>

                            <td>
                                <div class="actions">
                                    <button
                                        type="button"
                                        class="action copy-account-button"
                                        title="Copiar datos"
                                        data-message="<?= af_user_e($copyMessage) ?>"
                                    >
                                        <i class="fas fa-copy"></i>
                                    </button>

                                    <a
                                        class="action is-blue"
                                        target="_blank"
                                        rel="noopener noreferrer"
                                        href="consulta.php?plataforma=<?= (int) (
                                            $account['id_plataforma']
                                            ?? 0
                                        ) ?>&correo=<?= rawurlencode(
                                            (string) (
                                                $account['correo']
                                                ?? ''
                                            )
                                        ) ?>"
                                        title="Consultar acceso"
                                    >
                                        <i class="fas fa-eye"></i>
                                    </a>

                                    <button
                                        type="button"
                                        class="action is-amber regenerate-account-button"
                                        title="Regenerar ID de acceso"
                                        data-account-id="<?= (int) (
                                            $account['id_correo_servicio']
                                            ?? 0
                                        ) ?>"
                                    >
                                        <i class="fas fa-rotate"></i>
                                    </button>

                                    <button
                                        type="button"
                                        class="action is-green renew-account-button"
                                        title="Solicitar renovación"
                                        data-message="<?= af_user_e(
                                            $renewMessages[$index]
                                            ?? ''
                                        ) ?>"
                                    >
                                        <i class="fab fa-whatsapp"></i>
                                    </button>
                                </div>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        <?php endif; ?>

        <footer class="panel-footer">
            <span id="visibleCounter">
                <?= count($accounts) ?>
                servicio<?= count($accounts) === 1 ? '' : 's' ?>
                visible<?= count($accounts) === 1 ? '' : 's' ?>
            </span>

            <span>
                <i class="fas fa-shield-halved"></i>
                Solo puedes ver servicios vinculados a tu cuenta.
            </span>
        </footer>
    </section>
</main>

<div
    class="modal"
    id="messageModal"
    aria-hidden="true"
>
    <div
        class="modal-box"
        role="dialog"
        aria-modal="true"
        aria-labelledby="messageModalTitle"
    >
        <header class="modal-header">
            <div class="modal-title">
                <i class="fas fa-message"></i>

                <div>
                    <h3 id="messageModalTitle">
                        Mensaje
                    </h3>

                    <p>
                        Revisa el contenido antes de copiar o enviar.
                    </p>
                </div>
            </div>

            <button
                type="button"
                class="modal-close"
                id="closeMessageModal"
                aria-label="Cerrar"
            >
                &times;
            </button>
        </header>

        <div class="modal-body">
            <label for="messageComposer">
                Mensaje generado
            </label>

            <textarea
                id="messageComposer"
            ></textarea>
        </div>

        <footer class="modal-footer">
            <button
                type="button"
                class="button button-light"
                id="cancelMessageButton"
            >
                Cerrar
            </button>

            <button
                type="button"
                class="button button-blue"
                id="copyMessageButton"
            >
                <i class="fas fa-copy"></i>
                Copiar mensaje
            </button>

            <button
                type="button"
                class="button button-green"
                id="sendMessageButton"
            >
                <i class="fab fa-whatsapp"></i>
                Enviar WhatsApp
            </button>
        </footer>
    </div>
</div>

<?php
$afPublicContext = 'dashboard_usuario';
require __DIR__ . '/partials/public_footer.php';
?>

<script>
const AF_CSRF =
    <?= json_encode(
        Security::csrfToken(),
        JSON_UNESCAPED_UNICODE
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
    ) ?>;

const AF_ADMIN_PHONE =
    <?= json_encode(
        $administratorPhone,
        JSON_UNESCAPED_UNICODE
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
    ) ?>;

const AF_ADMIN_NAME =
    <?= json_encode(
        $administratorName,
        JSON_UNESCAPED_UNICODE
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
    ) ?>;

const AF_USER_NAME =
    <?= json_encode(
        $userName,
        JSON_UNESCAPED_UNICODE
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
    ) ?>;

const AF_CONTACT_MESSAGE =
    <?= json_encode(
        $contactMessage,
        JSON_UNESCAPED_UNICODE
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
    ) ?>;

const modal =
    document.getElementById('messageModal');

const composer =
    document.getElementById('messageComposer');

const modalTitle =
    document.getElementById('messageModalTitle');

function afToast(
    icon,
    title
) {
    Swal.fire({
        toast: true,
        position: 'top-end',
        icon: icon,
        title: title,
        showConfirmButton: false,
        timer: 1900,
        timerProgressBar: true
    });
}

async function afCopyText(
    text
) {
    text = String(text || '');

    if (!text.trim()) {
        Swal.fire({
            icon: 'warning',
            title: 'Mensaje vacío',
            text: 'No hay contenido para copiar.',
            confirmButtonColor:
                <?= json_encode($brandPrimary) ?>
        });

        return;
    }

    try {
        await navigator.clipboard.writeText(
            text
        );

        afToast(
            'success',
            'Contenido copiado'
        );
    } catch (error) {
        composer.value = text;

        openMessageModal(
            text,
            'Copia manualmente el mensaje'
        );

        composer.focus();
        composer.select();
    }
}

function openMessageModal(
    message,
    title
) {
    composer.value =
        String(message || '');

    modalTitle.textContent =
        title || 'Mensaje';

    modal.classList.add('is-open');

    modal.setAttribute(
        'aria-hidden',
        'false'
    );

    document.body.style.overflow =
        'hidden';
}

function closeMessageModal() {
    modal.classList.remove('is-open');

    modal.setAttribute(
        'aria-hidden',
        'true'
    );

    document.body.style.overflow =
        '';
}

function sendWhatsApp(
    text
) {
    text = String(text || '').trim();

    if (!text) {
        Swal.fire({
            icon: 'warning',
            title: 'Mensaje vacío',
            text: 'Escribe o genera un mensaje antes de enviarlo.',
            confirmButtonColor:
                <?= json_encode($brandPrimary) ?>
        });

        return;
    }

    const target = AF_ADMIN_PHONE
        ? 'https://wa.me/'
            + AF_ADMIN_PHONE
            + '?text='
            + encodeURIComponent(text)
        : 'https://wa.me/?text='
            + encodeURIComponent(text);

    window.open(
        target,
        '_blank',
        'noopener'
    );
}

function filterServices() {
    const query =
        String(
            document
                .getElementById('serviceSearch')
                ?.value || ''
        )
        .trim()
        .toLocaleLowerCase('es');

    const platform =
        String(
            document
                .getElementById('platformFilter')
                ?.value || ''
        );

    let visible = 0;

    document
        .querySelectorAll('[data-service-row]')
        .forEach(function (row) {
            const rowSearch =
                String(
                    row.dataset.search || ''
                );

            const rowPlatform =
                String(
                    row.dataset.platform || ''
                );

            const matchesSearch =
                !query
                || rowSearch.includes(query);

            const matchesPlatform =
                !platform
                || rowPlatform === platform;

            row.hidden =
                !(matchesSearch
                && matchesPlatform);

            if (!row.hidden) {
                visible++;
            }
        });

    const counter =
        document.getElementById(
            'visibleCounter'
        );

    if (counter) {
        counter.textContent =
            visible
            + ' servicio'
            + (visible === 1 ? '' : 's')
            + ' visible'
            + (visible === 1 ? '' : 's');
    }
}

document
    .getElementById('serviceSearch')
    ?.addEventListener(
        'input',
        filterServices
    );

document
    .getElementById('platformFilter')
    ?.addEventListener(
        'change',
        filterServices
    );

document
    .getElementById('clearFiltersButton')
    ?.addEventListener(
        'click',
        function () {
            const search =
                document.getElementById(
                    'serviceSearch'
                );

            const platform =
                document.getElementById(
                    'platformFilter'
                );

            if (search) {
                search.value = '';
            }

            if (platform) {
                platform.value = '';
            }

            filterServices();
        }
    );

document
    .getElementById('selectAllAccounts')
    ?.addEventListener(
        'change',
        function (event) {
            document
                .querySelectorAll(
                    '[data-service-row]:not([hidden]) .service-checkbox'
                )
                .forEach(function (checkbox) {
                    checkbox.checked =
                        event.currentTarget.checked;
                });
        }
    );

document
    .querySelectorAll(
        '.copy-account-button'
    )
    .forEach(function (button) {
        button.addEventListener(
            'click',
            function () {
                afCopyText(
                    button.dataset.message || ''
                );
            }
        );
    });

document
    .querySelectorAll(
        '.renew-account-button'
    )
    .forEach(function (button) {
        button.addEventListener(
            'click',
            function () {
                openMessageModal(
                    button.dataset.message || '',
                    'Mensaje de renovación listo'
                );
            }
        );
    });

document
    .querySelectorAll(
        '.regenerate-account-button'
    )
    .forEach(function (button) {
        button.addEventListener(
            'click',
            async function () {
                const accountId =
                    Number(
                        button.dataset.accountId
                        || 0
                    );

                if (!accountId) {
                    return;
                }

                const confirmation =
                    await Swal.fire({
                        icon: 'question',
                        title: '¿Regenerar ID de acceso?',
                        html:
                            'El ID actual dejará de funcionar y se creará uno nuevo para esta cuenta.',
                        showCancelButton: true,
                        confirmButtonText:
                            '<i class="fas fa-rotate"></i> Regenerar ID',
                        cancelButtonText:
                            'Cancelar',
                        confirmButtonColor:
                            <?= json_encode($brandPrimary) ?>
                    });

                if (!confirmation.isConfirmed) {
                    return;
                }

                button.disabled = true;

                try {
                    const body =
                        new URLSearchParams({
                            action:
                                'regenerate_assigned_account_id',
                            account_id:
                                String(accountId),
                            _csrf:
                                AF_CSRF
                        });

                    const response =
                        await fetch(
                            'dashboard_usuario.php',
                            {
                                method: 'POST',
                                headers: {
                                    'Content-Type':
                                        'application/x-www-form-urlencoded;charset=UTF-8',
                                    'X-Requested-With':
                                        'XMLHttpRequest'
                                },
                                body:
                                    body.toString()
                            }
                        );

                    let result = null;

                    try {
                        result =
                            await response.json();
                    } catch (error) {
                        throw new Error(
                            'El servidor devolvió una respuesta no válida.'
                        );
                    }

                    if (
                        !response.ok
                        || !result?.success
                    ) {
                        throw new Error(
                            result?.message
                            || 'No se pudo regenerar el ID.'
                        );
                    }

                    await Swal.fire({
                        icon: 'success',
                        title: 'ID regenerado',
                        html:
                            'Nuevo ID: <strong>'
                            + String(
                                result.codigo
                                || ''
                            )
                            + '</strong><br><small>El ID anterior ya no es válido.</small>',
                        confirmButtonColor:
                            <?= json_encode($brandPrimary) ?>
                    });

                    window.location.reload();
                } catch (error) {
                    button.disabled = false;

                    Swal.fire({
                        icon: 'error',
                        title: 'No se pudo regenerar',
                        text:
                            error?.message
                            || 'Inténtalo nuevamente.',
                        confirmButtonColor:
                            <?= json_encode($brandPrimary) ?>
                    });
                }
            }
        );
    });

document
    .getElementById('prepareSelectedButton')
    ?.addEventListener(
        'click',
        function () {
            const selected = [
                ...document.querySelectorAll(
                    '.service-checkbox:checked'
                )
            ];

            if (!selected.length) {
                Swal.fire({
                    icon: 'warning',
                    title: 'Selecciona servicios',
                    text: 'Marca una o más cuentas para preparar el mensaje.',
                    confirmButtonColor:
                        <?= json_encode($brandPrimary) ?>
                });

                return;
            }

            const list = selected
                .map(function (
                    checkbox,
                    index
                ) {
                    return (
                        '📌 Servicio '
                        + (index + 1)
                        + '\n'
                        + String(
                            checkbox.dataset.summary
                            || ''
                        )
                    );
                })
                .join(
                    '\n\n--------------------\n\n'
                );

            const message =
                'Hola '
                + AF_ADMIN_NAME
                + ', soy '
                + AF_USER_NAME
                + '.\n\n'
                + 'Necesito información o renovación para los siguientes servicios:\n\n'
                + list
                + '\n\nQuedo atento a tu respuesta.';

            openMessageModal(
                message,
                'Servicios seleccionados'
            );
        }
    );

document
    .getElementById('contactAdminButton')
    ?.addEventListener(
        'click',
        function () {
            openMessageModal(
                AF_CONTACT_MESSAGE,
                'Comunicarme con el administrador'
            );
        }
    );

document
    .getElementById('copyMessageButton')
    ?.addEventListener(
        'click',
        function () {
            afCopyText(
                composer.value
            );
        }
    );

document
    .getElementById('sendMessageButton')
    ?.addEventListener(
        'click',
        function () {
            sendWhatsApp(
                composer.value
            );
        }
    );

document
    .getElementById('closeMessageModal')
    ?.addEventListener(
        'click',
        closeMessageModal
    );

document
    .getElementById('cancelMessageButton')
    ?.addEventListener(
        'click',
        closeMessageModal
    );

modal?.addEventListener(
    'click',
    function (event) {
        if (event.target === modal) {
            closeMessageModal();
        }
    }
);

document.addEventListener(
    'keydown',
    function (event) {
        if (
            event.key === 'Escape'
            && modal?.classList.contains(
                'is-open'
            )
        ) {
            closeMessageModal();
        }
    }
);
</script>
</body>
</html>