<?php
declare(strict_types=1);

// Fase I: Inicialización Segura y Configuración
require_once __DIR__ . '/core/init.php';

// Verificación de Autenticación
if (!isset($skip_auth_check) || $skip_auth_check === false) {
    require_once __DIR__ . '/files/guardiankey.php';
}

// Configuración de Errores: Mantener la configuración del archivo original
ini_set('display_errors', '0');
ini_set('log_errors', '1');
error_reporting(E_ALL);

// Protección CSRF
$csrf_token = htmlspecialchars($_SESSION['csrf_token'] ?? '', ENT_QUOTES, 'UTF-8');

// --- CONFIGURACIÓN KANBAN (Estrictamente Estados de Seguimiento/Funnel) ---
// NOTA: 'Cotización Ganada' y 'Cotización Perdida' ya no se usan en este array, 
// se manejan por el estado OFICIAL.
$kanban_stages = [
    0 => [
        'id' => 0,
        'title' => 'ENVIADAS',
        'db_status' => 'Cotización Enviada',
        'color_class' => 'text-[var(--color-secondary)]',
        'border_class' => 'border-t-[var(--color-highlight)]',
        'icon' => 'file-check-2',
        'desc' => 'Cotizaciones con estado oficial "Enviado"'
    ],
    1 => [
        'id' => 1,
        'title' => 'SEGUIMIENTO POST ENVÍO',
        'db_status' => 'Seguimiento Post Envío',
        'color_class' => 'text-[var(--color-primary)]',
        'border_class' => 'border-l-[var(--color-primary)]',
        'icon' => 'badge-check',
        'desc' => 'Primer Contacto Después Del Envío'
    ],
    2 => [
        'id' => 2,
        'title' => 'SEGUIMIENTO RECORDATORIO',
        'db_status' => 'Seguimiento Recordatorio',
        'color_class' => 'text-[var(--color-secondary)]',
        'border_class' => 'border-l-[var(--color-secondary)]',
        'icon' => 'badge-info',
        'desc' => 'Prospectos Que Requieren Un Recordatorio'
    ],
    3 => [
        'id' => 3,
        'title' => 'NEGOCIACIÓN FINAL',
        'db_status' => 'Negociación Final',
        'color_class' => 'text-[var(--color-primary)]',
        'border_class' => 'border-l-[var(--color-primary)]',
        'icon' => 'badge-plus',
        'desc' => 'Etapa De Cierre O Gestión Para La Conversión'
    ]
];

// 🛑 DEFINICIÓN DE ESTADOS (ASEGURANDO QUE EXISTAN)
$official_status_sent = 'enviado';
$official_status_won = 'aprobado';
$official_status_lost = 'rechazado';
$official_status_generated = 'generado';
$official_status_converted = 'convertida'; // El estimado se convirtió a factura
$official_status_archived = 'archivado'; // Estado final de una cotización perdida

// Inicialización de arrays de datos
$sales_leads = [];
$won_quotes = [];
$lost_quotes = [];
$discarded_quotes = [];
$detailed_leads_data = [];
$total_quotes_count = 0;
$total_quotes_sent = 0;
$total_pipeline_value = 0.00;
$total_won_value = 0.00; // Será actualizado por la Consulta 2
$total_lost_value = 0.00;
$avg_ticket = 0.00;

try {
    $pdo = $pdo ?? null;
    if (!$pdo) {
        error_log("quotes-funnel.php: PDO connection not initialized.");
        throw new Exception("Database connection failed.");
    }
    
    $user_id = $user_id_session ?? 1; // ID del usuario logueado
    
    // ----------------------------------------------------
    // 🛑 CONSULTA 1: DATOS PARA EL KANBAN Y LISTAS (Excluye 'convertida' y 'generado')
    // ----------------------------------------------------
    // Se incluyó 'archivado' en la exclusión para que el proceso PHP decida si es 'lost' o 'discarded' visualmente.
    $sql = "
        SELECT 
            e.id AS quote_id, e.total_amount AS amount, e.estimate_date,
            e.status_seguimiento AS quote_status_funnel, -- Estado del Funnel (Seguimiento)
            e.lost_reason,
            e.status AS general_status, -- Estado Oficial (aprobado, rechazado, enviado)
            e.lead_id, e.client_id,
            COALESCE(l.first_name, c.first_name) as first_name,
            COALESCE(l.last_name, c.last_name) as last_name,
            COALESCE(l.company, c.company) as company,
            COALESCE(l.email, c.email) as email,
            COALESCE(l.phone, l.mobile, c.phone, c.mobile) as phone,
            (
                SELECT due_date FROM tasks t
                WHERE 
                    t.user_id = e.user_id AND 
                    (t.lead_id = e.lead_id OR t.client_id = e.client_id)
                AND t.status = 'pending' 
                ORDER BY t.due_date ASC LIMIT 1
            ) as next_task_date
        FROM estimates AS e
        LEFT JOIN leads AS l ON e.lead_id = l.id
        LEFT JOIN clients AS c ON e.client_id = c.id
        -- Excluye 'convertida' y 'generado'
        WHERE e.status != ? AND e.status != ? 
        AND e.user_id = ?
        ORDER BY e.estimate_date DESC
    ";
    
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$official_status_converted, $official_status_generated, $user_id]); 
    $all_quotes_raw = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // ----------------------------------------------------
    // 🛑 CONSULTA 2: CÁLCULO DEL VALOR TOTAL CERRADO (Incluye 'aprobado' Y 'convertida')
    // ----------------------------------------------------
    $closed_statuses = [$official_status_won, $official_status_converted];
    $closed_statuses_quoted = implode(',', array_map(fn($s) => $pdo->quote($s), $closed_statuses));

    $stmtClosedValue = $pdo->prepare("SELECT SUM(total_amount) FROM estimates WHERE status IN ({$closed_statuses_quoted}) AND user_id = ?");
    $stmtClosedValue->execute([$user_id]);
    $total_won_value = (float)$stmtClosedValue->fetchColumn();


    // --- Contadores KPI Activos (Solo el Funnel Activo, con status OFICIAL = ENVIADO) ---
    $active_funnel_statuses_quoted = implode(',', array_map(fn($s) => $pdo->quote($s['db_status']), $kanban_stages));
    
    // Contar leads en el pipeline activo (funnel stages)
    $stmtCount = $pdo->prepare("SELECT COUNT(id), SUM(total_amount) FROM estimates WHERE status_seguimiento IN ({$active_funnel_statuses_quoted}) AND status = ? AND user_id = ?");
    $stmtCount->execute([$official_status_sent, $user_id]);
    $kpi_data = $stmtCount->fetch(PDO::FETCH_NUM);
    $total_quotes_count = (int)($kpi_data[0] ?? 0);
    $total_pipeline_value = (float)($kpi_data[1] ?? 0.00);

    // Contar leads en la primera etapa del funnel: ENVIADAS
    $stmtSent = $pdo->prepare("SELECT COUNT(id) FROM estimates WHERE status_seguimiento = ? AND status = ? AND user_id = ?");
    $stmtSent->execute([$kanban_stages[0]['db_status'], $official_status_sent, $user_id]);
    $total_quotes_sent = (int)$stmtSent->fetchColumn();


    // --- Procesamiento de Datos (Llenado de Arrays) ---
    $stage_db_to_id_map = array_column($kanban_stages, 'id', 'db_status');

    foreach ($all_quotes_raw as $row) {
        $name_raw = trim(($row['first_name'] ?? '') . ' ' . ($row['last_name'] ?? ''));
        if (empty($name_raw)) {
            $name_raw = 'Sin Nombre (ID #' . $row['quote_id'] . ')';
        }
        
        $status_funnel = trim($row['quote_status_funnel'] ?? '');
        $general_status_raw = trim($row['general_status']);
        $quote_id = (int)$row['quote_id'];
        $amount = (float)($row['amount'] ?: 0.00);
        $date_to_use = $row['estimate_date'];
        
        $contact_type = !empty($row['client_id']) ? 'client' : 'lead';
        $contact_id = !empty($row['client_id']) ? $row['client_id'] : $row['lead_id'];

        // Normalización de estados (solo para los estados que pasaron el filtro SQL: aprobado, rechazado, enviado)
        $general_status = strtolower($general_status_raw);
        $general_status = str_replace(['aprobada', 'ganada'], $official_status_won, $general_status);
        $general_status = str_replace(['rechazada', 'perdida'], $official_status_lost, $general_status);
        $general_status = str_replace('enviada', $official_status_sent, $general_status); 

        $js_data = [
            'id' => $quote_id,
            'contact_id' => $contact_id,
            'contact_type' => $contact_type,
            'name' => $name_raw,
            'amount' => $amount,
            'date' => $date_to_use,
            'stage' => null,
            'phone' => formatearTelefono($row['phone']) ?: '',
            'email' => $row['email'] ?: '',
            'company' => $row['company'] ?: '',
            'next_task_date' => $row['next_task_date'],
            'status_text' => $status_funnel,
            'lost_reason' => $row['lost_reason']
        ];
        
        // --- LÓGICA DE CLASIFICACIÓN FINAL (REVISADA) ---
        if ($general_status === $official_status_won) {
            // ESTADO OFICIAL: APROBADO (GANADAS)
            $won_quotes[] = ['id' => $quote_id, 'name' => $name_raw, 'amount' => $amount, 'date' => $date_to_use];
            $js_data['stage'] = 'won';
        } 
        elseif ($general_status === $official_status_lost) {
            // ESTADO OFICIAL: RECHAZADO (PERDIDAS / ARCHIVADAS)
            
            // Si tiene 'lost_reason' o el status_funnel es 'Archivado', va a ARCHIVADAS.
            // La cotización ID 42 (rechazado, Lead Descartado) irá a descartadas.
            if (!empty($row['lost_reason']) || strtolower($status_funnel) === strtolower($official_status_archived) ) {
                $discarded_quotes[] = ['id' => $quote_id, 'name' => $name_raw, 'amount' => $amount, 'date' => $date_to_use, 'reason' => $row['lost_reason'] ?: 'No especificada'];
                $js_data['stage'] = 'discarded';
                $total_lost_value += $amount;
            } else {
                // Si no tiene motivo, va a PERDIDAS directas.
                $lost_quotes[] = ['id' => $quote_id, 'name' => $name_raw, 'amount' => $amount, 'date' => $date_to_use, 'reason' => $row['lost_reason'] ?: 'No especificada'];
                $js_data['stage'] = 'lost';
                $total_lost_value += $amount; 
            }
        }
        elseif ($general_status === $official_status_sent) {
            // PIPELINE ACTIVO (Estado Oficial ENVIADO)
            $final_stage_id = null;
            
            // 1. Intenta mapear el estado de seguimiento a una columna válida
            if (isset($stage_db_to_id_map[$status_funnel])) {
                $final_stage_id = $stage_db_to_id_map[$status_funnel];
            } 
            
            // 🛑 CORRECCIÓN CLAVE: Si el estado NO fue mapeado (o es null/vacío), 
            // y su estatus OFICIAL es ENVIADO, lo forzamos a la etapa ENVIADAS (ID 0).
            // Esto captura la ID 45 con 'Cotización Ganada' y la pone en el funnel activo.
            if ($final_stage_id === null) {
                $final_stage_id = $kanban_stages[0]['id']; // ENVIADAS
            }
            
            if ($final_stage_id !== null) {
                $js_data['stage'] = $final_stage_id;
                $sales_leads[] = [ 
                    'id' => $quote_id,
                    'name' => $name_raw,
                    'amount' => $amount,
                    'date' => $date_to_use,
                    'stage' => $final_stage_id
                ];
            }
        }
        
        $detailed_leads_data[$quote_id] = $js_data; 
    }

    $total_closed = count($won_quotes) + count($lost_quotes) + count($discarded_quotes); 
    $avg_ticket = ($total_quotes_count > 0) ? ($total_pipeline_value / $total_quotes_count) : 0.00;

} catch (Exception $e) {
    error_log("Error quotes-funnel: " . $e->getMessage());
}

// Usamos la función global formatearMoneda (de formatters.php)
function formatMoney(float $amount): string {
    // Reemplace esto si 'formatearMoneda' no es una función global válida.
    // return '$' . number_format($amount, 2, '.', ',');
    return formatearMoneda($amount);
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Centro De Seguimiento | <?php echo htmlspecialchars($branding['full_title'] ?? 'CRM'); ?></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 if(file_exists('files/gtm-head.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>
</head>
<body class="font-barlow" 
    data-page-title="Centro De Seguimiento De Cotizaciones" 
    data-page-subtitle="Seguimiento Estratégico Para Convertir Leads En Clientes" 
    data-page-icon="combine">
    
    <input type="hidden" id="csrf-token-php" value="<?php echo $csrf_token; ?>">
    <div id="toast-container" class="toast-container"></div>
    
    <?php if(file_exists('files/gtm-body.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)]">
            
            <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
                
                <div class="lg:col-span-2">
                    <div class="grid grid-cols-1 lg:grid-cols-2 lg:gap-8 space-y-8 lg:space-y-0">
                        
                        <div>
                            <?php $stage = $kanban_stages[0]; ?>
                            <div id="stage-<?php echo $stage['id']; ?>" data-stage-id="<?php echo $stage['id']; ?>" class="sales-column bg-white rounded-xl p-4 flex flex-col h-full max-h-[80vh] transition duration-300 transform 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-4xl font-black flex items-center <?php echo $stage['color_class']; ?>"><i data-lucide="<?php echo $stage['icon']; ?>" class="w-5 h-5 mr-2"></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 text-gray-500 mb-4"><?php echo htmlspecialchars($stage['desc']); ?></p>
                                </div>
                                <div class="kanban-list space-y-4 flex-grow overflow-y pr-2 min-h-[120px] transition-all duration-200" data-stage-id="<?php echo $stage['id']; ?>"></div>
                            </div>
                        </div>
                        
                        <div class="space-y-6">
                            <?php for ($i = 1; $i <= 3; $i++): $stage = $kanban_stages[$i]; ?>
                                <div id="stage-<?php echo $stage['id']; ?>" data-stage-id="<?php echo $stage['id']; ?>" class="sales-column bg-white rounded-xl p-4 flex flex-col 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-lg font-black flex items-center <?php echo $stage['color_class']; ?>"><i data-lucide="<?php echo $stage['icon']; ?>" class="w-4 h-4 mr-2"></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-xs text-gray-500 mb-3"><?php echo htmlspecialchars($stage['desc']); ?></p>
                                    </div>
                                    <div class="kanban-list space-y-3 flex-grow overflow-y pr-2 min-h-[120px] transition-all duration-200" data-stage-id="<?php echo $stage['id']; ?>"></div>
                                </div>
                            <?php endfor; ?>
                        </div>
                    </div>
                </div> 

                <div class="space-y-6">
                    <div id="won-column" data-action="win" class="sales-column bg-white rounded-xl p-4 flex flex-col h-1/2 border-l-4 border-emerald-500 transition duration-300 shadow-lg hover:shadow-xl">
                        <div class="flex-shrink-0">
                            <div class="flex justify-between items-center mb-2 border-b pb-2">
                                <h2 class="text-4xl font-black flex items-center text-emerald-600"><i data-lucide="trending-up" class="w-5 h-5 mr-2"></i>GANADAS</h2>
                                <span class="text-gray-500 font-bold" id="count-won"></span>
                            </div>
                        </div>
                        <div id="won-list" class="kanban-list space-y-4 flex-grow overflow-y pr-2 min-h-[120px] transition-all duration-200"></div>
                    </div>

                    <div id="lost-column" data-action="lost" class="sales-column bg-white rounded-xl p-4 flex flex-col h-1/2 border-l-4 border-[var(--color-secondary)] transition duration-300 shadow-lg hover:shadow-xl">
                        <div class="flex-shrink-0">
                            <div class="flex justify-between items-center mb-2 border-b pb-2">
                                <h2 class="text-4xl font-black flex items-center text-[var(--color-secondary)]"><i data-lucide="trending-down" class="w-5 h-5 mr-2"></i>PERDIDAS</h2>
                                <span class="text-gray-500 font-bold" id="count-lost"></span>
                            </div>
                        </div>
                        <div id="lost-list" class="kanban-list space-y-4 flex-grow overflow-y pr-2 min-h-[120px] transition-all duration-200"></div>
                    </div>
                </div> 
            </div> 
            
            <div id="discarded-section" class="mt-12">
                <h3 class="text-4xl font-black text-[var(--color-primary)] mb-4 flex items-center"><i data-lucide="archive" class="w-8 h-8 mr-3"></i>COTIZACIONES ARCHIVADAS (ANÁLISIS DE PÉRDIDA)</h3>
                
                <div class="bg-white rounded-xl shadow-lg p-6">
                    <div class="flex justify-between items-center mb-4 border-b pb-2">
                        <h4 class="text-xl font-black flex items-center text-gray-600 uppercase"><i data-lucide="folder-archive" class="w-5 h-5 mr-2"></i>ARCHIVADAS CON MOTIVO</h4>
                        <span class="text-gray-500 font-bold" id="count-discarded"></span>
                    </div>
                    <p class="text-sm text-gray-500 mb-4">Cotizaciones que tienen estado oficial 'Rechazado' y un motivo de pérdida especificado, conservadas para análisis. Se pueden eliminar definitivamente aquí.</p>
                    
                    <div class="overflow-x-auto">
                        <table class="min-w-full divide-y divide-gray-200">
                            <thead class="bg-gray-50">
                                <tr>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-black text-gray-500 uppercase tracking-wider">Cliente / ID</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-black text-gray-500 uppercase tracking-wider">Monto</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-black text-gray-500 uppercase tracking-wider">Fecha</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-black text-gray-500 uppercase tracking-wider">Motivo de Pérdida</th>
                                    <th scope="col" class="px-6 py-3 text-right text-xs font-black text-gray-500 uppercase tracking-wider">Acción</th>
                                </tr>
                            </thead>
                            <tbody id="discarded-list" class="bg-white divide-y divide-gray-200"></tbody>
                        </table>
                    </div>
                </div>
            </div>

            <div class="mt-12 mb-12">
                <h3 class="text-4xl font-black text-[var(--color-primary)] mb-4 flex items-center">
                    <i data-lucide="bar-chart-3" class="w-8 h-8 mr-3"></i>TABLERO DE CONTROL COMERCIAL
                </h3>
                <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-6 mb-6">
                    <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="users" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Total Leads Activos</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]"><?php echo $total_quotes_count; ?></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="send" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Cotizaciones Enviadas</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]"><?php echo $total_quotes_sent; ?></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="percent-circle" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Tasa de Cierre</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]">
                                <?php 
                                    $total_closed_won_lost = count($won_quotes) + count($lost_quotes) + count($discarded_quotes);
                                    echo ($total_closed_won_lost > 0) ? round((count($won_quotes) / $total_closed_won_lost) * 100, 1) . '%' : '0%'; 
                                ?>
                            </p>
                        </div>
                    </div>
                </div>
                <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-6">
                    <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="coins" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Valor Cotizado</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]"><?php echo formatMoney($total_pipeline_value); ?></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="trending-up" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Ventas Cerradas</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]"><?php echo formatMoney($total_won_value); ?></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="tag" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                        <div>
                            <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Ticket Promedio</h3>
                            <p class="text-5xl font-bold text-[var(--color-primary)]"><?php echo formatMoney($avg_ticket); ?></p>
                        </div>
                    </div>
                </div>
            </div> 
        </div> 
    </main>
</div>

<div id="confirmConvertModal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50">
    <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="file-check" class="w-16 h-16 text-green-600"></i></div>
            <p class="text-[var(--color-primary)] mb-6 uppercase text-lg font-bold leading-tight">
                ¿DESEAS CONVERTIR LA COTIZACIÓN DE <span id="convert-lead-name-display" class="font-black text-[var(--color-secondary)] inline"></span> EN UNA FACTURA?
            </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="close-modal-btn 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" data-modal="confirmConvertModal">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                <button type="button" id="confirm-convert-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">
                    <i data-lucide="check-circle" class="w-5 h-5"></i> SI, CREAR
                </button>
            </div>
            <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider">SE GENERARÁ UNA NUEVA FACTURA</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">
    <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="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 MOVER A <span id="archive-lead-name-display" class="font-black text-[var(--color-secondary)] inline"></span> AL ARCHIVO?
            </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="close-modal-btn 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" data-modal="confirmArchiveModal">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                <button type="button" id="confirm-archive-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">
                    <i data-lucide="archive-restore" class="w-5 h-5"></i> SÍ, ARCHIVAR
                </button>
            </div>
            <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider">SE MOVERÁ A ARCHIVADAS CON MOTIVO</p>
        </div>
    </div>
</div>

<div id="promptLostReasonModal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50">
    <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">MOTIVO</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-4 uppercase text-lg font-bold leading-tight">¿POR QUÉ SE PERDIÓ ESTA COTIZACIÓN?</p>
            <input type="text" id="lost-reason-input-quote" class="w-full p-3 border-2 border-gray-200 rounded-lg focus:outline-none focus:border-[var(--color-secondary)] text-gray-700 font-bold uppercase text-sm mb-6 text-center placeholder-gray-400" 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="close-modal-btn 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" data-modal="promptLostReasonModal">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                <button type="button" id="confirm-lost-reason-quote-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="check-circle" class="w-5 h-5"></i> CONFIRMAR
                </button>
            </div>
        </div>
        <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider">SE MOVERÁ A PERDIDAS OFICIALES</p>
    </div>
</div>

<div id="confirmGenericActionModal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50">
    <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">
                <span id="generic-modal-title">ADVERTENCIA</span>
            </h3>
        </div>
        <div class="p-8">
            <div class="flex justify-center mb-6"><i data-lucide="trash-2" 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">
                ¿DESEAS <span id="generic-action-text" class="font-black text-[var(--color-secondary)] inline">ELIMINAR</span> LA COTIZACIÓN DE <span id="generic-action-name" class="font-black text-[var(--color-secondary)] inline"></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="close-modal-btn 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" data-modal="confirmGenericActionModal">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                <button type="button" id="confirm-generic-action-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">
                    <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>

<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 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="notebook-pen" class="w-8 h-8 mr-2 text-white"></i>
                SEGUIMIENTO Y NOTAS
            </h3>
            <button id="close-notes-panel-btn" 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="flex-grow overflow-y-auto p-4 space-y-6 relative">
            <div id="client-info-card" class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <div class="border-b pb-3 mb-4">
                    <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"></i>
                        <span id="panel-client-name" class="break-words">Cargando...</span>
                    </h4>
                    <p class="text-xs font-bold text-gray-400 mt-1 uppercase">ID Cotización: <span id="panel-lead-id"></span></p>
                </div>
                
                <div class="space-y-3">
                    <div>
                        <label class="block text-xs font-bold text-gray-500 uppercase">Empresa</label>
                        <p class="text-sm font-semibold text-gray-800 flex items-center">
                            <i data-lucide="building" class="w-4 h-4 mr-2 text-[var(--color-primary)]"></i>
                            <span id="panel-client-company" class="break-words">---</span>
                        </p>
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-gray-500 uppercase">Email</label>
                        <p class="text-sm font-semibold text-gray-800 flex items-center">
                            <i data-lucide="mail" class="w-4 h-4 mr-2 text-[var(--color-primary)]"></i>
                            <span id="panel-client-email" class="break-words">---</span>
                        </p>
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-gray-500 uppercase">Teléfono</label>
                        <p class="text-sm font-semibold text-gray-800 flex items-center">
                            <i data-lucide="phone" class="w-4 h-4 mr-2 text-[var(--color-primary)]"></i>
                            <span id="panel-client-phone">---</span>
                        </p>
                    </div>
                </div>

                <div id="panel-next-task" class="mt-4 pt-3 border-t border-gray-100 bg-gray-50 p-3 rounded-lg">
                    <p class="text-xs font-bold text-gray-500 uppercase mb-1 flex items-center">
                        <i data-lucide="calendar-clock" class="w-4 h-4 mr-1.5"></i> PRÓXIMO CONTACTO
                    </p>
                    <span id="panel-task-date" class="text-lg font-black uppercase text-[var(--color-secondary)]"></span>
                </div>
            </div>
            
            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <div class="border-b pb-3 mb-4">
                    <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                        <i data-lucide="message-square-plus" class="w-5 h-5 mr-2"></i>
                        NUEVA NOTA
                    </h4>
                </div>
                
                <div class="space-y-4">
                    <div>
                        <label for="next-task-date" class="block text-md font-bold text-gray-600 mb-1 uppercase">
                            Programar Contacto
                        </label>
                        <input type="date" id="next-task-date" 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>
                        <label for="new-note-content" class="block text-md font-bold text-gray-600 mb-1 uppercase">
                            Contenido de la nota
                        </label>
                        <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" rows="3" placeholder="Escriba aquí el resumen..."></textarea>
                    </div>

                    <button type="button" id="save-note-btn" class="w-full bg-[var(--color-secondary)] hover:bg-gray-700 text-white font-bold py-2 uppercase px-4 rounded-lg shadow-sm hover:shadow-md transition-all duration-200 flex items-center justify-center gap-2">
                        <i data-lucide="plus-circle" class="w-5 h-5"></i>
                        AGREGAR NOTA A LA LISTA
                    </button>
                </div>
            </div>

            <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                <div class="border-b pb-3 mb-4">
                    <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                        <i data-lucide="history" class="w-5 h-5 mr-2"></i>
                        HISTORIAL
                    </h4>
                </div>
                <div id="notes-list" class="space-y-4 max-h-60 overflow-y-auto pr-1"></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-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" data-modal="confirmConvertModal">
                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                </button>
                
                <button type="button" id="save-tracking-btn-panel" 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="save" class="w-5 h-5"></i> ACTUALIZAR
                </button>
            </div>
        </div>
        
    </div>
</aside>

<script>
// BLOQUE 2: Frontend Lógico (JavaScript)
// --- API ENDPOINTS (Estandarización) ---
const API_ENDPOINTS = {
    CONVERT_TO_INVOICE: 'db/convert-quote-to-invoice.php',
    NOTE_TASK_MANAGER: 'db/quotes-add-note-task.php', 
    UPDATE_STATUS: 'db/quotes-update-status.php',
    DELETE: 'db/quote-delete.php',
};

// --- VARIABLES GLOBALES ---
let detailedLeadsData = {};
let currentQuoteId = null;
let draggedItem = null;
let draggedId = null;
let tempLeadDataForModal = null;
let leadIdAction = null;
let currentGenericCallback = null;

// Datos PHP inyectados de forma segura
const leadsData = <?php echo !empty($sales_leads) ? json_encode($sales_leads, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) : '[]'; ?>;
const wonData = <?php echo !empty($won_quotes) ? json_encode($won_quotes, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) : '[]'; ?>;
const lostData = <?php echo !empty($lost_quotes) ? json_encode($lost_quotes, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) : '[]'; ?>;
const discardedData = <?php echo !empty($discarded_quotes) ? json_encode($discarded_quotes, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) : '[]'; ?>;
    
detailedLeadsData = <?php echo !empty($detailed_leads_data) ? json_encode($detailed_leads_data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) : '{}'; ?>;    
    
const stagesData = <?php echo json_encode(array_values($kanban_stages), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); ?>;
const CSRF_TOKEN = document.getElementById('csrf-token-php').value;
    
// Acciones de Funnel que el backend de quotes-update-status.php traduce a estados oficiales
const wonActionStatus = 'Cotización Ganada'; 
const lostActionStatus = 'Cotización Perdida'; 

// Función de escape para prevenir XSS
function escapeHtml(text) {
    if (!text) return '';
    return String(text)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

// --- FUNCIÓN CENTRAL PARA GUARDAR NOTA/TAREA (Refactorizada y Estandarizada) ---
async function saveNoteAndTask() {
    const content = document.getElementById('new-note-content').value;
    const taskDate = document.getElementById('next-task-date').value;
    if(!content && !taskDate) { 
        if(typeof showToast === 'function') showToast('Ingrese nota o fecha.', 'warning'); 
        return; 
    }
    
    const lead = detailedLeadsData[currentQuoteId];
    
    try {
        const btnNote = document.getElementById('save-note-btn');
        const btnTrack = document.getElementById('save-tracking-btn-panel');
        
        const originalTextNote = btnNote.innerHTML;
        const originalTextTrack = btnTrack.innerHTML;
        
        // Set loading state on both buttons
        const loadingHtml = '<i data-lucide="loader-2" class="w-5 h-5 mr-2 inline-block animate-spin"></i> GUARDANDO...';
        btnNote.innerHTML = loadingHtml;
        btnTrack.innerHTML = loadingHtml;
        btnNote.disabled = true;
        btnTrack.disabled = true;

        const res = await fetch(API_ENDPOINTS.NOTE_TASK_MANAGER, {
            method: 'POST', headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({
                contact_id: lead.contact_id, 
                contact_type: lead.contact_type, 
                content: content,
                next_task_date: taskDate,
                csrf_token: CSRF_TOKEN 
            })
        });
        const result = await res.json();
        
        if(result.success) {
            if(typeof showToast === 'function') showToast('Guardado.', 'success');
            document.getElementById('new-note-content').value = '';
            document.getElementById('next-task-date').value = '';
            
            await window.openNotesPanel(currentQuoteId); 
            
            setTimeout(() => { window.location.reload(); }, 500); 
        } else {
            if(typeof showToast === 'function') showToast('Error al guardar: ' + (result.message || 'Desconocido'), 'error');
        }
        
        // Restore buttons state
        btnNote.innerHTML = originalTextNote;
        btnTrack.innerHTML = originalTextTrack;
        btnNote.disabled = false;
        btnTrack.disabled = false;
        if(typeof lucide !== 'undefined') lucide.createIcons();
    } catch(e) { 
        if(typeof showToast === 'function') showToast('Error de conexión', 'error'); 
        console.error("Save Note/Task Error:", e);
    }
}


// --- FUNCIÓN CORREGIDA: ABRIR PANEL DE NOTAS ---
window.openNotesPanel = async function(id) {
    const lead = detailedLeadsData[id] || detailedLeadsData[String(id)];
    
    if (!lead) { 
        if(typeof showToast === 'function') showToast('Datos no encontrados', 'error'); 
        return; 
    }
    currentQuoteId = id;

    // 1. Llenar información del cliente (el teléfono ya viene formateado desde PHP)
    document.getElementById('panel-client-name').textContent = lead.name;
    document.getElementById('panel-client-company').textContent = lead.company || 'SIN EMPRESA';
    document.getElementById('panel-client-email').textContent = lead.email || '---';
    document.getElementById('panel-client-phone').textContent = lead.phone || '---';
    document.getElementById('panel-lead-id').textContent = '#' + lead.id;
    
    const taskDateElem = document.getElementById('panel-task-date');
    if(lead.next_task_date) {
        // Formatear fecha para el display (DD/MM/YYYY)
        const date = new Date(lead.next_task_date + 'T00:00:00');
        taskDateElem.textContent = date.toLocaleDateString('es-ES', { year: 'numeric', month: '2-digit', day: '2-digit' });
    } else {
        taskDateElem.textContent = "Sin Tarea Pendiente";
    }
    
    // Limpiar campos de nueva nota
    document.getElementById('next-task-date').value = '';
    document.getElementById('new-note-content').value = '';

    // 2. Abrir el panel
    const panel = document.getElementById('notes-panel');
    const overlay = document.getElementById('notes-panel-overlay');
    
    if(panel) panel.classList.remove('translate-x-full');
    if(overlay) {
        overlay.classList.remove('opacity-0', 'pointer-events-none');
        overlay.classList.add('opacity-100');
    }

    // 3. Cargar notas vía AJAX (READ)
    const list = document.getElementById('notes-list');
    list.innerHTML = '<div class="flex justify-center p-4"><i data-lucide="loader-2" class="w-6 h-6 animate-spin text-gray-400"></i></div>';
    if(typeof lucide !== 'undefined') lucide.createIcons();
    
    try {
        // Usando el endpoint definido y pasando los IDs correctos (lead_id o client_id)
        const res = await fetch(`${API_ENDPOINTS.NOTE_TASK_MANAGER}?action=read&id=${lead.contact_id}&type=${lead.contact_type}&t=${Date.now()}`);
        const data = await res.json();
        list.innerHTML = '';
        
        if(data.success && data.notes && data.notes.length > 0) {
            data.notes.forEach(n => {
                const dateStr = new Date(n.created_at).toLocaleDateString('es-ES', { day: '2-digit', month: 'short', year: 'numeric' });
                const contentSafe = escapeHtml(n.content);
                list.innerHTML += `
                    <div class="bg-white p-3 rounded shadow-sm border-l-4 border-[var(--color-primary)] mb-2 text-sm">
                        <div class="text-xs text-gray-400 mb-1 font-bold">${dateStr}</div>
                        <div class="text-gray-700 whitespace-pre-wrap">${contentSafe}</div>
                    </div>
                `;
            });
        } else {
            list.innerHTML = '<p class="text-center text-gray-400 text-sm py-4">Sin notas registradas.</p>';
        }
    } catch(e) { 
        list.innerHTML = '<p class="text-center text-red-500 text-sm">Error al cargar notas.</p>'; 
        console.error("Fetch Error:", e);
    }
};

// --- FUNCIÓN CORREGIDA: CERRAR PANEL ---
window.closeNotesPanel = function() {
    const panel = document.getElementById('notes-panel');
    const overlay = document.getElementById('notes-panel-overlay');
    if(panel) panel.classList.add('translate-x-full');
    if(overlay) {
        overlay.classList.remove('opacity-100');
        overlay.classList.add('opacity-0', 'pointer-events-none');
    }
};

document.addEventListener('DOMContentLoaded', () => {
    try {
        
        // --- MANEJO DE MODALES ---
        document.querySelectorAll('.close-modal-btn').forEach(btn => {
            btn.addEventListener('click', function() { closeGenericModal(this.dataset.modal); });
        });

        document.querySelectorAll('[id$="Modal"]').forEach(modal => {
            modal.addEventListener('click', function(e) { if(e.target === this) closeGenericModal(this.id); });
        });

        function openGenericModal(modalId) {
            const modal = document.getElementById(modalId);
            if(!modal) return;
            modal.classList.remove('hidden');
            setTimeout(() => { 
                const box = modal.querySelector('div[class*="transform"]');
                if(box) { box.classList.remove('scale-95', 'opacity-0'); box.classList.add('scale-100', 'opacity-100'); }
            }, 10);
            if(typeof lucide !== 'undefined') lucide.createIcons(); 
        }

        function closeGenericModal(modalId) {
            const modal = document.getElementById(modalId);
            if(!modal) return;
            const box = modal.querySelector('div[class*="transform"]');
            if(box) { box.classList.add('scale-95', 'opacity-0'); box.classList.remove('scale-100', 'opacity-100'); }
            setTimeout(() => { modal.classList.add('hidden'); }, 300);
            
            const confirmBtn = document.getElementById('confirm-generic-action-button');
            if(confirmBtn) {
                confirmBtn.disabled = false;
                confirmBtn.classList.remove('opacity-50', 'pointer-events-none');
            }
        }
        window.closeGenericModal = closeGenericModal;

        // --- ATTACH HANDLERS TO REFACTORED FUNCTION ---
        document.getElementById('save-note-btn').addEventListener('click', saveNoteAndTask);
        document.getElementById('save-tracking-btn-panel')?.addEventListener('click', saveNoteAndTask);
        
        document.getElementById('close-notes-panel-btn').addEventListener('click', closeNotesPanel);

        // --- ACCIONES DE BOTONES (Convertir, Archivar, Eliminar) ---
        document.getElementById('confirm-convert-button').addEventListener('click', async () => {
            if(!leadIdAction) return;
            const btn = document.getElementById('confirm-convert-button');
            const originalText = btn.innerText;
            btn.innerText = "PROCESANDO...";
            btn.disabled = true;
            btn.classList.add('opacity-50', 'pointer-events-none');

            try {
                const response = await fetch(API_ENDPOINTS.CONVERT_TO_INVOICE, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ quote_id: leadIdAction, csrf_token: CSRF_TOKEN }) 
                });

                const result = await response.json();
                if (result.success) {
                    btn.innerText = "¡HECHO!";
                    if(typeof showToast === 'function') showToast('Cotización convertida a factura.', 'success');
                    setTimeout(() => { window.location.reload(); }, 1000);
                } else {
                    if(typeof showToast === 'function') showToast('Error: ' + (result.message || 'Desconocido'), 'error');
                    btn.innerText = originalText;
                    btn.disabled = false;
                    btn.classList.remove('opacity-50', 'pointer-events-none');
                }
            } catch (error) {
                if(typeof showToast === 'function') showToast('Error de conexión', 'error');
                btn.innerText = originalText;
                btn.disabled = false;
                btn.classList.remove('opacity-50', 'pointer-events-none');
            }
            closeGenericModal('confirmConvertModal');
        });

        document.getElementById('confirm-archive-button').addEventListener('click', async () => {
            if(!leadIdAction) return;
            const btn = document.getElementById('confirm-archive-button');
            const originalText = btn.innerHTML;
            btn.innerHTML = '<i data-lucide="loader-2" class="w-5 h-5 mr-2 inline-block animate-spin"></i> ARCHIVANDO...';
            btn.classList.add('opacity-50', 'pointer-events-none');
            
            const quote = detailedLeadsData[leadIdAction];
            const reason = 'Archivado desde Perdidas'; // Motivo por defecto al archivar desde la columna "Perdidas"
            const leadObj = { id: quote.id, name: quote.name, amount: quote.amount, date: quote.date, origin: 'lost' };

            // La acción de "archivar" es un movimiento a Lost (rechazado) con un motivo.
            await moveLead(leadObj, lostActionStatus, 'discarded', reason); 
            closeGenericModal('confirmArchiveModal');
            btn.innerHTML = originalText;
            btn.classList.remove('opacity-50', 'pointer-events-none');
        });

        document.getElementById('confirm-lost-reason-quote-btn').addEventListener('click', async () => {
            const reasonInput = document.getElementById('lost-reason-input-quote');
            const reason = reasonInput.value.trim();
            if(!reason) { 
                reasonInput.focus(); 
                if(typeof showToast === 'function') showToast('Ingrese un motivo.', 'warning'); 
                return; 
            }
            const btn = document.getElementById('confirm-lost-reason-quote-btn');
            btn.classList.add('opacity-50', 'pointer-events-none');
            
            if(tempLeadDataForModal) {
                // Mover a PERDIDAS (Lost) y registrar el motivo.
                await moveLead(tempLeadDataForModal, lostActionStatus, null, reason);
            }
            closeGenericModal('promptLostReasonModal');
        });

        document.getElementById('confirm-generic-action-button').addEventListener('click', function() {
            if (currentGenericCallback && leadIdAction) {
                const btn = this;
                btn.classList.add('opacity-50', 'pointer-events-none');
                currentGenericCallback(leadIdAction);
            }
        });
        
        function formatMoney(amount) {
            return '$' + parseFloat(amount).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
        }

        function formatQuoteDate(dateString) {
            try {
                const date = new Date(dateString + 'T00:00:00'); 
                if (isNaN(date)) return dateString;
                // Formato '8 DIC'
                return date.toLocaleDateString('es-ES', { month: 'short', day: 'numeric' }).toUpperCase();
            } catch (e) { return dateString; }
        }

        function renderAll() {
            document.querySelectorAll('.kanban-list[data-stage-id], #won-list, #lost-list').forEach(el => el.innerHTML = '');
            const discardedTableBody = document.getElementById('discarded-list');
            discardedTableBody.innerHTML = '';
            
            leadsData.forEach(lead => {
                const col = document.querySelector(`.kanban-list[data-stage-id="${lead.stage}"]`);
                if(col) col.appendChild(createCard(lead));
            });
            wonData.forEach(lead => document.getElementById('won-list').appendChild(createCard(lead, 'won')));
            lostData.forEach(lead => document.getElementById('lost-list').appendChild(createCard(lead, 'lost')));
            
            if (discardedData.length > 0) {
                discardedData.forEach(lead => discardedTableBody.appendChild(createCard(lead, 'discarded')));
            } else {
                discardedTableBody.innerHTML = `<tr><td colspan="5" class="px-6 py-4 text-center text-sm text-gray-500">No hay cotizaciones archivadas.</td></tr>`;
            }
            updateCounts();
            if(typeof lucide !== 'undefined') lucide.createIcons();
        }

        // --- FUNCIÓN PRINCIPAL DE CREACIÓN DE TARJETAS (Fixed) ---
        function createCard(lead, type = 'funnel') {
            
            // Determina si la tarjeta debe ser arrastrable (solo las que están en el embudo)
            const isDraggable = (type === 'funnel');

            // Caso especial: TABLA de descartados (no es tarjeta)
            if (type === 'discarded') {
                const tr = document.createElement('tr');
                tr.className = "hover:bg-gray-50 transition duration-150 ease-in-out cursor-pointer";
                tr.dataset.id = lead.id;
                tr.dataset.origin = type;
                tr.draggable = false; 

                const nameSafe = escapeHtml(lead.name);
                tr.innerHTML = `
                    <td class="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-900">${nameSafe} <spam class="text-xs text-gray-400 font-normal">#${lead.id}</spam></td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 font-bold">${formatMoney(lead.amount)}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${lead.date}</td>
                    <td class="px-6 py-4 whitespace-normal text-sm text-[var(--color-secondary)] font-semibold uppercase max-w-xs">${escapeHtml(lead.reason)}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
                        <button type="button" class="action-delete-btn inline-flex items-center justify-center bg-[var(--color-secondary)] hover:bg-[var(--color-secondary)] text-white text-xs font-black uppercase py-1.5 px-2 rounded-lg shadow-md transition-colors" data-id="${lead.id}" data-name="${nameSafe}">
                            <i data-lucide="trash-2" class="w-3 h-3 mr-1"></i> ELIMINAR
                        </button>
                    </td>
                `;
                
                tr.addEventListener('click', (e) => {
                    if(!e.target.closest('button')){ window.openNotesPanel(lead.id); }
                });
                const delBtn = tr.querySelector('.action-delete-btn');
                delBtn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    triggerGenericActionModal(this.dataset.id, this.dataset.name, 'ADVERTENCIA', 'ELIMINAR', deleteQuote);
                });
                return tr; 
            }

            // TARJETAS KANBAN (Won, Lost, Funnel)
            const el = document.createElement('div');
            let border = 'border-l-gray-300';
            if(type === 'won') border = 'border-l-emerald-500';
            else if(type === 'lost') border = 'border-l-[var(--color-secondary)]';
            else if(stagesData.find(s => s.id == lead.stage)) {
                border = stagesData.find(s => s.id == lead.stage).border_class.replace('border-t-', 'border-l-');
            }

            el.className = `sales-card bg-white p-2 rounded-lg shadow-md hover:shadow-lg border-l-4 transition-all mb-3 ${isDraggable ? 'cursor-grab' : 'cursor-default'} ${border}`;
            el.draggable = isDraggable; 
            el.dataset.id = lead.id;
            el.dataset.origin = type;

            const nameSafe = escapeHtml(lead.name);
            let actionButtonHTML = '';
            let dateAndReasonDisplay = '';
            
            if (type === 'won') {
                // FACTURAR (ROJO SECUNDARIO)
                actionButtonHTML = `
                    <button type="button" class="action-convert-btn flex items-center bg-[var(--color-secondary)] hover:opacity-90 text-white text-xs font-black uppercase py-1 px-2 rounded-md transition-colors shadow-md" data-id="${lead.id}" data-name="${nameSafe}">
                        <i data-lucide="file-check" class="w-3 h-3 mr-1"></i> FACTURAR
                    </button>
                `;
                    dateAndReasonDisplay = `<div class="text-xs text-gray-500 mt-1 flex items-center gap-1"><i data-lucide="calendar" class="w-3 h-3"></i> ${formatQuoteDate(lead.date)}</div>`;
            } else if (type === 'lost') {
                // ARCHIVAR (ROJO SECUNDARIO) - Mover a la tabla de ARCHIVADAS con un motivo por defecto
                actionButtonHTML = `
                    <button type="button" class="action-archive-btn flex items-center bg-[var(--color-secondary)] hover:opacity-90 text-white text-xs font-black uppercase py-1 px-2 rounded-md transition-colors shadow-md" data-id="${lead.id}" data-name="${nameSafe}">
                        <i data-lucide="archive" class="w-3 h-3 mr-1"></i> ARCHIVAR
                    </button>
                `;
                // Estilo de la imagen para fecha y motivo, sin usar float:
                dateAndReasonDisplay = `
                    <div class="text-xs text-gray-500 mt-1 flex flex-col gap-0.5">
                        <div class="flex items-center gap-1"><i data-lucide="calendar" class="w-3 h-3"></i> ${formatQuoteDate(lead.date)}</div>
                        <div>Motivo: ${escapeHtml(lead.reason || 'No especificado')}</div>
                    </div>
                `;
            } else { 
                actionButtonHTML = `
                    <button type="button" class="open-panel-btn inline-flex items-center text-xs font-bold text-white bg-[var(--color-primary)] py-1 px-2 rounded-full shadow-sm mt-1 hover:opacity-90">
                    VER DETALLES <i data-lucide="arrow-big-right-dash" class="ml-0.5 w-3 h-3"></i>
                    </button>
                `;
                    // Mostrar la próxima tarea si existe
                    const nextTaskDate = detailedLeadsData[lead.id]?.next_task_date;
                    let nextTaskDisplay = `<div class="text-xs text-gray-500 mt-1 flex items-center gap-1"><i data-lucide="calendar" class="w-3 h-3"></i> ${formatQuoteDate(lead.date)}</div>`;
                    if (nextTaskDate) {
                        const date = new Date(nextTaskDate + 'T00:00:00');
                        nextTaskDisplay = `<div class="text-xs text-red-500 font-bold mt-1 flex items-center gap-1"><i data-lucide="calendar-clock" class="w-3 h-3"></i> Próximo: ${date.toLocaleDateString('es-ES', { day: '2-digit', month: 'short' }).toUpperCase()}</div>`;
                    }
                    dateAndReasonDisplay = nextTaskDisplay;

            }

            // Aplicando la estructura con flex para forzar la alineación de la imagen
            el.innerHTML = `
                <div class="flex justify-between items-start mb-1">
                    <span class="font-black text-[var(--color-primary)] text-lg leading-tight truncate w-2/3">${nameSafe}</span>
                    <span class="text-xl font-black text-gray-800 uppercase whitespace-nowrap">${formatMoney(lead.amount)}</span>
                </div>
                
                <div class="flex justify-between items-end pt-1">
                    ${dateAndReasonDisplay}
                    ${actionButtonHTML}
                </div>
            `;
            
            // --- EVENTOS CLICK MEJORADOS PARA ABRIR PANEL ---
            let startX, startY;
            el.addEventListener('mousedown', function(e) {
                startX = e.clientX;
                startY = e.clientY;
            });

            el.addEventListener('click', function(e) {
                const diffX = Math.abs(e.clientX - startX);
                const diffY = Math.abs(e.clientY - startY);
                // Si el mouse se movió menos de 5px, es un clic, no un arrastre.
                if (diffX < 5 && diffY < 5) {
                    // Evitar abrir si se hace clic en botones de acción específicos
                    if (!e.target.closest('.action-convert-btn') && !e.target.closest('.action-archive-btn')) {
                        window.openNotesPanel(lead.id);
                    }
                }
            });

            // --- TUS EVENTOS DRAG & DROP ORIGINALES ---
            el.addEventListener('dragstart', handleDragStart);
            el.addEventListener('dragend', handleDragEnd);
            
            if(type === 'won') {
                const btn = el.querySelector('.action-convert-btn');
                btn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    leadIdAction = this.dataset.id; 
                    document.getElementById('convert-lead-name-display').textContent = this.dataset.name;
                    openGenericModal('confirmConvertModal');
                });
            } else if (type === 'lost') {
                const btn = el.querySelector('.action-archive-btn');
                btn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    leadIdAction = this.dataset.id;
                    document.getElementById('archive-lead-name-display').textContent = this.dataset.name;
                    openGenericModal('confirmArchiveModal');
                });
            } 
            
            if(typeof lucide !== 'undefined') lucide.createIcons({ parent: el });
            return el;
        }

        function triggerGenericActionModal(id, name, title, actionText, callback) {
            leadIdAction = id;
            currentGenericCallback = callback;
            const titleEl = document.getElementById('generic-modal-title');
            if(titleEl) titleEl.textContent = title ? title.toUpperCase() : 'ADVERTENCIA';
            const actionEl = document.getElementById('generic-action-text');
            if(actionEl) actionEl.textContent = actionText ? actionText.toUpperCase() : 'ELIMINAR';
            const nameEl = document.getElementById('generic-action-name');
            if(nameEl) nameEl.textContent = name;
            const confirmBtn = document.getElementById('confirm-generic-action-button');
            confirmBtn.innerText = actionText ? actionText.toUpperCase() : 'ELIMINAR';
            openGenericModal('confirmGenericActionModal');
        }

        function updateCounts() {
            stagesData.forEach(s => {
                const count = leadsData.filter(l => l.stage == s.id).length;
                document.getElementById(`count-${s.id}`).textContent = `(${count})`;
            });
            document.getElementById('count-won').textContent = `(${wonData.length})`;
            document.getElementById('count-lost').textContent = `(${lostData.length})`;
            const discardedCountEl = document.getElementById('count-discarded');
            if(discardedCountEl) discardedCountEl.textContent = `(${discardedData.length})`;
        }

        // --- FUNCIONES DRAG & DROP ---
        function handleDragStart(e) {
            draggedId = parseInt(e.target.dataset.id);
            draggedItem = e.target;
            requestAnimationFrame(() => e.target.classList.add('opacity-50'));
            const origin = e.target.dataset.origin;
            e.dataTransfer.setData('text/plain', JSON.stringify({ id: draggedId, origin: origin }));
        }

        function handleDragEnd(e) {
            e.target.classList.remove('opacity-50');
            document.querySelectorAll('.kanban-list').forEach(l => {
                l.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
            });
        }

        function handleDragOver(e) {
            e.preventDefault();
            const col = e.currentTarget.closest('.sales-column');
            const action = col ? col.dataset.action : null;
            const itemOrigin = draggedItem ? draggedItem.dataset.origin : null;

            // Bloquear arrastre desde estados finales (won, lost, discarded) a cualquier otro lugar
            if (itemOrigin === 'lost' || itemOrigin === 'discarded' || itemOrigin === 'won') {
                 e.dataTransfer.dropEffect = 'none';
                 e.currentTarget.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
                 return;
            }

            // Bloquear arrastre hacia la columna de archivados
            if (action === 'discarded') {
                e.dataTransfer.dropEffect = 'none';
                e.currentTarget.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
                return;
            }
            
            e.dataTransfer.dropEffect = 'move';
            e.currentTarget.classList.add('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
        }

        function handleDragLeave(e) {
            e.currentTarget.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
        }

        async function handleDrop(e) {
            e.preventDefault();
            e.currentTarget.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-300', 'ring-inset');
            if(!draggedId) return;

            const col = e.currentTarget.closest('.sales-column');
            if(!col) return;

            const action = col.dataset.action;
            const stageIdAttr = col.dataset.stageId;
            const itemOrigin = draggedItem ? draggedItem.dataset.origin : null;
            
            // Validar que no se arrastre desde un estado final
            if (itemOrigin === 'lost' || itemOrigin === 'discarded' || itemOrigin === 'won') {
                if(typeof showToast === 'function') showToast('No se puede mover un elemento cerrado.', 'warning');
                return;
            }
            // Validar que no se arrastre a la columna de archivados
            if (action === 'discarded') {
                 return;
            }

            let newStatus = '';
            let newFunnelStatus = null;
            
            if(action === 'win') {
                newStatus = wonActionStatus; // 'Cotización Ganada' (Se traduce a estado OFICIAL 'aprobado' en el backend)
            }
            else if(action === 'lost') {
                newStatus = lostActionStatus; // 'Cotización Perdida' (Se traduce a estado OFICIAL 'rechazado' en el backend)
            }
            else if(stageIdAttr !== undefined) {
                // Movimiento dentro del Funnel Activo. El estado oficial DEBE seguir siendo 'enviado'.
                newStatus = 'Cotización Enviada'; // Backend lo mantiene en 'enviado'
                newFunnelStatus = stagesData[parseInt(stageIdAttr)].db_status;
            } else return;

            const leadInfo = detailedLeadsData[draggedId];
            const leadObj = { 
                id: draggedId, 
                name: leadInfo.name, 
                amount: leadInfo.amount, 
                date: leadInfo.date, 
                origin: draggedItem.dataset.origin 
            };
            
            if (action === 'lost') { 
                tempLeadDataForModal = leadObj;
                document.getElementById('lost-reason-input-quote').value = leadInfo.lost_reason || '';
                openGenericModal('promptLostReasonModal');
            } else {
                // Para el Funnel o Ganadas, no se necesita Lost Reason
                await moveLead(leadObj, newStatus, newFunnelStatus, null);
            }
        }

        async function moveLead(leadObj, newStatus, newFunnelStatus, lostReason) {
            try {
                const res = await fetch(API_ENDPOINTS.UPDATE_STATUS, {
                    method: 'POST', headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ 
                        id: leadObj.id, 
                        status: newStatus, 
                        status_seguimiento: newFunnelStatus, // Añadido para movimientos internos
                        lost_reason: lostReason,
                        csrf_token: CSRF_TOKEN 
                    })
                });
                const result = await res.json();
                if(result.success) {
                       if(typeof showToast === 'function') showToast('Movido a ' + (newFunnelStatus || newStatus), 'success');
                       setTimeout(() => location.reload(), 500);
                }
                else { 
                    if(typeof showToast === 'function') showToast('Error al mover: ' + (result.message || 'Desconocido'), 'error'); 
                }
            } catch(e) { 
                if(typeof showToast === 'function') showToast('Error de conexión', 'error'); 
            }
        }
        
        async function deleteQuote(quoteId) {
            try {
                const confirmBtn = document.getElementById('confirm-generic-action-button');
                if(confirmBtn) {
                    confirmBtn.innerText = "ELIMINANDO...";
                    confirmBtn.disabled = true;
                }

                const response = await fetch(API_ENDPOINTS.DELETE, { 
                    method: 'POST', 
                    headers: { 'Content-Type': 'application/json' }, 
                    body: JSON.stringify({ id: quoteId, csrf_token: CSRF_TOKEN }) 
                });
                
                const result = await response.json();

                if (result.success) {
                    if(typeof showToast === 'function') showToast('Eliminado definitivamente.', 'success');
                    closeGenericModal('confirmGenericActionModal');
                    setTimeout(() => location.reload(), 500); 
                } else {
                    if(typeof showToast === 'function') showToast('Error: ' + (result.message || 'Error desconocido'), 'error');
                    if(confirmBtn) {
                        confirmBtn.innerText = "ELIMINAR";
                        confirmBtn.disabled = false;
                    }
                }
            } catch(e) {
                if(typeof showToast === 'function') showToast('Error de conexión', 'error');
            }
        }
        
        document.getElementById('mobile-menu-button')?.addEventListener('click', () => {
            document.getElementById('sidebar').classList.toggle('-translate-x-full');
            document.getElementById('sidebar-overlay').classList.toggle('hidden');
        });

        document.querySelectorAll('.sales-column').forEach(col => {
            col.addEventListener('dragover', handleDragOver);
            col.addEventListener('dragleave', handleDragLeave);
            col.addEventListener('drop', handleDrop);
        });

        renderAll();

    } catch (error) {
        console.error("Error crítico de inicialización JS:", error);
    }
});
</script>
<script src="files/toast.js"></script>
</body>
</html>