<?php include 'files/guardiankey.php'; ?>
<?php
// session_start() es importante, pero ob_start() no es necesario.
session_start();

// Configuración de errores (esto está perfecto)
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/php_errors.log');
error_reporting(E_ALL);

include_once 'db/db_connection.php';

// Variables con valores por defecto
$db_error_message = null;
$company_logo_url = 'img/placeholder-logo.png';
$company_name_from_db = 'Nombre de la Empresa';
$contact_name_from_db = 'Nombre de Contacto';
$contact_email_from_db = 'correo@ejemplo.com';
$contact_phone_from_db = 'N/A';

try {
    // ---- INICIO DE LA CORRECCIÓN ----

    // Cambio 1: La consulta ahora apunta a la tabla 'business_info' para obtener todos los datos.
    $stmt_config = $pdo->query("SELECT * FROM business_info WHERE id = 1");
    $config = $stmt_config->fetch(PDO::FETCH_ASSOC);

    if ($config) {
        // Cambio 2: Mapeo de las columnas de 'business_info' a tus variables PHP.
        $company_name_from_db = htmlspecialchars($config['company_name'] ?? 'Nombre de la Empresa');
        $contact_name_from_db = htmlspecialchars($config['full_name'] ?? 'Nombre de Contacto'); // Usamos 'full_name'
        $contact_email_from_db = htmlspecialchars($config['site_email'] ?? 'correo@ejemplo.com'); // Usamos 'site_email'
        $contact_phone_from_db = htmlspecialchars($config['phone_primary'] ?? 'N/A');
        
        // El logo ahora viene de la misma tabla.
        if (!empty($config['logo_url'])) {
            $company_logo_url = htmlspecialchars($config['logo_url']);
        }

    } else {
        $db_error_message = 'No se encontró la configuración en la tabla business_info. Se usarán valores por defecto.';
    }
    
    // ---- FIN DE LA CORRECCIÓN ----

} catch (PDOException $e) {
    error_log("Error PDO al cargar configuración desde business_info: " . $e->getMessage());
    $db_error_message = 'Error de Base de Datos: ' . $e->getMessage();
} catch (Exception $e) {
    error_log("Error general al cargar configuración desde business_info: " . $e->getMessage());
    $db_error_message = 'Error inesperado: ' . $e->getMessage();
}

// Nota: Puedes eliminar la línea ob_start() que tenías al principio, no es necesaria.
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Centro De Cotizaciones FlowCRM™  De OrozDesign Powered By OrozCO</title>
  <meta name="robots" content="noindex, nofollow">

    <link rel="icon" type="image/png" href="img/favicon.png">
    <link rel="apple-touch-icon" href="img/apple-touch-icon.png">

    <?php include 'files/gtm-head.php'; ?>
    
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Barlow:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">

    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    
    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://unpkg.com/imask"></script>

    <link rel="stylesheet" href="style.css">
    <script src="files/header-manager.js"></script>
    
    <style>
        .interactive-module { background-color: #f7fafc; padding: 2rem; border-radius: 0.75rem; border: 1px solid #e2e8f0; }
        .stat-card { background-color: white; padding: 1.5rem; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2 px 4px -2px rgb(0 0 0 / 0.1); border-left: 5px solid #FFC107; display: flex; align-items: center; gap: 1rem; }
        .stat-card .icon { color: #FFC107; }
        .stat-card .value { color: #98012E; font-weight: 800; font-size: 2.5rem; line-height: 1; }
        .stat-card .title { font-weight: 700; text-transform: uppercase; color: #4A5568; }
        .stat-card .subtitle { font-size: 0.8rem; text-transform: uppercase; color: #A0AEC0; }
        .input-with-icon { position: relative; }
        .input-with-icon input { padding-left: 2.5rem; }
        .input-with-icon .search-icon {
            position: absolute;
            left: 0.75rem;
            top: 50%;
            transform: translateY(-50%);
            color: #A0AEC0;
            pointer-events: none;
        }
        .status-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            visibility: hidden;
            opacity: 0;
            transition: visibility 0s, opacity 0.3s ease-in-out;
        }
        .status-modal-overlay.active {
            visibility: visible;
            opacity: 1;
        }
        .status-modal {
            background-color: white;
            padding: 2rem;
            border-radius: 0.75rem;
            box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.1);
            width: 90%;
            max-width: 400px;
            transform: translateY(-20px);
            transition: transform 0.3s ease-in-out;
        }
        .status-modal-overlay.active .status-modal {
            transform: translateY(0);
        }

        /* === NUEVAS REGLAS PARA TABLAS RESPONSIVAS === */
        @media (max-width: 767px) {
            .responsive-table-stack tbody,
            .responsive-table-stack tr,
            .responsive-table-stack td {
                display: block;
                width: 100%;
            }

            .responsive-table-stack thead {
                display: none; /* Oculta el encabezado de la tabla original */
            }

            .responsive-table-stack tr {
                margin-bottom: 1rem; /* Espacio entre las "tarjetas" de fila */
                border: 1px solid #e2e8f0;
                border-radius: 0.5rem;
                padding: 0.5rem;
                background-color: white;
                box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
            }

            .responsive-table-stack td {
                /* IMPORTANT: Removed display: flex, justify-content, align-items here to prevent conflicts */
                text-align: right !important; /* Alinea el valor a la derecha */
                padding-left: 50% !important; /* Deja espacio para la etiqueta */
                position: relative;
                border-bottom: 1px solid #edf2f7; /* Separador entre campos */
                padding-top: 0.75rem;
                padding-bottom: 0.75rem;
                white-space: normal; /* Permite que el texto se ajuste */
                word-break: break-word; /* Rompe palabras largas */
            }

            .responsive-table-stack td:last-child {
                border-bottom: 0; /* No hay borde inferior en el último campo */
            }

            /* Etiqueta del campo (header) */
            .responsive-table-stack td::before {
                content: attr(data-label); /* Usa el atributo data-label como contenido */
                position: absolute;
                left: 0.75rem;
                width: calc(50% - 1.5rem); /* Ocupa la mitad izquierda */
                padding-right: 1rem;
                white-space: nowrap; /* Evita que la etiqueta se rompa */
                text-align: left;
                font-weight: bold;
                text-transform: uppercase;
                color: #4a5568;
                flex-shrink: 0;
            }

            /* Ajustes para celdas de acciones/botones */
            .responsive-table-stack td.actions-cell {
                text-align: center !important;
                padding-left: 0 !important;
                display: flex;
                flex-direction: column; /* Apila los botones verticalmente */
                justify-content: center;
                align-items: center;
                gap: 0.75rem; /* Espacio entre botones */
                min-height: 48px; /* Altura mínima para la fila de botones */
                flex-wrap: wrap; /* Permite que los botones se envuelvan si hay muchos */
            }

            .responsive-table-stack td.actions-cell::before {
                content: none; /* No mostrar etiqueta para celdas de acciones */
            }

            /* Asegurar que los botones dentro de celdas de acción se apilen si es necesario */
            .responsive-table-stack td.actions-cell button {
                width: 100%; /* Toma todo el ancho disponible */
                flex-grow: 0; /* No permite que crezcan, solo que tomen el ancho */
                min-width: 80px; /* Asegura un tamaño mínimo para el botón */
            }
        }
        /* === FIN NUEVAS REGLAS === */
    </style>
</head>
<body data-page-title="Panel De Control De Estimados"
      data-page-subtitle="Genera Y Administra Oportunidades De Negocios"
      data-page-icon="file-text">
    
    <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="off-canvas-overlay"></div> 
    
    <?php include 'menu.php'; ?>

    <main class="flex-1 overflow-y-auto">
        <header class="bg-white shadow-sm p-4 flex justify-between items-center sticky top-0 z-20">
            <button id="mobile-menu-button" class="md:hidden text-gray-600 hover:text-gray-800">
                <i data-lucide="menu" class="w-6 h-6"></i>
            </button>
            <div class="page-header-container">
                <h2 id="page-title"></h2>
                <p id="page-subtitle"></p>
            </div>
        </header>

        <div id="content-area" class="p-4 md:p-8 space-y-8">
            <section id="dashboard-stats-section">
                <div class="grid grid-cols-1 md:grid-cols-2 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-primary)]">
                        <i data-lucide="user-plus" class="w-12 h-12 text-gray-700"></i>
                        <div>
                            <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Estimados a Prospectos</h3>
                            <p id="stats-prospects-count" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">0</p>
                            <p class="text-sm text-gray-400 mt-1 uppercase">En el mes seleccionado</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="users" class="w-12 h-12 text-gray-700"></i>
                        <div>
                            <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Estimados a Clientes</h3>
                            <p id="stats-clients-count" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">0</p>
                            <p class="text-sm text-gray-400 mt-1 uppercase">En el mes seleccionado</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="wallet" class="w-12 h-12 text-gray-700"></i>
                        <div>
                            <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Valor Total Estimado</h3>
                            <p id="stats-month-total" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">$0</p>
                            <p class="text-sm text-gray-400 mt-1 uppercase">En el mes seleccionado</p>
                        </div>
                    </div>
                </div>
            </section>

            <section id="list-view-section">
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <div class="flex flex-col md:flex-row justify-between items-center mb-6 gap-4">
                        <h3 class="text-2xl font-extrabold text-gray-800 flex items-center gap-2"><i data-lucide="file-check" class="w-7 h-7 text-[var(--color-primary)]"></i> TODOS LOS ESTIMADOS</h3>
                        <button id="show-generator-btn" class="btn-primary py-2 px-4 rounded-lg flex items-center justify-center w-full md:w-auto uppercase"><i data-lucide="plus" class="w-5 h-5 mr-2"></i> Nuevo Estimado</button>
                    </div>
                    <div class="flex flex-col md:flex-row gap-4 mb-6">
                        <div class="input-with-icon w-full">
                            <i data-lucide="search" class="search-icon w-5 h-5"></i>
                            <input type="text" id="list-search" placeholder="Buscar Por Nombre..." class="w-full p-3 border border-gray-300 rounded-lg">
                        </div>
                        <select id="month-filter" class="w-full md:w-auto p-3 border border-gray-300 rounded-lg bg-white"></select>
                        <select id="list-filter-contact-type" class="w-full md:w-auto p-3 border border-gray-300 rounded-lg bg-white"></select>
                        <select id="list-filter-status" class="w-full md:w-auto p-3 border border-gray-300 rounded-lg bg-white"></select>
                    </div>
                    <div class="overflow-x-auto pt-4">
                        <table class="min-w-full bg-white responsive-table-stack">
                            <thead class="bg-gray-50">
                                <tr class="text-left text-gray-500 uppercase text-sm">
                                    <th class="py-3 px-6 font-semibold">Fecha</th>
                                    <th class="py-3 px-6 font-semibold">Cliente/Prospecto</th>
                                    <th class="py-3 px-6 font-semibold">Servicio</th>
                                    <th class="py-3 px-6 font-semibold">Monto</th>
                                    <th class="py-3 px-6 font-semibold">Estado</th>
                                    <th class="py-3 px-6 font-semibold text-center">Acciones</th>
                                </tr>
                            </thead>
                            <tbody id="estimadosTableBody"></tbody>
                        </table>
                        <p id="no-estimados-msg" class="text-center text-gray-500 py-8 hidden">AÚN NO HAS GENERADO NINGÚN ESTIMADO</p>
                    </div>
                </div>
            </section>
        </div>
    </main>
</div>

<section id="generator-view-section" class="hidden">
    <div id="generator-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-40"></div>
    <div id="generator-panel" class="fixed inset-y-0 right-0 w-full max-w-6xl bg-gray-100 shadow-xl z-50 transform translate-x-full transition-transform duration-300 ease-in-out">
        <div class="grid grid-cols-1 lg:grid-cols-5 h-full">
            <div class="lg:col-span-2 bg-gray-100 p-6 overflow-y-auto space-y-6 h-full">
                <h1 id="generator-title" class="text-3xl font-black text-gray-800 text-center uppercase">Crear Estimado</h1>
                <input type="hidden" id="editing-quote-id">
                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="user-check"></i> Información de Contacto</h2>
                    <div id="contact-selection-area">
                        <div class="space-y-2">
                            <label for="clientSearch" class="text-sm font-semibold text-gray-700">Buscar Cliente</label>
                            <div class="relative input-with-icon">
                                <i data-lucide="search" class="search-icon w-5 h-5"></i>
                                <input type="text" id="clientSearch" placeholder="Nombre Del Cliente..." autocomplete="off" class="w-full p-2.5 border border-gray-300 rounded-lg">
                                <div id="client-suggestions" class="absolute w-full bg-white border rounded-md mt-1 shadow-lg z-20 hidden"></div>
                            </div>
                        </div>
                        <div class="flex items-center my-4"><hr class="flex-grow border-t border-gray-300"><span class="px-2 text-gray-500 text-sm">O</span><hr class="flex-grow border-t border-gray-300"></div>
                        <div class="space-y-2">
                            <label for="prospectSearch" class="text-sm font-semibold text-gray-700">Buscar Prospecto</label>
                            <div class="relative input-with-icon">
                                <i data-lucide="search" class="search-icon w-5 h-5"></i>
                                <input type="text" id="prospectSearch" placeholder="Nombre Del Prospecto..." autocomplete="off" class="w-full p-2.5 border border-gray-300 rounded-lg">
                                <div id="prospect-suggestions" class="absolute w-full bg-white border rounded-md mt-1 shadow-lg z-20 hidden"></div>
                            </div>
                        </div>
                    </div>
                    <div id="selected-contact-display" class="hidden items-center justify-between p-3 bg-blue-50 border border-blue-200 rounded-lg">
                        <div class="flex items-center gap-3">
                            <i data-lucide="user-check" class="w-6 h-6 text-blue-800"></i>
                            <div>
                                <p class="font-bold text-blue-800" id="selected-contact-name"></p>
                                <p class="text-xs text-blue-600" id="selected-contact-email"></p>
                            </div>
                        </div>
                        <button id="change-contact-btn" class="text-sm text-blue-600 hover:underline">Cambiar</button>
                    </div>
                </div>
                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="clipboard-list"></i> Detalles Del Servicio</h2>
                    <select id="tipoServicio" class="w-full p-2.5 border border-gray-300 rounded-lg"></select>
                </div>
                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="percent"></i> Impuestos (Taxes)</h2>
                    <input type="number" id="tax-rate" value="0" min="0" step="0.1" class="w-full p-2.5 border border-gray-300 rounded-lg">
                </div>
                <div class="flex flex-col space-y-3 pt-4"> <button id="save-quote-btn" class="btn-secondary w-full p-3 rounded-lg text-lg uppercase font-black flex items-center justify-center"><i data-lucide="save" class="w-6 h-6 mr-2"></i> Guardar Cambios</button>
                    <button id="download-pdf-btn" class="btn-primary w-full p-3 rounded-lg text-lg uppercase font-black flex items-center justify-center"><i data-lucide="download" class="w-6 h-6 mr-2"></i> Descargar Digital</button>
                    <button id="back-to-list-btn" class="bg-gray-300 hover:bg-gray-400 text-gray-800 w-full p-3 rounded-lg uppercase font-bold flex items-center justify-center"><i data-lucide="arrow-left" class="w-6 h-6 mr-2"></i> Cancelar</button>
                </div>
            </div>
            <div class="lg:col-span-3 bg-white p-2 overflow-y-auto h-full">
                <div id="pdf-preview" class="p-8"><div id="quote-content"></div></div>
            </div>
        </div>
    </div>
</section>

<div id="status-modal-overlay" class="status-modal-overlay">
    <div id="status-modal" class="status-modal">
        <h3 class="text-xl font-bold mb-4 text-gray-800">CAMBIAR ESTADO DEL ESTIMADO</h3>
        <input type="hidden" id="modal-estimate-id">
        <div class="mb-4">
            <label for="modal-status-select" class="block text-gray-700 text-sm font-semibold mb-2">Selecciona Un Nuevo Estado:</label>
            <select id="modal-status-select" class="w-full p-2.5 border border-gray-300 rounded-lg bg-white"></select>
        </div>
        <div class="flex flex-col sm:flex-row justify-end space-y-2 sm:space-y-0 sm:space-x-3"> <button id="modal-cancel-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg font-semibold w-full sm:w-auto">CANCELAR</button>
            <button id="modal-save-status-btn" class="btn-primary px-4 py-2 rounded-lg font-semibold w-full sm:w-auto">GUARDAR</button>
        </div>
    </div>
</div>

<div id="confirmDeleteModal" class="fixed inset-0 bg-gray-900 bg-opacity-75 flex items-center justify-center hidden z-50">
    <div class="bg-white p-8 rounded-xl shadow-2xl w-full max-w-sm m-4 transform transition-all duration-300 scale-95 opacity-0 text-center">
        <div class="flex justify-center mb-4">
            <i data-lucide="alert-triangle" class="w-16 h-16 text-[var(--color-secondary)]"></i>
        </div>
        <h3 class="text-2xl font-bold text-[var(--color-primary)] mb-4 uppercase">CONFIRMAR ELIMINACIÓN</h3>
        <p class="text-gray-700 mb-6 uppercase">¿ESTÁS SEGURO DE QUE DESEAS ELIMINAR ESTE <span id="confirm-item-type" class="font-semibold">ELEMENTO</span>? ESTA ACCIÓN NO SE PUEDE DESHACER.</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="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg uppercase w-full sm:w-auto" id="cancel-delete-btn">CANCELAR</button>
            <button type="button" class="btn-secondary font-bold py-2 px-4 rounded-lg uppercase w-full sm:w-auto" id="confirm-delete-button">CONFIRMAR</button>
        </div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
  	const urlParams = new URLSearchParams(window.location.search);
  	const notificationType = urlParams.get('notification_type');
  	const notificationMessage = urlParams.get('notification_message');

  	if (notificationType && notificationMessage) {
  	 	if (typeof showToast === 'function') {
  	 	 	showToast(notificationMessage, notificationType);
  	 	} else {
  	 	 	console.error("showToast function is not defined.");
  	 	}
  	}

  	if (window.jspdf) { window.jsPDF = window.jspdf.jsPDF; }

  	let allClients = [];
  	let allProspects = [];
  	let allServices = [];
  	let allEstimates = {};
  	let nextAvailableEstimateNumber = 1;

  	const quoteTemplateHTML = `<div class="flex justify-between items-start mb-10"><div><img src="<?php echo $company_logo_url; ?>" alt="Logo" class="h-16 mb-4"><h2 class="text-2xl font-black text-gray-800"><?php echo $company_name_from_db; ?></h2><p class="text-gray-600"><?php echo $contact_name_from_db; ?></p><p class="text-gray-600"><?php echo $contact_email_from_db; ?></p><p class="text-gray-600"><?php echo $contact_phone_from_db; ?></p></div><div class="text-right"><h1 class="text-5xl font-black text-gray-300 tracking-wider">ESTIMATE</h1><p><strong>Date:</strong> <span id="previewDate"></span></p><p><strong>Estimate No.:</strong> <span id="previewQuoteId"></span></p></div></div><div class="bg-gray-50 p-4 rounded-lg mb-8"><h3 class="font-bold text-gray-500 text-sm tracking-wider">QUOTE TO:</h3><p id="previewContactName" contenteditable="true"></p><p id="previewContactAddress" contenteditable="true"></p><p id="previewContactEmail" contenteditable="true"></p><p id="previewContactPhone" contenteditable="true"></p></div><table class="w-full mb-8"><thead class="bg-gray-800 text-white"><tr><th class="text-left p-3 rounded-tl-md">DESCRIPTION</th><th class="text-right p-3">QTY.</th><th class="text-right p-3">UNIT PRICE</th><th class="text-right p-3 rounded-tr-md">TOTAL</th><th class="p-3 rounded-tr-md"></th></tr></thead><tbody id="quote-items"></tbody></table><button id="addItemBtn" class="bg-gray-100 border w-full p-2.5 rounded-lg text-sm mb-6 flex items-center justify-center"><i data-lucide="plus-circle" class="w-5 h-5 mr-2"></i> AGREGAR ADICIONAL</button><div class="flex justify-end mt-4"><div class="w-full md:w-1/2"><div class="flex justify-between p-2"><span>Subtotal</span><span id="previewSubtotal"></span></div><div class="flex justify-between p-2 border-b"><span>Tax (<span id="previewTaxRate">0</span>%)</span><span id="previewTaxAmount"></span></div><div class="flex justify-between font-bold text-xl bg-yellow-300 p-3 rounded-md"><span>TOTAL</span><span id="previewTotal"></span></div></div></div><div class="mt-16 text-xs text-gray-500"><h4 class="font-bold mb-1">Terms and Conditions</h4><p contenteditable="true">This estimate is valid for 30 days.</p></div>`;

  	const elements = {
  	 	generatorView: document.getElementById('generator-view-section'),
  	 	generatorPanel: document.getElementById('generator-panel'),
  	 	generatorOverlay: document.getElementById('generator-overlay'),
  	 	showGeneratorBtn: document.getElementById('show-generator-btn'),
  	 	saveQuoteBtn: document.getElementById('save-quote-btn'),
  	 	downloadPdfBtn: document.getElementById('download-pdf-btn'),
  	 	backToListBtn: document.getElementById('back-to-list-btn'),
  	 	estimadosTableBody: document.getElementById('estimadosTableBody'),
  	 	noEstimadosMsg: document.getElementById('no-estimados-msg'),
  	 	listSearch: document.getElementById('list-search'),
  	 	monthFilter: document.getElementById('month-filter'),
  	 	listFilterContactType: document.getElementById('list-filter-contact-type'),
  	 	listFilterStatus: document.getElementById('list-filter-status'),
  	 	generatorTitle: document.getElementById('generator-title'),
  	 	editingQuoteId: document.getElementById('editing-quote-id'),
  	 	clientSearch: document.getElementById('clientSearch'),
  	 	clientSuggestions: document.getElementById('client-suggestions'),
  	 	prospectSearch: document.getElementById('prospectSearch'),
  	 	prospectSuggestions: document.getElementById('prospect-suggestions'),
  	 	contactSelectionArea: document.getElementById('contact-selection-area'),
  	 	selectedContactDisplay: document.getElementById('selected-contact-display'),
  	 	selectedContactName: document.getElementById('selected-contact-name'),
  	 	selectedContactEmail: document.getElementById('selected-contact-email'),
  	 	changeContactBtn: document.getElementById('change-contact-btn'),
  	 	tipoServicio: document.getElementById('tipoServicio'),
  	 	taxRate: document.getElementById('tax-rate'),
  	 	quoteContent: document.getElementById('quote-content'),
  	 	statsProspectsCount: document.getElementById('stats-prospects-count'),
  	 	statsClientsCount: document.getElementById('stats-clients-count'),
  	 	statsMonthTotal: document.getElementById('stats-month-total'),
  	 	statusModalOverlay: document.getElementById('status-modal-overlay'),
  	 	statusModal: document.getElementById('status-modal'),
  	 	modalEstimateId: document.getElementById('modal-estimate-id'),
  	 	modalStatusSelect: document.getElementById('modal-status-select'),
  	 	modalCancelBtn: document.getElementById('modal-cancel-btn'),
  	 	modalSaveStatusBtn: document.getElementById('modal-save-status-btn'),
  	 	confirmDeleteModal: document.getElementById('confirmDeleteModal'),
  	 	confirmDeleteButton: document.getElementById('confirm-delete-button'),
  	 	confirmItemTypeSpan: document.getElementById('confirm-item-type')
  	};
  	let dynamicElements = {};
  	let selectedContact = null;

  	const showGeneratorView = (externalId = null) => {
  	 	elements.generatorView.classList.remove('hidden');
  	 	setTimeout(() => { elements.generatorPanel.classList.remove('translate-x-full'); }, 10);
  	 	elements.quoteContent.innerHTML = quoteTemplateHTML;
  	 	
  	 	bindDynamicElements();
  	 	
  	 	selectedContact = null;
  	 	elements.editingQuoteId.value = '';
  	 	elements.contactSelectionArea.classList.remove('hidden');
  	 	elements.selectedContactDisplay.classList.add('hidden');
  	 	elements.clientSearch.value = '';
  	 	elements.prospectSearch.value = '';
  	 	elements.tipoServicio.value = '';
  	 	elements.taxRate.value = 0;
  	 	if(dynamicElements.quoteItemsBody) dynamicElements.quoteItemsBody.innerHTML = '';
  	 	
  	 	if (externalId && allEstimates[externalId]) {
  	 	 	const estimate = allEstimates[externalId];
  	 	 	elements.generatorTitle.textContent = `Editando Estimado #${estimate.id.replace('est-', '')}`;
  	 	 	elements.editingQuoteId.value = externalId;
  	 	 	if (estimate.contact) {
  	 	 	 	handleContactSelection(estimate.contact);
  	 	 	}
  	 	 	elements.taxRate.value = estimate.taxRate || 0;
  	 	 	dynamicElements.quoteItemsBody.innerHTML = '';
  	 	 	
  	 	 	estimate.items.forEach(([desc, price, quantity = 1]) => dynamicElements.quoteItemsBody.appendChild(createItemRow(desc, price, quantity)));
  	 	 	
  	 	 	if (estimate.items.length > 0) {
  	 	 	 	const firstItemDesc = estimate.items[0][0];
  	 	 	 	const matchingService = allServices.find(s => s.name === firstItemDesc);
  	 	 	 	if (matchingService) {
  	 	 	 	 	elements.tipoServicio.value = matchingService.id;
  	 	 	 	} else {
  	 	 	 	 	elements.tipoServicio.value = '';
  	 	 	 	}
  	 	 	}
  	 	 	recalculateTotal();
  	 	} else {
  	 	 	dynamicElements.quoteItemsBody.appendChild(createItemRow("Nuevo Ítem", 0.00, 1)); 
  	 	 	elements.generatorTitle.textContent = 'Crear Nuevo Estimado';
  	 	 	elements.editingQuoteId.value = '';
  	 	}
  	 	updatePreview();

  	 	if (typeof lucide !== 'undefined') {
  	 	 	lucide.createIcons({ container: elements.generatorPanel });
  	 	}
  	};
  	
  	const hideGeneratorView = () => {
  	 	elements.generatorPanel.classList.add('translate-x-full');
  	 	setTimeout(() => { elements.generatorView.classList.add('hidden'); }, 300);
  	};

  	const bindDynamicElements = () => {
  	 	dynamicElements = {
  	 	 	quoteItemsBody: document.getElementById('quote-items'),
  	 	 	addItemBtn: document.getElementById('addItemBtn'),
  	 	 	previewContactName: document.getElementById('previewContactName'),
  	 	 	previewContactAddress: document.getElementById('previewContactAddress'),
  	 	 	previewContactEmail: document.getElementById('previewContactEmail'),
  	 	 	previewContactPhone: document.getElementById('previewContactPhone'),
  	 	 	previewDate: document.getElementById('previewDate'),
  	 	 	previewQuoteId: document.getElementById('previewQuoteId'),
  	 	 	previewSubtotal: document.getElementById('previewSubtotal'),
  	 	 	previewTaxRate: document.getElementById('previewTaxRate'),
  	 	 	previewTaxAmount: document.getElementById('previewTaxAmount'),
  	 	 	previewTotal: document.getElementById('previewTotal')
  	 	};
  	 	
  	 	// ===============================================
  	 	// CAMBIO 1: SE AÑADE lucide.createIcons() AQUI
  	 	// ===============================================
  	 	dynamicElements.addItemBtn.addEventListener('click', () => {
  	 	 	dynamicElements.quoteItemsBody.appendChild(createItemRow());
  	 	 	if (typeof lucide !== 'undefined') {
  	 	 	 	lucide.createIcons();
  	 	 	}
  	 	});
  	 	
  	 	dynamicElements.quoteItemsBody.addEventListener('input', recalculateTotal);
  	 	elements.taxRate.addEventListener('input', recalculateTotal);
  	 	dynamicElements.quoteItemsBody.addEventListener('blur', (e) => {
  	 	 	if (e.target.matches('.item-unit-price')) {
  	 	 	 	e.target.textContent = `$${(parseFloat(e.target.textContent.replace(/[^\d.]/g, '')) || 0).toFixed(2)}`;
  	 	 	} else if (e.target.matches('.item-qty')) {
  	 	 	 	e.target.textContent = `${(parseInt(e.target.textContent) || 1)}`;
  	 	 	}
  	 	}, true);
  	};

  	// MENU MOBILE
  	const mobileMenuButton = document.getElementById('mobile-menu-button');
  	const sidebar = document.getElementById('sidebar');
  	const sidebarOverlay = document.getElementById('sidebar-overlay');

  	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');
  	});

  	
  	 // MASCARA DEL TELEFONO
  	const phoneInput = document.getElementById('contact_phone');
  	if (phoneInput) {
  	 	IMask(phoneInput, { mask: '(000) 000-0000' });
  	}
  	
  	const formatStatusText = (status) => (status ? status.replace(/_/g, ' ').toUpperCase() : '');
  	const getStatusClass = (status) => {
  	 	const s = status.toLowerCase();
  	 	if (s === 'aprobado') return 'bg-green-100 text-green-800';
  	 	if (s === 'enviado') return 'bg-blue-100 text-blue-800';
  	 	if (s === 'rechazado') return 'bg-[var(--color-secondary)] text-white';
  	 	if (s === 'en_revision') return 'bg-yellow-100 text-yellow-800';
  	 	if (s === 'generado') return 'bg-gray-300 text-gray-800';
  	 	if (s === 'convertida') return 'bg-green-100 text-green-800';
  	 	return 'bg-gray-100 text-gray-800';
  	};

  	const translateContactType = (type) => {
  	 	if (type === 'client') return 'CLIENTE';
  	 	if (type === 'prospect') return 'PROSPECTO';
  	 	return type;
  	};

  	const updateDisplay = () => {
  	 	const monthFilterValue = elements.monthFilter.value;
  	 	renderTable(monthFilterValue);
  	 	updateDashboardStats(monthFilterValue);
  	};

  	const renderTable = (monthFilterValue) => {
  	 	const filters = {
  	 	 	term: elements.listSearch.value.toLowerCase(),
  	 	 	contactType: elements.listFilterContactType.value,
  	 	 	status: elements.listFilterStatus.value
  	 	};

  	 	const filteredData = Object.values(allEstimates).filter(doc => {
  	 	 	const matchesTerm = doc.cliente.toLowerCase().includes(filters.term);
  	 	 	const matchesContactType = (filters.contactType === 'all' || doc.contactType === filters.contactType);
  	 	 	const matchesStatus = (filters.status === 'all' || doc.estado === filters.status);
  	 	 	let matchesMonth = true;
  	 	 	if (monthFilterValue !== 'all') {
  	 	 	 	const docDate = new Date(doc.fechaSolicitud + 'T00:00:00');
  	 	 	 	const filterYear = parseInt(monthFilterValue.substring(0, 4));
  	 	 	 	const filterMonth = parseInt(monthFilterValue.substring(5, 7)) - 1;
  	 	 	 	matchesMonth = (docDate.getFullYear() === filterYear && docDate.getMonth() === filterMonth);
  	 	 	}
  	 	 	return matchesTerm && matchesContactType && matchesStatus && matchesMonth;
  	 	});

  	 	elements.estimadosTableBody.innerHTML = '';
  	 	elements.noEstimadosMsg.classList.toggle('hidden', filteredData.length > 0);
  	 	filteredData.forEach(doc => {
  	 	 	const row = elements.estimadosTableBody.insertRow();
  	 	 	const contactTypeClass = doc.contactType === 'client' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800';
  	 	 	row.className = 'border-b hover:bg-gray-50';

  	 	 	row.innerHTML = `
  	 	 	 	<td class="py-4 px-6" data-label="FECHA">${doc.fechaSolicitud}</td>
  	 	 	 	<td class="py-4 px-6" data-label="CLIENTE/PROSPECTO">
  	 	 	 	 	<div class="flex flex-col items-end">
  	 	 	 	 	 	<span class="font-semibold">${doc.cliente}</span>
  	 	 	 	 	 	<span class="text-xs font-bold p-1 rounded ${contactTypeClass}">
  	 	 	 	 	 	 	${translateContactType(doc.contactType).toUpperCase()}
  	 	 	 	 	 	</span>
  	 	 	 	 	</div>
  	 	 	 	</td>
  	 	 	 	<td class="py-4 px-6" data-label="SERVICIO">${doc.servicio}</td>
  	 	 	 	<td class="py-4 px-6" data-label="MONTO">$${parseFloat(doc.montoEstimado).toFixed(2)}</td>
  	 	 	 	<td class="py-4 px-6" data-label="ESTADO"><span class="${getStatusClass(doc.estado)} py-1 px-3 rounded-full text-xs font-bold">${formatStatusText(doc.estado)}</span></td>
  	 	 	 	<td class="py-4 px-6 text-center actions-cell" data-label="ACCIONES">
  	 	 	 	 	<div class="flex flex-col sm:flex-row items-center justify-center space-y-2 sm:space-y-0 sm:space-x-3">
  	 	 	 	 	 	${doc.estado !== 'convertida' ? `
  	 	 	 	 	 	 	<button class="text-gray-500 hover:text-gray-700 change-status-btn w-full sm:w-auto" data-estimate-id="${doc.id}" data-current-status="${doc.estado}" title="Cambiar Estado">
  	 	 	 	 	 	 	 	<i data-lucide="edit-3" class="w-5 h-5"></i>
  	 	 	 	 	 	 	</button>
  	 	 	 	 	 	 	<button class="text-blue-600 hover:text-blue-800 edit-quote-btn w-full sm:w-auto" data-estimate-id="${doc.id}" title="Ver/Editar">
  	 	 	 	 	 	 	 	<i data-lucide="eye" class="w-5 h-5"></i>
  	 	 	 	 	 	 	</button>
  	 	 	 	 	 	 	<button class="text-green-600 hover:text-green-800 convert-quote-btn w-full sm:w-auto" data-quote-external-id="${doc.id}" title="Convertir a Factura">
  	 	 	 	 	 	 	 	<i data-lucide="check-circle" class="w-5 h-5"></i>
  	 	 	 	 	 	 	</button>
  	 	 	 	 	 	` : `
  	 	 	 	 	 	 	<span class="text-gray-400 w-full sm:w-auto" title="Cotización Convertida a Factura"><i data-lucide="check-check" class="w-5 h-5"></i> Convertida</span>
  	 	 	 	 	 	`}
  	 	 	 	 	 	<button class="text-[var(--color-secondary)] hover:text-[var(--color-secondary)] delete-estimate-btn w-full sm:w-auto" data-estimate-id="${doc.id}" title="Eliminar">
  	 	 	 	 	 	 	<i data-lucide="trash-2" class="w-5 h-5"></i>
  	 	 	 	 	 	</button>
  	 	 	 	 	</div>
  	 	 	 	</td>`;
  	 	 	elements.estimadosTableBody.appendChild(row);
  	 	});
  	 	lucide.createIcons();
  	 	setupStatusChangeListeners();
  	 	setupDeleteListeners();
  	 	setupConvertQuoteListeners();
  	 	setupEditQuoteListeners();
  	};

  	const setupStatusChangeListeners = () => {
  	 	document.querySelectorAll('.change-status-btn').forEach(button => {
  	 	 	button.onclick = null;
  	 	 	button.addEventListener('click', (event) => {
  	 	 	 	const externalId = button.dataset.estimateId;
  	 	 	 	const currentStatus = button.dataset.currentStatus;
  	 	 	 	showStatusModal(externalId, currentStatus);
  	 	 	 	event.stopPropagation();
  	 	 	});
  	 	});
  	};

  	const setupDeleteListeners = () => {
  	 	document.querySelectorAll('.delete-estimate-btn').forEach(button => {
  	 	 	button.onclick = null;
  	 	 	button.addEventListener('click', (event) => {
  	 	 	 	const externalId = button.dataset.estimateId;
  	 	 	 	openConfirmDeleteModal(externalId, 'estimado');
  	 	 	 	event.stopPropagation();
  	 	 	});
  	 	});
  	};

  	const setupEditQuoteListeners = () => {
  	 	document.querySelectorAll('.edit-quote-btn').forEach(button => {
  	 	 	button.onclick = null;
  	 	 	button.addEventListener('click', (event) => {
  	 	 	 	const externalId = button.dataset.estimateId;
  	 	 	 	showGeneratorView(externalId);
  	 	 	 	event.stopPropagation();
  	 	 	});
  	 	});
  	};


  	const setupConvertQuoteListeners = () => {
  	 	document.querySelectorAll('.convert-quote-btn').forEach(button => {
  	 	 	button.onclick = null;
  	 	 	button.addEventListener('click', async (event) => {
  	 	 	 	const quoteExternalId = button.dataset.quoteExternalId;
  	 	 	 	const quote = allEstimates[quoteExternalId];
  	 	 	 	if (!quote || !quote.db_id) {
  	 	 	 	 	showToast('Error: Datos de la cotización no encontrados.', 'error');
  	 	 	 	 	return;
  	 	 	 	}
  	 	 	 	showToast('Iniciando conversión a factura...', 'info');
  	 	 	 	try {
  	 	 	 	 	const response = await fetch('db/convert-quote-to-invoice.php', {
  	 	 	 	 	 	method: 'POST',
  	 	 	 	 	 	headers: { 'Content-Type': 'application/json' },
  	 	 	 	 	 	body: JSON.stringify({ quote_id: quote.db_id })
  	 	 	 	 	});
  	 	 	 	 	const result = await response.json();
  	 	 	 	 	if (result.success) {
  	 	 	 	 	 	showToast(result.message || 'Cotización convertida con éxito.', 'success');
  	 	 	 	 	 	allEstimates[quoteExternalId].estado = 'convertida';
  	 	 	 	 	 	location.reload();
  	 	 	 	 	} else {
  	 	 	 	 	 	showToast(result.message || 'Error al convertir la cotización.', 'error');
  	 	 	 	 	}
  	 	 	 	} catch (error) {
  	 	 	 	 	console.error('Error de conexión:', error);
  	 	 	 	 	showToast('Error de conexión al convertir.', 'error');
  	 	 	 	}
  	 	 	 	event.stopPropagation();
  	 	 	});
  	 	});
  	};

  	const showStatusModal = (externalId, currentStatus) => {
  	 	elements.modalEstimateId.value = externalId;
  	 	const statuses = ['generado', 'enviado', 'aprobado', 'rechazado', 'convertida'];
  	 	elements.modalStatusSelect.innerHTML = '';
  	 	statuses.forEach(status => {
  	 	 	const option = document.createElement('option');
  	 	 	option.value = status;
  	 	 	option.textContent = formatStatusText(status);
  	 	 	if (status === currentStatus) {
  	 	 	 	option.selected = true;
  	 	 	}
  	 	 	elements.modalStatusSelect.appendChild(option);
  	 	});
  	 	elements.statusModalOverlay.classList.add('active');
  	};

  	const hideStatusModal = () => {
  	 	elements.statusModalOverlay.classList.remove('active');
  	};

  	const openModal = function(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'); }, 50);
  	};

  	const closeModal = function(modalId) {
  	 	const modal = document.getElementById(modalId);
  	 	if (!modal) { return; }
  	 	const modalBox = modal.querySelector('div:first-of-type');
  	 	modalBox.classList.add('scale-95', 'opacity-0');
  	 	setTimeout(() => { modal.classList.add('hidden'); }, 300);
  	};

  	const openConfirmDeleteModal = function(itemId, itemType) {
  	 	if (!elements.confirmDeleteButton || !elements.confirmItemTypeSpan) { return; }
  	 	elements.confirmDeleteButton.dataset.itemId = itemId;
  	 	elements.confirmDeleteButton.dataset.itemType = itemType;
  	 	elements.confirmItemTypeSpan.textContent = itemType.toUpperCase();
  	 	openModal('confirmDeleteModal');
  	};

  	const executeDeleteQuote = async (externalId) => {
  	 	const estimateToDelete = allEstimates[externalId];
  	 	if (!estimateToDelete || !estimateToDelete.db_id) {
  	 	 	showToast('Error: ID de base de datos no encontrado.', 'error');
  	 	 	return;
  	 	}
  	 	try {
  	 	 	const response = await fetch('db/quote-delete.php', {
  	 	 	 	method: 'POST',
  	 	 	 	headers: { 'Content-Type': 'application/json' },
  	 	 	 	body: JSON.stringify({ id: estimateToDelete.db_id })
  	 	 	});
  	 	 	const result = await response.json();
  	 	 	if (result.success) {
  	 	 	 	showToast('Estimado eliminado con éxito.', 'success');
  	 	 	 	closeModal('confirmDeleteModal');
  	 	 	 	location.reload();
  	 	 	} else {
  	 	 	 	showToast(`Error al eliminar: ${result.message}`, 'error');
  	 	 	}
  	 	}
  	 	catch (error) {
  	 	 	console.error('Error al eliminar:', error);
  	 	 	showToast('Error de conexión al eliminar.', 'error');
  	 	}
  	};

  	const updateEstimateStatus = async (externalId, newStatus) => {
  	 	const estimate = allEstimates[externalId];
  	 	if (!estimate || !estimate.db_id) {
  	 	 	showToast('Error: Datos del estimado no encontrados.', 'error');
  	 	 	return;
  	 	}
  	 	try {
  	 	 	const response = await fetch('db/quote-update.php', {
  	 	 	 	method: 'POST',
  	 	 	 	headers: { 'Content-Type': 'application/json' },
  	 	 	 	body: JSON.stringify({ id: estimate.db_id, status: newStatus })
  	 	 	});
  	 	 	const result = await response.json();
  	 	 	if (result.success) {
  	 	 	 	hideStatusModal();
  	 	 	 	showToast('Estado actualizado con éxito.', 'success');
  	 	 	 	location.reload();
  	 	 	} else {
  	 	 	 	showToast(`Error al actualizar estado: ${result.message}`, 'error');
  	 	 	}
  	 	} catch (error) {
  	 	 	console.error('Error de conexión:', error);
  	 	 	showToast('Error de conexión al actualizar estado.', 'error');
  	 	}
  	};

  	const formatToK = (num) => {
  	 	if (num === 0) return '0';
  	 	return Math.abs(num) > 999 ? (Math.sign(num)*((Math.abs(num)/1000).toFixed(1))) + 'k' : Math.sign(num)*Math.abs(num);
  	};

  	const updateDashboardStats = (monthFilterValue) => {
  	 	let prospectsCount = 0, clientsCount = 0, monthTotal = 0;
  	 	const dataToProcess = Object.values(allEstimates).filter(doc => {
  	 	 	let matchesMonth = true;
  	 	 	if (monthFilterValue !== 'all') {
  	 	 	 	const docDate = new Date(doc.fechaSolicitud + 'T00:00:00');
  	 	 	 	const filterYear = parseInt(monthFilterValue.substring(0, 4));
  	 	 	 	const filterMonth = parseInt(monthFilterValue.substring(5, 7)) - 1;
  	 	 	 	matchesMonth = (docDate.getFullYear() === filterYear && docDate.getMonth() === filterMonth);
  	 	 	}
  	 	 	return matchesMonth;
  	 	});
  	 	dataToProcess.forEach(estimate => {
  	 	 	if (estimate.contactType === 'prospect') prospectsCount++;
  	 	 	if (estimate.contactType === 'client') clientsCount++;
  	 	 	monthTotal += parseFloat(estimate.montoEstimado) || 0;
  	 	});
  	 	elements.statsProspectsCount.textContent = prospectsCount;
  	 	elements.statsClientsCount.textContent = clientsCount;
  	 	elements.statsMonthTotal.textContent = `$${formatToK(monthTotal)}`;
  	};

  	const generatePDF = () => {
  	 	showToast('Generando PDF...', 'info');
  	 	const quoteElement = document.getElementById('pdf-preview');
  	 	if (!quoteElement) {
  	 	 	console.error('Element #pdf-preview not found.');
  	 	 	return;
  	 	}
  	 	const addItemBtn = quoteElement.querySelector('#addItemBtn');
  	 	const originalDisplayAddItem = addItemBtn ? addItemBtn.style.display : '';
  	 	const removeBtns = quoteElement.querySelectorAll('.remove-item-btn');
  	 	const originalDisplayRemoveBtns = Array.from(removeBtns).map(btn => btn.style.display);
  	 	const quoteItemsBody = quoteElement.querySelector('#quote-items');
  	 	const originalMarginBottom = quoteItemsBody ? quoteItemsBody.style.marginBottom : '';

  	 	if (addItemBtn) addItemBtn.style.display = 'none';
  	 	removeBtns.forEach(btn => btn.style.display = 'none');
  	 	if (quoteItemsBody) {
  	 	 	quoteItemsBody.style.marginBottom = '20px';
  	 	}

  	 	quoteElement.style.width = '816px';
  	 	quoteElement.style.margin = '0 auto';
  	 	quoteElement.style.padding = '32px';
  	 	quoteElement.style.boxSizing = 'border-box';


  	 	html2canvas(quoteElement, { 
  	 	 	scale: 2,
  	 	 	useCORS: true,
  	 	 	width: 816,
  	 	}).then(canvas => {
  	 	 	quoteElement.style.width = '';
  	 	 	quoteElement.style.margin = '';
  	 	 	quoteElement.style.padding = '';
  	 	 	quoteElement.style.boxSizing = '';

  	 	 	if (addItemBtn) addItemBtn.style.display = originalDisplayAddItem;
  	 	 	removeBtns.forEach((btn, i) => btn.style.display = originalDisplayRemoveBtns[i]);
  	 	 	if (quoteItemsBody) {
  	 	 	 	quoteItemsBody.style.marginBottom = originalMarginBottom;
  	 	 	}

  	 	 	const imgData = canvas.toDataURL('image/png');
  	 	 	const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'letter' });
  	 	 	const pdfWidth = pdf.internal.pageSize.getWidth();
  	 	 	const pdfHeight = pdf.internal.pageSize.getHeight();
  	 	 	
  	 	 	const imgHeight = (canvas.height * pdfWidth) / canvas.width;
  	 	 	let heightLeft = imgHeight;
  	 	 	let position = 0;

  	 	 	pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
  	 	 	heightLeft -= pdfHeight;

  	 	 	while (heightLeft >= 0) {
  	 	 	 	position = heightLeft - imgHeight;
  	 	 	 	pdf.addPage();
  	 	 	 	pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
  	 	 	 	heightLeft -= pdfHeight;
  	 	 	}
  	 	 	pdf.save(`Estimado-${dynamicElements.previewQuoteId.textContent}-${dynamicElements.previewContactName.textContent.replace(/\s+/g, '_')}.pdf`);
  	 	 	showToast('PDF generado.', 'success');
  	 	}).catch(err => {
  	 	 	quoteElement.style.width = '';
  	 	 	quoteElement.style.margin = '';
  	 	 	quoteElement.style.padding = '';
  	 	 	quoteElement.style.boxSizing = '';

  	 	 	if (addItemBtn) addItemBtn.style.display = originalDisplayAddItem;
  	 	 	removeBtns.forEach((btn, i) => btn.style.display = originalDisplayRemoveBtns[i]);
  	 	 	if (quoteItemsBody) {
  	 	 	 	quoteItemsBody.style.marginBottom = originalMarginBottom;
  	 	 	}
  	 	 	console.error("Error al generar PDF:", err);
  	 	 	showToast('Error al generar el PDF.', 'error');
  	 	});
  	};

  	const createItemRow = (desc = "Nuevo Ítem", unitPrice = 0.00, qty = 1) => {
  	 	const row = document.createElement('tr');
  	 	row.innerHTML = `<td class="p-3 border-b" contenteditable="true">${desc}</td><td class="text-right p-3 item-qty border-b" contenteditable="true">${qty}</td><td class="text-right p-3 item-unit-price border-b" contenteditable="true">$${parseFloat(unitPrice).toFixed(2)}</td><td class="text-right p-3 item-total-price border-b">$${(unitPrice * qty).toFixed(2)}</td><td class="p-3 border-b text-center"><button type="button" class="text-[var(--color-secondary)] hover:text-[var(--color-secondary)] remove-item-btn font-bold text-lg" title="Remove Item"><i data-lucide="x" class="w-5 h-5"></i></button></td>`;
  	 	const removeButton = row.querySelector('.remove-item-btn');
  	 	if (removeButton) {
  	 	 	removeButton.addEventListener('click', () => {
  	 	 	 	row.remove();
  	 	 	 	recalculateTotal();
  	 	 	});
  	 	}

  	 	// ===============================================
  	 	// CAMBIO 2: SE QUITA lucide.createIcons() DE AQUI
  	 	// ===============================================
  	 	// (La llamada a lucide.createIcons fue eliminada de aquí)
  	 	
  	 	return row;
  	};

  	const recalculateTotal = () => {
  	 	if (!dynamicElements.quoteItemsBody) return;
  	 	let subtotal = 0;
  	 	dynamicElements.quoteItemsBody.querySelectorAll('tr').forEach(row => {
  	 	 	const qty = parseInt(row.cells[1].textContent) || 0;
  	 	 	const unitPrice = parseFloat(row.cells[2].textContent.replace(/[$,]/g, '')) || 0;
  	 	 	const itemTotal = qty * unitPrice;
  	 	 	row.cells[3].textContent = `$${itemTotal.toFixed(2)}`;
  	 	 	subtotal += itemTotal;
  	 	});
  	 	const taxRate = parseFloat(elements.taxRate.value) || 0;
  	 	const taxAmount = subtotal * (taxRate / 100);
  	 	const total = subtotal + taxAmount;
  	 	dynamicElements.previewSubtotal.textContent = `$${subtotal.toFixed(2)}`;
  	 	dynamicElements.previewTaxRate.textContent = taxRate.toFixed(2);
  	 	dynamicElements.previewTaxAmount.textContent = `$${taxAmount.toFixed(2)}`;
  	 	dynamicElements.previewTotal.textContent = `$${total.toFixed(2)}`;
  	};

  	const resetGeneratorForm = () => {
  	 	selectedContact = null;
  	 	elements.editingQuoteId.value = '';
  	 	elements.contactSelectionArea.classList.remove('hidden');
  	 	elements.selectedContactDisplay.classList.add('hidden');
  	 	elements.clientSearch.value = '';
  	 	elements.prospectSearch.value = '';
  	 	elements.tipoServicio.value = '';
  	 	elements.taxRate.value = 0;
  	 	if(dynamicElements.quoteItemsBody) dynamicElements.quoteItemsBody.innerHTML = '';
  	 	
  	 	if(dynamicElements.quoteItemsBody) {
  	 	 	 dynamicElements.quoteItemsBody.appendChild(createItemRow("Nuevo Ítem", 0.00, 1));
  	 	 	 if (typeof lucide !== 'undefined') {
  	 	 	 	lucide.createIcons({ container: dynamicElements.quoteItemsBody });
  	 	 	 }
  	 	}

  	 	updatePreview();
  	};

  	const handleContactSelection = (contact) => {
  	 	selectedContact = contact;
  	 	elements.contactSelectionArea.classList.add('hidden');
  	 	elements.selectedContactName.textContent = contact.name;
  	 	elements.selectedContactEmail.textContent = contact.email;
  	 	dynamicElements.previewContactAddress.textContent = contact.street_address || contact.address || '';
  	 	elements.selectedContactDisplay.classList.remove('hidden');
  	 	elements.clientSuggestions.classList.add('hidden');
  	 	elements.prospectSuggestions.classList.add('hidden');
  	 	elements.clientSearch.value = '';
  	 	elements.prospectSearch.value = '';
  	 	updatePreview();
  	};

const updatePreview = () => {
  	 	if (!dynamicElements.previewContactName) return;

        // --- NOMBRE (Siempre se muestra) ---
  	 	dynamicElements.previewContactName.textContent = selectedContact?.name || "Nombre del Contacto";
        dynamicElements.previewContactName.style.display = ''; // 'block' por defecto

        // --- DIRECCIÓN (Se oculta si está vacía) ---
        const address = selectedContact?.street_address || selectedContact?.address;
        if (address) {
            dynamicElements.previewContactAddress.textContent = address;
            dynamicElements.previewContactAddress.style.display = ''; // 'block' por defecto
        } else {
            dynamicElements.previewContactAddress.textContent = '';
            dynamicElements.previewContactAddress.style.display = 'none'; // Ocultar
        }

        // --- EMAIL (Se oculta si está vacío) ---
        const email = selectedContact?.email;
         if (email) {
            dynamicElements.previewContactEmail.textContent = email;
            dynamicElements.previewContactEmail.style.display = ''; // 'block' por defecto
        } else {
            dynamicElements.previewContactEmail.textContent = '';
            dynamicElements.previewContactEmail.style.display = 'none'; // Ocultar
        }

        // --- TELÉFONO (Se oculta si está vacío) ---
        const phone = selectedContact?.phone || selectedContact?.mobile;
        if (phone) {
            dynamicElements.previewContactPhone.textContent = phone;
            dynamicElements.previewContactPhone.style.display = ''; // 'block' por defecto
        } else {
            dynamicElements.previewContactPhone.textContent = '';
            dynamicElements.previewContactPhone.style.display = 'none'; // Ocultar
        }

        // --- Resto de la función (esto no cambia) ---
  	 	dynamicElements.previewDate.textContent = new Date().toLocaleDateString('es-ES');
  	 	let quoteNumberDisplay = 'NUEVO';
  	 	if (elements.editingQuoteId.value) {
  	 	 	const externalIdKey = elements.editingQuoteId.value;
  	 	 	if (allEstimates[externalIdKey] && allEstimates[externalIdKey].db_id !== undefined) {
  	 	 	 	const numericId = allEstimates[externalIdKey].db_id;
  	 	 	 	if (!isNaN(numericId)) {
  	 	 	 	 	quoteNumberDisplay = String(numericId).padStart(3, '0');
  	 	 	 	}
  	 	 	}
  	 	} else {
  	 	 	quoteNumberDisplay = String(nextAvailableEstimateNumber).padStart(3, '0');
  	 	}
  	 	dynamicElements.previewQuoteId.textContent = quoteNumberDisplay;
  	 	recalculateTotal();
  	};

  	const saveQuote = async () => {
  	 	if (!selectedContact) {
  	 	 	showToast("Por favor, selecciona un contacto.", 'warning');
  	 	 	return;
  	 	}
  	 	const itemsData = Array.from(dynamicElements.quoteItemsBody.querySelectorAll('tr')).map(row => {
  	 	 	const desc = row.cells[0].textContent;
  	 	 	const qty = parseInt(row.cells[1].textContent) || 1;
  	 	 	const unitPrice = parseFloat(row.cells[2].textContent.replace(/[$,]/g, '')) || 0;
  	 	 	return [desc, unitPrice, qty];
  	 	});
  	 	if (itemsData.length === 0 || itemsData.every(item => item[0].trim() === '' && (parseInt(item[2]) || 0) === 0 && parseFloat(item[1]) === 0)) {
  	 	 	showToast("Por favor, agrega al menos un ítem.", 'warning');
  	 	 	return;
  	 	}
  	 	const quoteData = {
  	 	 	id: elements.editingQuoteId.value ? allEstimates[elements.editingQuoteId.value].db_id : null,
  	 	 	estimate_date: new Date().toISOString().split('T')[0],
  	 	 	status: 'generado',
  	 	 	tax_rate: parseFloat(elements.taxRate.value) || 0,
  	 	 	items: itemsData,
  	 	 	client_id: selectedContact.type === 'client' ? selectedContact.id : null,
  	 	 	lead_id: selectedContact.type === 'prospect' ? selectedContact.id : null,
  	 	};
  	 	const apiUrl = quoteData.id ? 'db/quote-update.php' : 'db/quote-create.php';
  	 	try {
  	 	 	const response = await fetch(apiUrl, {
  	 	 	 	method: 'POST',
  	 	 	 	headers: { 'Content-Type': 'application/json' },
  	 	 	 	body: JSON.stringify(quoteData)
  	 	 	});
  	 	 	const result = await response.json();
  	 	 	if (result.success) {
  	 	 	 	showToast(`Estimado guardado correctamente.`, 'success');
  	 	 	 	if (!quoteData.id) {
  	 	 	 	 	elements.editingQuoteId.value = result.external_id;
  	 	 	 	}
  	 	 	 	hideGeneratorView();
  	 	 	 	location.reload();
  	 	 	} else {
  	 	 	 	showToast(`Error al guardar: ${result.message}`, 'error');
  	 	 	}
  	 	} catch (error) {
  	 	 	console.error('Error al guardar:', error);
  	 	 	showToast('Error de conexión al guardar.', 'error');
  	 	}
  	};

  	const setupSearch = (inputEl, suggestionEl, contactType) => {
  	 	inputEl.addEventListener('input', async () => {
  	 	 	const searchTerm = inputEl.value.toLowerCase();
  	 	 	suggestionEl.innerHTML = '';
  	 	 	if (!searchTerm) { suggestionEl.classList.add('hidden'); return; }
  	 	 	const sourceArray = contactType === 'client' ? allClients : allProspects;
  	 	 	const matches = sourceArray.filter(c => c.name.toLowerCase().includes(searchTerm) || (c.email && c.email.toLowerCase().includes(searchTerm)));
  	 	 	if (matches.length > 0) {
  	 	 	 	matches.forEach(contact => {
  	 	 	 	 	const div = document.createElement('div');
  	 	 	 	 	const displayInfo = contact.type === 'prospect' && contact.company ? `${contact.name} (${contact.company} - ${contact.email})` : `${contact.name} (${contact.email})`;
  	 	 	 	 	div.textContent = displayInfo;
  	 	 	 	 	div.className = 'p-2 hover:bg-gray-100 cursor-pointer text-sm border-b last:border-b-0';
  	 	 	 	 	div.onclick = () => handleContactSelection(contact);
  	 	 	 	 	suggestionEl.appendChild(div);
  	 	 	 	});
  	 	 	 	suggestionEl.classList.remove('hidden');
s 	 	 	 } else {
  	 	 	 	suggestionEl.classList.add('hidden');
  	 	 	}
  	 	});
  	 	inputEl.addEventListener('blur', () => {
  	 	 	setTimeout(() => { if (!suggestionEl.matches(':hover')) { suggestionEl.classList.add('hidden'); } }, 200);
  	 	});
  	};

  	const populateServiceDropdown = () => {
  	 	elements.tipoServicio.innerHTML = '<option value="">-- Selecciona Un Servicio --</option>';
  	 	const servicesByCategory = {};
  	 	allServices.forEach(service => {
  	 	 	const category = service.category || 'Sin Categoría';
  	 	 	if (!servicesByCategory[category]) {
  	 	 	 	servicesByCategory[category] = [];
  	 	 	}
  	 	 	servicesByCategory[category].push(service);
  	 	});
  	 	for (const category in servicesByCategory) {
  	 	 	const optgroup = document.createElement('optgroup');
  	 	 	optgroup.label = category;
  	 	 	servicesByCategory[category].forEach(service => {
  	 	 	 	const option = document.createElement('option');
  	 	 	 	option.value = service.id;
  	 	 	 	option.textContent = `${service.name} ($${service.price.toFixed(2)})`;
  	 	 	 	optgroup.appendChild(option);
  	 	 	});
  	 	 	elements.tipoServicio.appendChild(optgroup);
  	 	}
  	};

  	// ===============================================
  	// CAMBIO 3: SE AÑADE lucide.createIcons() AQUI
  	// ===============================================
  	elements.tipoServicio.addEventListener('change', () => {
  	 	const selectedServiceId = elements.tipoServicio.value;
  	 	if (selectedServiceId) {
  	 	 	const service = allServices.find(s => s.id == selectedServiceId);
  	 	 	if (service) {
  	 	 	 	// ** LÓGICA DE INSERCIÓN DEL DROPDOWN CORREGIDA **
  	 	 	 	
  	 	 	 	// 1. Identificar si existe la fila inicial vacía/genérica
  	 	 	 	const firstRow = dynamicElements.quoteItemsBody.querySelector('tr');
  	 	 	 	const isDefaultRow = firstRow && firstRow.cells[0].textContent.trim() === 'Nuevo Ítem' && parseFloat(firstRow.cells[2].textContent.replace(/[$,]/g, '')) === 0;

  	 	 	 	// 2. Si es la fila por defecto, la eliminamos.
  	 	 	 	if (isDefaultRow) {
  	 	 	 	 	firstRow.remove();
  	 	 	 	}
  	 	 	 	
  	 	 	 	dynamicElements.quoteItemsBody.appendChild(createItemRow(service.name, service.price, 1));

  	 	 	 	recalculateTotal();
  	 	 	 	
  	 	 	 	// Esta línea se asegura de que el ícono [X] se dibuje
  	 	 	 	if (typeof lucide !== 'undefined') {
  	 	 	 	 	lucide.createIcons();
  	 	 	 	}
  	 	 	}
  	 	}
  	});

  	const fetchAndDisplayEstimates = async () => {
  	 	try {
  	 	 	const response = await fetch('db/quote-read.php');
  	 	 	const result = await response.json();

  	 	 	if (result.success) {
  	 	 	 	allEstimates = {};
  	 	 	 	let currentMaxDbId = 0;
  	 	 	 	result.data.forEach(estimate => {
  	 	 	 	 	allEstimates[estimate.id] = estimate;
  	 	 	 	 	if (parseInt(estimate.db_id) > currentMaxDbId) {
  	 	 	 	 	 	currentMaxDbId = parseInt(estimate.db_id);
  	 	 	 	 	}
  	 	 	 	});
  	 	 	 	nextAvailableEstimateNumber = currentMaxDbId + 1;
  	 	 	 	updateMonthFilterOptions();
  	 	 	 	updateDisplay();
  	 	 	} else {
  	 	 	 	showToast('Error al cargar estimados: ' + (result.message || 'Error desconocido.'), 'error');
  	 	 	 	console.error('Error al cargar estimados:', result.message);
  	 	 	}
  	 	} catch (error) {
  	 	 	showToast('Error de conexión al cargar estimados.', 'error');
  	 	 	console.error('Error de conexión al cargar estimados:', error);
  	 	}
  	};

  	const updateMonthFilterOptions = () => {
  	 	const months = [...new Set(Object.values(allEstimates).map(q => q.fechaSolicitud.substring(0, 7)))].sort().reverse();
  	 	elements.monthFilter.innerHTML = '<option value="all">TODOS LOS MESES</option>';
  	 	months.forEach(m => {
  	 	 	const date = new Date(m + '-02');
  	 	 	const monthName = date.toLocaleString('es-ES', { month: 'long' });
  	 	 	const year = date.getFullYear();
  	 	 	elements.monthFilter.add(new Option(`${monthName.charAt(0).toUpperCase() + monthName.slice(1).toUpperCase()} ${year}`, m));
  	 	});
  	 	elements.monthFilter.value = 'all';
  	};

  	(async function init() {
  	 	<?php if (isset($db_error_message) && $db_error_message): ?>
  	 	 	showToast('<?php echo addslashes($db_error_message); ?>', 'error');
  	 	<?php endif; ?>

  	 	elements.listFilterStatus.innerHTML = '<option value="all">TODOS LOS ESTADOS</option>';
  	 	['generado', 'enviado', 'aprobado', 'rechazado', 'convertida'].forEach(s => elements.listFilterStatus.add(new Option(formatStatusText(s), s)));
  	 	
  	 	elements.listFilterContactType.innerHTML = '<option value="all">TODOS LOS CONTACTOS</option>';
  	 	elements.listFilterContactType.add(new Option('CLIENTES', 'client'));
  	 	elements.listFilterContactType.add(new Option('PROSPECTOS', 'prospect'));

  	 	[elements.listSearch, elements.listFilterContactType, elements.listFilterStatus].forEach(el => el.addEventListener('input', updateDisplay));
  	 	elements.monthFilter.addEventListener('change', updateDisplay);

  	 	elements.showGeneratorBtn.addEventListener('click', () => showGeneratorView());
  	 	elements.backToListBtn.addEventListener('click', hideGeneratorView);
  	 	elements.generatorOverlay.addEventListener('click', hideGeneratorView);
  	 	elements.saveQuoteBtn.addEventListener('click', saveQuote);
  	 	elements.downloadPdfBtn.addEventListener('click', generatePDF);
  	 	elements.changeContactBtn.addEventListener('click', resetGeneratorForm);
  	 	elements.taxRate.addEventListener('input', recalculateTotal);

  	 	elements.modalCancelBtn.addEventListener('click', hideStatusModal);
  	 	elements.statusModalOverlay.addEventListener('click', (event) => {
  	 	 	if (event.target === elements.statusModalOverlay) {
  	 	 	 	hideStatusModal();
  	 	 	}
  	 	});
  	 	elements.modalSaveStatusBtn.addEventListener('click', () => {
  	 	 	const externalId = elements.modalEstimateId.value;
  	 	 	const newStatus = elements.modalStatusSelect.value;
  	 	 	updateEstimateStatus(externalId, newStatus);
  	 	});

  	 	const cancelDeleteBtn = document.getElementById('cancel-delete-btn');
  	 	if (cancelDeleteBtn) {
  	 	 	cancelDeleteBtn.addEventListener('click', () => closeModal('confirmDeleteModal'));
  	 	}

  	 	if (elements.confirmDeleteButton) {
  	 	 	elements.confirmDeleteButton.addEventListener('click', async function() {
  	 	 	 	const itemId = this.dataset.itemId;
  	 	 	 	executeDeleteQuote(itemId);
  	 	 	});
  	 	}
  	 	
  	 	const [clientsResponse, leadsResponse, servicesResponse] = await Promise.all([
  	 	 	fetch('db/clients-read-contact-data.php'),
  	 	 	fetch('db/leads-read-contact-data.php'),
  	 	 	fetch('db/services-read-all.php')
  	 	]);

  	 	const [clientsResult, leadsResult, servicesResult] = await Promise.all([
  	 	 	clientsResponse.json(),
  	 	 	leadsResponse.json(),
  	 	 	servicesResponse.json()
  	 	]);

  	 	if (clientsResult.success) {
  	 	 	allClients = clientsResult.data;
  	 	 	setupSearch(elements.clientSearch, elements.clientSuggestions, 'client');
  	 	} else {
  	 	 	showToast('Error al cargar clientes: ' + (clientsResult.message || 'Error desconocido.'), 'error');
  	 	}
  	 	if (leadsResult.success) {
  	 	 	allProspects = leadsResult.data;
  	 	 	setupSearch(elements.prospectSearch, elements.prospectSuggestions, 'prospect');
  	 	} else {
  	 	 	showToast('Error al cargar prospectos: ' + (leadsResult.message || 'Error desconocido.'), 'error');
  	 	}
  	 	if (servicesResult.success) {
  	 	 	allServices = servicesResult.data;
  	 	 	populateServiceDropdown();
  	 	} else {
  	 	 	showToast('Error al cargar servicios: ' + (servicesResult.message || 'Error desconocido.'), 'error');
  	 	}

  	 	await fetchAndDisplayEstimates();
  	 	
  	 	lucide.createIcons();
  	})();
});
</script>


</body>
</html>