<?php
// CARGA MAESTRA DE CONFIGURACIÓN Y BRANDING
require_once(__DIR__ . '/core/init.php');

$db_clients = [];
$db_leads = [];
$db_unique_appointments = [];
$db_recurring_appointments = [];
$db_config = ['company_name' => 'Tu Negocio', 'contact_name' => 'Tu Nombre'];
$db_error_message = null;
$db_schedule_config = ['slot_duration' => 60, 'capacity' => 1];
$db_weekly_hours = [];
$db_blocked_dates = [];

try {
    require_once 'db/db_connection.php';
    require_once 'files/guardiankey.php';

    // 1. INFO NEGOCIO
    $stmt_business_info = $pdo->prepare("SELECT full_name, company_name FROM business_info WHERE id = :id LIMIT 1");
    $stmt_business_info->execute(['id' => 1]);
    if ($row = $stmt_business_info->fetch(PDO::FETCH_ASSOC)) {
        $db_config['company_name'] = htmlspecialchars($row['company_name'], ENT_QUOTES, 'UTF-8');
        $db_config['contact_name'] = htmlspecialchars($row['full_name'], ENT_QUOTES, 'UTF-8');
    }

    // 2. CLIENTES
    $stmt_clients = $pdo->prepare("SELECT id, first_name, last_name, email, phone, mobile, street_address, city, state_province, zip_code, CONCAT(first_name, ' ', last_name) AS full_name FROM clients");
    $stmt_clients->execute();
    while ($row = $stmt_clients->fetch(PDO::FETCH_ASSOC)) {
        $db_clients['client-' . $row['id']] = [
            'id' => $row['id'],
            'first_name' => htmlspecialchars($row['first_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'last_name' => htmlspecialchars($row['last_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'name' => htmlspecialchars($row['full_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'email' => htmlspecialchars($row['email'] ?? '', ENT_QUOTES, 'UTF-8'),
            'phone' => htmlspecialchars($row['phone'] ?? '', ENT_QUOTES, 'UTF-8'),
            'mobile_phone' => htmlspecialchars($row['mobile'] ?? '', ENT_QUOTES, 'UTF-8'),
            'street_address' => htmlspecialchars($row['street_address'] ?? '', ENT_QUOTES, 'UTF-8'),
            'city' => htmlspecialchars($row['city'] ?? '', ENT_QUOTES, 'UTF-8'),
            'state_province' => htmlspecialchars($row['state_province'] ?? '', ENT_QUOTES, 'UTF-8'),
            'zip_code' => htmlspecialchars($row['zip_code'] ?? '', ENT_QUOTES, 'UTF-8')
        ];
    }

    // 3. LEADS (ACTUALIZADO: Ahora trae dirección)
    $stmt_leads = $pdo->prepare("SELECT id, first_name, last_name, company, email, phone, mobile, street_address, city, state_province, zip_code, CONCAT(first_name, ' ', last_name) AS full_name FROM leads");
    $stmt_leads->execute();
    while ($row = $stmt_leads->fetch(PDO::FETCH_ASSOC)) {
        $db_leads['lead-' . $row['id']] = [
            'id' => $row['id'],
            'first_name' => htmlspecialchars($row['first_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'last_name' => htmlspecialchars($row['last_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'company' => htmlspecialchars($row['company'] ?? '', ENT_QUOTES, 'UTF-8'),
            'name' => htmlspecialchars($row['full_name'] ?? '', ENT_QUOTES, 'UTF-8'),
            'email' => htmlspecialchars($row['email'] ?? '', ENT_QUOTES, 'UTF-8'),
            'phone' => htmlspecialchars($row['phone'] ?? '', ENT_QUOTES, 'UTF-8'),
            'mobile_phone' => htmlspecialchars($row['mobile'] ?? '', ENT_QUOTES, 'UTF-8'),
            // Agregamos campos de dirección
            'street_address' => htmlspecialchars($row['street_address'] ?? '', ENT_QUOTES, 'UTF-8'),
            'city' => htmlspecialchars($row['city'] ?? '', ENT_QUOTES, 'UTF-8'),
            'state_province' => htmlspecialchars($row['state_province'] ?? '', ENT_QUOTES, 'UTF-8'),
            'zip_code' => htmlspecialchars($row['zip_code'] ?? '', ENT_QUOTES, 'UTF-8')
        ];
    }

    $client_ids_map = array_column($db_clients, 'name', 'id');
    $lead_ids_map = array_column($db_leads, 'name', 'id');

    // 4. CITAS ÚNICAS
    // CORRECCIÓN CRÍTICA: Se agregó ', public_token' en la primera línea del SELECT
    $sql_unique = "SELECT id, client_id, lead_id, appointment_date, appointment_time, status, notes, recurring_parent_id, public_token
                    FROM unique_appointments
                    WHERE appointment_date >= DATE_SUB(CURDATE(), INTERVAL 2 MONTH)";
    $stmt_unique_appointments = $pdo->prepare($sql_unique);
    $stmt_unique_appointments->execute();
    
    while ($row = $stmt_unique_appointments->fetch(PDO::FETCH_ASSOC)) {
        if (!empty($row['client_id']) && !isset($client_ids_map[$row['client_id']])) { continue; }
        if (!empty($row['lead_id']) && !isset($lead_ids_map[$row['lead_id']])) { continue; }

        $row['type'] = $row['recurring_parent_id'] ? 'recurrente-hija' : 'unica'; 
        $row['notes'] = htmlspecialchars($row['notes'] ?? '', ENT_QUOTES, 'UTF-8');
        
        // ASEGURAR QUE EL TOKEN ESTÉ PRESENTE
        $row['public_token'] = $row['public_token'] ?? ''; 

        $associated_entity_name = 'N/A';
        $associated_entity_type = 'none';
        $associated_entity_id = null;

        if (!empty($row['client_id'])) {
            $associated_entity_name = $client_ids_map[$row['client_id']];
            $associated_entity_type = 'client';
            $associated_entity_id = $row['client_id'];
        } elseif (!empty($row['lead_id'])) {
            $associated_entity_name = $lead_ids_map[$row['lead_id']];
            $associated_entity_type = 'lead';
            $associated_entity_id = $row['lead_id'];
        }

        $row['associated_entity_name'] = $associated_entity_name;
        $row['associated_entity_type'] = $associated_entity_type;
        $row['associated_entity_id'] = $associated_entity_id;
        $db_unique_appointments['cita-unica-' . $row['id']] = $row;
    }

    // 5. CITAS RECURRENTES MAESTRAS
    $stmt_recurring_appointments = $pdo->prepare("SELECT id, client_id, lead_id, frequency, first_appointment_date, appointment_time, notes, next_appointment_date FROM recurring_appointments");
    $stmt_recurring_appointments->execute();
    while ($row = $stmt_recurring_appointments->fetch(PDO::FETCH_ASSOC)) {
        if (!empty($row['client_id']) && !isset($client_ids_map[$row['client_id']])) { continue; }
        if (!empty($row['lead_id']) && !isset($lead_ids_map[$row['lead_id']])) { continue; }

        $row['type'] = 'recurrente'; 
        $row['notes'] = htmlspecialchars($row['notes'] ?? '', ENT_QUOTES, 'UTF-8');
        $associated_entity_name = 'N/A';
        $associated_entity_type = 'none';
        $associated_entity_id = null;

        if (!empty($row['client_id'])) {
            $associated_entity_name = $client_ids_map[$row['client_id']];
            $associated_entity_type = 'client';
            $associated_entity_id = $row['client_id'];
        } elseif (!empty($row['lead_id'])) {
            $associated_entity_name = $lead_ids_map[$row['lead_id']];
            $associated_entity_type = 'lead';
            $associated_entity_id = $row['lead_id'];
        }

        $row['associated_entity_name'] = $associated_entity_name;
        $row['associated_entity_type'] = $associated_entity_type;
        $row['associated_entity_id'] = $associated_entity_id;
        $db_recurring_appointments['cita-recurrente-' . $row['id']] = $row;
    }

    // 6. CONFIGURACIÓN HORARIOS
    $stmt_sched_config = $pdo->prepare("SELECT slot_duration, capacity FROM schedule_config WHERE id = :id LIMIT 1");
    $stmt_sched_config->execute(['id' => 1]);
    if ($row = $stmt_sched_config->fetch(PDO::FETCH_ASSOC)) {
        $db_schedule_config = $row;
        $db_schedule_config['slot_duration'] = (int)$db_schedule_config['slot_duration'];
        $db_schedule_config['capacity'] = (int)$db_schedule_config['capacity'];
    }

    // 7. HORARIO SEMANAL
    $stmt_weekly_hours = $pdo->prepare("SELECT day, is_open, open_time, close_time FROM cms_weekly_hours WHERE schedule_id = :id");
    $stmt_weekly_hours->execute(['id' => 1]);
    while ($row = $stmt_weekly_hours->fetch(PDO::FETCH_ASSOC)) {
        $db_weekly_hours[$row['day']] = [
            'is_open' => (bool)$row['is_open'],
            'open_time' => $row['open_time'],
            'close_time' => $row['close_time']
        ];
    }
    
    // 8. FECHAS BLOQUEADAS
    $stmt_blocked_dates = $pdo->prepare("SELECT id, blocked_date FROM cms_blocked_dates");
    $stmt_blocked_dates->execute();
    while ($row = $stmt_blocked_dates->fetch(PDO::FETCH_ASSOC)) {
        $db_blocked_dates[] = $row;
    }

} catch (PDOException $e) {
    error_log("ERROR CRÍTICO EN AGENDA: " . $e->getMessage());
    $db_error_message = 'Error de conexión a base de datos. Verifique logs.';
}

$db_load_success = isset($pdo) && !$db_error_message;

if (ob_get_level() > 0) {
    ob_end_clean();
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Centro De Citas Agendadas De Servicios <?php echo htmlspecialchars($branding['full_title']); ?></title>
    <meta name="robots" content="noindex, nofollow">
    
    <link rel="icon" type="image/png" href="<?php echo htmlspecialchars($branding['favicon']); ?>">
    <link rel="apple-touch-icon" href="<?php echo htmlspecialchars($branding['favicon']); ?>">
    
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="<?php echo htmlspecialchars($google_font_url); ?>">

    <?php include 'files/gtm-head.php'; ?>
    
    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://unpkg.com/imask"></script>

    <link rel="stylesheet" href="style.css">
    <script src="files/header-manager.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

</head>
<body data-page-title="Centro De Citas Agendadas De Servicios"
      data-page-subtitle="Administrador De Calendario De Citas Y Servicios Programados"
      data-page-icon="calendar-check">
    
    <div id="toast-container" class="toast-container"></div>
        
<?php include 'files/gtm-body.php'; ?>

<div class="relative min-h-screen md:flex">

    <div id="sidebar-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-30 hidden md:hidden"></div>
    <div id="panel-overlay" class="fixed inset-0 bg-gray-900 bg-opacity-75 z-40 hidden transition-opacity duration-300"></div>
    
    <?php include 'menu.php'; ?>

    <main class="flex-1 overflow-y-auto">
        <header class="bg-white shadow-sm p-4 flex justify-between items-center sticky top-0 z-20">
            <button id="mobile-menu-button" class="md:hidden text-gray-600 hover:text-gray-800">
                <i data-lucide="menu" class="w-6 h-6"></i>
            </button>
            <div class="page-header-container">
                <h2 id="page-title"></h2>
                <p id="page-subtitle"></p>
            </div>
        </header>
        
        <div id="content-area" class="p-4 md:p-8 space-y-8">
            <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
                <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="calendar-check" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                    <div>
                        <h3 class="text-lg font-black text-gray-500 mb-1">TOTAL DEL MES</h3>
                        <p id="monthly-total" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                    </div>
                </div>
                <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="calendar-plus" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                    <div>
                        <h3 class="text-lg font-black text-gray-500 mb-1">NUEVAS</h3>
                        <p id="monthly-new" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                    </div>
                </div>
                <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="repeat" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                    <div>
                        <h3 class="text-lg font-black text-gray-500 mb-1">RECURRENTES</h3>
                        <p id="monthly-recurring" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                    </div>
                </div>
                <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="calendar-x" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                    <div>
                        <h3 class="text-lg font-black text-gray-500 mb-1">CANCELADAS</h3>
                        <p id="monthly-cancelled" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                    </div>
                </div>
            </div>

            <section id="agenda" class="dashboard-section">
                <div class="bg-white p-6 rounded-xl shadow-md">
                    
                    <div class="flex flex-col mb-6 gap-4">
                        
                        <div>
                            <h3 class="text-2xl font-extrabold text-gray-800 flex items-center gap-2">
                                <i data-lucide="calendar-days" class="w-7 h-7 text-[var(--color-primary)]"></i> CALENDARIO DE SERVICIOS Y EVENTOS
                            </h3>
                            <p class="text-gray-500 text-sm mt-1 uppercase">ORGANIZA Y MONITOREA TUS PRÓXIMAS PROGRAMACIONES.</p>
                        </div>
                        
                        <div class="flex flex-col sm:flex-row items-center md:items-start gap-4 w-full md:w-auto mt-4 pt-4 border-t border-gray-100">
                            <button id="config-panel-open-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg flex items-center w-full sm:w-auto justify-center uppercase transition-all shadow-sm">
                                <i data-lucide="settings" class="w-5 h-5 mr-2"></i> CONFIGURACIÓN
                            </button>
                            <button id="recurring-master-panel-open-btn" class="bg-[var(--color-highlight)] hover:opacity-90 text-[var(--color-primary)] font-bold py-2 px-4 rounded-lg flex items-center w-full sm:w-auto justify-center uppercase transition-all shadow-sm">
                                <i data-lucide="repeat" class="w-5 h-5 mr-2"></i> RECURRENTES
                            </button>
                            <button class="btn-secondary font-bold py-2 px-4 rounded-lg flex items-center w-full sm:w-auto justify-center uppercase shadow-sm hover:shadow-md transition-all bg-[var(--color-primary)] text-white" onclick="openPanel('agendarServicioPanel')">
                                <i data-lucide="plus" class="w-5 h-5 mr-2"></i> AGENDAR CITA
                            </button>
                            <div class="relative inline-block text-left w-full sm:w-auto">
                                <button type="button" id="download-citas-btn" class="btn-primary font-bold py-2 px-4 rounded-lg flex items-center w-full sm:w-auto justify-center uppercase shadow-sm hover:shadow-md transition-all bg-[var(--color-secondary)] text-white">
                                    <i data-lucide="download" class="w-5 h-5 mr-2"></i> EXPORTAR
                                </button>
                                <div id="download-dropdown" class="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none hidden z-50" role="menu" aria-orientation="vertical" aria-labelledby="download-citas-btn">
                                    <div class="py-1" role="none">
                                        <button class="text-gray-700 font-black block w-full text-left px-4 py-2 text-sm hover:bg-gray-100" role="menuitem" id="export-csv">CSV (Google Calendar)</button>
                                        <button class="text-gray-700 font-black block w-full text-left px-4 py-2 text-sm hover:bg-gray-100" role="menuitem" id="export-ical">iCalendar (.ics)</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                    </div>
                    <div class="mb-8 p-4 border border-gray-200 rounded-lg shadow-sm bg-gray-50">
                        <div class="flex justify-between items-center mb-4">
                            <button id="prev-btn" class="p-2 rounded-md hover:bg-gray-200 transition-colors"><i data-lucide="chevron-left"></i></button>
                            <h4 id="period-title" class="text-xl md:text-3xl font-extrabold text-gray-700 uppercase px-4 py-2 text-center"></h4>
                            <button id="next-btn" class="p-2 rounded-md hover:bg-gray-200 transition-colors"><i data-lucide="chevron-right"></i></button>
                        </div>
                        <div class="flex justify-center items-center gap-2 mb-4">
                            <button id="view-weekly-btn" class="bg-[var(--color-primary)] text-white font-bold py-2 px-4 rounded-lg uppercase shadow-sm">Semanal</button>
                            <button id="view-monthly-btn" class="bg-gray-200 text-gray-800 font-bold py-2 px-4 rounded-lg uppercase shadow-sm hover:bg-gray-300">Mensual</button>
                        </div>
                        <div id="calendar-grid" class="grid grid-cols-1 md:grid-cols-7 gap-px bg-gray-200 border border-gray-200 rounded-lg overflow-hidden">
                        </div>
                    </div>

            <div id="pending-requests-section" class="hidden mb-8">
                <div class="bg-yellow-50 border-l-4 border-yellow-400 p-6 rounded-xl shadow-md">
                    <h3 class="text-2xl font-black text-yellow-800 flex items-center gap-2 mb-4 uppercase">
                        <i data-lucide="alert-circle" class="w-8 h-8"></i> SOLICITUDES PENDIENTES DE APROBACIÓN
                    </h3>
                    <p class="text-yellow-700 mb-4 text-sm">Estas citas han sido solicitadas y requieren tu confirmación para ser agendadas oficialmente.</p>
                    <div id="pending-list" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
                        </div>
                </div>
            </div>

            <div id="pending-requests-section" class="hidden mb-6">
                <div class="bg-yellow-50 border-l-8 border-yellow-400 p-6 rounded-xl shadow-md">
                    <div class="flex flex-col md:flex-row justify-between items-center mb-4">
                        <h3 class="text-2xl font-black text-yellow-800 flex items-center gap-2 uppercase">
                            <i data-lucide="bell-ring" class="w-8 h-8 text-yellow-600"></i> 
                            ¡HAY SOLICITUDES WEB PENDIENTES!
                        </h3>
                        <span class="mt-2 md:mt-0 bg-yellow-600 text-white px-4 py-1 rounded-full font-bold text-xs uppercase tracking-wide">
                            Requiere Aprobación
                        </span>
                    </div>
                    <p class="text-yellow-800 text-sm font-medium mb-4">
                        Los siguientes clientes han solicitado una cita desde la página web. Revisa la información y apruébala para enviarles la confirmación automáticamente.
                    </p>
                    
                    <div id="pending-list" class="grid grid-cols-1 lg:grid-cols-2 gap-4">
                        </div>
                </div>
            </div>
            
                    <div>
                        <h4 class="text-xl font-extrabold text-gray-700 mb-4 uppercase flex items-center gap-2">
                            <i data-lucide="calendar-days" class="w-6 h-6 text-[var(--color-primary)]"></i> PRÓXIMAS CITAS ÚNICAS Y PROGRAMADAS
                        </h4>
                        <div class="flex flex-col md:flex-row gap-4 mb-4">
                            <div class="relative flex-grow">
                                <input type="text" id="appointment-search" placeholder="Buscar Por Cliente" class="w-full p-3 pl-10 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-highlight)]">
                                <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400"></i>
                            </div>
                            <select id="appointment-filter-status" class="w-full md:w-48 p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-highlight)] bg-white">
                                <optgroup label="FILTRAR POR FECHA">
                                    <option value="all">TODAS</option> <option value="hoy">HOY</option>
                                    <option value="proximas" selected>PRÓXIMAS</option>
                                    <option value="pasadas">PASADAS</option>
                                </optgroup>
                                <optgroup label="FILTRAR POR ESTADO">
                                    <option value="todas">TODAS</option>
                                    <option value="pending">PENDIENTE</option>
                                    <option value="confirmed">CONFIRMADA</option>
                                    <option value="completed">COMPLETADA</option>
                                    <option value="cancelled">CANCELADA</option>
                                </optgroup>
                            </select>
                            <select id="appointment-filter-type" class="w-full md:w-48 p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-highlight)] bg-white">
                                <option value="all">TODOS LOS TIPOS</option>
                                <option value="unica">ÚNICA</option>
                                <option value="recurrente">RECURRENTE</option>
                            </select>
                        </div>
                        <div id="appointment-list" class="space-y-3">
                        </div>
                    </div>
                    
                    <div id="recurring-list-section" class="mt-8 border-t pt-4">
                        <h4 class="text-xl font-extrabold text-gray-700 mb-4 uppercase flex items-center gap-2">
                            <i data-lucide="repeat" class="w-6 h-6 text-yellow-600"></i> CITAS AGENDADAS DE FORMA RECURRENTE
                        </h4>
                        <div class="overflow-x-auto">
                            <table class="min-w-full divide-y divide-gray-200 responsive-invoices-table text-sm text-left">
                                <thead class="bg-gray-50 hidden md:table-header-group">
                                    <tr>
                                        <th scope="col" class="px-6 py-3 font-medium text-gray-500 uppercase tracking-wider">Contacto</th>
                                        <th scope="col" class="px-6 py-3 font-medium text-gray-500 uppercase tracking-wider">Frecuencia</th>
                                        <th scope="col" class="px-6 py-3 font-medium text-gray-500 uppercase tracking-wider">Hora Base</th>
                                        <th scope="col" class="px-6 py-3 font-medium text-gray-500 uppercase tracking-wider">1ra Cita</th>
                                        <th scope="col" class="px-6 py-3 font-medium text-gray-500 uppercase tracking-wider">Próxima</th>
                                        <th scope="col" class="px-6 py-3 text-center font-medium text-gray-500 uppercase tracking-wider">Acciones</th>
                                    </tr>
                                </thead>
                                <tbody id="recurring-main-list" class="bg-white divide-y divide-gray-200">
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </main>
</div>

<div id="recurringMasterPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="repeat" class="w-8 h-8 mr-2 text-white"></i>
                GESTIÓN DE RECURRENCIAS
            </h3>
            <button onclick="closePanel('recurringMasterPanel')" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-4 space-y-6 relative">
            
            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <p class="text-sm text-gray-500 mb-4">
                    Estas son las Citas Maestras. Eliminar una de ellas cancelará todas las citas futuras asociadas.
                </p>
                
                <div class="overflow-x-auto border border-gray-200 rounded-lg">
                    <table class="min-w-full divide-y divide-gray-200 responsive-invoices-table text-sm text-left">
                        <thead class="bg-gray-50">
                            <tr>
                                <th scope="col" class="px-3 py-3 font-bold text-gray-700 uppercase tracking-wider">Contacto</th>
                                <th scope="col" class="px-3 py-3 font-bold text-gray-700 uppercase tracking-wider">Frec.</th>
                                <th scope="col" class="px-3 py-3 font-bold text-gray-700 uppercase tracking-wider">Hora</th>
                                <th scope="col" class="px-3 py-3 font-bold text-gray-700 uppercase tracking-wider">1ra Cita</th>
                                <th scope="col" class="px-3 py-3 font-bold text-gray-700 uppercase tracking-wider">Pend.</th>
                                <th scope="col" class="px-3 py-3 text-center font-bold text-gray-700 uppercase tracking-wider">Acciones</th>
                            </tr>
                        </thead>
                        <tbody id="recurring-master-list" class="bg-white divide-y divide-gray-100">
                            <tr><td colspan="6" class="text-center py-4 text-gray-500">Cargando Recurrencias...</td></tr>
                        </tbody>
                    </table>
                </div>
                </div>
        </div>
        
        <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10">
            <button type="button" onclick="closePanel('recurringMasterPanel')" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-all">
                <i data-lucide="x-circle" class="w-5 h-5"></i> CERRAR PANEL
            </button>
        </div>
    </div>
</div>

<div id="configPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="settings" class="w-8 h-8 mr-2 text-white"></i>
                CONFIGURACIÓN DE AGENDA
            </h3>
            <button onclick="closePanel('configPanel')" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-4 space-y-6 relative">
            
            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <form id="config-capacity-form" class="space-y-4">
                    <div>
                        <label for="config-slot-duration" class="block text-md font-bold text-gray-600 mb-1 uppercase">Duración del Slot (Minutos)</label>
                        <select id="config-slot-duration" name="slot_duration" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                            <option value="15">15 minutos</option>
                            <option value="30">30 minutos</option>
                            <option value="45">45 minutos</option>
                            <option value="60">60 minutos</option>
                            <option value="90">90 minutos</option>
                            <option value="120">120 minutos (2 horas)</option>
                        </select>
                    </div>
                    <div>
                        <label for="config-capacity" class="block text-md font-bold text-gray-600 mb-1 uppercase">Capacidad por Slot</label>
                        <input type="number" id="config-capacity" name="capacity" min="1" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                        <p class="mt-1 text-xs text-gray-500">Cuántas citas puede manejar a la vez.</p>
                    </div>
                    <button type="submit" id="save-capacity-btn" class="w-full btn-confirm uppercase flex items-center justify-center gap-2 bg-[var(--color-secondary)] hover:opacity-90 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all">
                        <i data-lucide="save" class="w-5 h-5"></i> GUARDAR CAPACIDAD Y DURACIÓN
                    </button>
                </form>
            </div>

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <form id="config-weekly-hours-form">
                    <div id="weekly-hours-list" class="space-y-2 border border-gray-200 p-2 rounded-lg">
                        <p class="text-center text-sm text-gray-500 py-4">Cargando horario...</p>
                    </div>
                    <button type="submit" id="save-weekly-hours-btn" class="w-full btn-confirm uppercase mt-4 flex items-center justify-center gap-2 bg-[var(--color-secondary)] hover:opacity-90 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all">
                        <i data-lucide="save" class="w-5 h-5"></i> GUARDAR HORARIO SEMANAL
                    </button>
                </form>
            </div>

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <h4 class="text-xl font-black uppercase text-gray-700 mb-4 flex items-center gap-2">
                    <i data-lucide="calendar-x" class="w-6 h-6 text-red-500"></i> Bloquear Fechas Específicas
                </h4>
                <div class="flex gap-2 mb-4">
                    <input type="date" id="config-block-date" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-red-500 focus:ring-red-500 focus:ring-1 transition duration-150 text-sm">
                    <button type="button" id="add-blocked-date-btn" class="bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg uppercase shadow-sm transition-all flex items-center justify-center flex-shrink-0">
                        <i data-lucide="plus" class="w-5 h-5"></i>
                    </button>
                </div>
                <div id="blocked-dates-list" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar">
                    <p class="text-sm text-gray-500 text-center py-2">No hay días bloqueados.</p>
                </div>
            </div>

        </div>
        
        <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10">
            <button type="button" onclick="closePanel('configPanel')" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-all">
                <i data-lucide="x-circle" class="w-5 h-5"></i> CERRAR PANEL
            </button>
        </div>
    </div>
</div>

<div id="agendarServicioPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="plus-circle" class="w-8 h-8 mr-2 text-white"></i>
                AGENDAR NUEVA CITA
            </h3>
            <button onclick="closePanel('agendarServicioPanel')" class="bg-[var(--color-primary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-4 space-y-6 relative">
            <form id="agendar-servicio-form" class="space-y-4">
                
                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <div class="mb-4">
                        <label for="cita-cliente-display" class="block text-md font-bold text-gray-600 mb-1 uppercase">Cliente Existente</label>
                        <input type="text" id="cita-cliente-display" placeholder="Escribe nombre o email del cliente" class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                        <input type="hidden" id="cita-cliente" name="client_id">
                        <div id="cita-cliente-suggestions" class="autocomplete-suggestions hidden bg-white border border-gray-300 rounded-lg shadow-lg mt-1 max-h-40 overflow-y-auto z-10"></div>
                        <p id="cita-cliente-info" class="text-xs text-gray-500 mt-1"></p>
                    </div>

                    <div>
                        <label for="cita-prospecto-display" class="block text-md font-bold text-gray-600 mb-1 uppercase">Prospecto (Lead)</label>
                        <input type="text" id="cita-prospecto-display" placeholder="Escribe nombre o email del prospecto" class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                        <input type="hidden" id="cita-prospecto" name="lead_id">
                        <div id="cita-prospecto-suggestions" class="autocomplete-suggestions hidden bg-white border border-gray-300 rounded-lg shadow-lg mt-1 max-h-40 overflow-y-auto z-10"></div>
                        <p id="cita-prospecto-info-adicional" class="text-xs text-gray-500 mt-1"></p>
                    </div>
                </div>

                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <div class="grid grid-cols-1 gap-4">
                        <div>
                            <label for="cita-fecha" class="block text-md font-bold text-gray-600 mb-1 uppercase">Fecha de la Cita</label>
                            <input type="date" id="cita-fecha" name="appointment_date" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                        </div>
                    </div>
                    <div class="grid grid-cols-2 gap-4 mt-4">
                        <div>
                            <label for="cita-hora-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Hora</label>
                            <select id="cita-hora-select" name="appointment_hour" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm bg-white"></select>
                        </div>
                        <div>
                            <label for="cita-minuto-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Minuto</label>
                            <select id="cita-minuto-select" name="appointment_minute" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm bg-white"></select>
                        </div>
                    </div>
                    <p class="text-xs text-gray-500 mt-2">Horario ajustado según slots disponibles (Capacidad: <span id="capacity-display"><?php echo $db_schedule_config['capacity'] ?? 1; ?></span>)</p>
                </div>

                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <div class="flex items-center">
                        <input id="cita-recurrente-checkbox" type="checkbox" name="is_recurring" class="h-4 w-4 text-yellow-600 border-gray-300 rounded focus:ring-yellow-500">
                        <label for="cita-recurrente-checkbox" class="ml-2 block text-md font-bold text-gray-600 uppercase">AGENDAR COMO RECURRENTE</label>
                    </div>
                    
                    <div id="recurrencia-options" class="mt-4 p-3 bg-yellow-50 rounded-lg border border-yellow-200 hidden">
                        <div class="mb-3">
                            <label for="cita-frecuencia" class="block text-sm font-medium text-gray-700">Frecuencia de Repetición</label>
                            <select id="cita-frecuencia" name="frequency" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-yellow-500 focus:border-yellow-500 transition duration-150 text-sm bg-white">
                                <option value="">Seleccione Frecuencia</option>
                                <option value="weekly">Semanal</option>
                                <option value="bi-weekly">Quincenal</option>
                                <option value="monthly">Mensual</option>
                            </select>
                        </div>
                        <p class="text-xs font-semibold text-yellow-700">
                            La primera cita se creará en la fecha y hora seleccionada arriba.
                            <br>Próxima cita calculada: <input type="text" id="cita-proxima-cita-display" class="styled-readonly-input w-full mt-1 text-sm p-1 rounded bg-gray-100 border border-gray-300" readonly>
                            <input type="hidden" id="cita-proxima-cita" name="next_appointment_date">
                        </p>
                    </div>
                </div>

                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <label for="cita-notas" class="block text-md font-bold text-gray-600 mb-1 uppercase">Notas de la Cita</label>
                    <textarea id="cita-notas" name="notes" rows="3" class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm"></textarea>
                </div>

            </form>
        </div>
        
        <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10">
            <div class="grid grid-cols-2 gap-3">
                <button type="button" onclick="closePanel('agendarServicioPanel')" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-all">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR Y CERRAR
                </button>
                <button type="submit" form="agendar-servicio-form" class="w-full btn-confirm uppercase flex items-center justify-center gap-2 bg-[var(--color-secondary)] hover:opacity-90 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all">
                    <i data-lucide="calendar-plus" class="w-5 h-5"></i> AGENDAR CITA
                </button>
            </div>
        </div>
    </div>
</div>

<div id="viewCitaPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="edit-2" class="w-8 h-8 mr-2 text-white"></i>
                VER / EDITAR CITA
            </h3>
            <button onclick="closePanel('viewCitaPanel')" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-4 space-y-6 relative">
            <form id="view-cita-form" class="space-y-4">
                <input type="hidden" id="view-cita-id" name="id">
                <input type="hidden" id="view-cita-type" name="type">
                <input type="hidden" id="view-cita-original-status" name="original_status">

                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <div class="mb-3">
                        <label for="view-cita-cliente" class="block text-md font-bold text-gray-600 mb-1 uppercase">Cliente</label>
                        <input type="text" id="view-cita-cliente" readonly class="w-full p-2 border border-gray-300 rounded-lg styled-readonly-input text-sm bg-gray-100 cursor-not-allowed">
                    </div>
                    <div class="mb-3">
                        <label for="view-cita-prospecto" class="block text-md font-bold text-gray-600 mb-1 uppercase">Prospecto (Lead)</label>
                        <input type="text" id="view-cita-prospecto" readonly class="w-full p-2 border border-gray-300 rounded-lg styled-readonly-input text-sm bg-gray-100 cursor-not-allowed">
                    </div>
                    <p id="view-cita-cliente-info" class="text-xs text-gray-500 mt-1"></p>
                    <p id="view-cita-prospecto-info-adicional" class="text-xs text-gray-500 mt-1"></p>
                </div>

                <div id="view-cita-fecha-group" class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <div class="grid grid-cols-1 gap-4">
                        <div>
                            <label for="view-cita-fecha" class="block text-md font-bold text-gray-600 mb-1 uppercase">Fecha de la Cita</label>
                            <input type="date" id="view-cita-fecha" name="appointment_date" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm">
                        </div>
                    </div>
                    <div id="view-cita-hora-group" class="grid grid-cols-2 gap-4 mt-4">
                        <div>
                            <label for="view-cita-hora-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Hora</label>
                            <select id="view-cita-hora-select" name="appointment_hour" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm bg-white"></select>
                        </div>
                        <div>
                            <label for="view-cita-minuto-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Minuto</label>
                            <select id="view-cita-minuto-select" name="appointment_minute" required class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm bg-white"></select>
                        </div>
                    </div>
                </div>

                <div id="view-cita-frecuencia-group" class="bg-white p-4 rounded-xl shadow-md transition duration-300 hidden">
                    <h4 class="font-bold text-lg text-gray-700 mb-3 uppercase">REGLA DE RECURRENCIA</h4>
                    <div class="mb-4">
                        <label for="view-cita-frecuencia" class="block text-md font-bold text-gray-600 mb-1 uppercase">Frecuencia</label>
                        <select id="view-cita-frecuencia" name="frequency" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-yellow-500 focus:border-yellow-500 transition duration-150 text-sm bg-white">
                            <option value="weekly">Semanal</option>
                            <option value="bi-weekly">Quincenal</option>
                            <option value="monthly">Mensual</option>
                        </select>
                    </div>
                    <div id="view-cita-proxima-cita-group" class="mb-4">
                        <label for="view-cita-proxima-cita-display" class="block text-md font-bold text-gray-600 mb-1 uppercase">Próximo Cálculo</label>
                        <input type="text" id="view-cita-proxima-cita-display" class="w-full p-2 border border-gray-300 rounded-lg styled-readonly-input text-sm bg-gray-100 cursor-not-allowed" readonly>
                        <input type="hidden" id="view-cita-proxima-cita" name="next_appointment_date_calculated">
                        <p class="text-xs text-gray-500 mt-1">Nota: Modificar la frecuencia no actualiza las citas ya creadas, solo la regla futura.</p>
                    </div>
                </div>

                <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                    <label for="view-cita-notas" class="block text-md font-bold text-gray-600 mb-1 uppercase">Notas de la Cita</label>
                    <textarea id="view-cita-notas" name="notes" rows="3" class="w-full p-2 border border-gray-300 rounded-lg focus:border-[var(--color-highlight)] focus:ring-[var(--color-highlight)] focus:ring-1 transition duration-150 text-sm"></textarea>
                </div>

            </form>
        </div>
        
        <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10">
            <div class="grid grid-cols-2 gap-3">
                <button type="button" onclick="closePanel('viewCitaPanel')" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-all">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                <button type="submit" form="view-cita-form" id="save-cita-changes-btn" class="w-full btn-confirm uppercase flex items-center justify-center gap-2 bg-[var(--color-secondary)] hover:opacity-90 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all">
                    <i data-lucide="save" class="w-5 h-5"></i> GUARDAR CAMBIOS
                </button>
            </div>
        </div>
    </div>
</div>

<div id="messageCitaPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="message-square" class="w-8 h-8 mr-2 text-white"></i>
                MENSAJE DE CONFIRMACIÓN
            </h3>
            <button onclick="closePanel('messageCitaPanel')" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-4 space-y-6 relative">

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <h4 class="font-black text-lg text-gray-700 mb-3 uppercase flex items-center gap-2">
                    <i data-lucide="calendar-check" class="w-5 h-5"></i> DETALLES DE LA CITA
                </h4>
                <div class="text-sm space-y-1">
                    <p><span class="font-semibold">Cliente:</span> <span id="msg-cita-cliente" class="font-medium">N/A</span></p>
                    <p><span class="font-semibold">Prospecto:</span> <span id="msg-cita-prospecto" class="font-medium">N/A</span></p>
                    <p><span class="font-semibold">Fecha:</span> <span id="msg-cita-fecha" class="font-medium">N/A</span></p>
                    <p><span class="font-semibold">Hora:</span> <span id="msg-cita-hora" class="font-medium">N/A</span></p>
                    <p><span class="font-semibold">Tipo:</span> <span id="msg-cita-tipo" class="font-medium">N/A</span></p>
                    <p><span class="font-semibold">Teléfono:</span> <span id="msg-cita-telefono" class="font-medium">N/A</span></p>
                </div>
            </div>

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <h4 class="font-black text-lg text-gray-700 mb-3 uppercase flex items-center gap-2">
                    <i data-lucide="speech" class="w-5 h-5"></i> MENSAJE EN ESPAÑOL
                </h4>
                <textarea id="message-spanish" rows="6" readonly class="w-full p-2 border border-gray-300 rounded-lg styled-readonly-input text-sm bg-gray-50"></textarea>
                <div class="flex space-x-2 mt-2">
                    <button type="button" data-lang="es" class="btn-cancel copy-message-btn w-full flex items-center justify-center gap-2 bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 rounded-lg uppercase shadow-sm transition-all">
                        <i data-lucide="copy" class="w-5 h-5"></i> COPIAR
                    </button>
                    <button type="button" data-lang="es" class="btn-confirm w-full flex items-center justify-center gap-2 send-whatsapp-btn bg-green-500 hover:bg-green-600 text-white font-bold py-2 rounded-lg uppercase shadow-md transition-all">
                        <i data-lucide="send" class="w-5 h-5"></i> WHATSAPP
                    </button>
                </div>
            </div>

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <h4 class="font-black text-lg text-gray-700 mb-3 uppercase flex items-center gap-2">
                    <i data-lucide="globe" class="w-5 h-5"></i> MENSAJE EN INGLES
                </h4>
                <textarea id="message-english" rows="6" readonly class="w-full p-2 border border-gray-300 rounded-lg styled-readonly-input text-sm bg-gray-50"></textarea>
                <div class="flex space-x-2 mt-2">
                    <button type="button" data-lang="en" class="btn-cancel copy-message-btn w-full flex items-center justify-center gap-2 bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 rounded-lg uppercase shadow-sm transition-all">
                        <i data-lucide="copy" class="w-5 h-5"></i> COPIAR
                    </button>
                    <button type="button" data-lang="en" class="btn-confirm w-full flex items-center justify-center gap-2 send-whatsapp-btn bg-green-500 hover:bg-green-600 text-white font-bold py-2 rounded-lg uppercase shadow-md transition-all">
                        <i data-lucide="send" class="w-5 h-5"></i> WHATSAPP
                    </button>
                </div>
            </div>

        </div>
        
        <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10">
            <button type="button" onclick="closePanel('messageCitaPanel')" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-all">
                <i data-lucide="x-circle" class="w-5 h-5"></i> CERRAR PANEL
            </button>
        </div>
    </div>
</div>

<div id="detailsCitaPanel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
    <div class="flex flex-col h-full">
        <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
            <h3 class="text-2xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="info" class="w-8 h-8 mr-2 text-white"></i>
                DETALLES DE SOLICITUD
            </h3>
            <button onclick="closePanel('detailsCitaPanel')" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                <i data-lucide="x" class="w-8 h-8"></i>
            </button>
        </div>
        
        <div class="flex-grow overflow-y-auto p-6 space-y-6 bg-gray-50">
            
            <div class="bg-white p-5 rounded-xl shadow-sm border border-gray-200">
                <h4 class="text-sm font-bold text-gray-400 uppercase mb-3 tracking-wider">Información de Contacto</h4>
                <div class="flex items-center gap-4 mb-4">
                    <div class="bg-blue-100 p-3 rounded-full">
                        <i data-lucide="user" class="w-8 h-8 text-blue-600"></i>
                    </div>
                    <div>
                        <h2 id="detail-name" class="text-2xl font-black text-gray-800">Nombre Cliente</h2>
                        <span id="detail-type" class="px-2 py-0.5 rounded text-xs font-bold bg-gray-200 text-gray-600 uppercase">TIPO</span>
                    </div>
                </div>
                <div class="space-y-3">
                    <p class="flex items-center text-gray-700"><i data-lucide="phone" class="w-5 h-5 mr-3 text-gray-400"></i> <span id="detail-phone">N/A</span></p>
                    <p class="flex items-center text-gray-700"><i data-lucide="mail" class="w-5 h-5 mr-3 text-gray-400"></i> <span id="detail-email">N/A</span></p>
                </div>
            </div>

            <div class="bg-white p-5 rounded-xl shadow-sm border border-gray-200">
                <h4 class="text-sm font-bold text-gray-400 uppercase mb-3 tracking-wider">Dirección de Servicio</h4>
                <p id="detail-address-full" class="text-lg font-medium text-gray-800 mb-4">No hay dirección registrada.</p>
                <a id="detail-maps-link" href="#" target="_blank" class="flex items-center justify-center w-full bg-blue-50 text-blue-600 hover:bg-blue-100 font-bold py-3 rounded-lg transition-colors border border-blue-200">
                    <i data-lucide="map-pin" class="w-5 h-5 mr-2"></i> VER EN GOOGLE MAPS
                </a>
            </div>

            <div class="bg-white p-5 rounded-xl shadow-sm border border-gray-200">
                <h4 class="text-sm font-bold text-gray-400 uppercase mb-3 tracking-wider">Detalles de la Cita</h4>
                <div class="grid grid-cols-2 gap-4 mb-4">
                    <div>
                        <p class="text-xs text-gray-500 uppercase">Fecha</p>
                        <p id="detail-date" class="text-lg font-bold text-[var(--color-primary)]">--</p>
                    </div>
                    <div>
                        <p class="text-xs text-gray-500 uppercase">Hora</p>
                        <p id="detail-time" class="text-lg font-bold text-[var(--color-primary)]">--</p>
                    </div>
                </div>
                <div>
                    <p class="text-xs text-gray-500 uppercase mb-1">Notas del Cliente</p>
                    <div id="detail-notes" class="bg-gray-50 p-3 rounded-lg text-sm text-gray-700 italic border border-gray-100 min-h-[60px]">
                        Sin notas adicionales.
                    </div>
                </div>
            </div>

        </div>
        
        <div class="p-4 bg-white border-t border-gray-200 flex-shrink-0 z-10 shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.1)]">
            <div id="detail-actions-pending" class="grid grid-cols-2 gap-3 hidden">
                <button id="btn-detail-reject" class="w-full btn-cancel uppercase flex items-center justify-center gap-2 bg-red-100 hover:bg-red-200 text-red-700 font-bold py-3 px-4 rounded-lg transition-all">
                    <i data-lucide="x" class="w-5 h-5"></i> RECHAZAR
                </button>
                <button id="btn-detail-approve" class="w-full btn-confirm uppercase flex items-center justify-center gap-2 bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-4 rounded-lg shadow-md transition-all">
                    <i data-lucide="check" class="w-5 h-5"></i> APROBAR
                </button>
            </div>
            <div id="detail-actions-normal" class="hidden">
                <button onclick="closePanel('detailsCitaPanel')" class="w-full uppercase flex items-center justify-center gap-2 bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-3 px-4 rounded-lg transition-all">
                    CERRAR
                </button>
            </div>
        </div>
    </div>
</div>

<div id="confirmDeleteModal" 
     class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50 font-barlow"
     onclick="if(event.target === this) document.getElementById('cancel-delete-button').click()">
    
    <div class="modal-dialog relative mx-auto p-0 border-0 shadow-2xl rounded-xl bg-white w-full max-w-sm m-4 text-center transform transition-all duration-300 scale-95 opacity-0 overflow-hidden">
        
        <div class="modal-header-container bg-[var(--color-primary)] p-6">
            <h3 class="modal-primary-title text-3xl font-black text-[var(--color-highlight)] uppercase leading-none">ADVERTENCIA</h3>
        </div>

        <div class="p-8">
            <div class="flex justify-center mb-6">
                <i data-lucide="alert-triangle" class="w-16 h-16 text-[var(--color-secondary)]"></i>
            </div>

            <p class="text-[var(--color-primary)] mb-6 uppercase text-lg font-bold leading-snug">
                ¿DESEAS ELIMINAR LA 
                <span id="confirm-item-type" class="font-black text-[var(--color-secondary)] text-lg inline">CITA/ELEMENTO</span>
                <span id="delete-item-name" class="font-black text-[var(--color-secondary)] text-lg inline"></span>?
            </p>
            <p id="recurring-delete-warning" class="text-sm text-red-600 mb-4 hidden font-semibold">
                ATENCIÓN: Eliminar la Cita Maestra eliminará todas las citas futuras asociadas.
            </p>

            <div class="flex flex-col sm:flex-row justify-center space-y-3 sm:space-y-0 sm:space-x-4 mt-6">
                <button type="button" class="btn-modal-cancel font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-sm" id="cancel-delete-button" onclick="window.closeModal('confirmDeleteModal')">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                
                <button type="button" class="btn-modal-confirm font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-md" id="confirm-delete-button">
                    <i data-lucide="trash-2" class="w-5 h-5"></i> ELIMINAR
                </button>
            </div>
             <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider"> 
                ESTA ACCIÓN NO SE PUEDE DESHACER
            </p>
        </div>
    </div>
</div>

</script>
<script>
    document.addEventListener('DOMContentLoaded', function() {
        let currentDate = new Date(); // Fecha de referencia para el calendario
        let currentView = 'weekly'; // 'weekly' o 'monthly'

        // Variables que recibirán los datos inyectados por PHP
        let dbClients = {};
        let dbLeads = {};
        let dbCitasUnicas = {};
        let dbCitasRecurrentes = {};
        let dbErrorMessage = null;
        let appSettings = {
            companyName: 'Tu Negocio',
            contactName: 'Tu Nombre'
        };
        // Variables globales de configuración inicializadas con los valores de PHP
        let dbScheduleConfig = {
            slot_duration: <?php echo json_encode($db_schedule_config['slot_duration'] ?? 60); ?>,
            capacity: <?php echo json_encode($db_schedule_config['capacity'] ?? 1); ?>
        };
        // CRÍTICO: dbWeeklyHours necesita que el JS sepa si está abierto (is_open) y las horas
        let dbWeeklyHours = <?php echo json_encode($db_weekly_hours); ?>;
        // CRÍTICO: dbBlockedDates es un array de objetos con ID y fecha
        let dbBlockedDates = <?php echo json_encode($db_blocked_dates); ?>;
        
        // INYECCIÓN DE DATOS DESDE PHP (Manejo de la variable de carga)
        const dbLoadSuccess = <?php echo json_encode($db_load_success); ?>;

        if (dbLoadSuccess) {
            dbClients = <?php echo json_encode($db_clients); ?>;
            dbLeads = <?php echo json_encode($db_leads); ?>;
            dbCitasUnicas = <?php echo json_encode($db_unique_appointments); ?>;
            dbCitasRecurrentes = <?php echo json_encode($db_recurring_appointments); ?>;
            appSettings.companyName = "<?php echo addslashes($db_config['company_name']); ?>";
            appSettings.contactName = "<?php echo addslashes($db_config['contact_name']); ?>";

            if ("<?php echo addslashes($db_error_message); ?>") {
                showToast("Error cargando datos iniciales de la DB: <?php echo addslashes($db_error_message); ?>", 'error');
            }
        } else {
            // Se asume que aquí se inyectó el error de PDO para diagnóstico
            const detailedError = "<?php echo addslashes($db_error_message); ?>";
            showToast(`No se pudieron cargar los datos iniciales de la agenda. Revise la configuración del servidor o si las tablas están vacías. Detalles: ${detailedError}`, 'error');
            dbErrorMessage = `No se pudieron cargar los datos iniciales de la agenda. Revise la configuración del servidor o si las tablas están vacías. Detalles: ${detailedError}`;
        }
        
        // --- NUEVAS FUNCIONES AUXILIARES ---
        function decodeHtmlEntities(text) {
            if (!text) return '';
            const textArea = document.createElement('textarea');
            textArea.innerHTML = text;
            return textArea.value;
        }

        function checkIfRecurringDateMatches(master, targetDateStr) {
            const targetDate = new Date(targetDateStr + 'T00:00:00');
            const startDate = new Date(master.first_appointment_date + 'T00:00:00');
            if (targetDate < startDate) return false;
            
            // Verificacion rápida para semanal/quincenal
            const diffTime = Math.abs(targetDate - startDate);
            const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

            if (master.frequency === 'weekly') return diffDays % 7 === 0;
            if (master.frequency === 'bi-weekly') return diffDays % 14 === 0;
            if (master.frequency === 'monthly') return targetDate.getDate() === startDate.getDate();
            
            return false;
        }
        
        // Elementos del DOM
        const mobileMenuButton = document.getElementById('mobile-menu-button');
        const sidebar = document.getElementById('sidebar');
        const sidebarOverlay = document.getElementById('sidebar-overlay');
        const prevBtn = document.getElementById('prev-btn');
        const nextBtn = document.getElementById('next-btn');
        const periodTitle = document.getElementById('period-title');
        const viewWeeklyBtn = document.getElementById('view-weekly-btn');
        const viewMonthlyBtn = document.getElementById('view-monthly-btn');
        const agendarServicioForm = document.getElementById('agendar-servicio-form');
        const viewCitaForm = document.getElementById('view-cita-form');
        const confirmDeleteButton = document.getElementById('confirm-delete-button');
        const confirmItemTypeSpan = document.getElementById('confirm-item-type');
        const citaRecurrenteCheckbox = document.getElementById('cita-recurrente-checkbox');
        const recurrenciaOptionsDiv = document.getElementById('recurrencia-options');
        const citaFrecuenciaSelect = document.getElementById('cita-frecuencia');
        const citaFecha = document.getElementById('cita-fecha');
        const citaProximaCitaDisplay = document.getElementById('cita-proxima-cita-display');
        const citaProximaCitaInput = document.getElementById('cita-proxima-cita');
        const citaClienteDisplay = document.getElementById('cita-cliente-display');
        const citaClienteInput = document.getElementById('cita-cliente');
        const citaClienteSuggestions = document.getElementById('cita-cliente-suggestions');
        const citaClienteInfo = document.getElementById('cita-cliente-info');
        const citaProspectoDisplay = document.getElementById('cita-prospecto-display');
        const citaProspectoInput = document.getElementById('cita-prospecto');
        const citaProspectoSuggestions = document.getElementById('cita-prospecto-suggestions');
        const citaProspectoInfoAdicional = document.getElementById('cita-prospecto-info-adicional');
        const citaNotas = document.getElementById('cita-notas');
        const citaHoraSelect = document.getElementById('cita-hora-select');
        const citaMinutoSelect = document.getElementById('cita-minuto-select');
        const viewCitaId = document.getElementById('view-cita-id');
        const viewCitaType = document.getElementById('view-cita-type');
        const viewCitaOriginalStatus = document.getElementById('view-cita-original-status');
        const viewCitaCliente = document.getElementById('view-cita-cliente');
        const viewCitaClienteInfo = document.getElementById('view-cita-cliente-info');
        const viewCitaProspecto = document.getElementById('view-cita-prospecto');
        const viewCitaProspectoInfoAdicional = document.getElementById('view-cita-prospecto-info-adicional');
        const viewCitaFecha = document.getElementById('view-cita-fecha');
        const viewCitaHoraSelect = document.getElementById('view-cita-hora-select');
        const viewCitaMinutoSelect = document.getElementById('view-cita-minuto-select');
        const viewCitaFrecuencia = document.getElementById('view-cita-frecuencia');
        const viewCitaProximaCitaDisplay = document.getElementById('view-cita-proxima-cita-display');
        const viewCitaProximaCita = document.getElementById('view-cita-proxima-cita');
        const viewCitaNotas = document.getElementById('view-cita-notas');
        const saveCitaChangesBtn = document.getElementById('save-cita-changes-btn');
        const viewCitaFechaGroup = document.getElementById('view-cita-fecha-group');
        const viewCitaHoraGroup = document.getElementById('view-cita-hora-group');
        const viewCitaFrecuenciaGroup = document.getElementById('view-cita-frecuencia-group');
        const viewCitaProximaCitaGroup = document.getElementById('view-cita-proxima-cita-group');
        const appointmentSearch = document.getElementById('appointment-search');
        const appointmentFilterStatus = document.getElementById('appointment-filter-status');
        const appointmentFilterType = document.getElementById('appointment-filter-type');
        const downloadCitasBtn = document.getElementById('download-citas-btn');
        const downloadDropdown = document.getElementById('download-dropdown');
        const exportCsvBtn = document.getElementById('export-csv');
        const exportIcalBtn = document.getElementById('export-ical');
        const panelOverlay = document.createElement('div');
        panelOverlay.id = 'panel-overlay';
        panelOverlay.className = 'fixed inset-0 bg-gray-900 bg-opacity-75 z-40 hidden';
        document.body.appendChild(panelOverlay);
        const messageCitaPanel = document.getElementById('messageCitaPanel');
        const msgCitaCliente = document.getElementById('msg-cita-cliente');
        const msgCitaProspecto = document.getElementById('msg-cita-prospecto');
        const msgCitaFecha = document.getElementById('msg-cita-fecha');
        const msgCitaHora = document.getElementById('msg-cita-hora');
        const msgCitaTipo = document.getElementById('msg-cita-tipo');
        const msgCitaTelefono = document.getElementById('msg-cita-telefono');
        const messageSpanish = document.getElementById('message-spanish');
        const messageEnglish = document.getElementById('message-english');
        const copyMessageBtns = document.querySelectorAll('.copy-message-btn');
        const sendWhatsappBtns = document.querySelectorAll('.send-whatsapp-btn');
        // Nuevas referencias al DOM para el panel de configuración
        const configPanel = document.getElementById('configPanel');
        const configCapacityForm = document.getElementById('config-capacity-form');
        const configSlotDuration = document.getElementById('config-slot-duration');
        const configCapacity = document.getElementById('config-capacity');
        const saveCapacityBtn = document.getElementById('save-capacity-btn');
        const weeklyHoursList = document.getElementById('weekly-hours-list');
        const addBlockedDateBtn = document.getElementById('add-blocked-date-btn');
        const configBlockDate = document.getElementById('config-block-date');
        const blockedDatesList = document.getElementById('blocked-dates-list');
        const configWeeklyHoursForm = document.getElementById('config-weekly-hours-form');
        const saveWeeklyHoursBtn = document.getElementById('save-weekly-hours-btn');
        const configPanelOpenBtn = document.getElementById('config-panel-open-btn');
        const deleteItemNameSpan = document.getElementById('delete-item-name');
        const cancelDeleteButton = document.getElementById('cancel-delete-button');
        // NUEVAS REFERENCIAS PARA RECURRENCIA
        const recurringMasterPanelOpenBtn = document.getElementById('recurring-master-panel-open-btn');
        const recurringMasterPanel = document.getElementById('recurringMasterPanel');
        const recurringMasterList = document.getElementById('recurring-master-list');
        const recurringMainList = document.getElementById('recurring-main-list'); // Nueva referencia para la tabla en el cuerpo principal
        const recurringDeleteWarning = document.getElementById('recurring-delete-warning');

        // --- Funciones para manejar el sidebar del menú hamburguesa ---
        if (mobileMenuButton && sidebar && sidebarOverlay) {
            mobileMenuButton.addEventListener('click', () => {
                sidebar.classList.toggle('-translate-x-full');
                sidebarOverlay.classList.toggle('hidden');
            });

            sidebarOverlay.addEventListener('click', () => {
                sidebar.classList.add('-translate-x-full');
                sidebarOverlay.classList.add('hidden');
            });
        }
        // --- FIN Funciones para manejar el sidebar del menú hamburguesa ---


// --- FUNCIONES CORE DE AGENDA (HORARIOS Y SLOTS) ---
        // Funcion que crea los slots disponibles
        function generateAvailableSlots(dateStr) {
            // 1. Determinar el día de la semana y si está bloqueado
            const selectedDate = new Date(dateStr + 'T00:00:00');
            // getDay() devuelve 0 para Domingo, 1 para Lunes, etc.
            const dayOfWeekIndex = selectedDate.getDay();
            const daysMap = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
            const dayName = daysMap[dayOfWeekIndex];

            // 2. Verificar si el día está en la lista de fechas bloqueadas
            const isDateBlocked = dbBlockedDates.some(item => item.blocked_date === dateStr);

            // 3. Obtener la configuración del día y duración del slot
            const dayConfig = dbWeeklyHours[dayName];
            const slotDuration = dbScheduleConfig.slot_duration || 60; // 60 minutos por defecto

            let isAvailable = false;
            let openTimeStr = null;
            let closeTimeStr = null;

            if (dayConfig) {
                // Aseguramos que is_open sea true (no solo '1' o 'true')
                isAvailable = dayConfig.is_open === true;
                openTimeStr = dayConfig.open_time;
                closeTimeStr = dayConfig.close_time;
            }
            
            // Si la fecha está bloqueada o no está disponible en la configuración
            if (isDateBlocked || !isAvailable || !openTimeStr || !closeTimeStr) {
                showToast(`El ${dayName} (${dateStr}) no está disponible.`, 'warning');
                return []; // Retorna lista vacía si no está disponible
            }

            // 4. Generar los slots
            const slots = [];
            // Usamos la fecha seleccionada para el contexto de hora (YYYY-MM-DDT)
            let currentTime = new Date(dateStr + 'T' + openTimeStr);
            const endTime = new Date(dateStr + 'T' + closeTimeStr);
            
            // Si la fecha seleccionada es HOY, ajustar la hora de inicio al futuro
            const now = new Date();
            const isToday = selectedDate.toDateString() === now.toDateString();
            
            if (isToday) {
                // Ajustar el tiempo actual al múltiplo superior del slotDuration
                const currentMinutes = now.getHours() * 60 + now.getMinutes();
                // Calcula el inicio del siguiente slot
                let nextSlotMinutes = Math.ceil(currentMinutes / slotDuration) * slotDuration;

                const nextSlotHour = Math.floor(nextSlotMinutes / 60);
                const nextSlotMinute = nextSlotMinutes % 60;

                // Crear el punto de inicio ajustado para HOY
                let todayStartTime = new Date(dateStr + 'T00:00:00');
                todayStartTime.setHours(nextSlotHour, nextSlotMinute, 0);

                // Si el tiempo ajustado es posterior a la hora de cierre, no hay más slots hoy
                if (todayStartTime.getTime() >= endTime.getTime()) {
                    return [];
                }
                
                // Si el tiempo ajustado es anterior a la hora de apertura definida (ej. estás ajustando a las 8:00 pero abre a las 9:00)
                if (todayStartTime.getTime() < currentTime.getTime()) {
                    // Usamos la hora de apertura definida si ya pasó la hora actual
                    currentTime = new Date(dateStr + 'T' + openTimeStr);
                } else {
                    // Usamos el tiempo ajustado si es posterior a la hora actual y posterior a la hora de apertura
                    currentTime = todayStartTime;
                }
            }
            
            // Generar slots hasta la hora de cierre
            while (currentTime.getTime() < endTime.getTime()) {
                const hour = String(currentTime.getHours()).padStart(2, '0');
                const minute = String(currentTime.getMinutes()).padStart(2, '0');
                slots.push({ hour, minute });
                
                // Avanzar al siguiente slot
                currentTime.setTime(currentTime.getTime() + slotDuration * 60 * 1000);
            }

            return slots;
        }

        // Modificar la función populateTimeSelect existente
        function populateTimeSelect(selectElement, type, slots, selectedHour = null, selectedMinute = null) {
            selectElement.innerHTML = '';
            
            // Si no hay slots disponibles, mostramos una opción vacía
            if (!slots || slots.length === 0) {
                const option = document.createElement('option');
                option.value = '';
                option.textContent = (type === 'hour') ? '🚫 Cerrado o Lleno' : 'N/A';
                selectElement.appendChild(option);
                return;
            }

            if (type === 'hour') {
                const uniqueHours = [...new Set(slots.map(s => s.hour))].sort();
                
                uniqueHours.forEach(hour => {
                    const option = document.createElement('option');
                    option.value = hour;
                    option.textContent = hour;
                    if (hour === selectedHour) {
                        option.selected = true;
                    }
                    selectElement.appendChild(option);
                });
                
            } else if (type === 'minute') {
                const currentSelectedHour = document.getElementById('cita-hora-select').value || selectedHour;

                if (!currentSelectedHour) return;

                const filteredMinutes = slots
                    .filter(s => s.hour === currentSelectedHour)
                    .map(s => s.minute);

                [...new Set(filteredMinutes)].sort().forEach(minute => {
                    const option = document.createElement('option');
                    option.value = minute;
                    option.textContent = minute;
                    if (minute === selectedMinute) {
                        option.selected = true;
                    }
                    selectElement.appendChild(option);
                });
            }
        }
        
        // Función que se ejecuta al cambiar la fecha, actualiza Hora y Minuto
        function updateTimeSlots(dateStr) {
            // Verificación de bloqueo para mostrar alerta visual
            const isBlocked = dbBlockedDates.some(item => item.blocked_date === dateStr);
            if (isBlocked) {
                showToast('ATENCIÓN: Esta fecha está marcada como bloqueada.', 'warning');
            }

            const slots = generateAvailableSlots(dateStr);

            // 1. Popular la hora
            populateTimeSelect(citaHoraSelect, 'hour', slots);
            
            // 2. Almacenar los slots disponibles en el DOM para referencia del minuto
            citaHoraSelect.dataset.slots = JSON.stringify(slots);
            
            // 3. Actualizar los minutos al final, basado en la hora seleccionada por defecto (si hay)
            citaHoraSelect.dispatchEvent(new Event('change'));
            
            // Si no hay slots, deshabilitar los selectores
            const hasSlots = slots && slots.length > 0;
            toggleInputDisabledStyle(citaHoraSelect, !hasSlots);
            toggleInputDisabledStyle(citaMinutoSelect, !hasSlots);
        }

        // Función corregida para alternar el estilo de input deshabilitado
        function toggleInputDisabledStyle(element, isDisabled) {
            element.disabled = isDisabled;
            if (isDisabled) {
                element.classList.add('disabled-input');
            } else {
                element.classList.remove('disabled-input');
            }
        }
        
        async function renderConfigPanel() {
            try {
                const response = await fetch('db/agenda-config-read.php');
                const result = await response.json();

                if (result.status === 'success') {
                    const data = result.data;
                    
                    dbScheduleConfig = data.schedule_config;
                    dbWeeklyHours = data.weekly_hours;
                    dbBlockedDates = data.blocked_dates;
                    
                    configSlotDuration.value = data.schedule_config.slot_duration;
                    configCapacity.value = data.schedule_config.capacity;

                    renderWeeklyHours();

                    renderBlockedDates(data.blocked_dates);
                } else {
                    showToast(`Error al cargar configuración: ${result.message}`, 'error');
                }
            } catch (error) {
                showToast("Error de conexión al cargar la configuración de agenda.", 'error');
            }
        }

        function renderWeeklyHours() {
            weeklyHoursList.innerHTML = '';
            const daysOrder = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
            const daysMap = { 'Monday': 'Lunes', 'Tuesday': 'Martes', 'Wednesday': 'Miércoles', 'Thursday': 'Jueves', 'Friday': 'Viernes', 'Saturday': 'Sábado', 'Sunday': 'Domingo' };

            daysOrder.forEach(dayKey => {
                // Usamos dbWeeklyHours que fue actualizado por la llamada READ
                const config = dbWeeklyHours[dayKey] || { is_open: false, open_time: '09:00', close_time: '17:00' };
                const dayEl = document.createElement('div');
                // Se agregó la clase 'weekly-hour-day' y data-day para el JS
                dayEl.className = 'flex flex-col sm:flex-row items-center justify-between p-3 border-b border-gray-100 weekly-hour-day';
                dayEl.dataset.day = dayKey;
                
                // Asegurar formato HH:MM (slice es por seguridad si el valor viene de una constante 'HH:MM:SS')
                const openTimeDisplay = (config.open_time.length > 5 ? config.open_time.substring(0, 5) : config.open_time) || '09:00';
                const closeTimeDisplay = (config.close_time.length > 5 ? config.close_time.substring(0, 5) : config.close_time) || '17:00';

                dayEl.innerHTML = `
                    <div class="flex items-center w-full sm:w-1/4 mb-2 sm:mb-0">
                        <label class="inline-flex items-center cursor-pointer">
                            <input type="checkbox" data-day="${dayKey}" class="day-checkbox open-checkbox form-checkbox h-5 w-5 text-[var(--color-primary)] rounded focus:ring-[var(--color-highlight)]" ${config.is_open ? 'checked' : ''}>
                            <span class="ml-2 font-bold text-gray-700">${daysMap[dayKey]}</span>
                        </label>
                    </div>
                    <div class="flex gap-2 w-full sm:w-3/4 time-inputs" data-is-open="${config.is_open}">
                        <div class="w-1/2">
                            <label for="${dayKey}-open" class="text-xs text-gray-500 uppercase block">Abre</label>
                            <input type="time" id="${dayKey}-open" value="${openTimeDisplay}" class="w-full p-2 border border-gray-300 rounded-lg bg-white open-time" ${!config.is_open ? 'disabled' : ''}>
                        </div>
                        <div class="w-1/2">
                            <label for="${dayKey}-close" class="text-xs text-gray-500 uppercase block">Cierra</label>
                            <input type="time" id="${dayKey}-close" value="${closeTimeDisplay}" class="w-full p-2 border border-gray-300 rounded-lg bg-white close-time" ${!config.is_open ? 'disabled' : ''}>
                        </div>
                    </div>
                `;
                weeklyHoursList.appendChild(dayEl);
                // Asegurar que el estilo deshabilitado se aplique correctamente al cargar
                const openInput = dayEl.querySelector('.open-time');
                const closeInput = dayEl.querySelector('.close-time');
                toggleInputDisabledStyle(openInput, !config.is_open);
                toggleInputDisabledStyle(closeInput, !config.is_open);
            });

            // Añadir listeners para habilitar/deshabilitar inputs de tiempo
            weeklyHoursList.querySelectorAll('.day-checkbox').forEach(checkbox => {
                checkbox.addEventListener('change', function() {
                    const inputs = this.closest('.weekly-hour-day').querySelectorAll('input[type="time"]');
                    inputs.forEach(input => {
                        input.disabled = !this.checked;
                        toggleInputDisabledStyle(input, !this.checked);
                    });
                });
            });
        }

        // Modificamos para recibir el array de objetos de la BD
        function renderBlockedDates(datesArray) {
            blockedDatesList.innerHTML = '';
            
            if (datesArray.length === 0 || !Array.isArray(datesArray)) {
                 blockedDatesList.innerHTML = '<p class="text-sm text-gray-500 text-center py-2">No hay días bloqueados.</p>';
                 return;
            }

            // Usamos el array de objetos con ID para la eliminación
            datesArray.forEach(item => {
                const dateStr = item.blocked_date;
                const date = new Date(dateStr + 'T00:00:00');
                const dateDisplay = date.toLocaleDateString('es-ES', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
                const dateEl = document.createElement('div');
                dateEl.className = 'flex justify-between items-center bg-white p-2 rounded-md shadow-sm border border-gray-100';
                dateEl.innerHTML = `
                    <span class="text-sm font-medium text-gray-700">${dateDisplay}</span>
                    <button type="button" class="text-red-600 hover:text-red-900 remove-blocked-date" data-id="${item.id}" data-date="${dateStr}" title="Desbloquear Fecha">
                        <i data-lucide="x" class="w-4 h-4"></i>
                    </button>
                `;
                blockedDatesList.appendChild(dateEl);
            });
            lucide.createIcons();
            setupBlockedDateListeners();
        }

        // Modificamos setupBlockedDateListeners para usar el ID de la fila para DELETE
        function setupBlockedDateListeners() {
            blockedDatesList.querySelectorAll('.remove-blocked-date').forEach(button => {
                button.removeEventListener('click', handleRemoveBlockedDate);
                button.addEventListener('click', handleRemoveBlockedDate);
            });
        }
        
        // FUNCIÓN: Eliminar Día Bloqueado (USA agenda-config-delete.php)
        async function handleRemoveBlockedDate(e) {
            e.preventDefault();
            const button = e.currentTarget;
            const idToRemove = button.dataset.id;
            const dateDisplay = button.dataset.date;
            if (!confirm(`¿Estás seguro de que deseas desbloquear la fecha ${dateDisplay}?`)) return;

             try {
                const response = await fetch('db/agenda-config-delete.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ id: idToRemove })
                });
                const result = await response.json();
                if (result.status === 'success') {
                    showToast(`Fecha ${dateDisplay} desbloqueada con éxito.`, 'success');
                    // Recargar el panel para actualizar la lista de bloqueados
                    renderConfigPanel();
                    renderAgenda();
                } else {
                    showToast("Error al desbloquear fecha: " + result.message, 'error');
                }
            } catch (error) {
                showToast("Error de conexión al desbloquear la fecha.", 'error');
            }
        }


// --- MANEJO DE EVENTOS Y ENVÍOS (CONECTADO A LOS ARCHIVOS CONFIG-PHP) ---

        // Listener para abrir el panel de gestión de recurrencias
        if (recurringMasterPanelOpenBtn) {
            recurringMasterPanelOpenBtn.addEventListener('click', () => {
                openPanel('recurringMasterPanel');
                renderRecurringMasterPanel();
            });
        }

        // Nuevo Listener para abrir el panel de configuración
        if (configPanelOpenBtn) {
            configPanelOpenBtn.addEventListener('click', () => {
                // Abre el panel y luego carga los datos
                openPanel('configPanel');
                renderConfigPanel();
            });
        }

        // EVENTO: Guardar Capacidad y Duración (CORREGIDO)
        if (configCapacityForm) {
            configCapacityForm.addEventListener('submit', async function(e) {
                e.preventDefault();
                const slotDuration = parseInt(configSlotDuration.value);
                const capacity = parseInt(configCapacity.value);
                const saveButton = document.getElementById('save-capacity-btn');
                toggleButtonDisabledStyle(saveButton, true);

                if (isNaN(slotDuration) || slotDuration < 15 || isNaN(capacity) || capacity < 1) {
                    showToast("Por favor, introduce valores válidos para la duración (mín. 15) y capacidad (mín. 1).", 'warning');
                    toggleButtonDisabledStyle(saveButton, false);
                    return;
                }

                try {
                    const response = await fetch('db/agenda-config-update.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ action: 'update_schedule_config', slot_duration: slotDuration, capacity: capacity })
                    });
                    const result = await response.json();
                    if (result.status === 'success') {
                        showToast("Capacidad y duración actualizadas con éxito.", 'success');
                        // Actualizar variable global y recargar la agenda
                        dbScheduleConfig.slot_duration = slotDuration;
                        dbScheduleConfig.capacity = capacity;
                        renderAgenda();
                    } else {
                        showToast("Error al guardar capacidad: " + result.message, 'error');
                    }
                } catch (error) {
                    showToast("Error de conexión al guardar la configuración.", 'error');
                } finally {
                    toggleButtonDisabledStyle(saveButton, false);
                }
            });
        }

        // EVENTO: Guardar Horario Semanal (CORREGIDO)
        if (configWeeklyHoursForm) {
            configWeeklyHoursForm.addEventListener('submit', async function(e) {
                e.preventDefault();
                const saveButton = document.getElementById('save-weekly-hours-btn');
                toggleButtonDisabledStyle(saveButton, true);
                
                const updates = [];
                let hasInvalidHours = false;

                // CRÍTICO: Recorrer los elementos generados por renderWeeklyHours
                weeklyHoursList.querySelectorAll('.weekly-hour-day').forEach(dayRow => {
                    const checkbox = dayRow.querySelector('.open-checkbox');
                    const openTimeInput = dayRow.querySelector('.open-time');
                    const closeTimeInput = dayRow.querySelector('.close-time');

                    const day = dayRow.dataset.day; // Usar el data-day del contenedor
                    const isOpen = checkbox.checked;
                    const openTime = openTimeInput.value;
                    const closeTime = closeTimeInput.value;
                    
                    if (isOpen && openTime >= closeTime) {
                        showToast(`El horario de cierre para ${day} debe ser posterior al de apertura.`, 'warning');
                        hasInvalidHours = true;
                    }

                    // CRÍTICO: Asegurar formato HH:MM:SS y booleano/entero
                    updates.push({
                        day: day,
                        is_open: isOpen ? 1 : 0,
                        open_time: openTime + ':00',
                        close_time: closeTime + ':00'
                    });
                });

                if (hasInvalidHours) {
                    toggleButtonDisabledStyle(saveButton, false);
                    return;
                }

                try {
                    const response = await fetch('db/agenda-config-update.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ action: 'update_weekly_hours', updates: updates })
                    });
                    const result = await response.json();
                    if (result.status === 'success') {
                        showToast("Horario semanal actualizado con éxito.", 'success');
                        result.new_hours.forEach(item => {
                            dbWeeklyHours[item.day] = {
                                is_open: item.is_open,
                                open_time: item.open_time,
                                close_time: item.close_time
                            };
                        });
                        renderAgenda();
                        // Re-renderiza el panel para mostrar el estado actualizado de los inputs
                        renderWeeklyHours();
                    } else {
                        showToast("Error al guardar horario: " + result.message, 'error');
                    }
                } catch (error) {
                    showToast("Error de conexión al guardar el horario.", 'error');
                } finally {
                    toggleButtonDisabledStyle(saveButton, false);
                }
            });
        }

        // EVENTO: Añadir Día Bloqueado (USA agenda-config-create.php)
        if (addBlockedDateBtn) {
            addBlockedDateBtn.addEventListener('click', async function() {
                const dateToBlock = configBlockDate.value;
                
                // CRÍTICO: dbBlockedDates ahora es un array de objetos.
                const blockedDatesArray = dbBlockedDates.map(item => item.blocked_date);
                
                if (!dateToBlock) {
                    showToast("Selecciona una fecha para bloquear.", 'warning');
                    return;
                }
                if (blockedDatesArray.includes(dateToBlock)) {
                    showToast("Esta fecha ya está bloqueada.", 'info');
                    return;
                }

                try {
                    const response = await fetch('db/agenda-config-create.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ blocked_date: dateToBlock })
                    });
                    const result = await response.json();
                    if (result.status === 'success' || result.status === 'warning') {
                        showToast(result.message, result.status);
                        // Llama a renderConfigPanel para recargar todo el panel y la lista de bloqueados
                        renderConfigPanel();
                        renderAgenda();
                        configBlockDate.value = '';
                    } else {
                        showToast("Error al bloquear fecha: " + result.message, 'error');
                    }
                } catch (error) {
                    showToast("Error de conexión al bloquear la fecha.", 'error');
                }
            });
        }
        
        // --- FUNCIONES HELPER GLOBALES ---

        function toggleButtonDisabledStyle(element, isDisabled) {
            element.disabled = isDisabled;
            if (isDisabled) {
                element.classList.add('opacity-50', 'cursor-not-allowed', 'pointer-events-none');
            } else {
                element.classList.remove('opacity-50', 'cursor-not-allowed', 'pointer-events-none');
            }
        }

        window.openPanel = function(panelId) {
            const panel = document.getElementById(panelId);
            if (!panel) { showToast(`Error: Panel con ID "${panelId}" no encontrado.`, 'error'); return; }

            if (panelId === 'agendarServicioPanel') {
                agendarServicioForm.reset();
                citaClienteInfo.textContent = '';
                citaProspectoInfoAdicional.textContent = '';
                
                toggleInputDisabledStyle(citaClienteDisplay, false);
                toggleInputDisabledStyle(citaProspectoDisplay, false);
                
                const today = new Date();
                const todayFormatted = today.toISOString().split('T')[0];
                
                // Establecer la fecha de hoy por defecto y el mínimo
                citaFecha.value = todayFormatted;
                citaFecha.setAttribute('min', todayFormatted);
                
                // CRÍTICO: Generar y popular los slots basados en la fecha de hoy
                updateTimeSlots(todayFormatted);
                
                // Añadir listener para actualizar los slots al cambiar la fecha
                citaFecha.removeEventListener('change', handleDateChangeForSlots);
                citaFecha.addEventListener('change', handleDateChangeForSlots);

                // Añadir listener para actualizar minutos al cambiar la hora
                citaHoraSelect.removeEventListener('change', handleHourChangeForMinutes);
                citaHoraSelect.addEventListener('change', handleHourChangeForMinutes);
            }

            panel.classList.remove('translate-x-full');
            panelOverlay.classList.remove('hidden');
            document.body.style.overflow = 'hidden';
        };

        // Handlers para los Listeners de tiempo
        function handleDateChangeForSlots() {
            updateTimeSlots(this.value);
            calculateAndDisplayNextRecurringDate();
        }

        function handleHourChangeForMinutes() {
            const slots = JSON.parse(this.dataset.slots || '[]');
            populateTimeSelect(citaMinutoSelect, 'minute', slots);
        }

        window.closePanel = function(panelId) {
            const panel = document.getElementById(panelId);
            if (!panel) { showToast(`Error: Panel con ID "${panelId}" no encontrado para cerrar.`, 'error'); return; }
            panel.classList.add('translate-x-full');
            panelOverlay.classList.add('hidden');
            document.body.style.overflow = '';
        };

        window.openModal = function(modalId) {
            const modal = document.getElementById(modalId);
            if (!modal) { showToast(`Error: Modal con ID "${modalId}" no encontrado.`, 'error'); return; }
            const modalBox = modal.querySelector('div:first-of-type');
            modal.classList.remove('hidden');
            setTimeout(() => { modalBox.classList.remove('scale-95', 'opacity-0'); }, 50);
            document.body.style.overflow = 'hidden';
        };

        window.closeModal = function(modalId) {
            const modal = document.getElementById(modalId);
            if (!modal) { showToast(`Error: Modal con ID "${modalId}" no encontrado para cerrar.`, 'error'); return; }
            const modalBox = modal.querySelector('div:first-of-type');
            modalBox.classList.add('scale-95', 'opacity-0');
            setTimeout(() => {
                modal.classList.add('hidden');
                document.body.style.overflow = '';
            }, 300);
        };

        window.openConfirmDeleteModal = function(citaIdFull, citaType) {
            // Asegúrate de que deleteItemNameSpan esté definido en la lista de consts del DOM.
            if (!confirmDeleteButton || !confirmItemTypeSpan || !deleteItemNameSpan || !recurringDeleteWarning) {
                showToast("Error: Elementos del modal de confirmación de eliminación no encontrados.", 'error');
                return;
            }
            
            let cita = null;
            let displayName = 'SIN DETALLE';
            let itemTypeText = 'CITA/ELEMENTO';
            
            // Ocultar la advertencia por defecto
            recurringDeleteWarning.classList.add('hidden');

            // 1. Obtener la data y el tipo
            if (citaType.includes('unica')) {
                cita = dbCitasUnicas[citaIdFull];
                itemTypeText = 'CITA ÚNICA';
            } else if (citaType.includes('recurrente')) {
                cita = dbCitasRecurrentes[citaIdFull];
                itemTypeText = 'CITA RECURRENTE MAESTRA'; // Título más específico para la maestra
                recurringDeleteWarning.classList.remove('hidden'); // Mostrar la advertencia
            }

            if (cita) {
                // 2. Construir la frase completa: "CON [Nombre] [Fecha] [Hora]"
                
                let detalleCita = '';
                
                // Obtener nombre del asociado
                const associatedName = cita.associated_entity_name || `(ID: ${citaIdFull.split('-').pop()})`;

                if (citaType.includes('unica') && cita.appointment_date && cita.appointment_time) {
                    // Formatear la fecha como "21 NOV"
                    const dateObj = new Date(cita.appointment_date + 'T00:00:00');
                    const date = dateObj.toLocaleDateString('es-ES', { day: 'numeric', month: 'short' }).toUpperCase().replace('.', '');
                    const time = cita.appointment_time.substring(0, 5);
                    
                    // Resultado esperado: "CON JAVIER ORTIZ EL 21 NOV A LAS 13:00"
                    detalleCita = `CON ${associatedName} EL ${date} A LAS ${time}`;

                } else if (citaType.includes('recurrente')) {
                    // Resultado esperado: "CON JAVIER ORTIZ (SEMANAL)"
                    detalleCita = `CON ${associatedName} (${cita.frequency ? cita.frequency.toUpperCase() : 'RECURRENCIA'})`;
                } else {
                     detalleCita = associatedName;
                }

                displayName = detalleCita;
            }

            // 3. Inyectar datos en el modal
            confirmDeleteButton.dataset.itemId = citaIdFull;
            confirmDeleteButton.dataset.itemType = citaType;
            
            // Inyectar el TIPO del elemento y el NOMBRE DETALLADO
            confirmItemTypeSpan.textContent = itemTypeText;
            deleteItemNameSpan.textContent = displayName.toUpperCase();

            // 4. Abrir modal
            openModal('confirmDeleteModal');
        };

        function setupDeleteListeners() {
            document.querySelectorAll('.delete-btn').forEach(button => {
                button.removeEventListener('click', handleDeleteButtonClick);
                button.addEventListener('click', handleDeleteButtonClick);
            });
        }

        function handleDeleteButtonClick(e) {
            e.stopPropagation();
            const citaIdFull = this.dataset.itemId;
            const itemType = this.dataset.itemType;
            window.openConfirmDeleteModal(citaIdFull, itemType);
        }

        window.openViewCitaPanel = function(citaId, citaType) {
            let cita;
            if (citaType === 'unica' || citaType === 'recurrente-hija') { // Una cita hija se trata como única para la edición
                cita = dbCitasUnicas[citaId];
            } else if (citaType === 'recurrente') {
                cita = dbCitasRecurrentes[citaId];
            }
            if (!cita) {
                showToast('[Agenda] Cita no encontrada: ' + citaId + ' ' + citaType, 'error');
                return;
            }

            // Set basic values
            viewCitaId.value = citaId;
            viewCitaType.value = citaType;
            viewCitaOriginalStatus.value = cita.status || '';

            const client = Object.values(dbClients).find(c => c.id == cita.client_id);
            viewCitaCliente.value = decodeHtmlEntities(client ? client.name : (cita.client_name || ''));
            viewCitaClienteInfo.textContent = client ? `Email: ${client.email || 'N/A'} | Tel: ${formatPhoneNumber(client.phone) || formatPhoneNumber(client.mobile_phone) || 'N/A'}` : '';
            toggleInputDisabledStyle(viewCitaCliente, true);

            const lead = Object.values(dbLeads).find(l => l.id == cita.lead_id);
            viewCitaProspecto.value = decodeHtmlEntities(lead ? lead.name : (cita.prospect_name || ''));
            viewCitaProspectoInfoAdicional.textContent = lead ? `Email: ${lead.email || 'N/A'} | Tel: ${formatPhoneNumber(lead.phone) || formatPhoneNumber(lead.mobile_phone) || 'N/A'}` : '';
            toggleInputDisabledStyle(viewCitaProspecto, true);

            viewCitaNotas.value = decodeHtmlEntities(cita.notes || '');

            const now = new Date();
            const todayFormatted = now.toISOString().split('T')[0];
            viewCitaFecha.setAttribute('min', todayFormatted);

            const isCitaCompletedOrCancelled = cita.status === 'completed' || cita.status === 'cancelled';

            // Logic for unique vs recurring appointments
            if (citaType === 'unica' || citaType === 'recurrente-hija') { // Cita Única o Cita Hija
                viewCitaFechaGroup.classList.remove('hidden');
                viewCitaHoraGroup.classList.remove('hidden');
                viewCitaFrecuenciaGroup.classList.add('hidden');
                viewCitaProximaCitaGroup.classList.add('hidden');

                viewCitaFecha.value = cita.appointment_date || '';
                const [hora, minuto] = (cita.appointment_time || '00:00').split(':');
                
                // Usamos la función original de populacion simple para evitar complejidad de regeneración de slots en edición por ahora
                // ya que los slots fijos ya fueron guardados
                populateTimeSelectOriginal(viewCitaHoraSelect, 'hour', hora);
                populateTimeSelectOriginal(viewCitaMinutoSelect, 'minute', minuto);

                const citaDateTime = new Date(cita.appointment_date + 'T' + (cita.appointment_time || '00:00'));
                const isPastAppointment = citaDateTime < now;

                toggleInputDisabledStyle(viewCitaFecha, isPastAppointment || isCitaCompletedOrCancelled);
                toggleInputDisabledStyle(viewCitaHoraSelect, isPastAppointment || isCitaCompletedOrCancelled);
                toggleInputDisabledStyle(viewCitaMinutoSelect, isPastAppointment || isCitaCompletedOrCancelled);

            } else { // Recurring appointment Master
                viewCitaFechaGroup.classList.add('hidden');
                viewCitaHoraGroup.classList.add('hidden');
                viewCitaFrecuenciaGroup.classList.remove('hidden');
                viewCitaProximaCitaGroup.classList.remove('hidden');

                viewCitaFrecuencia.value = cita.frequency || '';
                const initialDateForCalculation = cita.next_appointment_date || cita.first_appointment_date || (new Date().toISOString().split('T')[0]);
                const nextCalculatedDate = calculateNextRecurringDate(initialDateForCalculation, viewCitaFrecuencia.value);
                viewCitaProximaCitaDisplay.value = nextCalculatedDate.toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' });
                viewCitaProximaCita.value = nextCalculatedDate.toISOString().split('T')[0];

                toggleInputDisabledStyle(viewCitaFrecuencia, isCitaCompletedOrCancelled);
                toggleInputDisabledStyle(viewCitaProximaCitaDisplay, true); // Always readonly as it's calculated
            }

            // Disable notes and save button if completed or cancelled
            toggleInputDisabledStyle(viewCitaNotas, isCitaCompletedOrCancelled);
            toggleButtonDisabledStyle(saveCitaChangesBtn, isCitaCompletedOrCancelled);

            openPanel('viewCitaPanel');
        };
        
        // Versión original de populateTimeSelect para la edición de citas (donde no necesitamos lógica de slots complejos)
        function populateTimeSelectOriginal(selectElement, type, selectedValue = null) {
            selectElement.innerHTML = '';
            if (type === 'hour') {
                for (let i = 0; i < 24; i++) {
                    const option = document.createElement('option');
                    option.value = String(i).padStart(2, '0');
                    option.textContent = String(i).padStart(2, '0');
                    if (option.value === selectedValue) {
                        option.selected = true;
                    }
                    selectElement.appendChild(option);
                }
            } else if (type === 'minute') {
                for (let i = 0; i < 60; i += 15) {
                    const option = document.createElement('option');
                    option.value = String(i).padStart(2, '0');
                    option.textContent = String(i).padStart(2, '0');
                    if (option.value === selectedValue) {
                        option.selected = true;
                    }
                    selectElement.appendChild(option);
                }
            }
        }


        function updateViewRecurringDate() {
            const currentCitaId = viewCitaId.value;
            const currentCitaType = viewCitaType.value;
            let baseDateStr = '';
            
            if (currentCitaType === 'recurrente') {
                const citaObj = dbCitasRecurrentes[currentCitaId];
                if (citaObj) {
                    // Usamos la fecha de la cita maestra como base para el cálculo de la siguiente
                    baseDateStr = citaObj.first_appointment_date || (new Date().toISOString().split('T')[0]);
                }
            } else if (currentCitaType === 'unica' || currentCitaType === 'recurrente-hija') {
                baseDateStr = viewCitaFecha.value;
            }

            const frequency = viewCitaFrecuencia.value;

            if (baseDateStr && frequency) {
                const nextDate = calculateNextRecurringDate(baseDateStr, frequency);
                viewCitaProximaCitaDisplay.value = nextDate.toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' });
                viewCitaProximaCita.value = nextDate.toISOString().split('T')[0];
            } else {
                viewCitaProximaCitaDisplay.value = 'Selecciona una fecha y frecuencia';
                viewCitaProximaCita.value = '';
            }
        }
        
        function setupDeleteListeners() {
            document.querySelectorAll('.delete-btn').forEach(button => {
                button.removeEventListener('click', handleDeleteButtonClick);
                button.addEventListener('click', handleDeleteButtonClick);
            });
        }

        function handleDeleteButtonClick(e) {
            e.stopPropagation();
            const citaIdFull = this.dataset.itemId;
            const itemType = this.dataset.itemType;
            window.openConfirmDeleteModal(citaIdFull, itemType);
        }

        function setupEditListeners() {
            // Este es el punto crítico para asegurar que los listeners se adjunten
            document.querySelectorAll('.edit-cita-btn').forEach(button => {
                button.removeEventListener('click', handleEditCitaButtonClick); // Eliminar listener previo
                button.addEventListener('click', handleEditCitaButtonClick); // Adjuntar nuevo listener
            });
        }

        function handleEditCitaButtonClick(e) {
            e.stopPropagation();
            const citaId = this.dataset.citaId;
            const citaType = this.dataset.citaType;
            window.openViewCitaPanel(citaId, citaType);
        }

        function setupStatusActionListeners() {
            document.querySelectorAll('.action-complete-btn').forEach(button => {
                button.removeEventListener('click', handleCompleteCitaClick);
                button.addEventListener('click', handleCompleteCitaClick);
            });
            document.querySelectorAll('.action-cancel-btn').forEach(button => {
                button.removeEventListener('click', handleCancelCitaClick);
                button.addEventListener('click', handleCancelCitaClick);
            });
            document.querySelectorAll('.action-confirm-btn').forEach(button => {
                button.removeEventListener('click', handleConfirmCitaClick);
                button.addEventListener('click', handleConfirmCitaClick);
            });
            document.querySelectorAll('.action-message-btn').forEach(button => {
                button.removeEventListener('click', handleMessageCitaClick);
                button.addEventListener('click', handleMessageCitaClick);
            });
        }

        async function handleStatusUpdate(button, newStatus) {
            const citaIdFull = button.dataset.citaId;
            const citaType = button.dataset.citaType;
            const numericId = citaIdFull.split('-').pop();
            try {
                const response = await fetch('db/agenda-update.php', {
                    method: 'PUT',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ id: numericId, type: 'unica', status: newStatus }) // Forzamos a 'unica' para que afecte solo a la hija
                });
                const result = await response.json();
                if (result.status === 'success') {
                    showToast(`Cita marcada como ${newStatus}.`, 'success');
                    // La actualización solo afecta a la cita "hija" o única, por eso solo actualizamos dbCitasUnicas
                    dbCitasUnicas[citaIdFull].status = newStatus;
                    renderAppointmentList();
                    renderAgenda();
                } else {
                    showToast(`Error al actualizar estado: ${result.message}`, 'error');
                }
            } catch (error) {
                showToast('Hubo un problema de conexión al actualizar.', 'error');
            }
        }
        
        function handleCompleteCitaClick() { handleStatusUpdate(this, 'completed'); }
        function handleCancelCitaClick() { handleStatusUpdate(this, 'cancelled'); }
        function handleConfirmCitaClick() { handleStatusUpdate(this, 'confirmed'); }

        function handleMessageCitaClick() {
            const citaIdFull = this.dataset.citaId;
            const citaType = this.dataset.citaType;
            let cita = (citaType === 'unica' || citaType === 'recurrente-hija') ? dbCitasUnicas[citaIdFull] : dbCitasRecurrentes[citaIdFull];

            if (!cita) {
                showToast(`Cita no encontrada: ${citaIdFull}`, 'error');
                return;
            }

            const client = cita.client_id ? Object.values(dbClients).find(c => c.id == cita.client_id) : null;
            const prospect = cita.lead_id ? Object.values(dbLeads).find(l => l.id == cita.lead_id) : null;

            if (!client && !prospect) {
                showToast(`Falta cliente/prospecto asociado.`, 'error');
                return;
            }

            const mainContact = client || prospect;
            const mainContactName = mainContact.first_name;
            const phoneToUse = mainContact.mobile_phone || mainContact.phone;
            const appointmentDetails = client && prospect ? ` con *${prospect.name}*` : '';

            // Visualizar info en el panel
            msgCitaCliente.textContent = client ? client.name : 'N/A';
            msgCitaProspecto.textContent = prospect ? prospect.name : 'N/A';
            const dateObj = new Date(cita.appointment_date + 'T00:00:00');
            msgCitaFecha.textContent = dateObj.toLocaleDateString('es-ES', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
            msgCitaHora.textContent = cita.appointment_time ? cita.appointment_time.substring(0, 5) : 'N/A';
            msgCitaTipo.textContent = (cita.type === 'unica' || cita.type === 'recurrente-hija') ? 'Única' : 'Recurrente';
            msgCitaTelefono.textContent = formatPhoneNumber(phoneToUse) || 'N/A';

            // --- LÓGICA DE LINK ---
// --- LÓGICA INTELIGENTE DE ENLACE ---
            const baseUrl = window.location.origin + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/'));
            let actionLink = '';
            let showLinkInMessage = false;
            
            if (cita.public_token) {
                // SI TIENE TOKEN (Correcto)
                showLinkInMessage = true;
                if (cita.status === 'pending') {
                    // Si está pendiente -> Link para APROBAR (booking-confirm)
                    actionLink = `${baseUrl}/booking-confirm.php?token=${cita.public_token}`;
                } else {
                    // Si ya está confirmada -> Link para VER ESTADO (appointment-status)
                    actionLink = `${baseUrl}/booking-status.php?token=${cita.public_token}`;
                }
            } else {
                // SI NO TIENE TOKEN (Error de datos viejos)
                // NO enviamos a booking.php. Simplemente no generamos link.
                showLinkInMessage = false;
                actionLink = "Enlace no disponible (Contactar soporte)";
                // Opcional: Mostrar alerta visual al admin
                showToast("Atención: Esta cita antigua no tiene token generado.", "warning");
            }

            const businessIdentifier = `${appSettings.contactName}, ${appSettings.companyName}`;
            const dateFormattedEs = dateObj.toLocaleDateString('es-ES', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
            const timeFormatted = cita.appointment_time ? cita.appointment_time.substring(0, 5) : '';

            // --- MENSAJE ESPAÑOL ---
            let msgEs = `¡Hola ${mainContactName}!\n\n`;
            
            if (cita.status === 'pending') {
                msgEs += `He agendado tu cita para el día *${dateFormattedEs}* a las *${timeFormatted}*.\n\n`;
                if (showLinkInMessage) {
                    msgEs += `Por favor, confirma tu asistencia aquí:\n${actionLink}`;
                } else {
                    msgEs += `Por favor contéstame este mensaje para confirmar.`;
                }
            } else {
                msgEs += `Te confirmo tu cita${appointmentDetails} el día *${dateFormattedEs}* a las *${timeFormatted}*.\n\n`;
                if (showLinkInMessage) {
                    msgEs += `Puedes ver los detalles aquí:\n${actionLink}`;
                }
            }
            msgEs += `\n\n¡Gracias!\n${businessIdentifier}`;
            messageSpanish.value = msgEs;
            
            // --- MENSAJE INGLÉS ---
            const dateFormattedEn = dateObj.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
            let msgEn = `Hi ${mainContactName}!\n\n`;
            
            if (cita.status === 'pending') {
                msgEn += `I have scheduled your appointment for *${dateFormattedEn}* at *${timeFormatted}*.\n\n`;
                if (showLinkInMessage) {
                    msgEn += `Please confirm your attendance here:\n${actionLink}`;
                } else {
                    msgEn += `Please reply to confirm.`;
                }
            } else {
                msgEn += `This is to confirm your appointment${appointmentDetails} on *${dateFormattedEn}* at *${timeFormatted}*.\n\n`;
                if (showLinkInMessage) {
                    msgEn += `You can view details here:\n${actionLink}`;
                }
            }
            msgEn += `\n\nThanks!\n${businessIdentifier}`;
            messageEnglish.value = msgEn;

            openPanel('messageCitaPanel');
        }

        copyMessageBtns.forEach(button => {
            button.addEventListener('click', async function() {
                const lang = this.dataset.lang;
                const messageTextArea = lang === 'es' ? messageSpanish : messageEnglish;
                try {
                    await navigator.clipboard.writeText(messageTextArea.value);
                    showToast(`Mensaje copiado al portapapeles.`, 'success');
                } catch (err) {
                    showToast('Error al copiar el mensaje.', 'error');
                }
            });
        });

        sendWhatsappBtns.forEach(button => {
            button.addEventListener('click', function() {
                const lang = this.dataset.lang;
                const messageTextArea = lang === 'es' ? messageSpanish : messageEnglish;
                let phoneNumber = msgCitaTelefono.textContent.replace(/\D/g, ''); // Usamos let para poder modificarlo

                if (phoneNumber && phoneNumber !== 'NA') {
                    // Lógica para agregar el '1' si es un número de 10 dígitos (para números de EE.UU.)
                    // Recordatorio: Estás en Chiquimulilla, Guatemala, por lo que esta lógica podría no ser universalmente aplicable
                    // y debería considerarse si tus clientes están en EE.UU. o Guatemala.
                    if (phoneNumber.length === 10) { // Assuming 10-digit numbers are US numbers
                        phoneNumber = '1' + phoneNumber;
                    }

                    const encodedMessage = encodeURIComponent(messageTextArea.value);
                    window.open(`https://wa.me/${phoneNumber}?text=${encodedMessage}`, '_blank');
                    showToast(`Abriendo WhatsApp...`, 'info');
                } else {
                    showToast('Número de teléfono no disponible.', 'warning');
                }
            });
        });

        function renderAgenda() {
            const calendarGrid = document.getElementById('calendar-grid');
            const periodTitle = document.getElementById('period-title');
            const monthlyTotal = document.getElementById('monthly-total');
            const monthlyNew = document.getElementById('monthly-new');
            const monthlyCancelled = document.getElementById('monthly-cancelled');
            const monthlyRecurring = document.getElementById('monthly-recurring');
            renderPendingRequests();
            if (!calendarGrid || !periodTitle || !monthlyTotal || !monthlyNew || !monthlyCancelled || !monthlyRecurring) return;
            calendarGrid.innerHTML = '';
            const todayAtMidnight = new Date();
            todayAtMidnight.setHours(0, 0, 0, 0);
            let displayStartDate, daysToRender;
            if (currentView === 'weekly') {
                const startOfWeek = new Date(currentDate);
                startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay());
                displayStartDate = startOfWeek;
                const displayEndDate = new Date(startOfWeek);
                displayEndDate.setDate(displayEndDate.getDate() + 6);
                periodTitle.textContent = `${displayStartDate.toLocaleDateString('es-ES', {day: 'numeric', month: 'short'}).toUpperCase()} - ${displayEndDate.toLocaleDateString('es-ES', {day: 'numeric', month: 'short', year: 'numeric'}).toUpperCase()}`;
                daysToRender = 7;
                // MODIFICACIÓN: Añadir clase para la vista semanal en móvil para activar el grid de 2 en 2
                calendarGrid.className = 'grid grid-cols-1 md:grid-cols-7 gap-px bg-gray-200 border border-gray-200 rounded-lg overflow-hidden weekly-mobile-grid';
                viewWeeklyBtn.className = 'btn-secondary font-bold py-2 px-4 rounded-lg uppercase';
                viewMonthlyBtn.className = 'bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg uppercase';
            } else {
                const startOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
                displayStartDate = startOfMonth;
                periodTitle.textContent = `${displayStartDate.toLocaleDateString('es-ES', {month: 'long', year: 'numeric'}).toUpperCase()}`;
                let firstDayOfMonth = startOfMonth.getDay();
                let startGridDate = new Date(startOfMonth);
                startGridDate.setDate(startOfMonth.getDate() - firstDayOfMonth);
                daysToRender = 42;
                // MODIFICACIÓN CLAVE: Clases responsivas para la cuadrícula del calendario y altura mínima
                // Se ha ajustado el min-h para la vista mensual para que sea más compacto en móviles.
                calendarGrid.className = 'grid grid-cols-7 gap-px bg-gray-200 border border-gray-200 rounded-lg overflow-hidden';
                // REMOVER CLASE weekly-mobile-grid para que no afecte la vista mensual
                calendarGrid.classList.remove('weekly-mobile-grid');
                displayStartDate = startGridDate;
                viewMonthlyBtn.className = 'btn-secondary font-bold py-2 px-4 rounded-lg uppercase';
                viewWeeklyBtn.className = 'bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg uppercase';
            }
            const currentMonthStart = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
            const nextMonthStart = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
            const monthlyUniqueAppointments = Object.values(dbCitasUnicas).filter(c => {
                const citaDate = new Date(c.appointment_date + 'T00:00:00');
                return citaDate >= currentMonthStart && citaDate < nextMonthStart;
            });
            
            // Contar citas maestras (no citas hijas)
            const monthlyRecurringMasters = Object.values(dbCitasRecurrentes).filter(c => {
                const firstCitaDate = new Date(c.first_appointment_date + 'T00:00:00');
                return firstCitaDate >= currentMonthStart && firstCitaDate < nextMonthStart;
            });
            
            monthlyTotal.textContent = (monthlyUniqueAppointments.length).toString(); // Solo citas únicas, las maestras recurrentes no son citas en sí
            monthlyNew.textContent = monthlyUniqueAppointments.filter(c => c.status === 'pending' || c.status === 'confirmed').length.toString();
            monthlyCancelled.textContent = monthlyUniqueAppointments.filter(c => c.status === 'cancelled').length.toString();
            monthlyRecurring.textContent = monthlyRecurringMasters.length.toString(); // Contar las reglas maestras

            for (let i = 0; i < daysToRender; i++) {
                const day = new Date(displayStartDate);
                day.setDate(day.getDate() + i);
                const dayCol = document.createElement('div');
                // MODIFICACIÓN CLAVE: min-h para vista mensual en móvil (más compacto)
                // Se ha ajustado el min-h para la vista mensual para que sea más compacto en móviles.
                const minHeightClass = currentView === 'monthly' ? 'min-h-[70px] sm:min-h-[100px] md:min-h-[150px]' : 'min-h-[150px]';
                dayCol.className = `bg-white p-2 ${minHeightClass} calendar-day-clickable relative`;
                dayCol.dataset.date = day.toISOString().split('T')[0];
                const isToday = day.toDateString() === todayAtMidnight.toDateString();
                const isOutsideMonth = currentView === 'monthly' && (day.getMonth() !== currentDate.getMonth());
                dayCol.innerHTML = `<div class="calendar-day-header text-center p-2 mb-2 rounded-lg ${isToday ? 'today' : ''} ${isOutsideMonth ? 'opacity-50' : ''}"><p class="font-bold text-sm">${day.toLocaleDateString('es-ES', { weekday: 'short' }).toUpperCase()}</p><p class="text-2xl font-bold">${day.getDate()}</p></div><div class="space-y-2 appointment-list-day overflow-y-auto max-h-[90px] pr-1 -mr-1"></div>`;
                const appointmentListDayEl = dayCol.querySelector('.appointment-list-day');
                const dayString = day.toISOString().split('T')[0];
                
                // 1. Citas Reales (Únicas o Hijas ya creadas)
                let dailyAppointments = Object.values(dbCitasUnicas)
                    .filter(cita => cita.appointment_date === dayString && cita.status !== 'cancelled' && cita.status !== 'completed')
                    .map(cita => ({...cita, id: `cita-unica-${cita.id}`, isVirtual: false }));

                // 2. Proyección de Recurrencias (Virtuales)
                Object.values(dbCitasRecurrentes).forEach(master => {
                    if (checkIfRecurringDateMatches(master, dayString)) {
                        // Solo mostrar si no existe ya una cita real ese día para esa serie
                        const existsReal = dailyAppointments.some(real => real.recurring_parent_id == master.id);
                        if (!existsReal) {
                            dailyAppointments.push({
                                id: `virtual-${master.id}`,
                                type: 'recurrente', 
                                appointment_date: dayString,
                                appointment_time: master.appointment_time,
                                associated_entity_name: master.associated_entity_name + ' (R)',
                                status: 'virtual',
                                notes: master.notes,
                                isVirtual: true 
                            });
                        }
                    }
                });

                const allDayAppointments = dailyAppointments.sort((a,b) => (a.appointment_time || '00:00').localeCompare(b.appointment_time || '00:00'));
                
                if (allDayAppointments.length > 0) {
                    allDayAppointments.forEach(cita => {
                        const appointmentEl = document.createElement('div');
                        let statusClasses = '', statusIcon = '';
                        if (cita.status === 'cancelled') { statusClasses = 'cancelled'; statusIcon = '<i data-lucide="x-circle" class="w-4 h-4 text-gray-500"></i>'; }
                        else if (cita.status === 'completed') { statusClasses = 'completed'; statusIcon = '<i data-lucide="check-circle" class="w-4 h-4 text-green-600"></i>'; }
                        else if (cita.isVirtual) { statusClasses = 'bg-purple-50 border border-purple-100 opacity-75'; statusIcon = '<i data-lucide="calendar-clock" class="w-4 h-4 text-purple-500"></i>'; } // Cita Virtual
                        else if (cita.recurring_parent_id) { statusIcon = '<i data-lucide="repeat" class="w-4 h-4 text-blue-600"></i>'; } // Icono para citas hijas
                        else if (cita.status === 'pending') { statusClasses = 'bg-orange-100'; statusIcon = '<i data-lucide="bell" class="w-4 h-4 text-orange-500"></i>'; }
                        else if (cita.status === 'confirmed') { statusClasses = 'bg-blue-100'; statusIcon = '<i data-lucide="check" class="w-4 h-4 text-blue-600"></i>'; }
                        else { statusClasses = 'bg-gray-100'; statusIcon = '<i data-lucide="help-circle" class="w-4 h-4 text-gray-500"></i>'; }

                        // Ajuste en las clases para la visualización del estado
                        const statusBadgeClass = `px-2 py-1 rounded-full text-xs font-semibold uppercase ${statusClasses}`;

                        appointmentEl.className = `appointment-card bg-blue-50 p-2 rounded-md text-xs cursor-pointer hover:bg-blue-100 relative`;
                        appointmentEl.dataset.citaId = cita.id;
                        appointmentEl.dataset.citaType = cita.type || 'unica';
                        // Event listener para abrir el panel de vista/edición de cita
                        appointmentEl.addEventListener('click', (e) => { e.stopPropagation(); window.openViewCitaPanel(cita.id, cita.type || 'unica'); });
                        appointmentEl.innerHTML = `
                            <p class="font-bold uppercase flex items-center gap-1">
                                ${cita.appointment_time === 'N/A' ? 'Recurrente' : cita.appointment_time.substring(0, 5)}
                            </p>
                            <p class="truncate uppercase">${cita.associated_entity_name || ''}</p>
                            <div class="absolute top-1 right-1 flex items-center justify-center">
                                ${statusIcon}
                            </div>
                        `;
                        appointmentListDayEl.appendChild(appointmentEl);
                    });
                } else {
                    appointmentListDayEl.innerHTML = `<p class="text-xs text-center text-gray-400 mt-4 uppercase">SIN CITAS</p>`;
                }
                calendarGrid.appendChild(dayCol);
            }
            // Re-adjuntar listeners a los días del calendario
            calendarGrid.querySelectorAll('.calendar-day-clickable').forEach(dayElement => {
                const oldListener = dayElement._clickListener;
                if (oldListener) dayElement.removeEventListener('click', oldListener);
                const newListener = function() {
                    const clickedDate = new Date(this.dataset.date + 'T00:00:00');
                    const today = new Date(); today.setHours(0, 0, 0, 0);
                    if (clickedDate < today) {
                        showToast(`No se puede agendar en fechas pasadas.`, 'info');
                        return;
                    }
                    citaFecha.value = this.dataset.date;
                    openPanel('agendarServicioPanel');
                };
                dayElement.addEventListener('click', newListener);
                dayElement._clickListener = newListener;
            });
            renderAppointmentList(); // Llamar para la lista de abajo
            renderRecurringMainList(); // Llamar para la lista de recurrentes maestras en el cuerpo principal
            lucide.createIcons(); // Re-renderizar iconos
        }


// --- NUEVA FUNCIÓN: RENDERIZAR PENDIENTES ---
        function renderPendingRequests() {
            const pendingSection = document.getElementById('pending-requests-section');
            const pendingList = document.getElementById('pending-list');
            
            // FILTRO ESTRICTO:
            // 1. Status debe ser 'pending'
            // 2. La nota debe indicar que viene de la Web (para no mezclar con las manuales)
            const pendingAppointments = Object.values(dbCitasUnicas).filter(c => {
                const isPending = c.status === 'pending';
                // Verificamos las notas que pone el sistema automático
                const isFromWeb = c.notes && (c.notes.includes('Agendado desde Web') || c.notes.includes('Booked from Website') || c.notes.includes('Booked from Web'));
                return isPending && isFromWeb;
            });

            if (pendingAppointments.length === 0) {
                pendingSection.classList.add('hidden');
                return;
            }

            pendingSection.classList.remove('hidden');
            pendingList.innerHTML = '';

            pendingAppointments.forEach(cita => {
                const itemEl = document.createElement('div');
                itemEl.className = 'bg-white p-4 rounded-lg border-2 border-yellow-200 shadow-sm flex flex-col justify-between';
                
                const dateObj = new Date(cita.appointment_date + 'T00:00:00');
                const dateStr = dateObj.toLocaleDateString('es-ES', {day: 'numeric', month: 'short'}).toUpperCase();
                const timeStr = cita.appointment_time.substring(0, 5);
                
                itemEl.innerHTML = `
                    <div class="flex justify-between items-start mb-2">
                        <div>
                            <h4 class="font-black text-gray-800 text-md uppercase">${cita.associated_entity_name}</h4>
                            <p class="text-xs text-gray-500 uppercase font-bold"><i data-lucide="calendar" class="w-3 h-3 inline mr-1"></i>${dateStr} - ${timeStr}</p>
                        </div>
                        <div class="bg-yellow-100 text-yellow-700 text-xs font-bold px-2 py-1 rounded uppercase">Web Request</div>
                    </div>
                    <div class="text-xs text-gray-600 mb-3 italic">
                        "${cita.notes || ''}"
                    </div>
                    <div class="grid grid-cols-2 gap-2 mt-auto">
                        <button class="bg-green-500 hover:bg-green-600 text-white py-2 rounded font-bold text-xs uppercase flex items-center justify-center gap-1 action-confirm-btn" data-cita-id="cita-unica-${cita.id}" data-cita-type="unica">
                            <i data-lucide="check" class="w-4 h-4"></i> Aprobar
                        </button>
                        <button class="bg-white border border-gray-300 text-gray-700 hover:bg-gray-50 py-2 rounded font-bold text-xs uppercase flex items-center justify-center gap-1 view-details-btn" data-cita-id="cita-unica-${cita.id}">
                            <i data-lucide="eye" class="w-4 h-4"></i> Info
                        </button>
                    </div>
                `;
                pendingList.appendChild(itemEl);
            });
            
            lucide.createIcons();
            setupStatusActionListeners();
            setupDetailsListeners();
        }

// --- NUEVA FUNCIÓN: ABRIR PANEL DE DETALLES ---
        window.openDetailsPanel = function(citaIdFull) {
            const numericId = citaIdFull.split('-').pop();
            const cita = dbCitasUnicas[citaIdFull] || dbCitasRecurrentes[citaIdFull];
            
            if (!cita) return;

            // 1. Encontrar la entidad (Cliente o Lead)
            let entity = null;
            let typeLabel = '';
            
            if (cita.associated_entity_type === 'client') {
                entity = Object.values(dbClients).find(c => c.id == cita.client_id);
                typeLabel = 'CLIENTE REGISTRADO';
            } else if (cita.associated_entity_type === 'lead') {
                entity = Object.values(dbLeads).find(l => l.id == cita.lead_id);
                typeLabel = 'PROSPECTO (LEAD)';
            }

            // 2. Llenar Datos de Contacto
            document.getElementById('detail-name').textContent = cita.associated_entity_name;
            document.getElementById('detail-type').textContent = typeLabel;
            
            const phone = entity ? (entity.mobile_phone || entity.phone) : 'N/A';
            const email = entity ? entity.email : 'N/A';
            document.getElementById('detail-phone').textContent = formatPhoneNumber(phone);
            document.getElementById('detail-email').textContent = email;

            // 3. Llenar Dirección y Mapa
            const street = entity ? entity.street_address : '';
            const city = entity ? entity.city : '';
            const state = entity ? entity.state_province : '';
            const zip = entity ? entity.zip_code : '';
            
            const addressFull = [street, city, state, zip].filter(Boolean).join(', ');
            const addressDisplay = addressFull || "Dirección no provista.";
            
            document.getElementById('detail-address-full').textContent = addressDisplay;
            
            const mapsLinkBtn = document.getElementById('detail-maps-link');
            if (addressFull) {
                mapsLinkBtn.href = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(addressFull)}`;
                mapsLinkBtn.classList.remove('opacity-50', 'pointer-events-none');
                mapsLinkBtn.innerHTML = `<i data-lucide="map-pin" class="w-5 h-5 mr-2"></i> ABRIR EN MAPS`;
            } else {
                mapsLinkBtn.href = '#';
                mapsLinkBtn.classList.add('opacity-50', 'pointer-events-none');
                mapsLinkBtn.innerHTML = `<i data-lucide="map-pin-off" class="w-5 h-5 mr-2"></i> SIN DIRECCIÓN`;
            }

            // 4. Llenar Datos de Cita
            const dateObj = new Date(cita.appointment_date + 'T00:00:00');
            document.getElementById('detail-date').textContent = dateObj.toLocaleDateString('es-ES', {weekday: 'long', day: 'numeric', month: 'long'}).toUpperCase();
            document.getElementById('detail-time').textContent = cita.appointment_time ? cita.appointment_time.substring(0, 5) : 'N/A';
            document.getElementById('detail-notes').textContent = cita.notes || "Sin notas adicionales.";

            // 5. Configurar Botones de Acción (Aprobar/Rechazar)
            const actionsPending = document.getElementById('detail-actions-pending');
            const actionsNormal = document.getElementById('detail-actions-normal');
            const btnApprove = document.getElementById('btn-detail-approve');
            const btnReject = document.getElementById('btn-detail-reject');

            if (cita.status === 'pending') {
                actionsPending.classList.remove('hidden');
                actionsNormal.classList.add('hidden');
                
                // Asignar eventos a los botones del panel (clonar para limpiar listeners viejos)
                const newApprove = btnApprove.cloneNode(true);
                const newReject = btnReject.cloneNode(true);
                btnApprove.parentNode.replaceChild(newApprove, btnApprove);
                btnReject.parentNode.replaceChild(newReject, btnReject);

                newApprove.addEventListener('click', () => {
                    handleStatusUpdate({ dataset: { citaId: citaIdFull, citaType: 'unica' } }, 'confirmed');
                    closePanel('detailsCitaPanel');
                });
                newReject.addEventListener('click', () => {
                    handleStatusUpdate({ dataset: { citaId: citaIdFull, citaType: 'unica' } }, 'cancelled');
                    closePanel('detailsCitaPanel');
                });

            } else {
                actionsPending.classList.add('hidden');
                actionsNormal.classList.remove('hidden');
            }

            lucide.createIcons();
            openPanel('detailsCitaPanel');
        };

        function setupDetailsListeners() {
            document.querySelectorAll('.view-details-btn').forEach(button => {
                button.addEventListener('click', function(e) {
                    e.stopPropagation();
                    const citaId = this.dataset.citaId;
                    openDetailsPanel(citaId);
                });
            });
        }
        
        function renderAppointmentList() {
            const listEl = document.getElementById('appointment-list');
            listEl.innerHTML = '';
            
            const searchTerm = appointmentSearch.value.toLowerCase();
            const filterStatusValue = appointmentFilterStatus.value;
            const filterType = appointmentFilterType.value;
            
            // Fechas de referencia
            const todayAtMidnight = new Date();
            todayAtMidnight.setHours(0, 0, 0, 0);

            // CRÍTICO: Calcular el final del mes actual para limitar la lista
            const endOfMonth = new Date(todayAtMidnight.getFullYear(), todayAtMidnight.getMonth() + 1, 0);
            endOfMonth.setHours(23, 59, 59, 999);

            // Preparar datos
            // Solo usamos citas únicas y citas hijas (ambas están en dbCitasUnicas)
            const allUnique = Object.values(dbCitasUnicas).map(c => ({
                ...c,
                id: `cita-unica-${c.id}`,
                type: c.recurring_parent_id ? 'recurrente-hija' : 'unica',
                sortType: c.recurring_parent_id ? 'recurrente' : 'unica'})
            );
            
            const combinedAppointments = [...allUnique];

            const filteredAppointments = combinedAppointments.filter(cita => {
                // 1. Filtro de Texto (Búsqueda)
                const clientName = cita.associated_entity_type === 'client' ? (cita.associated_entity_name || '') : '';
                const prospectName = cita.associated_entity_type === 'lead' ? (cita.associated_entity_name || '') : '';
                const matchesSearch = (clientName.toLowerCase().includes(searchTerm)) || (prospectName.toLowerCase().includes(searchTerm)) || (cita.notes && cita.notes.toLowerCase().includes(searchTerm));
                
                // 2. Filtro de Tipo (Usamos sortType para chequear si es hija de recurrente o única)
                const matchesType = (filterType === 'all') || (cita.sortType === filterType);
                
                // 3. Filtro de Fecha y Estado
                const citaDate = new Date(cita.appointment_date + (cita.appointment_time && cita.appointment_time !== 'N/A' ? 'T' + cita.appointment_time : 'T00:00:00'));
                
                let matchesStatusAndDate = false;
                switch (filterStatusValue) {
                    case 'all': case 'todas':
                        matchesStatusAndDate = true;
                        break;
                    case 'hoy':
                        matchesStatusAndDate = citaDate >= todayAtMidnight && citaDate < new Date(todayAtMidnight.getTime() + 24 * 60 * 60 * 1000) && cita.status !== 'cancelled' && cita.status !== 'completed';
                        break;
                    case 'proximas':
                        // Debe ser mayor a hoy Y MENOR O IGUAL al fin de mes
                        matchesStatusAndDate = citaDate >= todayAtMidnight &&
                                               citaDate <= endOfMonth &&
                                               cita.status !== 'cancelled' &&
                                               cita.status !== 'completed';
                        break;
                    case 'pasadas':
                        matchesStatusAndDate = citaDate < todayAtMidnight;
                        break;
                    default:
                        matchesStatusAndDate = cita.status === filterStatusValue;
                        break;
                }
                return matchesSearch && matchesType && matchesStatusAndDate;
            }).sort((a,b) => new Date(a.appointment_date + 'T' + (a.appointment_time || '00:00')) - new Date(b.appointment_date + 'T' + (b.appointment_time || '00:00')));
            
            // Renderizado (Sin cambios)
            if (filteredAppointments.length === 0) {
                listEl.innerHTML = `<p class="text-center text-gray-500 py-4 uppercase">NO HAY CITAS QUE CUMPLAN ESTE FILTRO.</p>`;
                return;
            }
            
            filteredAppointments.forEach(cita => {
                const itemEl = document.createElement('div');
                itemEl.className = `appointment-list-item flex flex-col sm:flex-row items-start sm:items-center p-4 rounded-lg border bg-white`;
                
                const isCancelled = cita.status === 'cancelled', isCompleted = cita.status === 'completed', isRecurring = cita.recurring_parent_id !== null;
                let statusDisplayHtml = '', iconColorClass = '', actionButtonsHtml = '';

                if (isCancelled) { statusDisplayHtml = '<span class="px-2 py-1 bg-gray-200 text-gray-700 rounded-full text-xs font-semibold uppercase">CANCELADA</span>'; iconColorClass = 'text-gray-500'; }
                else if (isCompleted) { statusDisplayHtml = '<span class="px-2 py-1 bg-green-200 text-green-700 rounded-full text-xs font-semibold uppercase">COMPLETADA</span>'; iconColorClass = 'text-green-600'; }
                else if (isRecurring) { statusDisplayHtml = '<span class="px-2 py-1 bg-blue-100 text-blue-700 rounded-full text-xs font-semibold uppercase">RECURRENTE</span>'; iconColorClass = 'text-blue-600'; actionButtonsHtml = `<button class="btn-primary py-1 px-2 rounded-md text-xs uppercase action-complete-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Marcar como Completada">Completar</button><button class="bg-yellow-500 hover:bg-yellow-600 text-white py-1 px-2 rounded-md text-xs uppercase action-cancel-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Marcar como Cancelada">Cancelar</button>`;}
                else if (cita.status === 'pending') { statusDisplayHtml = '<span class="px-2 py-1 bg-orange-100 text-orange-700 rounded-full text-xs font-semibold uppercase">PENDIENTE</span>'; iconColorClass = 'text-orange-500'; actionButtonsHtml = `<button class="bg-blue-600 hover:bg-blue-700 text-white py-1 px-2 rounded-md text-xs uppercase action-confirm-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Confirmar Cita">Confirmar</button><button class="bg-yellow-500 hover:bg-yellow-600 text-white py-1 px-2 rounded-md text-xs uppercase action-cancel-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Marcar como Cancelada">Cancelar</button><button class="bg-purple-600 hover:bg-purple-700 text-white py-1 px-2 rounded-md text-xs uppercase action-message-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Enviar Mensaje de Confirmación">Mensaje</button>`; }
                else if (cita.status === 'confirmed') { statusDisplayHtml = '<span class="px-2 py-1 bg-primary-100 text-[var(--color-primary)] rounded-full text-xs font-semibold uppercase">CONFIRMADA</span>'; iconColorClass = 'text-[var(--color-primary)]'; actionButtonsHtml = `<button class="btn-primary py-1 px-2 rounded-md text-xs uppercase action-complete-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Marcar como Completada">Completar</button><button class="bg-yellow-500 hover:bg-yellow-600 text-white py-1 px-2 rounded-md text-xs uppercase action-cancel-btn" data-cita-id="${cita.id}" data-cita-type="unica" title="Marcar como Cancelada">Cancelar</button>`; }
                else { statusDisplayHtml = '<span class="px-2 py-1 bg-gray-100 text-gray-500 rounded-full text-xs font-semibold uppercase">DESCONOCIDO</span>'; iconColorClass = 'text-gray-400'; }
                
                let statusIconHtml = '';
                if (isCancelled) statusIconHtml = `<i data-lucide="x-circle" class="w-5 h-5 ${iconColorClass} mr-2"></i>`;
                else if (isCompleted) statusIconHtml = `<i data-lucide="check-circle" class="w-5 h-5 ${iconColorClass} mr-2"></i>`;
                else if (isRecurring) statusIconHtml = `<i data-lucide="repeat" class="w-5 h-5 ${iconColorClass} mr-2"></i>`;
                else statusIconHtml = `<i data-lucide="calendar-check" class="w-5 h-5 ${iconColorClass} mr-2"></i>`;
                
                itemEl.innerHTML = `
                    <div class="flex-shrink-0 w-full sm:w-1/6 text-left sm:text-center mr-4 mb-2 sm:mb-0">
                        <p class="font-bold text-lg text-[var(--color-primary)]" data-label="DÍA">${new Date(cita.appointment_date + 'T00:00:00').toLocaleDateString('es-ES', {day: 'numeric'})}</p>
                        <p class="text-xs text-gray-500 uppercase" data-label="MES">${new Date(cita.appointment_date + 'T00:00:00').toLocaleDateString('es-ES', {month: 'short'}).toUpperCase()}</p>
                    </div>
                    <div class="flex-grow flex flex-col sm:flex-row sm:items-center sm:justify-between w-full sm:w-auto">
                        <div class="flex-grow mb-2 sm:mb-0">
                            <p class="font-bold ${isCancelled ? 'line-through text-gray-500' : 'text-gray-800'} uppercase flex items-center">
                                ${statusIconHtml} ${cita.associated_entity_name} ${isRecurring ? `(RECURRENTE)` : ''}
                            </p>
                            <p class="text-sm ${isCancelled ? 'line-through text-gray-400' : 'text-gray-600'} uppercase" data-label="HORA">
                                A LAS ${cita.appointment_time ? cita.appointment_time.substring(0, 5) : 'N/A'}
                            </p>
                            <div class="mt-1" data-label="ESTADO">${statusDisplayHtml}</div>
                        </div>
                        <div class="flex items-center space-x-2 flex-shrink-0">
                            ${actionButtonsHtml}
                            <button class="text-blue-600 hover:text-blue-800 edit-cita-btn" title="Editar Cita" data-cita-id="${cita.id}" data-cita-type="unica"><i data-lucide="edit-2" class="w-5 h-5"></i></button>
                            <button class="text-[var(--color-secondary)] hover:text-red-900 delete-btn" data-item-type="unica" data-item-id="${cita.id}" title="Eliminar Cita"><i data-lucide="trash-2" class="w-5 h-5"></i></button>
                        </div>
                    </div>
                `;
                listEl.appendChild(itemEl);
            });
            lucide.createIcons();
            setupEditListeners();
            setupDeleteListeners();
            setupStatusActionListeners();
        }

        // --- FUNCIÓN NUEVA: Renderizar la lista de Recurrentes Maestras en el cuerpo principal ---
        function renderRecurringMainList() {
            if (!recurringMainList) return; // Asegurar que el elemento existe

            // 1. Tomar solo las citas recurrentes MAESTRAS
            const masters = Object.values(dbCitasRecurrentes);
            recurringMainList.innerHTML = '';

            if (masters.length === 0) {
                recurringMainList.innerHTML = '<tr><td colspan="6" class="text-center py-4 text-gray-500">No hay Reglas de Recurrencia activas.</td></tr>';
                return;
            }

            // 2. Renderizar la tabla
            masters.forEach(master => {
                const row = document.createElement('tr');
                row.className = 'hover:bg-gray-50 transition duration-150';

                const frequencyDisplay = {
                    'weekly': 'Semanal',
                    'bi-weekly': 'Quincenal',
                    'monthly': 'Mensual'
                }[master.frequency] || 'N/A';
                
                const firstDateDisplay = new Date(master.first_appointment_date + 'T00:00:00').toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: 'numeric' });
                const nextDateDisplay = new Date(master.next_appointment_date + 'T00:00:00').toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: 'numeric' });
                
                // NOTA: No podemos contar las pendientes desde el JS cargado estáticamente sin un nuevo endpoint
                // Usaremos un placeholder o lo dejamos vacío ya que el panel de gestión es el lugar correcto para esto.

                row.innerHTML = `
                    <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900" data-label="Contacto">${master.associated_entity_name}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="Frecuencia">${frequencyDisplay}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="Hora Base">${master.appointment_time ? master.appointment_time.substring(0, 5) : 'N/A'}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="1ra Cita">${firstDateDisplay}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="Próxima">${nextDateDisplay}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-center text-sm font-medium actions-cell">
                        <button class="text-blue-600 hover:text-blue-900 edit-cita-btn" title="Editar Regla" data-cita-id="${master.id}" data-cita-type="${master.type}"><i data-lucide="edit-2" class="w-5 h-5"></i></button>
                        <button class="text-[var(--color-secondary)] hover:text-red-900 ml-2 delete-btn" data-item-type="${master.type}" data-item-id="${master.id}" title="Eliminar Regla y Citas Futuras"><i data-lucide="trash-2" class="w-5 h-5"></i></button>
                    </td>
                `;
                recurringMainList.appendChild(row);
            });
            lucide.createIcons();
            setupEditListeners();
            setupDeleteListeners();
        }
        // --- FIN FUNCIÓN NUEVA: Renderizar la lista de Recurrentes Maestras en el cuerpo principal ---


        // --- FUNCIÓN ANTERIOR: Panel de Gestión de Recurrencias (Mantenida para el panel) ---
        async function renderRecurringMasterPanel() {
            recurringMasterList.innerHTML = '<tr><td colspan="6" class="text-center py-4 text-gray-500">Cargando Recurrencias...</td></tr>';
            
            try {
                // 1. Cargar las citas maestras desde el nuevo endpoint
                const response = await fetch('db/agenda-recurring-read.php');
                const result = await response.json();

                if (result.status === 'success') {
                    const masters = result.data.recurring_masters;
                    recurringMasterList.innerHTML = '';

                    if (masters.length === 0) {
                        recurringMasterList.innerHTML = '<tr><td colspan="6" class="text-center py-4 text-gray-500">No hay Citas Maestras Recurrentes.</td></tr>';
                        return;
                    }

                    // 2. Renderizar la tabla
                    masters.forEach(master => {
                        const row = document.createElement('tr');
                        row.className = 'hover:bg-gray-50 transition duration-150';

                        const frequencyDisplay = {
                            'weekly': 'Semanal',
                            'bi-weekly': 'Quincenal',
                            'monthly': 'Mensual'
                        }[master.frequency] || 'N/A';
                        
                        // NOTA: Se usa 'first_appointment_date' como referencia inicial
                        const firstDateDisplay = new Date(master.first_appointment_date + 'T00:00:00').toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: 'numeric' });
                        
                        const remainingHtml = master.remaining_appointments > 0
                            ? `<span class="px-2 py-1 bg-green-100 text-green-700 rounded-full text-xs font-semibold">${master.remaining_appointments}</span>`
                            : `<span class="px-2 py-1 bg-red-100 text-red-700 rounded-full text-xs font-semibold">0</span>`;

                        row.innerHTML = `
                            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900" data-label="Contacto">${master.contact_name}</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="Frecuencia">${frequencyDisplay}</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="Hora Base">${master.appointment_time}</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" data-label="1ra Cita">${firstDateDisplay}</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-center" data-label="Pendientes">${remainingHtml}</td>
                            <td class="px-6 py-4 whitespace-nowrap text-center text-sm font-medium actions-cell">
                                <button class="text-blue-600 hover:text-blue-900 edit-cita-btn" title="Editar Regla" data-cita-id="${master.id}" data-cita-type="${master.type}"><i data-lucide="edit-2" class="w-5 h-5"></i></button>
                                <button class="text-[var(--color-secondary)] hover:text-red-900 ml-2 delete-btn" data-item-type="${master.type}" data-item-id="${master.id}" title="Eliminar Regla y Citas Futuras"><i data-lucide="trash-2" class="w-5 h-5"></i></button>
                            </td>
                        `;
                        recurringMasterList.appendChild(row);
                    });

                    lucide.createIcons();
                    setupEditListeners();
                    setupDeleteListeners();
                } else {
                    recurringMasterList.innerHTML = `<tr><td colspan="6" class="text-center py-4 text-red-500">Error al cargar Recurrencias: ${result.message}</td></tr>`;
                }

            } catch (error) {
                console.error("Error al cargar el panel de recurrentes:", error);
                recurringMasterList.innerHTML = `<tr><td colspan="6" class="text-center py-4 text-red-500">Error de conexión al cargar el panel de recurrentes.</td></tr>`;
            }
        }
        // --- FIN FUNCIÓN ANTERIOR: Panel de Gestión de Recurrencias ---

        if (confirmDeleteButton) {
            confirmDeleteButton.addEventListener('click', async function() {
                const itemId = this.dataset.itemId;
                const itemType = this.dataset.itemType;
                try {
                    const response = await fetch('db/agenda-delete.php', {
                        method: 'DELETE',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ id: itemId, type: itemType })
                    });
                    const result = await response.json();
                    if (result.status === 'success') {
                        showToast(`${itemType.toUpperCase()} eliminada con éxito.`, 'success');
                        if (itemType === 'unica' || itemType === 'recurrente-hija') {
                            delete dbCitasUnicas[itemId];
                        } else if (itemType === 'recurrente') {
                            // Si se eliminó la maestra, se elimina la regla y se recarga el panel
                            delete dbCitasRecurrentes[itemId];
                            renderRecurringMasterPanel();
                        }
                        
                        renderAppointmentList();
                        renderAgenda();
                    } else {
                        showToast(`Error al eliminar: ${result.message}`, 'error');
                    }
                } catch (error) {
                    showToast('Hubo un problema de conexión al eliminar.', 'error');
                }
                window.closeModal('confirmDeleteModal');
            });
        }
        
        if(prevBtn) prevBtn.addEventListener('click', () => { if (currentView === 'weekly') currentDate.setDate(currentDate.getDate() - 7); else currentDate.setMonth(currentDate.getMonth() - 1); renderAgenda(); });
        if(nextBtn) nextBtn.addEventListener('click', () => { if (currentView === 'weekly') currentDate.setDate(currentDate.getDate() + 7); else currentDate.setMonth(currentDate.getMonth() + 1); renderAgenda(); });
        if(viewWeeklyBtn) viewWeeklyBtn.addEventListener('click', () => { currentView = 'weekly'; renderAgenda(); });
        if(viewMonthlyBtn) viewMonthlyBtn.addEventListener('click', () => { currentView = 'monthly'; renderAgenda(); });
        
        if (agendarServicioForm) {
            citaRecurrenteCheckbox.addEventListener('change', function() {
                recurrenciaOptionsDiv.classList.toggle('hidden', !this.checked);
                calculateAndDisplayNextRecurringDate();
            });
            // Listener de cambio de fecha ya está configurado en openPanel
            // citaFecha.addEventListener('change', handleDateChangeForSlots);
            citaFrecuenciaSelect.addEventListener('change', calculateAndDisplayNextRecurringDate);

            function calculateAndDisplayNextRecurringDate() {
                if (citaRecurrenteCheckbox.checked) {
                    const initialDateStr = citaFecha.value;
                    const frequency = citaFrecuenciaSelect.value;
                    if (initialDateStr && frequency) {
                        const nextDate = calculateNextRecurringDate(initialDateStr, frequency);
                        citaProximaCitaDisplay.value = nextDate.toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' });
                        citaProximaCitaInput.value = nextDate.toISOString().split('T')[0];
                    } else {
                        citaProximaCitaDisplay.value = 'Selecciona fecha y frecuencia';
                        citaProximaCitaInput.value = '';
                    }
                }
            }

           function calculateNextRecurringDate(initialDateStr, frequency) {
                const initialDate = new Date(initialDateStr + 'T00:00:00');
                let nextDate = new Date(initialDate);
                
                // NOTA IMPORTANTE: Para este cálculo, siempre se debe tomar la fecha de referencia
                // y sumarle el intervalo para calcular la siguiente repetición.
                
                switch (frequency) {
                    case 'weekly': nextDate.setDate(nextDate.getDate() + 7); break;
                    case 'bi-weekly': nextDate.setDate(nextDate.getDate() + 14); break;
                    case 'monthly':
                        // Lógica para mantener el día del mes si es posible
                        const dayOfMonth = nextDate.getDate();
                        nextDate.setMonth(nextDate.getMonth() + 1);
                        // Si el día del mes cambia (ej. del 31 de Enero al 28 de Febrero)
                        if (nextDate.getDate() !== dayOfMonth) {
                            // Regresa al último día del mes si no pudo mantener el día
                            nextDate = new Date(nextDate.getFullYear(), nextDate.getMonth(), 0);
                        }
                        break;
                }
                return nextDate;
            }

            function setupAutocomplete(displayEl, inputEl, suggestionsEl, data, type, infoEl) {
                let searchTimeout = null;
                displayEl.addEventListener('input', function() {
                    const otherDisplayEl = type === 'client' ? citaProspectoDisplay : citaClienteDisplay;
                    
                    clearTimeout(searchTimeout);
                    const searchTerm = this.value.toLowerCase();
                    inputEl.value = '';
                    if (infoEl) infoEl.textContent = '';
                    suggestionsEl.innerHTML = '';
                    if (searchTerm.length < 2) {
                        suggestionsEl.classList.add('hidden');
                        return;
                    }
                    searchTimeout = setTimeout(() => {
                        const filteredData = Object.values(data).filter(item =>
                            item.name.toLowerCase().includes(searchTerm) ||
                            (item.email && item.email.toLowerCase().includes(searchTerm)) ||
                            (item.phone && item.phone.includes(searchTerm)) ||
                            (item.mobile_phone && item.mobile_phone.includes(searchTerm))
                        );
                        if (filteredData.length > 0) {
                            filteredData.forEach(item => {
                                const suggestionItem = document.createElement('div');
                                suggestionItem.className = 'autocomplete-suggestion';
                                suggestionItem.textContent = `${item.name} (${item.email || item.phone || item.mobile_phone || 'N/A'})`;
                                suggestionItem.addEventListener('click', () => {
                                    displayEl.value = item.name;
                                    inputEl.value = item.id;
                                    if (infoEl) infoEl.textContent = `Email: ${item.email || 'N/A'} | Tel: ${formatPhoneNumber(item.phone) || formatPhoneNumber(item.mobile_phone) || 'N/A'}`;
                                    suggestionsEl.classList.add('hidden');
                                    showToast(`${type === 'client' ? 'Cliente' : 'Prospecto'} "${item.name}" seleccionado.`, 'info');
                                    
                                    // CRÍTICO: BLOQUEAR el otro campo al seleccionar
                                    const otherInputDisplay = type === 'client' ? citaProspectoDisplay : citaClienteDisplay;
                                    const otherInputHidden = type === 'client' ? citaProspectoInput : citaClienteInput;
                                    const otherInfoEl = type === 'client' ? citaProspectoInfoAdicional : citaClienteInfo;
                                    
                                    otherInputDisplay.value = '';
                                    otherInputHidden.value = '';
                                    if (otherInfoEl) otherInfoEl.textContent = '';
                                    toggleInputDisabledStyle(otherInputDisplay, true); // Bloquear el otro
                                    toggleInputDisabledStyle(displayEl, false); // Asegurar que este esté desbloqueado
                                });
                                suggestionsEl.appendChild(suggestionItem);
                            });
                            suggestionsEl.classList.remove('hidden');
                        } else {
                            suggestionsEl.classList.add('hidden');
                        }
                    }, 300);
                });
                displayEl.addEventListener('blur', () => {
                    setTimeout(() => suggestionsEl.classList.add('hidden'), 150);
                });
                
                // CRÍTICO: Habilitar el otro campo al vaciar este
                displayEl.addEventListener('change', function() {
                    if (this.value.trim() === '') {
                        const otherInputDisplay = type === 'client' ? citaProspectoDisplay : citaClienteDisplay;
                        toggleInputDisabledStyle(otherInputDisplay, false); // Desbloquear el otro
                        inputEl.value = '';
                        if (infoEl) infoEl.textContent = '';
                    }
                });
            }

            setupAutocomplete(citaClienteDisplay, citaClienteInput, citaClienteSuggestions, dbClients, 'client', citaClienteInfo);
            setupAutocomplete(citaProspectoDisplay, citaProspectoInput, citaProspectoSuggestions, dbLeads, 'prospect', citaProspectoInfoAdicional);

            agendarServicioForm.addEventListener('submit', async function(e) {
                e.preventDefault();
                const client_id = citaClienteInput.value;
                const lead_id = citaProspectoInput.value;
                const appointment_date = citaFecha.value;

                if (!(client_id || lead_id) || !appointment_date) {
                    showToast("Por favor, selecciona una fecha y un Cliente O un Prospecto.", 'warning');
                    return;
                }
                
                // Validación crítica de slots
                if (!citaRecurrenteCheckbox.checked) {
                    const hora = citaHoraSelect.value;
                    const minuto = citaMinutoSelect.value;
                    if (!hora || !minuto) {
                         showToast("Debes seleccionar una hora y minuto válidos según tu horario de servicio.", 'warning');
                        return;
                    }
                }


                const notes = citaNotas.value;
                const is_recurring = citaRecurrenteCheckbox.checked;
                
                let citaData = {
                    client_id: client_id || null,
                    lead_id: lead_id || null,
                    notes: notes,
                    type: is_recurring ? 'recurrente' : 'unica',
                    appointment_date: appointment_date, // Incluimos la fecha de inicio en ambos casos
                    appointment_time: `${citaHoraSelect.value}:${citaMinutoSelect.value}:00` // Incluimos la hora de inicio en ambos casos
                };

                if (is_recurring) {
                    const frequency = citaFrecuenciaSelect.value;
                    if (!frequency) {
                        showToast("Por favor, selecciona una frecuencia.", 'warning');
                        return;
                    }
                    citaData.frequency = frequency;
                }
                
                // NOTA: En el caso 'unica' no se envía el status, el backend lo establece a 'pending'
                
                try {
                    const response = await fetch('db/agenda-create.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(citaData)
                    });
                    const result = await response.json();
                    if (result.status === 'success') {
                        showToast("Cita agendada con éxito. Recargando datos...", 'success');
                        closePanel('agendarServicioPanel');
                        location.reload();
                    } else {
                        showToast("Error al agendar cita: " + result.message, 'error');
                    }
                } catch (error) {
                    showToast("Hubo un problema de conexión al agendar la cita.", 'error');
                }
            });
        }
        
        if (viewCitaForm) {
            viewCitaFrecuencia.addEventListener('change', updateViewRecurringDate);
            viewCitaFecha.addEventListener('change', updateViewRecurringDate);
            viewCitaForm.addEventListener('submit', async function(e) {
                e.preventDefault();
                const cita_id_full = viewCitaId.value;
                const cita_type = viewCitaType.value;
                const numeric_id = cita_id_full.split('-').pop();
                const notes = viewCitaNotas.value;
                let updateData = {
                    id: numeric_id,
                    type: cita_type,
                    notes: notes
                };
                if (cita_type === 'unica' || cita_type === 'recurrente-hija') {
                    const appointment_date = viewCitaFecha.value;
                    const appointment_time = `${viewCitaHoraSelect.value}:${viewCitaMinutoSelect.value}:00`;
                    if (!appointment_date || !appointment_time) {
                        showToast("Por favor, selecciona una fecha y hora.", 'warning');
                        return;
                    }
                    updateData.appointment_date = appointment_date;
                    updateData.appointment_time = appointment_time;
                    // Forzamos el tipo a 'unica' para que el endpoint de UPDATE lo procese correctamente
                    updateData.type = 'unica';
                } else if (cita_type === 'recurrente') {
                    const frequency = viewCitaFrecuencia.value;
                    if (!frequency) {
                        showToast("Por favor, selecciona una frecuencia.", 'warning');
                        return;
                    }
                    updateData.frequency = frequency;
                    // El backend (agenda-update.php) debe manejar la lógica de la regla
                }
                try {
                    const response = await fetch('db/agenda-update.php', {
                        method: 'PUT',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(updateData)
                    });
                    const result = await response.json();
                    if (result.status === 'success') {
                        showToast("Cambios guardados con éxito. Recargando datos...", 'success');
                        closePanel('viewCitaPanel');
                        location.reload();
                    } else {
                        showToast("Error al guardar cambios: " + result.message, 'error');
                    }
                } catch (error) {
                    showToast("Hubo un problema de conexión al guardar los cambios.", 'error');
                }
            });
        }
        
        if (appointmentSearch) appointmentSearch.addEventListener('input', renderAppointmentList);
        if (appointmentFilterStatus) appointmentFilterStatus.addEventListener('change', renderAppointmentList);
        if (appointmentFilterType) appointmentFilterType.addEventListener('change', renderAppointmentList);
        
        if (downloadCitasBtn) {
            downloadCitasBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                downloadDropdown.classList.toggle('hidden');
            });
            document.addEventListener('click', function(e) {
                if (!downloadDropdown.contains(e.target) && !downloadCitasBtn.contains(e.target)) {
                    downloadDropdown.classList.add('hidden');
                }
            });
            exportCsvBtn.addEventListener('click', () => {
                const allAppointments = [...Object.values(dbCitasUnicas), ...Object.values(dbCitasRecurrentes)];
                if (allAppointments.length > 0) {
                    showToast('Preparando descarga CSV...', 'info');
                    const dataToExport = allAppointments.map(cita => ({
                        ID: String(cita.id).match(/(\d+)$/)?.[1] || cita.id,
                        Tipo: cita.type,
                        Asociado: cita.associated_entity_name,
                        Fecha: cita.appointment_date || cita.next_appointment_date,
                        Hora: cita.appointment_time || 'N/A',
                        Estado: cita.status || 'N/A',
                        Frecuencia: cita.frequency || 'N/A',
                        Notas: cita.notes
                    }));
                    descargarComoCSV(dataToExport, 'agenda.csv');
                } else {
                    showToast('No hay citas para descargar.', 'info');
                }
                downloadDropdown.classList.add('hidden');
            });
            exportIcalBtn.addEventListener('click', () => {
                const allAppointments = [...Object.values(dbCitasUnicas), ...Object.values(dbCitasRecurrentes)];
                if (allAppointments.length > 0) {
                    showToast('Preparando descarga iCalendar...', 'info');
                    const dataToExport = allAppointments.map(cita => ({
                        id: String(cita.id).match(/(\d+)$/)?.[1] || cita.id,
                        type: cita.type,
                        associated_entity_name: cita.associated_entity_name,
                        appointment_date: cita.appointment_date || cita.next_appointment_date,
                        appointment_time: cita.appointment_time || '00:00:00',
                        notes: cita.notes,
                        frequency: cita.frequency || ''
                    }));
                    descargarComoICS(dataToExport, 'agenda.ics');
                } else {
                    showToast('No hay citas para descargar.', 'info');
                }
                downloadDropdown.classList.add('hidden');
            });
        }

        if (dbErrorMessage) showToast(dbErrorMessage, 'error');
        
        // --- LLAMADA INICIAL AL FINAL ---
        renderAgenda();
        lucide.createIcons();

        function formatPhoneNumber(phoneNumberString) {
            if (!phoneNumberString) return '';
            const cleaned = ('' + phoneNumberString).replace(/\D/g, '');
            const match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
            // Ensure US format: (XXX) XXX-XXXX
            return match ? `(${match[1]}) ${match[2]}-${match[3]}` : phoneNumberString;
        }
        
        function descargarComoCSV(data, filename) {
            const headers = Object.keys(data[0]);
            const csvRows = [headers.map(h => `"${h}"`).join(',')]; // Add quotes to headers
            for (const row of data) {
                const values = headers.map(header => {
                    const value = String(row[header] || '');
                    // Escape double quotes by doubling them, then wrap in double quotes
                    return `"${value.replace(/"/g, '""')}"`;
                });
                csvRows.push(values.join(','));
            }
            // Add BOM for proper UTF-8 encoding in Excel
            const blob = new Blob(["\uFEFF" + csvRows.join('\n')], { type: 'text/csv;charset=utf-8;' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = filename;
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
        
        // --- FUNCIÓN NUEVA: Descargar como iCalendar (.ics) ---
        function descargarComoICS(data, filename) {
            if (!data || data.length === 0) {
                showToast('No hay datos para exportar a iCalendar.', 'info');
                return;
            }

            let icalContent = "BEGIN:VCALENDAR\r\n";
            icalContent += "VERSION:2.0\r\n";
            icalContent += "PRODID:-//Tu Negocio CRM//NONSGML Agenda//ES\r\n";
            icalContent += "CALSCALE:GREGORIAN\r\n";
            icalContent += "METHOD:PUBLISH\r\n";

            data.forEach(cita => {
                const startDate = new Date(cita.appointment_date + 'T' + cita.appointment_time);
                const endDate = new Date(startDate.getTime() + 60 * 60 * 1000); // Duración de 1 hora
                const dtStamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\..*Z/, 'Z');
                const dtStart = startDate.toISOString().replace(/[-:]/g, '').replace(/\..*Z/, 'Z');
                const dtEnd = endDate.toISOString().replace(/[-:]/g, '').replace(/\..*Z/, 'Z');
                
                icalContent += "BEGIN:VEVENT\r\n";
                icalContent += `UID:${cita.type}-${cita.id}@tu-negocio-crm.com\r\n`;
                icalContent += `DTSTAMP:${dtStamp}\r\n`;
                icalContent += `DTSTART:${dtStart}\r\n`;
                icalContent += `DTEND:${dtEnd}\r\n`;
                icalContent += `SUMMARY:Cita con ${cita.associated_entity_name}\r\n`;
                icalContent += `DESCRIPTION:Notas: ${cita.notes || 'N/A'}\r\n`;
                
                // Agrega la lógica de recurrencia si es una cita recurrente
                if (cita.type === 'recurrente' && cita.frequency) {
                    let rrule = '';
                    switch (cita.frequency) {
                        case 'weekly':
                            rrule = 'FREQ=WEEKLY';
                            break;
                        case 'bi-weekly':
                            rrule = 'FREQ=WEEKLY;INTERVAL=2';
                            break;
                        case 'monthly':
                            rrule = `FREQ=MONTHLY`;
                            // Agregamos la regla del día del mes
                            rrule += `;BYMONTHDAY=${startDate.getDate()}`;
                            break;
                    }
                    if (rrule) {
                        icalContent += `RRULE:${rrule}\r\n`;
                    }
                }
                
                // Recordatorio de 15 minutos antes de la cita
                icalContent += "BEGIN:VALARM\r\n";
                icalContent += "ACTION:DISPLAY\r\n";
                icalContent += "DESCRIPTION:Recordatorio de Cita\r\n";
                icalContent += "TRIGGER:-PT15M\r\n";
                icalContent += "END:VALARM\r\n";
                
                icalContent += "END:VEVENT\r\n";
            });

            icalContent += "END:VCALENDAR\r\n";
            
            const blob = new Blob([icalContent], { type: 'text/calendar;charset=utf-8' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = filename;
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    });
</script>
<script src="files/toast.js"></script>
</body>
</html>