<?php
// gestionar_clientes.php
// Este script gestiona la creación, edición y eliminación de clientes.

// Aseguramos que init.php se cargue primero
require_once __DIR__ . '/init.php';
require_once __DIR__ . '/../lib/ConsultationCodeService.php';
restringir_modulo_superadmin('Clientes y usuarios');

// Lógica para manejar acciones AJAX, POST y GET
if (isset($_REQUEST['action']) || isset($_GET['fetch_data'])) {
    
    if (!tiene_permiso('gestionar_propios_clientes')) {
        Security::json(['success' => false, 'message' => 'Acceso denegado.'], 403);
    }

    $id_admin_actual = (int) ($_SESSION['admin']['uid'] ?? 0);

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        Security::headers(true);
        Security::requireCsrf();
    }

    // --- ACCIÓN: OBTENER LISTA DE CUENTAS DEL CLIENTE (MODIFICADO ORDER BY) ---
    if (isset($_GET['action']) && $_GET['action'] === 'fetch_client_accounts') {
        Security::headers(true);
        $id_cliente = filter_input(INPUT_GET, 'id_cliente', FILTER_VALIDATE_INT);
        
        if ($id_cliente) {
            try {
                // Buscamos las cuentas asociadas a este cliente que pertenezcan a este admin
                // SE ASEGURA EL ORDEN ALFABÉTICO POR NOMBRE DE PLATAFORMA
                $stmt = $pdo->prepare("
                    SELECT 
                        p.nombre AS plataforma,
                        cs.correo,
                        cs.codigo_acceso_cuenta
                    FROM asociaciones a
                    JOIN correos_servicios cs ON a.id_correo_servicio = cs.id
                    JOIN plataformas p ON cs.id_plataforma = p.id
                    WHERE a.id_usuario = ? AND a.id_admin_propietario = ?
                    ORDER BY p.nombre ASC 
                ");
                $stmt->execute([$id_cliente, $id_admin_actual]);
                $cuentas = $stmt->fetchAll(PDO::FETCH_ASSOC);
                
                echo json_encode(['success' => true, 'cuentas' => $cuentas]);
            } catch (Throwable $e) {
                error_log('Error al consultar cuentas del cliente: ' . $e->getMessage());
                echo json_encode(['success' => false, 'message' => 'No se pudieron cargar las cuentas del cliente.']);
            }
        } else {
            echo json_encode(['success' => false, 'message' => 'ID inválido']);
        }
        exit;
    }
    // -----------------------------------------------------------------------

    if (isset($_POST['action']) && $_POST['action'] === 'regenerate_client_id') {
        $id_cliente = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if (!$id_cliente) {
            Security::json(['success' => false, 'message' => 'ID de cliente no válido.'], 422);
        }

        try {
            $roleStmt = $pdo->prepare("SELECT r.nombre_rol
                FROM usuarios u
                JOIN roles r ON r.id = u.id_rol
                WHERE u.id = ? AND u.id_admin_propietario = ?
                  AND r.nombre_rol IN ('Revendedor', 'Cliente Final')
                LIMIT 1");
            $roleStmt->execute([$id_cliente, $id_admin_actual]);
            $roleName = $roleStmt->fetchColumn();
            if (!$roleName) {
                throw new RuntimeException('Cliente no encontrado o sin permiso.');
            }

            $new_code = ConsultationCodeService::generate($pdo, (string) $roleName);
            $stmt_update = $pdo->prepare('UPDATE usuarios SET codigo_consulta = ? WHERE id = ? AND id_admin_propietario = ?');
            $stmt_update->execute([$new_code, $id_cliente, $id_admin_actual]);
            if ($stmt_update->rowCount() < 1) {
                throw new RuntimeException('No se pudo regenerar el ID o no tienes permiso.');
            }
            Security::json(['success' => true, 'message' => 'ID regenerado correctamente.', 'codigo' => $new_code]);
        } catch (Throwable $e) {
            error_log('Error al regenerar ID de cliente: ' . $e->getMessage());
            Security::json(['success' => false, 'message' => $e instanceof RuntimeException ? $e->getMessage() : 'No se pudo regenerar el ID.'], 422);
        }
    }

    if (isset($_POST['action']) && $_POST['action'] === 'delete_client') {
        Security::headers(true);
        $response = ['success' => false, 'message' => 'Error desconocido.'];
        $id_a_borrar = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id_a_borrar) {
            try {
                $stmt_check = $pdo->prepare("SELECT 1 FROM asociaciones WHERE id_usuario = ? AND id_admin_propietario = ? AND id_correo_servicio IS NOT NULL LIMIT 1");
                $stmt_check->execute([$id_a_borrar, $id_admin_actual]);
                if ($stmt_check->fetchColumn()) {
                    throw new Exception("No se puede eliminar. El cliente aún tiene cuentas asociadas.");
                }
                
                $pdo->beginTransaction();
                $pdo->prepare("DELETE FROM asociaciones WHERE id_usuario = ? AND id_admin_propietario = ? AND id_correo_servicio IS NULL")->execute([$id_a_borrar, $id_admin_actual]);

                $sql_delete_user = "DELETE FROM usuarios WHERE id = ? AND id_admin_propietario = ?";
                $stmt_delete = $pdo->prepare($sql_delete_user);
                $stmt_delete->execute([$id_a_borrar, $id_admin_actual]);

                if ($stmt_delete->rowCount() > 0) {
                    $pdo->commit();
                    $response = ['success' => true, 'message' => 'Cliente eliminado con éxito.'];
                } else {
                    throw new Exception("No se pudo eliminar el cliente o no tienes permiso.");
                }
            } catch (Throwable $e) {
                if ($pdo->inTransaction()) { $pdo->rollBack(); }
                error_log('Error al eliminar cliente: ' . $e->getMessage());
                $response['message'] = $e instanceof RuntimeException || $e instanceof Exception ? $e->getMessage() : 'No se pudo eliminar el cliente.';
            }
        } else { $response['message'] = 'ID de cliente no válido.'; }
        echo json_encode($response);
        exit;
    }


    if (isset($_POST['action']) && $_POST['action'] === 'delete_clients_bulk') {
        $rawIds = is_array($_POST['selected_clients'] ?? null) ? $_POST['selected_clients'] : [];
        $ids = array_values(array_unique(array_filter(array_map('intval', $rawIds), static fn(int $id): bool => $id > 0)));
        if (!$ids) {
            Security::json(['success' => false, 'message' => 'Selecciona al menos un cliente.'], 422);
        }
        if (count($ids) > 500) {
            Security::json(['success' => false, 'message' => 'Solo puedes eliminar hasta 500 clientes por operación.'], 422);
        }

        $deleted = 0;
        $skippedWithAccounts = 0;
        $skippedInvalid = 0;
        $pdo->beginTransaction();
        try {
            $ownerCheck = $pdo->prepare("SELECT u.id
                FROM usuarios u
                JOIN roles r ON r.id = u.id_rol
                WHERE u.id = ? AND u.id_admin_propietario = ?
                  AND r.nombre_rol IN ('Revendedor', 'Cliente Final')
                LIMIT 1");
            $accountCheck = $pdo->prepare("SELECT 1 FROM asociaciones
                WHERE id_usuario = ? AND id_admin_propietario = ?
                  AND id_correo_servicio IS NOT NULL LIMIT 1");
            $deleteLooseAssociations = $pdo->prepare("DELETE FROM asociaciones
                WHERE id_usuario = ? AND id_admin_propietario = ?
                  AND id_correo_servicio IS NULL");
            $deleteUser = $pdo->prepare("DELETE FROM usuarios
                WHERE id = ? AND id_admin_propietario = ?");

            foreach ($ids as $clientId) {
                $ownerCheck->execute([$clientId, $id_admin_actual]);
                if (!$ownerCheck->fetchColumn()) {
                    $skippedInvalid++;
                    continue;
                }

                $accountCheck->execute([$clientId, $id_admin_actual]);
                if ($accountCheck->fetchColumn()) {
                    $skippedWithAccounts++;
                    continue;
                }

                $deleteLooseAssociations->execute([$clientId, $id_admin_actual]);
                $deleteUser->execute([$clientId, $id_admin_actual]);
                $deleted += $deleteUser->rowCount();
            }

            $pdo->commit();
            $message = "Eliminados: {$deleted}.";
            if ($skippedWithAccounts > 0) $message .= " Omitidos por tener cuentas asociadas: {$skippedWithAccounts}.";
            if ($skippedInvalid > 0) $message .= " No válidos o sin permiso: {$skippedInvalid}.";
            Security::json(['success' => true, 'message' => $message, 'deleted' => $deleted, 'skipped' => $skippedWithAccounts + $skippedInvalid]);
        } catch (Throwable $e) {
            if ($pdo->inTransaction()) $pdo->rollBack();
            error_log('Error en eliminación masiva de clientes: ' . $e->getMessage());
            Security::json(['success' => false, 'message' => 'No se pudo completar la eliminación masiva.'], 500);
        }
    }

    if (isset($_GET['fetch_data'])) {
        Security::headers(true);
        $response = ['success' => false, 'data' => null];
        $id_a_buscar = filter_input(INPUT_GET, 'fetch_data', FILTER_VALIDATE_INT);
        if ($id_a_buscar) {
            $sql_fetch_user = "SELECT id, nombre_usuario, correo, telefono, id_rol FROM usuarios WHERE id = ? AND id_admin_propietario = ?";
            $stmt = $pdo->prepare($sql_fetch_user);
            $stmt->execute([$id_a_buscar, $id_admin_actual]);
            if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { $response = ['success' => true, 'data' => $data]; }
            else { $response['message'] = 'Cliente no encontrado o no tienes permiso para verlo.'; }
        }
        echo json_encode($response);
        exit;
    }

    if (isset($_POST['action']) && $_POST['action'] === 'guardar_cliente') {
        Security::headers(true);
        $response = ['success' => false, 'message' => 'Datos incompletos.'];
        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $nombre_usuario = trim($_POST['nombre_usuario'] ?? '');
        $correo = filter_input(INPUT_POST, 'correo', FILTER_VALIDATE_EMAIL);
        $telefono = trim($_POST['telefono'] ?? '');
        $id_rol = filter_input(INPUT_POST, 'id_rol', FILTER_VALIDATE_INT);
        
        if (empty($nombre_usuario) || empty($correo) || empty($id_rol)) {
            $response['message'] = "Nombre, Correo y Rol son obligatorios.";
        } else {
            try {
                $roleCheck = $pdo->prepare("SELECT nombre_rol FROM roles WHERE id = ? AND nombre_rol IN ('Revendedor', 'Cliente Final') LIMIT 1");
                $roleCheck->execute([$id_rol]);
                $selectedRoleName = $roleCheck->fetchColumn();
                if (!$selectedRoleName) {
                    throw new InvalidArgumentException('El rol seleccionado no está permitido para un cliente.');
                }
                if ($id) {
                    $currentStmt = $pdo->prepare("SELECT u.codigo_consulta, r.nombre_rol
                        FROM usuarios u
                        JOIN roles r ON r.id = u.id_rol
                        WHERE u.id = ? AND u.id_admin_propietario = ?
                        LIMIT 1");
                    $currentStmt->execute([$id, $id_admin_actual]);
                    $currentUser = $currentStmt->fetch(PDO::FETCH_ASSOC);
                    if (!$currentUser) {
                        throw new RuntimeException('Cliente no encontrado o sin permiso.');
                    }

                    $codigoConsulta = (string) ($currentUser['codigo_consulta'] ?? '');
                    $codeRegenerated = !ConsultationCodeService::matchesRole($codigoConsulta, (string) $selectedRoleName);
                    if ($codeRegenerated) {
                        $codigoConsulta = ConsultationCodeService::generate($pdo, (string) $selectedRoleName);
                    }

                    $sql_update_user = "UPDATE usuarios SET nombre_usuario = ?, correo = ?, telefono = ?, id_rol = ?, codigo_consulta = ? WHERE id = ? AND id_admin_propietario = ?";
                    $stmt = $pdo->prepare($sql_update_user);
                    $stmt->execute([$nombre_usuario, $correo, $telefono !== '' ? $telefono : null, $id_rol, $codigoConsulta, $id, $id_admin_actual]);
                    $message = $codeRegenerated
                        ? 'Cliente actualizado. Su nuevo ID de consulta es ' . $codigoConsulta . '.'
                        : 'Cliente actualizado con éxito.';
                    $response = ['success' => true, 'message' => $message, 'codigo' => $codigoConsulta];
                } else {
                    $codigo_consulta = ConsultationCodeService::generate($pdo, (string) $selectedRoleName);
                    $clave_temporal = bin2hex(random_bytes(8));
                    $clave_por_defecto = password_hash($clave_temporal, PASSWORD_DEFAULT);
                    
                    $stmt = $pdo->prepare("INSERT INTO usuarios (nombre_usuario, correo, clave, id_rol, telefono, codigo_consulta, id_admin_propietario) VALUES (?, ?, ?, ?, ?, ?, ?)");
                    $stmt->execute([$nombre_usuario, $correo, $clave_por_defecto, $id_rol, $telefono !== '' ? $telefono : null, $codigo_consulta, $id_admin_actual]);
                    $response = ['success' => true, 'message' => 'Cliente guardado con éxito. ID asignado: ' . $codigo_consulta . '.', 'codigo' => $codigo_consulta];
                }
            } catch (Throwable $e) {
                if ($e instanceof PDOException && $e->getCode() == '23000') {
                    $response['message'] = 'Error: El correo electrónico ya está en uso.';
                } elseif ($e instanceof InvalidArgumentException) {
                    $response['message'] = $e->getMessage();
                } else {
                    error_log('Error al guardar cliente: ' . $e->getMessage());
                    $response['message'] = 'No se pudo guardar el cliente.';
                }
            }
        }
        echo json_encode($response);
        exit;
    }
}

$titulo_pagina = 'Gestionar Clientes'; 
$current_page = basename($_SERVER['PHP_SELF']);
$nombre_usuario_logueado = $_SESSION['admin']['nombre_usuario'] ?? 'Usuario';
$id_admin_actual = (int) ($_SESSION['admin']['uid'] ?? 0);
$sql_clientes = "SELECT u.*, r.nombre_rol FROM usuarios u LEFT JOIN roles r ON u.id_rol = r.id WHERE u.id_admin_propietario = ? AND u.id_rol IN (SELECT id FROM roles WHERE nombre_rol IN ('Revendedor', 'Cliente Final')) ORDER BY u.nombre_usuario ASC";
$stmt_clientes = $pdo->prepare($sql_clientes);
$stmt_clientes->execute([$id_admin_actual]);
$clientes = $stmt_clientes->fetchAll(PDO::FETCH_ASSOC);
$roles_para_clientes = $pdo->query("SELECT id, nombre_rol FROM roles WHERE nombre_rol IN ('Revendedor', 'Cliente Final') ORDER BY nombre_rol")->fetchAll(PDO::FETCH_ASSOC);
$totalRevendedores = count(array_filter($clientes, static fn(array $row): bool => ($row['nombre_rol'] ?? '') === 'Revendedor'));
$totalFinales = count(array_filter($clientes, static fn(array $row): bool => ($row['nombre_rol'] ?? '') === 'Cliente Final'));
$totalConTelefono = count(array_filter($clientes, static fn(array $row): bool => trim((string) ($row['telefono'] ?? '')) !== ''));
require_once 'admin_header.php';
?>
<div class="af-page">
    <header class="af-heading">
        <div class="af-heading-main"><span class="af-heading-icon"><i class="fas fa-users"></i></span><div><p class="af-eyebrow">Clientes y revendedores</p><h1>Clientes</h1><p>Registra usuarios, entrega su ID de consulta y envía sus cuentas de acceso sin salir del módulo.</p></div></div>
        <div class="af-heading-actions"><button type="button" id="openClientModal" class="af-btn af-btn-primary"><i class="fas fa-user-plus"></i> Nuevo cliente</button></div>
    </header>
    <section class="af-stats">
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-users"></i></span><div><p class="af-stat-label">Total clientes</p><p class="af-stat-value"><?= number_format(count($clientes)) ?></p><div class="af-stat-note">Usuarios administrados</div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-shop"></i></span><div><p class="af-stat-label">Revendedores</p><p class="af-stat-value"><?= number_format($totalRevendedores) ?></p><div class="af-stat-note">Con acceso de reventa</div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-user"></i></span><div><p class="af-stat-label">Clientes finales</p><p class="af-stat-value"><?= number_format($totalFinales) ?></p><div class="af-stat-note">Consulta individual</div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fab fa-whatsapp"></i></span><div><p class="af-stat-label">Con WhatsApp</p><p class="af-stat-value"><?= number_format($totalConTelefono) ?></p><div class="af-stat-note">Listos para contactar</div></div></article>
    </section>
    <section class="af-panel">
        <div class="af-panel-head"><div class="af-panel-title"><span class="af-panel-title-icon"><i class="fas fa-address-book"></i></span><div><h2>Registros de clientes</h2><p>Busca, filtra el rol y administra los accesos de cada usuario.</p></div></div></div>
        <div class="af-toolbar">
            <div class="af-field"><label class="af-label" for="clientSearch"><i class="fas fa-search"></i> Buscar</label><input id="clientSearch" type="search" class="af-control" placeholder="Nombre, correo, teléfono o ID"></div>
            <div class="af-field"><label class="af-label" for="clientRoleFilter"><i class="fas fa-user-tag"></i> Rol</label><select id="clientRoleFilter" class="af-control"><option value="">Todos</option><option value="Revendedor">Revendedor</option><option value="Cliente Final">Cliente final</option></select></div>
            <div class="af-field"><label class="af-label" for="clientWhatsappFilter"><i class="fab fa-whatsapp"></i> WhatsApp</label><select id="clientWhatsappFilter" class="af-control"><option value="">Todos</option><option value="with">Con WhatsApp</option><option value="without">Sin WhatsApp</option></select></div>
            <div class="af-field"><label class="af-label" for="clientPerPage"><i class="fas fa-list-ol"></i> Mostrar</label><select id="clientPerPage" class="af-control"><option value="100">100 registros</option><option value="200">200 registros</option><option value="400">400 registros</option><option value="all">Todos</option></select></div>
            <div class="af-toolbar-actions"><button type="button" id="clearClientFilters" class="af-btn af-btn-secondary"><i class="fas fa-eraser"></i> Limpiar</button></div>
        </div>
        <div class="af-bulk-bar"><div class="af-bulk-controls"><button type="button" id="deleteSelectedClients" class="af-btn af-btn-danger" disabled><i class="fas fa-trash"></i> Eliminar seleccionados</button><span id="selectedClientCount" class="af-selected-counter">0 seleccionados</span></div><span class="af-pagination-summary">Solo se eliminarán clientes sin cuentas asociadas.</span></div>
        <div class="af-list-meta"><span><?= number_format(count($clientes)) ?> clientes registrados</span><span id="clientPageSummary"></span></div>
        <div class="af-table-wrap"><table id="clientTable" class="af-table"><thead><tr><th class="af-text-center"><input type="checkbox" id="selectAllClients" aria-label="Seleccionar clientes visibles"></th><th>Cliente</th><th>Teléfono</th><th>Rol</th><th>ID de consulta</th><th class="af-text-center">Acciones</th></tr></thead><tbody>
        <?php foreach ($clientes as $client): $hasWhatsapp = trim((string) ($client['telefono'] ?? '')) !== ''; ?>
            <tr data-af-row data-role="<?= htmlspecialchars((string) ($client['nombre_rol'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" data-whatsapp="<?= $hasWhatsapp ? 'with' : 'without' ?>" data-search="<?= htmlspecialchars(($client['nombre_usuario'] ?? '') . ' ' . ($client['correo'] ?? '') . ' ' . ($client['telefono'] ?? '') . ' ' . ($client['codigo_consulta'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
                <td class="af-text-center"><input type="checkbox" class="js-client-check" value="<?= (int) $client['id'] ?>" aria-label="Seleccionar <?= htmlspecialchars((string) $client['nombre_usuario'], ENT_QUOTES, 'UTF-8') ?>"></td>
                <td><span class="af-row-title"><?= htmlspecialchars((string) $client['nombre_usuario']) ?></span><span class="af-row-sub"><?= htmlspecialchars((string) $client['correo']) ?></span></td>
                <td><?= htmlspecialchars((string) ($client['telefono'] ?: '—')) ?></td>
                <td><span class="af-badge <?= ($client['nombre_rol'] ?? '') === 'Revendedor' ? 'af-badge-warning' : 'af-badge-neutral' ?>"><?= htmlspecialchars((string) ($client['nombre_rol'] ?? 'Sin rol')) ?></span></td>
                <td><span class="af-code"><?= htmlspecialchars((string) ($client['codigo_consulta'] ?? '—')) ?> <button type="button" class="js-copy-client-code" data-code="<?= htmlspecialchars((string) ($client['codigo_consulta'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" title="Copiar"><i class="fas fa-copy"></i></button></span></td>
                <td><div class="af-actions af-actions-center"><button type="button" class="af-btn af-btn-icon af-action-edit js-edit-client" data-id="<?= (int) $client['id'] ?>" title="Editar"><i class="fas fa-pen"></i></button><button type="button" class="af-btn af-btn-icon af-action-whatsapp js-send-client-id" data-phone="<?= htmlspecialchars((string) ($client['telefono'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" data-name="<?= htmlspecialchars((string) $client['nombre_usuario'], ENT_QUOTES, 'UTF-8') ?>" data-code="<?= htmlspecialchars((string) ($client['codigo_consulta'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" title="Notificar ID por WhatsApp"><i class="fab fa-whatsapp"></i></button><button type="button" class="af-btn af-btn-icon af-action-list js-send-client-accounts" data-id="<?= (int) $client['id'] ?>" data-phone="<?= htmlspecialchars((string) ($client['telefono'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" data-name="<?= htmlspecialchars((string) $client['nombre_usuario'], ENT_QUOTES, 'UTF-8') ?>" title="Generar lista de accesos"><i class="fas fa-rectangle-list"></i></button><button type="button" class="af-btn af-btn-icon af-action-renew js-regenerate-client" data-id="<?= (int) $client['id'] ?>" title="Regenerar ID"><i class="fas fa-rotate"></i></button><button type="button" class="af-btn af-btn-icon af-action-delete js-delete-client" data-id="<?= (int) $client['id'] ?>" data-name="<?= htmlspecialchars((string) $client['nombre_usuario'], ENT_QUOTES, 'UTF-8') ?>" title="Eliminar"><i class="fas fa-trash"></i></button></div></td>
            </tr>
        <?php endforeach; ?>
        </tbody></table><div id="clientEmpty" class="af-empty" hidden><i class="fas fa-users"></i><strong>No se encontraron clientes</strong><div>Modifica los filtros o registra un cliente nuevo.</div></div></div>
        <div class="af-pagination-bar"><span class="af-pagination-summary">Los ID de consulta pueden regenerarse cuando sea necesario.</span><div id="clientPagination" class="af-pagination"></div></div>
    </section>
</div>

<div id="clientModal" class="af-modal-backdrop" aria-hidden="true"><section class="af-modal af-modal-sm" role="dialog" aria-modal="true" aria-labelledby="clientModalTitle"><header class="af-modal-head"><div class="af-modal-title"><span class="af-modal-icon"><i class="fas fa-user-plus"></i></span><div><h2 id="clientModalTitle">Nuevo cliente</h2><p id="clientModalDescription">Registra los datos que utilizarás para identificarlo y contactarlo.</p></div></div><button type="button" class="af-modal-close" data-af-close><i class="fas fa-xmark"></i></button></header><form id="clientForm"><?= Security::csrfField() ?><input type="hidden" name="action" value="guardar_cliente"><input type="hidden" name="id" id="clientId"><div class="af-modal-body"><div class="af-guide"><i class="fas fa-circle-info"></i><div>El sistema generará automáticamente un ID de consulta para los clientes nuevos. El rol define si tendrá acceso como Revendedor o Cliente Final.</div></div><div class="af-form-grid"><div class="full"><label class="af-label" for="clientName"><i class="fas fa-user"></i> Nombre *</label><input id="clientName" name="nombre_usuario" class="af-control" required maxlength="160" placeholder="Nombre del cliente"><span class="af-help">Usa un nombre reconocible para buscarlo rápidamente.</span></div><div class="full"><label class="af-label" for="clientEmail"><i class="fas fa-envelope"></i> Correo *</label><input id="clientEmail" name="correo" type="email" class="af-control" required placeholder="cliente@correo.com"><span class="af-help">Debe ser válido y no estar registrado por otro usuario.</span></div><div><label class="af-label" for="clientPhone"><i class="fab fa-whatsapp"></i> Teléfono <span class="af-optional">Opcional</span></label><input id="clientPhone" name="telefono" class="af-control" maxlength="20" inputmode="tel" placeholder="51999999999"><span class="af-help">Agrégalo solo cuando quieras enviar avisos por WhatsApp. Incluye el código de país.</span></div><div><label class="af-label" for="clientRole"><i class="fas fa-user-tag"></i> Rol *</label><select id="clientRole" name="id_rol" class="af-control" required><?php foreach ($roles_para_clientes as $clientRole): ?><option value="<?= (int) $clientRole['id'] ?>"><?= htmlspecialchars((string) $clientRole['nombre_rol']) ?></option><?php endforeach; ?></select><span class="af-help">Selecciona Revendedor o Cliente Final.</span></div></div></div><footer class="af-modal-footer"><button type="button" class="af-btn af-btn-secondary" data-af-close>Cancelar</button><button type="submit" class="af-btn af-btn-primary"><i class="fas fa-floppy-disk"></i> Guardar cliente</button></footer></form></section></div>

<script>
document.addEventListener('DOMContentLoaded',()=>{
 const list=new AfenixAdmin.UnifiedList({table:'#clientTable',search:'#clientSearch',perPage:'#clientPerPage',filters:[{selector:'#clientRoleFilter',data:'role'},{selector:'#clientWhatsappFilter',data:'whatsapp'}],summary:'#clientPageSummary',pagination:'#clientPagination',empty:'#clientEmpty'});
 document.getElementById('clearClientFilters').addEventListener('click',()=>{document.getElementById('clientSearch').value='';document.getElementById('clientRoleFilter').value='';document.getElementById('clientWhatsappFilter').value='';document.getElementById('clientPerPage').value='100';list.currentPage=1;list.render();});
 const modal=new AfenixAdmin.ModalController('#clientModal'); const form=document.getElementById('clientForm'); const csrf=<?= json_encode(Security::csrfToken()) ?>;
 const selectAllClients=document.getElementById('selectAllClients');
 const deleteSelectedClients=document.getElementById('deleteSelectedClients');
 const selectedClientCount=document.getElementById('selectedClientCount');
 const selectedClientIds=()=>[...document.querySelectorAll('.js-client-check:checked')].map(check=>check.value);
 function updateClientSelection(){const count=selectedClientIds().length;const visibleChecks=[...document.querySelectorAll('#clientTable tbody tr[data-af-row]:not([hidden]) .js-client-check')];const visibleSelected=visibleChecks.filter(check=>check.checked).length;selectedClientCount.textContent=`${count} seleccionado${count===1?'':'s'}`;deleteSelectedClients.disabled=count===0;selectAllClients.checked=visibleChecks.length>0&&visibleSelected===visibleChecks.length;selectAllClients.indeterminate=visibleSelected>0&&visibleSelected<visibleChecks.length;}
 selectAllClients.addEventListener('change',function(){document.querySelectorAll('#clientTable tbody tr[data-af-row]:not([hidden]) .js-client-check').forEach(check=>{check.checked=this.checked;});updateClientSelection();});
 document.getElementById('clientTable').addEventListener('change',event=>{if(event.target.matches('.js-client-check'))updateClientSelection();});
 document.getElementById('clientTable').addEventListener('af:list-rendered',updateClientSelection);
 deleteSelectedClients.addEventListener('click',async()=>{const ids=selectedClientIds();if(!ids.length)return;const confirm=await Swal.fire({title:`¿Eliminar ${ids.length} cliente${ids.length===1?'':'s'}?`,text:'Los clientes con cuentas asociadas serán omitidos para proteger la información.',icon:'warning',showCancelButton:true,confirmButtonText:'Eliminar seleccionados',cancelButtonText:'Cancelar',confirmButtonColor:'#dc2626'});if(!confirm.isConfirmed)return;try{const body=new URLSearchParams({action:'delete_clients_bulk',_csrf:csrf});ids.forEach(id=>body.append('selected_clients[]',id));const result=await AfenixAdmin.request('gestionar_clientes.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded','X-Requested-With':'XMLHttpRequest'},body});await Swal.fire('Proceso completado',result.message,'success');location.reload();}catch(e){Swal.fire('Error',e.message,'error');}});
 function resetForm(data=null){form.reset();document.getElementById('clientId').value='';document.getElementById('clientModalTitle').textContent=data?'Editar cliente':'Nuevo cliente';document.getElementById('clientModalDescription').textContent=data?'Actualiza solo la información necesaria.':'Registra los datos que utilizarás para identificarlo y contactarlo.';if(!data)return;document.getElementById('clientId').value=data.id;document.getElementById('clientName').value=data.nombre_usuario||'';document.getElementById('clientEmail').value=data.correo||'';document.getElementById('clientPhone').value=data.telefono||'';document.getElementById('clientRole').value=data.id_rol||'';}
 const escapeClientPreview=(value)=>String(value??'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#039;');
 const formatClientWhatsapp=(message)=>escapeClientPreview(message).replace(/\*([^*\n]+)\*/g,'<strong>$1</strong>').replace(/\n/g,'<br>');
 async function showClientWhatsappMessage({title,message,phone}){
  const cleanPhone=String(phone||'').replace(/\D/g,'');
  const result=await Swal.fire({
   title,
   html:`<div style="text-align:left">
     ${cleanPhone?'':`<div style="margin-bottom:12px;padding:10px 12px;border:1px solid #fde68a;border-radius:10px;background:#fffbeb;color:#92400e"><i class="fas fa-triangle-exclamation"></i> Este usuario no tiene teléfono. Puedes copiar el mensaje.</div>`}
     <div style="max-height:380px;overflow:auto;padding:16px;border:1px solid #dbe4ee;border-radius:12px;background:#f8fafc;color:#1e293b;line-height:1.65">${formatClientWhatsapp(message)}</div>
   </div>`,
   icon:'info',
   allowEscapeKey:true,
   stopKeydownPropagation:false,
   showCancelButton:true,
   showDenyButton:true,
   showConfirmButton:Boolean(cleanPhone),
   confirmButtonText:'<i class="fab fa-whatsapp"></i> Abrir WhatsApp',
   denyButtonText:'<i class="fas fa-copy"></i> Copiar mensaje',
   cancelButtonText:'Cancelar',
   confirmButtonColor:'#16a34a',
   denyButtonColor:'#475569',
   reverseButtons:true,
   width:620
  });
  if(result.isDenied){
   await AfenixAdmin.copy(message);
   await Swal.fire({toast:true,position:'top-end',icon:'success',title:'Mensaje copiado',showConfirmButton:false,timer:1600});
  }else if(result.isConfirmed&&cleanPhone){
   window.open(`https://wa.me/${cleanPhone}?text=${encodeURIComponent(message)}`,'_blank','noopener');
  }
 }
 document.getElementById('openClientModal').addEventListener('click',function(){resetForm();modal.open(this);});
 document.getElementById('clientTable').addEventListener('click',async(event)=>{
  const copy=event.target.closest('.js-copy-client-code');if(copy){await AfenixAdmin.copy(copy.dataset.code);Swal.fire({toast:true,position:'top-end',icon:'success',title:'ID copiado',showConfirmButton:false,timer:1400});return;}
  const edit=event.target.closest('.js-edit-client');if(edit){try{const result=await AfenixAdmin.request(`gestionar_clientes.php?fetch_data=${encodeURIComponent(edit.dataset.id)}`);resetForm(result.data);modal.open(edit);}catch(e){Swal.fire('Error',e.message,'error');}return;}
  const sendId=event.target.closest('.js-send-client-id');if(sendId){const login=new URL('../login_consulta.php',window.location.href).href;const message=`👋 Hola *${sendId.dataset.name}*, aquí tienes tu acceso de consulta.\n\n🪪 *ID de consulta:* ${sendId.dataset.code||'No disponible'}\n🌐 *Ingresa aquí:*\n${login}\n\n🔐 Guarda este ID y evita compartirlo con personas no autorizadas.\n✅ Cuando necesites consultar un código, abre el enlace e ingresa tu ID.`;await showClientWhatsappMessage({title:'Notificación de acceso',message,phone:sendId.dataset.phone});return;}
  const accounts=event.target.closest('.js-send-client-accounts');if(accounts){try{Swal.fire({title:'Preparando lista de accesos...',allowOutsideClick:false,didOpen:()=>Swal.showLoading()});const result=await AfenixAdmin.request(`gestionar_clientes.php?action=fetch_client_accounts&id_cliente=${encodeURIComponent(accounts.dataset.id)}`);if(!result.cuentas?.length){Swal.fire('Sin cuentas','Este cliente todavía no tiene cuentas asignadas.','info');return;}const login=new URL('../login_consulta.php',window.location.href).href;let message=`👋 Hola *${accounts.dataset.name}*, aquí tienes la lista actualizada de tus accesos:\n\n`;result.cuentas.forEach((row,index)=>{message+=`${index+1}. 📺 *Plataforma:* ${row.plataforma||'Sin plataforma'}\n📧 *Correo:* ${row.correo||'No disponible'}\n🔑 *ID de cuenta:* ${row.codigo_acceso_cuenta||'No disponible'}\n\n`;});message+=`🌐 *Ingresa con estos códigos en:*\n${login}\n\n🔐 Conserva esta información en un lugar seguro.\n✅ Cuando necesites un código, abre el enlace y utiliza el ID correspondiente.`;Swal.close();await showClientWhatsappMessage({title:'Lista de accesos del usuario',message,phone:accounts.dataset.phone});}catch(e){Swal.fire('Error',e.message,'error');}return;}
  const regenerate=event.target.closest('.js-regenerate-client');if(regenerate){const confirm=await Swal.fire({title:'¿Regenerar ID?',text:'El ID actual dejará de funcionar y deberás entregar el nuevo al cliente.',icon:'question',showCancelButton:true,confirmButtonText:'Sí, regenerar',cancelButtonText:'Cancelar'});if(!confirm.isConfirmed)return;try{const body=new URLSearchParams({action:'regenerate_client_id',id:regenerate.dataset.id,_csrf:csrf});const result=await AfenixAdmin.request('gestionar_clientes.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body});await Swal.fire({icon:'success',title:'ID regenerado',html:`Nuevo ID: <strong>${result.codigo}</strong>`});location.reload();}catch(e){Swal.fire('Error',e.message,'error');}return;}
  const del=event.target.closest('.js-delete-client');if(del){const confirm=await Swal.fire({title:'¿Eliminar cliente?',html:`Se intentará eliminar a <strong>${del.dataset.name}</strong>.`,text:'No podrá eliminarse mientras tenga cuentas asociadas.',icon:'warning',showCancelButton:true,confirmButtonText:'Sí, eliminar',cancelButtonText:'Cancelar',confirmButtonColor:'#dc2626'});if(!confirm.isConfirmed)return;try{const body=new URLSearchParams({action:'delete_client',id:del.dataset.id,_csrf:csrf});const result=await AfenixAdmin.request('gestionar_clientes.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body});await Swal.fire('Eliminado',result.message,'success');location.reload();}catch(e){Swal.fire('Error',e.message,'error');}}
 });
 form.addEventListener('submit',async(event)=>{event.preventDefault();const submit=form.querySelector('[type=submit]');submit.disabled=true;try{const result=await AfenixAdmin.request('gestionar_clientes.php',{method:'POST',body:new FormData(form)});modal.clean();await Swal.fire('Guardado',result.message,'success');location.reload();}catch(e){Swal.fire('Error',e.message,'error');}finally{submit.disabled=false;}});
});
</script>
<?php require_once __DIR__ . '/admin_footer.php'; ?>
