<?php
/**
 * ARCHITECT: LEADS FUNNEL VIEW & DATA PREPARATION
 * Descripción: Inicializa la sesión, configura el embudo de ventas y extrae los datos de leads de la BD para la vista Kanban.
 * Seguridad: Utiliza PDO Prepared Statements para todas las consultas.
 */

declare(strict_types=1);

// 1. Carga del Núcleo y Seguridad
require_once __DIR__ . '/core/init.php';
require_once __DIR__ . '/files/guardiankey.php';

// Inicialización de variables para la vista (necesarias incluso si las consultas fallan)
$funnel_stages_js = [];
$lead_sources = [];
$priority_levels = [];
$funnel_prospects = [];
$converted_prospects = [];
$lost_prospects = [];
$all_leads_with_date = [];
$total_new_prospects = 0;
$total_converted = 0;
$conversion_rate = 0;
$converted_db_status = '';
$lost_db_status = '';
$archived_db_status = '';
$user_id = $user_id_session ?? 1; // Usar el ID de sesión o 1 como fallback

try {
    // 2. Definición de Constantes y Configuración del Embudo
    $funnel_stages = [
        0 => [
            'id' => 0,
            'title' => 'EN SEGUIMIENTO',
            'db_status' => 'En Seguimiento',
            'color_class' => 'text-[var(--color-primary)]',
            'border_class' => 'border-l-[var(--color-primary)]',
            'icon' => 'search-check',
            'desc' => 'ACCIÓN: Validar interés y comprender necesidades del cliente'
        ],
        1 => [
            'id' => 1,
            'title' => 'PRESENTAR SOLUCIÓN',
            'db_status' => 'Presentar Solución',
            'color_class' => 'text-[var(--color-primary)]',
            'border_class' => 'border-l-[var(--color-highlight)]',
            'icon' => 'presentation',
            'desc' => 'ACCIÓN: Presentar propuesta de valor para generar confianza'
        ],
        2 => [
            'id' => 2,
            'title' => 'INTRODUCIR SERVICIO',
            'db_status' => 'Introducir Servicio',
            'color_class' => 'text-[var(--color-secondary)]',
            'border_class' => 'border-l-[var(--color-secondary)]',
            'icon' => 'package-check',
            'desc' => 'ACCIÓN: Demostración final y llamada a la acción'
        ],
    ];

    $config = [
        'converted_status' => 'Lead Ganado',
        'lost_status' => 'Lead Perdido',
        'archived_status' => 'Lead Archivado',
        'priority_levels' => ['Alta', 'Media', 'Baja']
    ];

    $priority_levels = $config['priority_levels']; 
    $converted_db_status = $config['converted_status'];
    $lost_db_status = $config['lost_status'];
    $archived_db_status = $config['archived_status'];


    // 3. Funciones Helper (Encapsuladas para este contexto)
    function format_lead_internal(array $lead, array $stages, array $config): array
    {
        $name = trim(($lead['first_name'] ?? '') . ' ' . ($lead['last_name'] ?? ''));
        // Usamos html_entity_decode para limpiar textos que vienen de la BD y fueron codificados
        $status_text = trim(html_entity_decode($lead['status'] ?? 'Nuevo', ENT_QUOTES | ENT_HTML5, 'UTF-8'));
        
        // Normalización de estados especiales (ajuste de nombres largos en DB)
        if (strpos($status_text, 'Cotización Ganada') !== false) {
            $status_text = $config['converted_status'];
        } elseif (strpos($status_text, 'Cotización Perdida') !== false) {
            $status_text = $config['lost_status'];
        }
        
        // Determinar Stage ID
        $stage_id = array_search($status_text, array_column($stages, 'db_status'));
        
        $company_name = (empty($lead['company']) || strtoupper($lead['company'] ?? '') === 'RESIDENCIAL') 
            ? '' 
            : ($lead['company'] ?? '');
        
        // Obtener fecha limpia
        $created_date = $lead['created_at_date'] ?? null;
        if (!$created_date && !empty($lead['created_at'])) {
            $created_date = date('Y-m-d', strtotime($lead['created_at']));
        }
        
        // Asegurar que los números de teléfono se pasen sin formato para el JS
        $phone_fixed = preg_replace('/[^0-9]/', '', (string)($lead['phone'] ?? ''));
        $phone_mobile = preg_replace('/[^0-9]/', '', (string)($lead['mobile'] ?? ''));

        return [
            'id' => (int)$lead['id'],
            'name' => $name ?: 'Sin Nombre',
            'status_text' => $status_text,
            'source' => $lead['source'] ?? 'Desconocido',
            'stage' => ($stage_id !== false) ? (int)$stage_id : null,
            'first_name' => $lead['first_name'] ?? '',
            'last_name' => $lead['last_name'] ?? '',
            'email' => $lead['email'] ?? '',
            'phone_fixed' => $phone_fixed,
            'phone_mobile' => $phone_mobile,
            'company' => $company_name,
            'address' => $lead['street_address'] ?? '',
            'city' => $lead['city'] ?? '',
            'state_region' => $lead['state_province'] ?? '',
            'postal_code' => $lead['zip_code'] ?? '',
            'priority' => $lead['priority'] ?? 'Media',
            'lost_reason' => $lead['lost_reason'] ?? '',
            'created_at' => $created_date,
        ];
    }

    // 4. Ejecución de Consultas (PDO Prepared Statements for Security)
    if (!isset($pdo)) {
        throw new Exception("Error de conexión a BD");
    }

    // 4.1 Obtener Leads del Funnel (Leads activos en el pipeline)
    $funnel_db_statuses = array_column($funnel_stages, 'db_status');
    $in_placeholders = implode(',', array_fill(0, count($funnel_db_statuses), '?'));
    
    $sqlFunnel = "SELECT 
                    id, first_name, last_name, company, email, phone, mobile, source, 
                    street_address, city, state_province, zip_code, priority, lost_reason, 
                    status, created_at, DATE(created_at) as created_at_date 
                  FROM leads 
                  WHERE user_id = ? AND status IN ($in_placeholders) 
                  ORDER BY priority DESC, created_at ASC";
                  
    $stmtFunnel = $pdo->prepare($sqlFunnel);
    $paramsFunnel = array_merge([$user_id], $funnel_db_statuses); // [user_id, status1, status2, ...]
    $stmtFunnel->execute($paramsFunnel);
    $rawFunnel = $stmtFunnel->fetchAll(PDO::FETCH_ASSOC);

    // 4.2 Obtener Leads Convertidos y Perdidos
    $sqlDecided = "SELECT 
                    id, first_name, last_name, company, email, phone, mobile, source, 
                    street_address, city, state_province, zip_code, priority, lost_reason, 
                    status, created_at, DATE(created_at) as created_at_date 
                  FROM leads 
                  WHERE user_id = ? AND status = ? 
                  ORDER BY created_at DESC";
    $stmtDecided = $pdo->prepare($sqlDecided);

    // Convertidos
    $stmtDecided->execute([$user_id, $converted_db_status]);
    $rawConverted = $stmtDecided->fetchAll(PDO::FETCH_ASSOC);

    // Perdidos
    $stmtDecided->execute([$user_id, $lost_db_status]);
    $rawLost = $stmtDecided->fetchAll(PDO::FETCH_ASSOC);

    // 4.3 Obtener Fuentes (Standardized Prepared Statement)
    $sqlSources = "SELECT name FROM lead_sources WHERE user_id = ? ORDER BY name ASC";
    $stmtSources = $pdo->prepare($sqlSources);
    $stmtSources->execute([$user_id]);
    $sources = $stmtSources->fetchAll(PDO::FETCH_COLUMN);
    $lead_sources = $sources;

    // 5. Procesamiento y Mapeo a variables del view
    $leads = [
        'funnel' => [],
        'converted' => [],
        'lost' => [],
        'all_with_date' => []
    ];

    foreach ($rawFunnel as $row) {
        $l = format_lead_internal($row, $funnel_stages, $config);
        if ($l['stage'] !== null) {
            $leads['funnel'][] = $l;
            $leads['all_with_date'][] = $l;
        }
    }

    foreach ($rawConverted as $row) {
        $l = format_lead_internal($row, $funnel_stages, $config);
        $leads['converted'][] = $l;
        $leads['all_with_date'][] = $l;
    }

    foreach ($rawLost as $row) {
        $l = format_lead_internal($row, $funnel_stages, $config);
        $l['lost_reason'] = $row['lost_reason'] ?? 'Razón no especificada';
        $leads['lost'][] = $l;
        $leads['all_with_date'][] = $l;
    }

    $funnel_stages_js = $funnel_stages;

    $funnel_prospects = $leads['funnel'];
    $converted_prospects = $leads['converted'];
    $lost_prospects = $leads['lost'];
    $all_leads_with_date = $leads['all_with_date'];

    // 6. Cálculo de Estadísticas
    $total_converted = count($leads['converted']);
    $total_lost = count($leads['lost']);
    $total_decided = $total_converted + $total_lost;
    $conversion_rate = ($total_decided > 0) ? round(($total_converted / $total_decided) * 100, 1) : 0;
    $total_new_prospects = count($leads['funnel']);

} catch (Exception $e) {
    error_log("Error al cargar datos del embudo (Vista): " . $e->getMessage());
    // Fallback variables remain set to empty/zero
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Embudo De Conversión De Prospectos <?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>
    <link rel="stylesheet" href="style.css">
    <script src="files/header-manager.js"></script>
    
    <script src="https://unpkg.com/imask"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
        
</head>

<body data-page-title="Embudo De Conversión De Prospectos"
    data-page-subtitle="Convirtiendo Desconocidos En Clientes Potenciales"
    data-page-icon="shuffle">
    
    <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="task-panel-overlay" class="fixed inset-0 bg-black/60 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 bg-[var(--color-background)] space-y-8">
            
        <div>
            <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                                <div class="stat-card bg-white p-3 lg:p-6 rounded-xl shadow-md flex items-center border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="users" class="w-8 h-8 lg:w-12 lg:h-12 text-[var(--color-secondary)] shrink-0"></i>
                    <div class="flex-1 flex justify-between items-center ml-3 lg:ml-4">
                        <h3 class="text-md lg:text-lg font-black text-gray-500 leading-tight uppercase">LEADS EN SEGUIMIENTO</h3>
                        <p id="kpi-new-prospects" class="text-5xl lg:text-5xl font-black text-[var(--color-primary)]"><?php echo $total_new_prospects; ?></p>
                    </div>
                </div>

                                <div class="stat-card bg-white p-3 lg:p-6 rounded-xl shadow-md flex items-center border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="user-check" class="w-8 h-8 lg:w-12 lg:h-12 text-[var(--color-secondary)] shrink-0"></i>
                    <div class="flex-1 flex justify-between items-center ml-3 lg:ml-4">
                        <h3 class="text-md lg:text-lg font-black text-gray-500 leading-tight uppercase">LEADS CONVERTIDOS</h3>
                        <p id="kpi-converted" class="text-5xl lg:text-5xl font-black text-[var(--color-primary)]"><?php echo $total_converted; ?></p>
                    </div>
                </div>

                                <div class="stat-card bg-white p-3 lg:p-6 rounded-xl shadow-md flex items-center border-l-4 border-[var(--color-highlight)]">
                    <i data-lucide="percent-circle" class="w-8 h-8 lg:w-12 lg:h-12 text-[var(--color-secondary)] shrink-0"></i>
                    <div class="flex-1 flex justify-between items-center ml-3 lg:ml-4">
                        <h3 class="text-md lg:text-lg font-black text-gray-500 leading-tight uppercase">TASA DE CONVERSIÓN</h3>
                        <p id="kpi-rate" class="text-5xl lg:text-5xl font-black text-[var(--color-primary)]"><?php echo $conversion_rate; ?>%</p>
                    </div>
                </div>
            </div>
        </div>
        
                
        <div class="bg-white p-6 rounded-xl shadow-md">
                <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-6">
                    <?php foreach ($funnel_stages as $stage): ?>
                    <div>
                        <div id="stage-<?php echo $stage['id']; ?>" data-stage-id="<?php echo $stage['id']; ?>" class="funnel-column bg-white rounded-xl p-4 flex flex-col min-h-[65vh] border-l-4 border-[var(--color-highlight)] transition duration-300 shadow-lg hover:shadow-xl <?php echo $stage['border_class']; ?>">
                            <div class="flex-shrink-0">
                                <div class="flex justify-between items-center mb-2 border-b pb-2">
                                                                        <h2 class="text-2xl font-black flex items-center text-[var(--color-primary)]"><i data-lucide="<?php echo $stage['icon']; ?>" class="w-5 h-5 mr-2 text-[var(--color-secondary)]"></i><?php echo htmlspecialchars($stage['title']); ?></h2>
                                    <span class="text-gray-500 font-bold" id="count-<?php echo $stage['id']; ?>"></span>
                                </div>
                                                                <p class="text-sm font-semibold text-gray-500 mb-4 h-10 uppercase"><?php echo htmlspecialchars($stage['desc']); ?></p><br />
                            </div>
                           <div class="kanban-list space-y-4 flex-grow overflow-y-auto pr-2" data-stage-id="<?php echo $stage['id']; ?>"></div>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>

<div class="mt-8">
        <h3 class="text-4xl font-black text-[var(--color-primary)] mb-1 flex items-center">
        <i data-lucide="check-square" class="w-7 h-7 mr-2 text-[var(--color-secondary)] "></i>
        RESULTADOS DE LA FASE DE SEGUIMIENTO
    </h3>
</div>
    
    <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                            
                                <div class="w-full">
                                    <div id="converted-column" data-action="convert" class="funnel-column bg-white rounded-xl p-4 flex flex-col min-h-[30vh] transition duration-300 shadow-lg hover:shadow-xl border-l-4 border-[var(--color-highlight)]">
                                        <div class="flex-shrink-0">
                                            <div class="flex justify-between items-center mb-2 border-b pb-2">
                                                                                                <h2 class="text-3xl font-black flex items-center uppercase text-[var(--color-primary)]"><i data-lucide="user-check" class="w-5 h-5 mr-2 text-[var(--color-secondary)]"></i>LEAD GANADO</h2>
                                            </div>
                                                                                        <p class="text-sm text-gray-500 mb-3 h-8 uppercase">Leads calificados listos para convertirse en clientes.</p>
                                        </div>
                                        <div id="converted-list" class="kanban-list space-y-3 flex-grow overflow-y-auto pr-2"></div>
                                    </div>
                                </div>

                                <div class="w-full">
                                    <div id="lost-column" data-action="lost" class="funnel-column bg-white rounded-xl p-4 flex flex-col min-h-[30vh] transition duration-300 shadow-lg hover:shadow-xl border-l-4 border-[var(--color-secondary)]">
                                        <div class="flex-shrink-0">
                                            <div class="flex justify-between items-center mb-2 border-b pb-2">
                                                                                                <h2 class="text-3xl font-black flex items-center text-[var(--color-primary)]"><i data-lucide="user-x" class="w-5 h-5 mr-2 text-[var(--color-secondary)]"></i>LEAD PERDIDO</h2>
                                            </div>
                                                                                        <p class="text-sm text-gray-500 mb-3 h-8 uppercase">No interesados por ahora (Mantener en radar)</p>
                                        </div>
                                        <div id="lost-list" class="kanban-list space-y-3 flex-grow overflow-y-auto pr-2"></div>
                                    </div>
                                </div>
                                </div>
                                    </div>
                            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
            
                        <div class="bg-white p-6 rounded-xl shadow-md">
                <h3 class="text-2xl font-black text-[var(--color-primary)] mb-4 flex items-center">
                    <i data-lucide="bar-chart-3" class="w-6 h-6 mr-2 text-[var(--color-highlight)]"></i>
                    PROSPECTOS DIARIOS DEL MES
                </h3>
                <div class="relative h-96 w-full">
                    <canvas id="dailyLeadsBarChart"></canvas>
                </div>
            </div>
            
                        <div class="bg-white p-6 rounded-xl shadow-md">
                <h3 class="text-2xl font-black text-[var(--color-primary)] mb-4 flex items-center">
                    <i data-lucide="pie-chart" class="w-6 h-6 mr-2 text-[var(--color-highlight)]"></i>
                    COMPARACIÓN DE ESTADO DE LEADS
                </h3>
                <div class="relative h-96 w-full flex justify-center items-center">
                    <canvas id="statusComparisonDoughnutChart"></canvas>
                </div>
            </div>
        </div>
        
               
            </div>
        </div>
        
        
    </main>
    
    
</div>

<div id="notes-panel-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-40 transition-opacity duration-300 opacity-0 pointer-events-none" onclick="closeNotesPanel()"></div>
<aside id="notes-panel" 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 flex flex-col shadow-2xl">
    
    <div class="flex-grow overflow-y-auto h-full relative">
        
        <div class="p-4 bg-[var(--color-primary)] border-b border-gray-200 flex justify-between items-center">
            <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase">
                <i data-lucide="user-plus" class="w-8 h-8 mr-2 text-white"></i> 
                DATOS DEL PROSPECTO 
            </h3> 
                        <button class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200" onclick="closeNotesPanel()"> 
                <i data-lucide="x" class="w-8 h-8"></i> 
            </button> 
        </div>
        
        <div class="p-4 space-y-6">	
            <div id="prospect-info-card" class="bg-white p-4 rounded-xl transition duration-300">
                <div class="border-b pb-3 mb-4"> 
                    <div class="flex justify-between items-start mb-1"> 
                                                <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center"> 
                            <i data-lucide="user" class="w-5 h-5 mr-2 text-[var(--color-primary)]"></i> 
                            <span id="panel-prospect-name" class="break-words"></span> 
                        </h4> 
                        <span class="text-xs font-black bg-[var(--color-highlight)] text-black px-2 py-0.5 rounded-full" id="panel-prospect-stage"></span> 
                    </div> 
                                        <p class="text-sm text-gray-500 font-semibold flex items-center uppercase"> 
                        <i data-lucide="compass" class="w-4 h-4 mr-1.5 text-gray-500"></i>Fuente: <span id="panel-prospect-source" class="ml-1 font-medium text-gray-700"></span> 
                    </p> 
                    <p class="text-xs font-light text-gray-400 mt-1 text-right">ID: <span id="panel-prospect-id"></span></p> 
                </div>
                <div class="space-y-4">
                    <div class="grid grid-cols-2 gap-4"> 
                        <div> 
                            <label for="panel-prospect-first-name" class="block text-md font-bold text-gray-600 mb-1 uppercase">Primer Nombre</label> 
                            <input type="text" id="panel-prospect-first-name" 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" placeholder="Nombre"> 
                        </div> 
                        <div> 
                            <label for="panel-prospect-last-name" class="block text-md font-bold text-gray-600 mb-1 uppercase">Apellido</label> 
                            <input type="text" id="panel-prospect-last-name" 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" placeholder="Apellido"> 
                        </div> 
                    </div>
                    <div> 
                        <label for="panel-prospect-company" class="block text-md font-bold text-gray-600 mb-1 uppercase">Empresa (Opcional)</label>
                        <input type="text" id="panel-prospect-company" 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" placeholder="Nombre del Negocio">
                    </div>
                    
                    <div>
                        <label for="panel-prospect-source-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Fuente del Prospecto</label>
                        <select id="panel-prospect-source-select" 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>
                    <label for="panel-prospect-status-select" class="block text-md font-bold text-gray-600 mb-1 uppercase">Estado del Prospecto</label>
                    <select id="panel-prospect-status-select" 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 class="border-t pt-4"> 
                        <div> 
                            <label for="panel-prospect-email" class="block text-md font-bold text-gray-600 mb-1 uppercase">Email</label> 
                            <input type="email" id="panel-prospect-email" 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" placeholder="ejemplo@cliente.com"> 
                        </div> 
                        <div class="grid grid-cols-2 gap-4 mt-4"> 
                            <div> 
                                <label for="panel-prospect-phone-fixed" class="block text-md font-bold text-gray-600 mb-1 uppercase">Teléfono Fijo</label> 
                                <input type="tel" id="panel-prospect-phone-fixed" 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" placeholder="(XXX) XXX-XXXX"> 
                            </div> 
                            <div> 
                                <label for="panel-prospect-phone-mobile" class="block text-md font-bold text-gray-600 mb-1 uppercase">Celular</label> 
                                <input type="tel" id="panel-prospect-phone-mobile" 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" placeholder="(XXX) XXX-XXXX"> 
                            </div> 
                        </div> 
                    </div>
                    <div class="border-t pt-4"> 
                        <div> 
                            <label for="panel-prospect-address" class="block text-md font-bold text-gray-600 mb-1 uppercase">Dirección (Calle y Número)</label> 
                            <input type="text" id="panel-prospect-address" 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" placeholder="Ej. 123 Main St"> 
                        </div> 
                        <div class="grid grid-cols-3 gap-4 mt-4"> 
                            <div> 
                                <label for="panel-prospect-city" class="block text-md font-bold text-gray-600 mb-1 uppercase">Ciudad</label> 
                                <input type="text" id="panel-prospect-city" 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" placeholder="Ej. Springfield"> 
                            </div> 
                            <div> 
                                <label for="panel-prospect-state-region" class="block text-md font-bold text-gray-600 mb-1 uppercase">Estado</label> 
                                <input type="text" id="panel-prospect-state-region" 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" placeholder="Ej. IL"> 
                            </div> 
                            <div> 
                                <label for="panel-prospect-postal-code" class="block text-md font-bold text-gray-600 mb-1 uppercase">Zip Code</label> 
                                <input type="text" id="panel-prospect-postal-code" 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" placeholder="Ej. 62704"> 
                            </div> 
                        </div> 
                    </div>
                    <div> 
                        <label for="panel-prospect-priority" class="block text-md font-bold text-gray-600 mb-1 uppercase">Prioridad</label> 
                        <select id="panel-prospect-priority" 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"> 
                            <?php foreach ($priority_levels as $level): ?> 
                            <option value="<?php echo htmlspecialchars($level); ?>"><?php echo htmlspecialchars(strtoupper($level)); ?></option> 
                            <?php endforeach; ?> 
                        </select> 
                    </div> 
                </div> 
            </div>
            
            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">	
                                <h4 class="text-2xl font-black text-[var(--color-primary)] mb-3 flex items-center border-b pb-1">	
                    <i data-lucide="message-square-plus" class="w-5 h-5 mr-2 text-[var(--color-secondary)]"></i> NUEVA NOTA DE SEGUIMIENTO	
                </h4>	
                <textarea id="new-note-content" 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 mb-3" rows="3" placeholder="Escriba aquí el resumen de la interacción, dudas del cliente, o el siguiente paso..."></textarea>	
                                <h4 class="text-2xl font-black text-[var(--color-primary)] mb-3 flex items-center border-b pb-1">	
                    <i data-lucide="history" class="w-5 h-5 mr-2 text-[var(--color-secondary)]"></i> HISTORIAL DE SEGUIMIENTO	
                </h4>	
                <div id="notes-list" class="space-y-3 max-h-60 overflow-y-auto pr-2"> </div>	
            </div>
        </div>
    </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="closeNotesPanel()" class="w-full bg-[var(--color-primary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2">
                <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
            </button>
            
                        <button id="save-tracking-btn" class="w-full bg-[var(--color-secondary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2"> 
                <i data-lucide="save" class="w-5 h-5"></i> ACTUALIZAR
            </button> 
        </div>
    </div>
</aside>

<div id="promptLostReasonModal" 
     class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50"
     onclick="if(event.target === this) closeModal('promptLostReasonModal')">
    
    <div class="bg-white rounded-xl shadow-2xl w-full max-w-sm m-4 transform transition-all duration-300 scale-95 opacity-0 text-center">
        
        <div class="modal-header-container rounded-t-xl pt-6">
            <h3 class="modal-primary-title text-4xl 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="help-circle" 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-tight">
                INGRESE LA RAZÓN POR LA QUE ESTE PROSPECTO PASA A ESTADO <span id="lost-rejected-status-display" class="font-black text-[var(--color-secondary)]">PERDIDO</span>
            </p>
            
            <input type="text" id="lost-reason-input" 
                   class="w-full p-3 border-2 border-gray-200 rounded-lg focus:outline-none focus:border-[var(--color-highlight)] focus:ring-0 text-gray-700 font-black uppercase text-sm mb-6 text-center placeholder-gray-400 transition-colors" 
                   placeholder="EJ: PRECIO, COMPETENCIA..." required>

            <div class="flex flex-col sm:flex-row justify-center space-y-2 sm:space-y-0 sm:space-x-4">
                                <button type="button" 
                        class="w-full bg-[var(--color-primary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2" 
                        onclick="closeModal('promptLostReasonModal')">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                
                                <button type="button" 
                        id="confirm-lost-reason-btn"
                        class="w-full bg-[var(--color-secondary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2">
                    <i data-lucide="check-circle" class="w-5 h-5"></i> CONFIRMAR
                </button>
            </div>

            <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider"> 
                ESTA ACCIÓN REGISTRARÁ EL EVENTO
            </p>
        </div>
        
    </div>
</div>

<div id="confirmArchiveModal" 
     class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50"
     onclick="if(event.target === this) closeModal('confirmArchiveModal')">
    
    <div class="bg-white rounded-xl shadow-2xl w-full max-w-sm m-4 transform transition-all duration-300 scale-95 opacity-0 text-center">
        
        <div class="modal-header-container rounded-t-xl pt-6">
            <h3 class="modal-primary-title text-4xl font-black text-[var(--color-highlight)] uppercase leading-none">
                ADVERTENCIA
            </b>
        </div>

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

            <p class="text-[var(--color-primary)] mb-6 uppercase text-lg font-bold leading-tight">
                ¿ESTÁS SEGURO DE ARCHIVAR A <span id="archive-lead-name" class="font-black text-[var(--color-secondary)]"></span>?
            </p>

            <div class="flex flex-col sm:flex-row justify-center space-y-2 sm:space-y-0 sm:space-x-4">
                                <button type="button" 
                        class="w-full bg-[var(--color-secondary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2" 
                        onclick="closeModal('confirmArchiveModal')">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                
                                <button type="button" 
                        id="confirm-archive-btn"
                        class="w-full bg-[var(--color-primary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2">
                    <i data-lucide="archive-restore" class="w-5 h-5"></i> ARCHIVAR
                </button>
            </div>

            <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider"> 
                SE MOVERÁ A PROSPECTOS DESCARTADOS
            </p>
        </div>
    </div>
</div>

<div id="confirmConvertToClientModal" 
     class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50"
     onclick="if(event.target === this) closeModal('confirmConvertToClientModal')">
    
    <div class="bg-white rounded-xl shadow-2xl w-full max-w-sm m-4 transform transition-all duration-300 scale-95 opacity-0 text-center">
        
        <div class="modal-header-container rounded-t-xl pt-6">
            <h3 class="modal-primary-title text-4xl 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="user-plus" class="w-16 h-16 text-[var(--color-highlight)]"></i>
            </div>

            <p class="text-[var(--color-primary)] mb-6 uppercase text-lg font-bold leading-tight">
                ¿CONFIRMAS CONVERTIR EN CLIENTE A <span id="convert-client-name" class="font-black text-[var(--color-secondary)]"></span>?
            </p>

            <div class="flex flex-col sm:flex-row justify-center space-y-2 sm:space-y-0 sm:space-x-4">
                                <button type="button" 
                        class="w-full bg-[var(--color-primary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2" 
                        onclick="closeModal('confirmConvertToClientModal')">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                
                                <button type="button" 
                        id="confirm-convert-client-btn"
                        class="w-full bg-[var(--color-secondary)] hover:opacity-90 text-white font-black py-2.5 px-4 rounded-lg uppercase sm:w-auto flex items-center justify-center gap-2">
                    <i data-lucide="user-check" class="w-5 h-5"></i> CONFIRMAR
                </button>
            </div>

            <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider"> 
                SE MOVERÁ A LA BASE DE CLIENTES
            </p>
        </div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
    
    // OBLIGATORIO: Definición de Endpoints de la API
    const API_ENDPOINTS = {
        READ_NOTES: 'db/leads-get-notes.php',
        ADD_NOTE: 'db/leads-add-note.php',
        UPDATE_LEAD: 'db/leads-update.php',
        CONVERT_TO_CLIENT: 'db/leads-convert-to-client.php',
    };

    // Inyección de variables iniciales desde PHP (Garantizando la existencia de las variables)
    let funnelData = <?php echo json_encode($funnel_prospects); ?>;
    let convertedData = <?php echo json_encode($converted_prospects); ?>;
    let lostData = <?php echo json_encode($lost_prospects); ?>;
    const allLeadsWithDate = <?php echo json_encode($all_leads_with_date); ?>; 
    const stagesData = <?php echo json_encode(array_values($funnel_stages_js)); ?>;
    const leadSources = <?php echo json_encode($lead_sources); ?>;
    const priorityLevels = <?php echo json_encode($priority_levels); ?>;

    const convertedDbStatus = '<?php echo htmlspecialchars($converted_db_status); ?>';
    const lostDbStatus = '<?php echo htmlspecialchars($lost_db_status); ?>';
    const archivedDbStatus = '<?php echo htmlspecialchars($archived_db_status); ?>';
    
    let draggedItem = null; 
    let currentProspectId = null; 
    let draggedProspectIdToLose = null; 
    let leadIdToMoveOrArchive = null; 
    window.tempProspectDataForUpdate = null; 
    
    window.dailyLeadsBarChartInstance = null; 
    window.statusComparisonDoughnutChartInstance = null; 

    function escapeHtml(text) {
        if (text == null) return '';
        return text.toString()
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }

    const notesPanel = document.getElementById('notes-panel');
    const notesOverlay = document.getElementById('notes-panel-overlay');

function openModal(modalId) {
    const modal = document.getElementById(modalId);
    if (!modal) return;
    
    const modalBox = modal.querySelector('div:first-of-type'); 
    
    modal.classList.remove('hidden');
    
    setTimeout(() => { 
        modalBox.classList.remove('scale-95', 'opacity-0');
        modalBox.classList.add('scale-100', 'opacity-100'); 
    }, 50);
    
    document.body.style.overflow = 'hidden';
    
    if(typeof lucide !== 'undefined') {
        lucide.createIcons();
    }
}

window.closeModal = function(modalId) {
    const modal = document.getElementById(modalId);
    if (!modal) return;
    const modalBox = modal.querySelector('div:first-of-type');
    
    modalBox.classList.remove('scale-100', 'opacity-100');
    modalBox.classList.add('scale-95', 'opacity-0');
    
    setTimeout(() => {
        modal.classList.add('hidden');
        document.body.style.overflow = '';
        // Limpieza específica para el modal de motivo
        if (modalId === 'promptLostReasonModal') {
             const input = document.getElementById('lost-reason-input');
             if(input) input.value = '';
        }
    }, 300); 
}

    window.closeNotesPanel = function() {
        if (!notesPanel || !notesOverlay) return;
        notesPanel.classList.add('translate-x-full');
        notesOverlay.classList.remove('opacity-100');
        notesOverlay.classList.add('opacity-0', 'pointer-events-none');
        currentProspectId = null;
        document.getElementById('new-note-content').value = '';
    }
    
    function applyPhoneMasksToPanel() {
        const phoneFixedInput = document.getElementById('panel-prospect-phone-fixed');
        const phoneMobileInput = document.getElementById('panel-prospect-phone-mobile');
        if (typeof IMask !== 'undefined') {
            try {
                if (phoneFixedInput && phoneFixedInput.imask) { phoneFixedInput.imask.destroy(); delete phoneFixedInput.imask; }
                if (phoneMobileInput && phoneMobileInput.imask) { phoneMobileInput.imask.destroy(); delete phoneMobileInput.imask; }

                if (phoneFixedInput) {
                    phoneFixedInput.imask = IMask(phoneFixedInput, { mask: '(000) 000-0000', lazy: false });
                }
                if (phoneMobileInput) {
                    phoneMobileInput.imask = IMask(phoneMobileInput, { mask: '(000) 000-0000', lazy: false });
                }
            } catch (error) { console.error("Error al aplicar iMask:", error); }
        }
    }

    window.openNotesPanel = async function(prospectId) {
        const prospect = [...funnelData, ...convertedData, ...lostData].find(p => p.id == prospectId);
        if (!prospect) { showToast(`Error: Prospecto ID ${prospectId} no encontrado.`, 'error'); return; }
        currentProspectId = prospectId;

        document.getElementById('panel-prospect-name').textContent = prospect.name || 'N/A';
        document.getElementById('panel-prospect-source').textContent = prospect.source || 'N/A';
        document.getElementById('panel-prospect-id').textContent = prospect.id;

        const stageInfo = stagesData.find(s => s.db_status === prospect.status_text);
        let statusDisplay = prospect.status_text.toUpperCase();
        if (stageInfo) { statusDisplay = stageInfo.title; }
        else if (prospect.status_text === convertedDbStatus) { statusDisplay = 'LEAD GANADO'; }
        else if (prospect.status_text === lostDbStatus) {   
            statusDisplay = 'LEAD PERDIDO'; 
        }
        
        document.getElementById('panel-prospect-stage').textContent = statusDisplay;

        document.getElementById('panel-prospect-first-name').value = prospect.first_name || '';
        document.getElementById('panel-prospect-last-name').value = prospect.last_name || '';
        document.getElementById('panel-prospect-company').value = prospect.company || '';
        document.getElementById('panel-prospect-email').value = prospect.email || '';
        document.getElementById('panel-prospect-phone-fixed').value = prospect.phone_fixed || '';
        document.getElementById('panel-prospect-phone-mobile').value = prospect.phone_mobile || '';
        document.getElementById('panel-prospect-address').value = prospect.address || '';
        document.getElementById('panel-prospect-city').value = prospect.city || '';
        document.getElementById('panel-prospect-state-region').value = prospect.state_region || '';
        document.getElementById('panel-prospect-postal-code').value = prospect.postal_code || '';
        
        const sourceSelect = document.getElementById('panel-prospect-source-select');
        sourceSelect.innerHTML = '';  
        
        let defaultOption = document.createElement('option');
        defaultOption.value = '';
        defaultOption.textContent = 'Seleccione una Fuente';
        sourceSelect.appendChild(defaultOption);

        leadSources.forEach(source => { 
            const option = document.createElement('option');
            option.value = source;
            option.textContent = source;
            sourceSelect.appendChild(option);
        });
        
        sourceSelect.value = prospect.source || '';
        
        document.getElementById('panel-prospect-priority').value = prospect.priority || 'Media';

        const statusSelect = document.getElementById('panel-prospect-status-select');
        statusSelect.innerHTML = '';  
        
        stagesData.forEach(stage => {
            const option = document.createElement('option');
            option.value = stage.db_status; option.textContent = stage.title; statusSelect.appendChild(option);
        });
        const convertedOpt = document.createElement('option');
        convertedOpt.value = convertedDbStatus; convertedOpt.textContent = 'LEAD GANADO'; statusSelect.appendChild(convertedOpt);
        const lostOpt = document.createElement('option');
        lostOpt.value = lostDbStatus; lostOpt.textContent = 'LEAD PERDIDO'; statusSelect.appendChild(lostOpt);

        statusSelect.value = prospect.status_text;

        document.getElementById('new-note-content').value = '';
        await renderNotes(prospectId);

        notesPanel.classList.remove('translate-x-full');
        notesOverlay.classList.remove('opacity-0', 'pointer-events-none');
        notesOverlay.classList.add('opacity-100');
        applyPhoneMasksToPanel();
        lucide.createIcons();
    }

    async function renderNotes(leadId) {
        const notesList = document.getElementById('notes-list');
        notesList.innerHTML = '<p class="text-gray-500 italic text-sm p-3">Cargando notas...</p>';
        try {
            // USANDO API_ENDPOINTS
            const response = await fetch(`${API_ENDPOINTS.READ_NOTES}?lead_id=${leadId}`);
            const data = await response.json();
            notesList.innerHTML = '';
            if (data.success && data.notes.length > 0) {
                data.notes.forEach(note => {
                    const noteDiv = document.createElement('div');
                    noteDiv.className = 'bg-white p-2 rounded-lg shadow border-l-4 border-l-[var(--color-primary)] text-sm';
                    noteDiv.innerHTML = `<div class="flex justify-between items-center text-xs mb-1 text-gray-500 font-medium"><span>${new Date(note.created_at).toLocaleString('es-ES')}</span><i data-lucide="tag" class="w-3 h-3 text-[var(--color-highlight)]"></i></div><p class="text-gray-700">${escapeHtml(note.content)}</p>`;
                    notesList.appendChild(noteDiv);
                });
            } else {
                notesList.innerHTML = '<p class="text-gray-500 italic text-sm p-3 bg-gray-50 rounded-lg">No hay notas registradas.</p>';
            }
        } catch (error) {
            console.error("Error cargando notas:", error);
            notesList.innerHTML = '<p class="text-[var(--color-secondary)] italic text-sm p-3">Error al cargar notas.</p>';
        }
        lucide.createIcons();
    }

    document.getElementById('save-tracking-btn').addEventListener('click', async () => {
        if (!currentProspectId) return;
        showToast('Guardando...', 'info');
        const prospect = [...funnelData, ...convertedData, ...lostData].find(p => p.id == currentProspectId);
        if (!prospect) { showToast('Error: Prospecto no encontrado.', 'error'); return; }

        const newNoteContent = document.getElementById('new-note-content').value.trim();
        if (newNoteContent) {
            try {
                // USANDO API_ENDPOINTS
                const noteRes = await fetch(API_ENDPOINTS.ADD_NOTE, { 
                    method: 'POST', 
                    headers: { 'Content-Type': 'application/json' }, 
                    body: JSON.stringify({ lead_id: currentProspectId, content: newNoteContent }) 
                });
                const noteResult = await noteRes.json();
                if (noteResult.success) {
                    showToast('Nota guardada.', 'success'); document.getElementById('new-note-content').value = ''; await renderNotes(currentProspectId);
                } else { showToast(noteResult.message || 'Error al guardar nota.', 'error'); }
            } catch (err) { console.error("Error fetch nota:", err); }
        }

        const phoneFixedInput = document.getElementById('panel-prospect-phone-fixed');
        const phoneMobileInput = document.getElementById('panel-prospect-phone-mobile');
        
        // Uso de unmaskedValue de IMask si está disponible
        const phoneFixedValue = phoneFixedInput.imask ? phoneFixedInput.imask.unmaskedValue : phoneFixedInput.value.trim().replace(/\D/g, '');
        const phoneMobileValue = phoneMobileInput.imask ? phoneMobileInput.imask.unmaskedValue : phoneMobileInput.value.trim().replace(/\D/g, '');
        
        
        const updatedData = {
            id: currentProspectId,
            first_name: document.getElementById('panel-prospect-first-name').value.trim(),
            last_name: document.getElementById('panel-prospect-last-name').value.trim(),
            company: document.getElementById('panel-prospect-company').value.trim(),
            email: document.getElementById('panel-prospect-email').value.trim(),
            phone: phoneFixedValue, 
            mobile: phoneMobileValue,
            street_address: document.getElementById('panel-prospect-address').value.trim(),
            city: document.getElementById('panel-prospect-city').value.trim(),
            state_province: document.getElementById('panel-prospect-state-region').value.trim(),
            zip_code: document.getElementById('panel-prospect-postal-code').value.trim(),
            source: document.getElementById('panel-prospect-source-select').value,  
            priority: document.getElementById('panel-prospect-priority').value,
            status: document.getElementById('panel-prospect-status-select').value    
        };

        let lostReason = prospect.lost_reason;
        let requiresModal = false;
        let newStatusFinal = updatedData.status;

        // Si el nuevo estado es perdido Y el estado anterior NO era perdido (se movió desde el funnel)
        if (newStatusFinal === lostDbStatus && prospect.status_text !== newStatusFinal) {    
            requiresModal = true;    
        } 
        // Si el estado sigue siendo perdido (actualización de datos de la ficha)
        else if (newStatusFinal === lostDbStatus && prospect.status_text === lostDbStatus) {
            // Conservamos la razón de pérdida existente para la actualización.
            lostReason = prospect.lost_reason;
        }
        // Si el estado no es perdido, la razón se borra o es nula
        else if (newStatusFinal !== lostDbStatus) { 
            lostReason = null;   
        }

        if (requiresModal) {
            window.tempProspectDataForUpdate = updatedData;
            document.getElementById('lost-reason-input').value = prospect.lost_reason || ''; // Pre-llenar si existe
            document.getElementById('lost-rejected-status-display').textContent = 'PERDIDO';  
            openModal('promptLostReasonModal');
            document.getElementById('confirm-lost-reason-btn').onclick = handleConfirmLostReasonAndUpdate;
        } else {
            // Enviamos la razón existente o nula
            await executeProspectUpdate(updatedData, lostReason);
        }
    });

    async function handleConfirmLostReasonAndUpdate() {
        const reasonInput = document.getElementById('lost-reason-input');
        const reason = reasonInput.value.trim();
        if (!reason) { showToast('Debe ingresar una razón.', 'warning'); reasonInput.focus(); return; }
        closeModal('promptLostReasonModal');
        const dataToUpdate = window.tempProspectDataForUpdate;
        if (!dataToUpdate) return;
        // Aquí se pasa la razón capturada del modal
        await executeProspectUpdate(dataToUpdate, reason);
        window.tempProspectDataForUpdate = null;
    }

    async function executeProspectUpdate(prospectData, reason) {
            try {
                // USANDO API_ENDPOINTS
                const response = await fetch(API_ENDPOINTS.UPDATE_LEAD, { 
                    method: 'POST', 
                    headers: { 'Content-Type': 'application/json' }, 
                    body: JSON.stringify({ ...prospectData, lost_reason: reason }) 
                });
                const result = await response.json();
                if (result.success) {
                    showToast('Información actualizada.', 'success');
                    
                    let prospectInMemory = [...funnelData, ...convertedData, ...lostData].find(p => p.id == prospectData.id);

                    if (prospectInMemory) {
                        const finalStatusText = prospectData.status;
                        
                        Object.assign(prospectInMemory, {
                            first_name: prospectData.first_name, last_name: prospectData.last_name,
                            name: `${prospectData.first_name} ${prospectData.last_name}`.trim(),
                            company: prospectData.company, email: prospectData.email,
                            // Los teléfonos se actualizan limpios (sin máscara)
                            phone_fixed: prospectData.phone, phone_mobile: prospectData.mobile,
                            address: prospectData.street_address, city: prospectData.city,
                            state_region: prospectData.state_province, postal_code: prospectData.zip_code,
                            source: prospectData.source, priority: prospectData.priority,
                            status_text: prospectData.status,
                            // CLAVE DE PERSISTENCIA: La razón viene del argumento 'reason' que es la que debe persistir
                            lost_reason: reason, 
                            stage: Object.fromEntries(stagesData.map(s => [s.db_status, s.id]))[prospectData.status] ?? null
                        });
                        
                        funnelData = funnelData.filter(p => p.id != prospectInMemory.id);
                        convertedData = convertedData.filter(p => p.id != prospectInMemory.id);
                        lostData = lostData.filter(p => p.id != prospectInMemory.id);
                        
                        if (prospectInMemory.stage !== null) funnelData.push(prospectInMemory);
                        else if (prospectInMemory.status_text === convertedDbStatus) convertedData.push(prospectInMemory);
                        else if (prospectInMemory.status_text === lostDbStatus) lostData.push(prospectInMemory);
                    }
                    closeNotesPanel();
                    renderAll();
                } else { showToast(result.message || 'Error al actualizar.', 'error'); }
            } catch (error) { console.error("Error fetch executeUpdate:", error); showToast('Error conexión al guardar.', 'error'); }
    }
    
    function renderDailyLeadsBarChart() {
        const ctx = document.getElementById('dailyLeadsBarChart');
        if (!ctx || typeof Chart === 'undefined') return;

        const getStyle = (prop) => getComputedStyle(document.documentElement).getPropertyValue(prop).trim();
        const primaryColor = getStyle('--color-primary');
        
        // 1. Calcular el conteo por día del mes
        const dailyCounts = {};
        const today = new Date();
        const currentMonth = today.getMonth();
        const currentYear = today.getFullYear();
        const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
        
        for(let i = 1; i <= daysInMonth; i++) {
            dailyCounts[i] = 0;
        }

        allLeadsWithDate.forEach(lead => {
            if (lead.created_at) {
                try {
                    const date = new Date(lead.created_at.replace(/-/g, '/')); // Fix for cross-browser date parsing
                    if (date.getMonth() === currentMonth && date.getFullYear() === currentYear) {
                        const dayOfMonth = date.getDate();
                        dailyCounts[dayOfMonth]++;
                    }
                } catch (e) {
                    console.error("Error al parsear fecha:", lead.created_at, e);
                }
            }
        });
        
        const labels = Object.keys(dailyCounts);
        const data = Object.values(dailyCounts);

        // 2. Destruir gráfico anterior si existe
        if (window.dailyLeadsBarChartInstance) {
            window.dailyLeadsBarChartInstance.destroy();
        }

        // 3. Crear nuevo gráfico de BARRA
        window.dailyLeadsBarChartInstance = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: labels,
                datasets: [{
                    label: 'Leads por Día',
                    data: data,
                    backgroundColor: primaryColor,
                    borderColor: primaryColor,
                    borderWidth: 1
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: { display: false },
                    tooltip: {
                        callbacks: {
                            title: (context) => `Día ${context[0].label}`,
                            label: (context) => ` Leads: ${context.formattedValue}`
                        }
                    }
                },
                scales: {
                    y: { beginAtZero: true, ticks: { precision: 0 } },
                    x: { title: { display: true, text: 'Día del Mes' } }
                }
            }
        });
    }
    
    // MODIFICACIÓN 2: Función para renderizar el gráfico CIRCULAR (Comparación)
    function renderStatusComparisonDoughnutChart() {
        const ctx = document.getElementById('statusComparisonDoughnutChart');
        if (!ctx || typeof Chart === 'undefined') return;

        const getStyle = (prop) => getComputedStyle(document.documentElement).getPropertyValue(prop).trim();
        
        // 1. Calcular el conteo total por estado
        const totalInFunnel = funnelData.length;
        const totalConverted = convertedData.length;
        const totalLost = lostData.length;
        
        // 2. Destruir gráfico anterior si existe
        if (window.statusComparisonDoughnutChartInstance) {
            window.statusComparisonDoughnutChartInstance.destroy();
        }

        // 3. Crear nuevo gráfico DOUGHNUT
        window.statusComparisonDoughnutChartInstance = new Chart(ctx, {
            type: 'doughnut',
            data: {
                labels: [
                    'Leads En Seguimiento',
                    'Leads Convertidos',
                    'Leads Perdidos'
                ],
                datasets: [{
                    label: 'Cantidad de Leads',
                    data: [totalInFunnel, totalConverted, totalLost],
                    backgroundColor: [
                        getStyle('--color-highlight'), // Para En Seguimiento
                        '#10B981', // emerald-500 para Convertidos
                        getStyle('--color-secondary') // Para Perdidos
                    ],
                    hoverOffset: 4
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: {
                        position: 'bottom',
                        labels: {
                            font: { family: "'Barlow', sans-serif", weight: '600' }
                        }
                    },
                    title: {
                        display: true,
                        text: `Total Leads: ${totalInFunnel + totalConverted + totalLost}`,
                        font: { family: "'Barlow', sans-serif", size: 18, weight: 'bold' }
                    },
                    tooltip: {
                        callbacks: {
                            label: function(context) {
                                const label = context.label || '';
                                const value = context.parsed;
                                const total = context.dataset.data.reduce((a, b) => a + b, 0);
                                const percentage = ((value / total) * 100).toFixed(1);
                                return `${label}: ${value} (${percentage}%)`;
                            }
                        }
                    }
                }
            }
        });
    }

    function renderAll() {
        renderFunnelCards();
        renderConvertedCards();
        renderLostCards();
        updateAllCounts();
        renderDailyLeadsBarChart(); 
        renderStatusComparisonDoughnutChart(); 
        lucide.createIcons();
    }

    function renderFunnelCards() {
        document.querySelectorAll('.kanban-list[data-stage-id]').forEach(list => list.innerHTML = '');
        funnelData.forEach(prospect => {
            if (prospect.stage !== null && prospect.stage >= 0 && prospect.stage < stagesData.length) {
                const stageInfo = stagesData[prospect.stage];
                const targetList = document.querySelector(`.kanban-list[data-stage-id="${prospect.stage}"]`);
                if (targetList) targetList.appendChild(createProspectCard(prospect, stageInfo));
            }
        });
    }

    function renderConvertedCards() {
        const list = document.getElementById('converted-list'); 
        if(list) {
            list.innerHTML = '';
            convertedData.forEach(prospect => list.appendChild(createConvertedCard(prospect)));
        }
    }

    function renderLostCards() {
        const list = document.getElementById('lost-list');  
        if(list) {
            list.innerHTML = '';
            lostData.filter(p => p.status_text === lostDbStatus).forEach(prospect => list.appendChild(createLostCard(prospect)));
        }
    }
    
    // MODIFICADO: Tarjeta de Prospectos SÚPER compacta (Elimina Fuente, Botón de Detalles minimalista)
    function createProspectCard(prospect, stage) {
        const card = document.createElement('div');
        card.className = `prospect-card bg-white p-2 rounded-lg shadow-md hover:shadow-lg border-l-4 ${stage.border_class} cursor-grab transition-all duration-200 ease-in-out hover:-translate-y-0.5`;
        card.dataset.prospectId = prospect.id;
        card.dataset.stageId = prospect.stage;
        card.setAttribute('draggable', true);
        card.innerHTML = `
            <div class="flex justify-between items-center">
                <span class="font-black text-gray-800 text-lg w-full pr-2">${escapeHtml(prospect.name)}</span>
                <button onclick="window.openNotesPanel(${prospect.id})" title="Ver Detalles" class="flex-shrink-0 inline-flex items-center text-xs font-black uppercase text-white bg-[var(--color-secondary)] hover:bg-[var(--color-primary)] py-1 px-1.5 rounded-md shadow-sm transition-all duration-200 ease-in-out">
                    <i data-lucide="arrow-big-right-dash" class="w-3.5 h-3.5"></i> Ver Detalles
                </button>
            </div>`;
        card.addEventListener('dragstart', handleDragStart);
        card.addEventListener('dragend', handleDragEnd);
        return card;
    }

    // MODIFICADO: Tarjeta de Lead Ganado más compacta (Botones estilizados)
    function createConvertedCard(prospect) {
        const card = document.createElement('div');
        card.className = 'prospect-card-result bg-white p-2 rounded-lg shadow-sm border-l-2 border-emerald-500 cursor-grab transition-all duration-200 hover:shadow-md';
        card.setAttribute('draggable', true);
        card.dataset.prospectId = prospect.id;
        card.dataset.stageId = null;
        
        card.innerHTML = `
            <div class="flex justify-between items-center mb-1">
                <span class="font-black text-gray-800 text-lg truncate w-full pr-1">${escapeHtml(prospect.name)}</span>
                <div class="flex space-x-1.5 flex-shrink-0">
                    <button onclick="window.openNotesPanel(${prospect.id})" title="Ver Detalles" class="inline-flex items-center text-xs font-semibold text-white bg-[var(--color-secondary)] hover:bg-[var(--color-primary)] py-0.5 px-1.5 rounded-md shadow-sm transition-all duration-200 ease-in-out">
                        <i data-lucide="notebook-text" class="w-6 h-6"></i>
                    </button>
                     <button onclick="openConvertToClientModal(${prospect.id}, '${escapeHtml(prospect.name.replace(/'/g, "\\'"))}')" title="Convertir En Cliente" class="inline-flex items-center text-xs font-black text-white uppercase bg-emerald-600 hover:bg-emerald-700 py-0.5 px-1.5 rounded-md shadow-sm transition-all duration-200 ease-in-out">
                        <i data-lucide="user-check" class="w-6 h-6"></i> Convertir En Cliente
                    </button>
                </div>
            </div>
            <div class="text-xs text-gray-500 font-medium flex items-center"><i data-lucide="compass" class="w-3 h-3 mr-1"></i> Fuente: ${escapeHtml(prospect.source || 'N/A')}</div>`;
        card.addEventListener('dragstart', handleDragStart);
        card.addEventListener('dragend', handleDragEnd);
        return card;
    }

    // MODIFICADO: Tarjeta de Lead Perdido más compacta (Botones estilizados)
    function createLostCard(prospect) {
        const card = document.createElement('div');
        card.className = 'prospect-card-result bg-white p-2 rounded-lg shadow-sm border-l-2 border-[var(--color-secondary)] cursor-grab transition-all duration-200 hover:shadow-md';
        card.setAttribute('draggable', true);
        card.dataset.prospectId = prospect.id;
        card.dataset.stageId = null;
        
        // Aseguramos que la razón de pérdida esté en el DOM para mostrarla
        const reasonDisplay = escapeHtml(prospect.lost_reason || 'Razón no especificada');
        
        card.innerHTML = `
            <div class="flex justify-between items-center mb-1">
                <span class="font-black text-gray-800 text-lg truncate w-full pr-1">${escapeHtml(prospect.name)}</span>
                <div class="flex space-x-1.5 flex-shrink-0">
                    <button onclick="openArchiveModal(${prospect.id}, '${escapeHtml(prospect.name.replace(/'/g, "\\'"))}')" title="Archivar Lead" class="inline-flex items-center text-xs font-black uppercase text-white bg-[var(--color-primary)] hover:bg-[var(--color-secondary)] py-0.5 px-1.5 rounded-md shadow-sm transition-all duration-200 ease-in-out">
                        <i data-lucide="archive" class="w-3 h-3"></i> Archivar Lead
                    </button>
                    <button onclick="window.openNotesPanel(${prospect.id})" title="Ver Detalles" class="inline-flex items-center text-xs font-semibold text-white bg-[var(--color-secondary)] hover:bg-[var(--color-primary)] py-0.5 px-1.5 rounded-md shadow-sm transition-all duration-200 ease-in-out">
                        <i data-lucide="notebook-text" class="w-3 h-3"></i>
                    </button>
                </div>
            </div>
            <div class="text-xs font-black uppercase text-[var(--color-secondary)] flex items-center truncate"><i data-lucide="octagon-x" class="w-3 h-3 mr-1 flex-shrink-0"></i>${reasonDisplay}</div>`;
        card.addEventListener('dragstart', handleDragStart);
        card.addEventListener('dragend', handleDragEnd);
        return card;
    }

    function updateAllCounts() {
        stagesData.forEach((stage) => {
            const count = funnelData.filter(p => p.stage == stage.id).length;
            const el = document.getElementById(`count-${stage.id}`); if(el) el.textContent = `(${count})`;
        });
        const countConv = document.getElementById('kpi-converted'); if(countConv) countConv.textContent = convertedData.length;
        const countLost = document.getElementById('kpi-new-prospects'); if(countLost) countLost.textContent = funnelData.length;
        
        const totalInFunnel = funnelData.length, totalConv = convertedData.length, totalL = lostData.length;
        const totalDecided = totalConv + totalL;
        const rate = (totalDecided > 0) ? Math.round((totalConv / totalDecided) * 100) : 0;
        const kpiFunnel = document.getElementById('kpi-new-prospects'); if(kpiFunnel) kpiFunnel.textContent = totalInFunnel;
        const kpiConv = document.getElementById('kpi-converted'); if(kpiConv) kpiConv.textContent = totalConv;
        const kpiRate = document.getElementById('kpi-rate'); if(kpiRate) kpiRate.textContent = `${rate}%`;
    }

    function handleDragStart(e) { draggedItem = e.target; e.dataTransfer.setData('text/plain', e.target.dataset.prospectId); setTimeout(() => { if(draggedItem) draggedItem.classList.add('opacity-50'); }, 0); }
    function handleDragEnd(e) { if (draggedItem) draggedItem.classList.remove('opacity-50'); draggedItem = null; }
    function handleDragOver(e) { e.preventDefault(); const list = e.currentTarget; if (list.classList.contains('kanban-list') || list.closest('.funnel-column')) list.classList.add('bg-gray-100'); }
    function handleDragLeave(e) { const list = e.currentTarget; if (list.classList.contains('kanban-list') || list.closest('.funnel-column')) list.classList.remove('bg-gray-100'); }

    async function handleDrop(e) {
        e.preventDefault();
        const column = e.currentTarget.closest('.funnel-column');
        if (!column) return;
        
        if (e.currentTarget.classList.contains('kanban-list')) {
             e.currentTarget.classList.remove('bg-gray-100');
        } else {
             column.classList.remove('bg-gray-100');
        }

        const pId = parseInt(e.dataTransfer.getData('text/plain'));
        draggedProspectIdToLose = pId;
        let p = [...funnelData, ...convertedData, ...lostData].find(x => x.id === pId);
        if (!p || !draggedItem) { console.warn("Drop: Prospecto/Item no hallado."); renderAll(); return; }

        const action = column.dataset.action;
        const stageId = parseInt(column.dataset.stageId, 10);
        let newStatus = null, reason = p.lost_reason;

        if (action === 'lost') {   
            document.getElementById('lost-rejected-status-display').textContent = 'PERDIDO';
            document.getElementById('confirm-lost-reason-btn').onclick = window.confirmLostReasonLogic;
            // Pre-llenar el campo de razón de pérdida si existe (para re-clasificación)
            document.getElementById('lost-reason-input').value = p.lost_reason || '';
            openModal('promptLostReasonModal'); 
            return; 
        }
        else if (action === 'convert') { newStatus = convertedDbStatus; reason = null; }
        else if (!isNaN(stageId) && stageId >= 0 && stageId < stagesData.length) {
            newStatus = stagesData[stageId].db_status;
            // Si se mueve al funnel, limpiamos la razón de pérdida
            if (p.status_text === lostDbStatus || p.status_text === archivedDbStatus) reason = null;    
        } else { console.warn("Drop en zona inválida."); renderAll(); return; }

        if (newStatus && newStatus !== p.status_text) { updateStatusInDb(pId, newStatus, reason); }
        else { console.log("Mismo estado."); renderAll(); }
    }
    
    document.querySelectorAll('.funnel-column').forEach(column => {
        const list = column.querySelector('.kanban-list');
        if (list) {
            list.addEventListener('dragover', handleDragOver);
            list.addEventListener('dragleave', handleDragLeave);
            list.addEventListener('drop', handleDrop);
        }
    });

    async function updateStatusInDb(prospectId, newDbStatus, lostReason = null) {
        const prospect = [...funnelData, ...convertedData, ...lostData].find(p => p.id === prospectId);
        if (!prospect) { showToast("Error interno al actualizar estado.", "error"); return; }

        try {
            // Si estamos marcando como perdido y no se proporcionó una razón (ej. arrastrar y soltar a perdido),
            // usamos la razón que el lead ya tenía si existía. (Esto es redundante si se usa el modal, pero seguro)
            if (newDbStatus === lostDbStatus && lostReason === null) {
                // Si la función no nos dio una razón, intentamos usar la que ya tiene el prospecto en memoria.
                lostReason = prospect.lost_reason;
            }
            
            const dbStatusToSave = newDbStatus;

            // USANDO API_ENDPOINTS
            const response = await fetch(API_ENDPOINTS.UPDATE_LEAD, { 
                method: 'POST', 
                headers: { 'Content-Type': 'application/json' }, 
                body: JSON.stringify({ 
                    // Enviamos todos los campos necesarios para la actualización completa en leads-update.php
                    id: prospectId,
                    first_name: prospect.first_name, 
                    last_name: prospect.last_name, 
                    company: prospect.company, 
                    email: prospect.email, 
                    phone: prospect.phone_fixed, 
                    mobile: prospect.phone_mobile,
                    street_address: prospect.address, 
                    city: prospect.city, 
                    state_province: prospect.state_region, 
                    zip_code: prospect.postal_code,
                    source: prospect.source,
                    priority: prospect.priority,
                    // CLAVE: Nuevo estado y razón
                    status: dbStatusToSave, 
                    lost_reason: lostReason 
                }) 
            });
            const result = await response.json();
            if (result.success) {
                showToast('¡ACTUALIZADO CON ÉXITO!', 'success');
                
                let prospectInMemory = [...funnelData, ...convertedData, ...lostData].find(p => p.id == prospectId);

                if (prospectInMemory) {
                    const finalStatusText = newDbStatus;
                    
                    Object.assign(prospectInMemory, {
                        status_text: finalStatusText,
                        lost_reason: lostReason, // Aseguramos que se actualice la memoria con la razón
                        stage: Object.fromEntries(stagesData.map(s => [s.db_status, s.id]))[newDbStatus] ?? null
                    });

                    funnelData = funnelData.filter(p => p.id != prospectId);
                    convertedData = convertedData.filter(p => p.id != prospectId);
                    lostData = lostData.filter(p => p.id != prospectId);
                    
                    if (prospectInMemory.stage !== null) funnelData.push(prospectInMemory);
                    else if (prospectInMemory.status_text === convertedDbStatus) convertedData.push(prospectInMemory);
                    else if (prospectInMemory.status_text === lostDbStatus) lostData.push(prospectInMemory);
                }
                renderAll();
            } else { showToast(result.message || 'Error al mover.', 'error'); renderAll(); }
        } catch (error) { console.error("Error fetch updateStatus:", error); showToast('Error conexión al mover.', 'error'); renderAll(); }
    }

    window.confirmLostReasonLogic = async function() {
        const reasonInput = document.getElementById('lost-reason-input');
        const reason = reasonInput.value.trim();
        const pId = draggedProspectIdToLose;
        const newStatus = lostDbStatus;
        
        if (!reason) { showToast('Debe ingresar una razón.', 'warning'); reasonInput.focus(); return; }
        if (!pId) { showToast('Error: ID no encontrado.', 'error'); closeModal('promptLostReasonModal'); return; }
        closeModal('promptLostReasonModal');
        
        await updateStatusInDb(pId, newStatus, reason);
        draggedProspectIdToLose = null;
    }
    
    window.promptLostReasonLogic = function(leadId, leadName) {
        draggedProspectIdToLose = leadId;
        document.getElementById('lost-rejected-status-display').textContent = 'PERDIDO';
        // Aquí se toma la razón de la data del cliente si ya existe
        const prospect = [...funnelData, ...convertedData, ...lostData].find(p => p.id == leadId);
        document.getElementById('lost-reason-input').value = prospect.lost_reason || '';
        openModal('promptLostReasonModal');
        document.getElementById('confirm-lost-reason-btn').onclick = window.confirmLostReasonLogic;
    }
    
    // FUNCIONES PARA ARCHIVAR
    window.openArchiveModal = function(leadId, leadName) {
        leadIdToMoveOrArchive = leadId;
        document.getElementById('archive-lead-name').textContent = leadName;
        openModal('confirmArchiveModal');
    }
    
    window.confirmArchiveLogic = function() {
        if (!leadIdToMoveOrArchive) return;
        closeModal('confirmArchiveModal');
        // Usar la razón de pérdida existente para el archivo si la tiene
        const prospect = [...funnelData, ...convertedData, ...lostData].find(p => p.id == leadIdToMoveOrArchive);
        const reason = prospect.lost_reason || 'Archivado por usuario';
        
        updateStatusInDb(leadIdToMoveOrArchive, archivedDbStatus, reason);
    }
    
    // FUNCIONES PARA CONVERTIR A CLIENTE
    window.openConvertToClientModal = function(leadId, leadName) {
        leadIdToMoveOrArchive = leadId;
        document.getElementById('convert-client-name').textContent = leadName;
        openModal('confirmConvertToClientModal');
    }

    window.confirmConvertToClientLogic = async function() {
        if (!leadIdToMoveOrArchive) return;
        closeModal('confirmConvertToClientModal');
        
        showToast('Convirtiendo a cliente...', 'info');

        try {
            // USANDO API_ENDPOINTS
            const response = await fetch(API_ENDPOINTS.CONVERT_TO_CLIENT, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ prospect_id: leadIdToMoveOrArchive })
            });
            const data = await response.json();

            if (data.success) {
                showToast('¡CONVERTIDO A CLIENTE CON ÉXITO!', 'success');
                // Eliminar de la vista porque ya no es Lead
                convertedData = convertedData.filter(p => p.id != leadIdToMoveOrArchive);
                renderAll();
            } else {
                showToast(data.message || 'Error al convertir.', 'error');
            }
        } catch (error) {
            console.error("Error al convertir cliente:", error);
            showToast('Error de conexión.', 'error');
        }
    }
    
    const confirmArchiveBtn = document.getElementById('confirm-archive-btn'); if (confirmArchiveBtn) confirmArchiveBtn.addEventListener('click', window.confirmArchiveLogic);
    const confirmConvertClientBtn = document.getElementById('confirm-convert-client-btn'); if (confirmConvertClientBtn) confirmConvertClientBtn.addEventListener('click', window.confirmConvertToClientLogic);

    const mobileMenuButton = document.getElementById('mobile-menu-button'); const sidebar = document.getElementById('sidebar'); const sidebarOverlay = document.getElementById('sidebar-overlay');
    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'); });
    }

    renderAll();
});
</script>
<script src="files/toast.js"></script>
</body>
</html>