<?php
/**
 * ASISMA CRM - Formulario de creación de Cotizaciones
 */
?>
<!-- Header -->
<div class="mb-8">
    <a href="<?php echo APP_URL; ?>/leads/ver?id=<?php echo $lead['id']; ?>" class="inline-flex items-center gap-1.5 text-xs text-slate-500 hover:text-slate-300 font-semibold mb-3">
        <i data-lucide="arrow-left" class="w-3.5 h-3.5"></i>
        <span>Volver a la Ficha del Lead</span>
    </a>
    <h1 class="text-3xl font-extrabold text-white tracking-tight">Generar Cotización</h1>
    <p class="text-slate-400 text-sm mt-1">Cree una cotización comercial para <strong class="text-slate-200"><?php echo htmlspecialchars($lead['contacto_nombre']); ?></strong> (<?php echo htmlspecialchars($lead['empresa_razon_social']); ?>).</p>
</div>

<!-- Main Creator Layout -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
    
    <!-- Left Area: Builder -->
    <div class="lg:col-span-2 space-y-6">
        
        <!-- Products builder card (SIN overflow-hidden: recortaba el dropdown del autocompletar) -->
        <div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl relative">
            <div class="flex justify-between items-center border-b border-slate-800 pb-4 mb-6">
                <h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center gap-2">
                    <i data-lucide="shopping-cart" class="w-4 h-4 text-blue-500"></i>
                    <span>Detalle de Productos Cotizados</span>
                </h3>
                <button type="button" id="addProductRowBtn"
                        class="px-3.5 py-1.5 bg-blue-600/10 border border-blue-500/30 hover:bg-blue-600 hover:text-white text-blue-400 text-xs font-semibold rounded-lg transition-colors flex items-center gap-1">
                    <i data-lucide="plus" class="w-3.5 h-3.5"></i>
                    <span>Añadir Producto</span>
                </button>
            </div>

            <!-- Products List Container -->
            <div id="productsList" class="space-y-4">
                <!-- Template row (Hidden) -->
                <div class="hidden product-row flex flex-col sm:flex-row gap-3 items-end bg-slate-950 p-4 border border-slate-850 rounded-xl relative group animate-fade-in">
                    <!-- Autocompletar de producto (escribe para buscar, patron OPS) -->
                    <div class="flex-1 min-w-0 relative">
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Producto</label>
                        <input type="text" autocomplete="off" placeholder="Escribe para buscar el producto..."
                               class="product-buscar w-full px-3 py-2 bg-slate-900 border border-slate-800 rounded-lg text-slate-200 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500">
                        <input type="hidden" class="product-id" value="">
                        <div class="product-dropdown hidden absolute left-0 top-full mt-1 bg-slate-900 border border-slate-700 rounded-xl shadow-2xl max-h-64 overflow-y-auto"
                             style="z-index: 9999; min-width: 380px; max-width: 560px;"></div>
                        <!-- La leyenda va ABSOLUTA para no empujar el alto de la columna
                             (si no, el input queda desnivelado respecto a cantidad/precio) -->
                        <div class="banda-hint absolute left-0 top-full mt-0.5 text-[10px] text-slate-500 whitespace-nowrap"></div>
                    </div>
                    <!-- Cantidad -->
                    <div class="w-full sm:w-16 shrink-0">
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Cant.</label>
                        <input type="number" min="1" value="1" class="product-qty w-full px-2 py-2 bg-slate-900 border border-slate-800 rounded-lg text-slate-200 text-xs text-center focus:outline-none focus:ring-2 focus:ring-blue-500">
                    </div>
                    <!-- Precio Unitario (en la moneda del producto) -->
                    <div class="w-full sm:w-28 shrink-0">
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Precio (<span class="moneda-etiqueta">$</span>)</label>
                        <input type="number" min="0" value="0" step="0.01" class="product-price w-full px-2 py-2 bg-slate-900 border border-slate-800 rounded-lg text-slate-200 text-xs text-right font-mono focus:outline-none focus:ring-2 focus:ring-blue-500">
                    </div>
                    <!-- Total Item -->
                    <div class="w-full sm:w-28 shrink-0 text-right pb-2.5 font-mono text-sm text-slate-400 font-bold">
                        $<span class="item-total">0</span>
                    </div>
                    <!-- Remove Row -->
                    <button type="button" class="remove-row-btn p-2 bg-red-950/20 border border-red-900/30 text-red-400 hover:bg-red-950 hover:text-red-300 rounded-lg transition-colors absolute top-2 right-2 sm:relative sm:top-0 sm:right-0">
                        <i data-lucide="trash-2" class="w-4 h-4"></i>
                    </button>
                </div>
            </div>

            <!-- Empty indicator -->
            <div id="emptyListMsg" class="py-12 text-center text-slate-500">
                <i data-lucide="shopping-bag" class="w-10 h-10 mx-auto mb-2 text-slate-600"></i>
                <p class="text-xs">No hay productos agregados a la cotización.</p>
                <button type="button" id="addFirstProductBtn" class="mt-3 text-xs text-blue-500 font-bold hover:underline">Haga clic aquí para añadir el primero</button>
            </div>
        </div>

        <?php if (!empty($servicios)): ?>
        <!-- SERVICIO con plan (cotización premium estilo OPS). El servicio se
             elige desde el MISMO buscador de productos: al seleccionarlo esta
             card se abre con sus planes. Máximo UN servicio por cotización. -->
        <div class="hidden bg-slate-900 border border-purple-500/30 rounded-2xl p-6 shadow-xl" id="cardServicio">
            <div class="flex justify-between items-center border-b border-slate-800 pb-4 mb-6">
                <h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center gap-2">
                    <i data-lucide="briefcase" class="w-4 h-4 text-purple-500"></i>
                    <span>Servicio: <span id="servicioNombre" class="text-purple-300"></span></span>
                </h3>
                <button type="button" id="btnQuitarServicio" class="px-3.5 py-1.5 bg-red-950/20 border border-red-900/30 hover:bg-red-950 text-red-400 text-xs font-semibold rounded-lg transition-colors flex items-center gap-1">
                    <i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
                    <span>Quitar Servicio</span>
                </button>
            </div>

            <div id="panelServicio" class="space-y-5">
                <!-- Planes del servicio (radio: se cotiza UNO) -->
                <div id="listaPlanes" class="grid grid-cols-1 md:grid-cols-3 gap-3"></div>

                <!-- Características del plan elegido (SOLO LECTURA: las define
                     la matriz en el configurador del servicio, no el vendedor) -->
                <div>
                    <h4 class="text-[11px] font-bold text-slate-400 uppercase tracking-wider mb-2">Características incluidas en el documento <span class="normal-case font-normal text-slate-600">(definidas por el plan)</span></h4>
                    <div id="listaCaracteristicas" class="space-y-1.5"></div>
                </div>

                <!-- Bonos del servicio (los define la matriz en el configurador;
                     aquí solo se marca cuáles incluir) -->
                <div>
                    <h4 class="text-[11px] font-bold text-slate-400 uppercase tracking-wider mb-2">Bonos / Regalos <span class="normal-case font-normal text-slate-600">(marca cuáles incluir)</span></h4>
                    <div id="listaBonos" class="space-y-1.5"></div>
                </div>

                <!-- Cuotas y descuento del pago inicial -->
                <div class="grid grid-cols-1 sm:grid-cols-3 gap-3 border-t border-slate-800 pt-4">
                    <div>
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Cuotas del pago inicial</label>
                        <select id="cuotasServicio" class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-lg text-slate-300 text-xs focus:outline-none focus:ring-2 focus:ring-purple-500">
                            <?php for ($i = 1; $i <= 12; $i++): ?>
                            <option value="<?php echo $i; ?>"><?php echo $i === 1 ? 'Pago contado (1)' : $i . ' cuotas sin recargo'; ?></option>
                            <?php endfor; ?>
                        </select>
                    </div>
                    <div>
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Descuento pago inicial</label>
                        <input type="number" id="descuentoServicio" min="0" value="0" step="0.01" class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-lg text-slate-200 text-xs focus:outline-none focus:ring-2 focus:ring-purple-500">
                    </div>
                    <div>
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Tipo de descuento</label>
                        <select id="descuentoServicioTipo" class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-lg text-slate-300 text-xs focus:outline-none focus:ring-2 focus:ring-purple-500">
                            <option value="fijo">Monto (moneda del plan)</option>
                            <option value="porcentaje">Porcentaje (%)</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <?php endif; ?>

        <!-- Notes and terms -->
        <div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl">
            <h3 class="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-slate-800 pb-2">Condiciones y Notas de la Oferta</h3>
            <textarea id="notes" rows="4"
                      class="block w-full px-4 py-3 bg-slate-950 border border-slate-800 rounded-xl text-slate-200 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                      placeholder="Escriba condiciones adicionales (ej. Plazos de entrega, vigencia especial, forma de pago...)"></textarea>
        </div>

    </div>

    <!-- Right Area: Summary & Settings -->
    <div class="lg:col-span-1 space-y-6">
        
        <!-- Totals & Settings card -->
        <div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl flex flex-col justify-between">
            <div>
                <h3 class="text-sm font-bold text-white uppercase tracking-wider mb-6 border-b border-slate-800 pb-2">Resumen Financiero</h3>
                
                <!-- Settings: Discount -->
                <div class="space-y-4 mb-6">
                    <?php if (false): // DESCUENTO OCULTO (pedido de Ivan 20-07-2026): cambiar false por true para reactivarlo ?>
                    <div class="grid grid-cols-2 gap-3">
                        <div>
                            <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Descuento</label>
                            <input type="number" id="discountValue" min="0" value="0"
                                   class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-slate-200 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500">
                        </div>
                        <div>
                            <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Tipo Descuento</label>
                            <select id="discountType"
                                    class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-slate-300 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500">
                                <option value="fijo">Monto Fijo ($)</option>
                                <option value="porcentaje">Porcentaje (%)</option>
                            </select>
                        </div>
                    </div>
                    <?php endif; ?>

                    <!-- settings: vigencia por calendario (obligatoria) -->
                    <div>
                        <label class="block text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-1.5">Vigente Hasta <span class="text-red-400">*</span></label>
                        <input type="date" id="vigenciaFecha" required min="<?php echo date('Y-m-d'); ?>" style="color-scheme: dark;"
                               onkeydown="return false" onpaste="return false" inputmode="none"
                               class="block w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-slate-300 text-xs cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500">
                        <p class="text-[10px] text-slate-500 mt-1">La cotización vence al final del día elegido.</p>
                    </div>
                </div>

                <!-- Totals lines -->
                <div class="space-y-3 border-t border-slate-800 pt-6 text-sm">
                    <div class="flex justify-between text-slate-400">
                        <span>Subtotal Neto:</span>
                        <span class="font-mono text-slate-200 font-bold">$<span id="subtotalVal">0</span></span>
                    </div>
                    <div class="flex justify-between text-slate-400 hidden" id="discountLine">
                        <span>Descuento aplicado:</span>
                        <span class="font-mono text-red-400 font-bold">-$<span id="discountVal">0</span></span>
                    </div>
                    <div class="flex justify-between text-slate-400">
                        <span>IVA (19%):</span>
                        <span class="font-mono text-slate-200 font-bold">$<span id="taxVal">0</span></span>
                    </div>
                    
                    <div class="flex justify-between text-slate-200 border-t border-slate-850 pt-4 text-base font-bold">
                        <span>Total Final (CLP):</span>
                        <span class="font-mono text-emerald-400 font-extrabold">$<span id="totalVal">0</span></span>
                    </div>
                    <div class="text-sm font-medium text-slate-100 hidden" id="lineaUf">
                        Los productos en UF se convierten con la UF de hoy: <span class="font-mono font-bold">$<?php echo number_format($valorUfHoy, 2, ',', '.'); ?></span>
                    </div>
                    <div class="text-sm font-semibold text-slate-100 hidden border-t border-slate-850 pt-3" id="lineaMensualidad">
                        <!-- Mensualidad del plan (recurrente, informativa: NO entra al total inicial) -->
                    </div>
                </div>
            </div>

            <!-- Submit actions -->
            <div class="mt-8 border-t border-slate-800 pt-6">
                <button type="button" id="submitQuoteBtn"
                        class="w-full py-3.5 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-500 hover:to-indigo-500 text-white font-semibold rounded-xl text-sm transition-all duration-300 shadow-lg shadow-blue-500/10 hover:shadow-blue-500/25 flex items-center justify-center gap-2">
                    <span>Generar Cotización</span>
                    <i data-lucide="file-check" class="w-4 h-4"></i>
                </button>
                <a href="<?php echo APP_URL; ?>/leads/ver?id=<?php echo $lead['id']; ?>"
                   class="block text-center mt-4 py-2.5 border border-red-500/40 hover:border-red-500/70 hover:bg-red-500/10 text-red-400 font-medium rounded-xl text-xs transition-colors">
                    Cancelar y salir
                </a>
            </div>
        </div>

    </div>

</div>

<?php if (!empty($servicios)): ?>
<!-- Vista previa en tiempo real del documento de SERVICIO: reusa la MISMA
     plantilla del PDF/cotización pública (cotizaciones/publica_servicio), pero
     con datos "de mentira" armados en el servidor a partir de lo que el
     vendedor va editando (sin guardar nada). Se muestra solo con servicio activo. -->
<div class="hidden bg-slate-900 border border-slate-800 rounded-2xl shadow-xl overflow-hidden mt-8" id="cardPreview">
    <div class="flex flex-wrap items-center justify-between gap-3 px-6 py-4 border-b border-slate-800">
        <h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center gap-2">
            <i data-lucide="eye" class="w-4 h-4 text-emerald-500"></i>
            <span>Vista previa en tiempo real</span>
        </h3>
        <div class="flex items-center gap-3">
            <span id="previewEstado" class="text-[11px] text-slate-500"></span>
            <button type="button" id="btnPreviewNuevaPestana" class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-300 text-xs font-semibold rounded-lg transition-colors">
                <i data-lucide="external-link" class="w-3.5 h-3.5"></i>
                <span>Abrir grande</span>
            </button>
        </div>
    </div>
    <iframe id="previewFrame" class="w-full bg-white" style="height: 900px; border: 0;" title="Vista previa de la cotización"></iframe>
</div>
<?php endif; ?>

<style>
    /* La fila que esta usando el autocompletar se LEVANTA sobre las demas:
       asi su dropdown nunca queda detras de las filas siguientes */
    .product-row.fila-activa { z-index: 45; }
</style>

<!-- jQuery Script for dynamic quote calculation -->
<script>
    $(document).ready(function() {

        // 1. Añadir fila de producto
        function addRow() {
            $('#emptyListMsg').addClass('hidden');
            const $row = $('.product-row.hidden').first().clone().removeClass('hidden');
            $('#productsList').append($row);
            lucide.createIcons();
            recalculate();
        }

        $('#addProductRowBtn, #addFirstProductBtn').on('click', function() {
            addRow();
        });

        // 2. Eliminar fila
        $(document).on('click', '.remove-row-btn', function() {
            $(this).closest('.product-row').remove();
            if ($('#productsList .product-row:not(.hidden)').length === 0) {
                $('#emptyListMsg').removeClass('hidden');
            }
            recalculate();
        });

        // 3. Autocompletar de producto (escribe y elige, patron OPS timesheet)
        var VALOR_UF = <?php echo (float)$valorUfHoy; ?>;
        var PRODUCTOS = <?php
            $catalogoJs = array();
            foreach ($productos as $p) {
                $catalogoJs[] = array(
                    'id'      => (int)$p['id'],
                    'nombre'  => $p['nombre'],
                    'precio'  => (float)$p['precio_sugerido'],
                    'minimo'  => (float)$p['precio_minimo'],
                    'maximo'  => ($p['precio_maximo'] > 0) ? (float)$p['precio_maximo'] : 0,
                    'moneda'  => $p['moneda'],
                    'suscripcion' => !empty($p['es_suscripcion']) ? $p['periodo_suscripcion'] : '',
                    'tipo'        => isset($p['tipo']) ? $p['tipo'] : 'producto',
                    'servicio_id' => !empty($p['servicio_id']) ? (int)$p['servicio_id'] : 0
                );
            }
            echo json_encode($catalogoJs, JSON_UNESCAPED_UNICODE);
        ?>;

        // Servicios con planes (configurados por la matriz)
        var SERVICIOS = <?php
            $serviciosJs = array();
            foreach ((isset($servicios) ? $servicios : array()) as $srv) {
                $planesJs = array();
                foreach ($srv['planes'] as $plan) {
                    $caracsJs = array();
                    foreach ($plan['caracteristicas'] as $c) {
                        $caracsJs[] = array('titulo' => $c['titulo'], 'desc' => (string)$c['descripcion']);
                    }
                    $planesJs[] = array(
                        'id'          => (int)$plan['id'],
                        'nombre'      => $plan['nombre'],
                        'moneda'      => $plan['moneda'],
                        'inicial'     => $plan['precio_inicial'] !== null ? (float)$plan['precio_inicial'] : null,
                        'mensual'     => $plan['precio_mensual'] !== null ? (float)$plan['precio_mensual'] : null,
                        'inicial_min' => $plan['precio_inicial_minimo'] !== null ? (float)$plan['precio_inicial_minimo'] : null,
                        'mensual_min' => $plan['precio_mensual_minimo'] !== null ? (float)$plan['precio_mensual_minimo'] : null,
                        'inicial_max' => !empty($plan['precio_inicial_maximo']) ? (float)$plan['precio_inicial_maximo'] : null,
                        'mensual_max' => !empty($plan['precio_mensual_maximo']) ? (float)$plan['precio_mensual_maximo'] : null,
                        'caracteristicas' => $caracsJs
                    );
                }
                $bonosJs = array();
                foreach ($srv['bonos'] as $b) {
                    $bonosJs[] = array('titulo' => $b['titulo'], 'desc' => (string)$b['descripcion'], 'incluido' => (int)$b['incluido_por_defecto']);
                }
                $serviciosJs[] = array(
                    'id'          => (int)$srv['id'],
                    'producto_id' => !empty($srv['producto_id']) ? (int)$srv['producto_id'] : 0,
                    'nombre'      => $srv['nombre'],
                    'planes'      => $planesJs,
                    'bonos'       => $bonosJs
                );
            }
            echo json_encode($serviciosJs, JSON_UNESCAPED_UNICODE);
        ?>;
        var servicioActivo = false;

        function normalizarTexto(t) {
            t = (t || '').toLowerCase();
            var mapa = { 'á':'a', 'é':'e', 'í':'i', 'ó':'o', 'ú':'u', 'ñ':'n' };
            return t.replace(/[áéíóúñ]/g, function(c) { return mapa[c]; });
        }
        function datosProducto(id) {
            for (var i = 0; i < PRODUCTOS.length; i++) if (PRODUCTOS[i].id == id) return PRODUCTOS[i];
            return null;
        }
        function escaparHtml(t) { return $('<i>').text(t == null ? '' : t).html(); }

        // Valida la banda min-max EN VIVO: si el precio queda fuera, el input se
        // pinta rojo y la leyenda avisa al tiro (no hay que esperar al guardar)
        function pintarBanda($row) {
            const prod = datosProducto($row.find('.product-id').val());
            const $precio = $row.find('.product-price');
            const $hint = $row.find('.banda-hint');

            if (!prod) {
                $precio.removeClass('border-red-500 ring-2 ring-red-500/40 text-red-300').addClass('border-slate-800');
                $hint.text('').removeClass('text-red-400 font-bold').addClass('text-slate-500');
                return;
            }

            const sim = prod.moneda === 'UF' ? 'UF ' : '$';
            const dec = prod.moneda === 'UF' ? 2 : 0;
            const price = parseFloat($precio.val() || 0);

            let fuera = '';
            if (prod.minimo > 0 && price < prod.minimo) {
                fuera = '⚠ BAJO el mínimo permitido (' + sim + numberFormatDec(prod.minimo, dec) + ')';
            } else if (prod.maximo > 0 && price > prod.maximo) {
                fuera = '⚠ SUPERA el máximo permitido (' + sim + numberFormatDec(prod.maximo, dec) + ')';
            }

            if (fuera) {
                $precio.addClass('border-red-500 ring-2 ring-red-500/40 text-red-300').removeClass('border-slate-800');
                $hint.text(fuera).removeClass('text-slate-500').addClass('text-red-400 font-bold');
            } else {
                $precio.removeClass('border-red-500 ring-2 ring-red-500/40 text-red-300').addClass('border-slate-800');
                let hint = 'Permitido: desde ' + sim + numberFormatDec(prod.minimo, dec);
                if (prod.maximo > 0) hint += ' hasta ' + sim + numberFormatDec(prod.maximo, dec);
                if (prod.moneda === 'UF') hint += ' · 1 UF = $' + numberFormatDec(VALOR_UF, 2);
                $hint.text(hint).removeClass('text-red-400 font-bold').addClass('text-slate-500');
            }
        }

        // Cada cambio del precio revalida la banda al instante
        $(document).on('input change', '.product-price', function() {
            pintarBanda($(this).closest('.product-row'));
        });

        // Autocompletar POR FILA (la version que funciona): el dropdown vive en
        // su fila; la fila activa se levanta con z-index (clase fila-activa)
        // para que el listado nunca quede detras de las filas siguientes.
        $(document).on('input focus', '.product-buscar', function() {
            const $row = $(this).closest('.product-row');
            const $drop = $row.find('.product-dropdown');
            $('.product-row').removeClass('fila-activa');
            $row.addClass('fila-activa');
            // Con producto ya elegido el input queda readonly: no hay nada que buscar
            if ($row.find('.product-id').val()) { return; }
            const q = normalizarTexto($(this).val().trim());
            if (q.length < 1) { $drop.addClass('hidden').empty(); return; }

            const resultados = [];
            for (var i = 0; i < PRODUCTOS.length && resultados.length < 15; i++) {
                if (normalizarTexto(PRODUCTOS[i].nombre).indexOf(q) !== -1) resultados.push(PRODUCTOS[i]);
            }
            if (!resultados.length) {
                $drop.html('<div class="px-3 py-2.5 text-xs text-slate-500 italic">Sin resultados para esa búsqueda</div>').removeClass('hidden');
                return;
            }
            let html = '';
            resultados.forEach(function(p) {
                const sim = p.moneda === 'UF' ? 'UF ' : '$';
                const dec = p.moneda === 'UF' ? 2 : 0;
                if (p.tipo === 'servicio') {
                    // Los SERVICIOS aparecen en el mismo buscador: al elegirlos
                    // se abre el panel de planes (documento premium)
                    html += '<div class="product-opcion px-3 py-2.5 cursor-pointer hover:bg-slate-800 border-b border-slate-800/60 flex items-center justify-between gap-2" data-id="' + p.id + '">' +
                            '<span class="text-xs text-slate-200 font-semibold truncate">' + escaparHtml(p.nombre) +
                            ' <span class="text-[10px] text-purple-400 font-bold border border-purple-500/40 rounded-full px-1.5">SERVICIO</span>' +
                            '</span>' +
                            '<span class="text-[11px] font-mono text-purple-300 shrink-0">Planes</span></div>';
                    return;
                }
                html += '<div class="product-opcion px-3 py-2.5 cursor-pointer hover:bg-slate-800 border-b border-slate-800/60 flex items-center justify-between gap-2" data-id="' + p.id + '">' +
                        '<span class="text-xs text-slate-200 font-semibold truncate">' + escaparHtml(p.nombre) +
                        (p.moneda === 'UF' ? ' <span class="text-[10px] text-sky-400 font-bold">UF</span>' : '') +
                        (p.suscripcion ? ' <span class="text-[10px] text-purple-400 font-bold">suscripción ' + escaparHtml(p.suscripcion) + '</span>' : '') +
                        '</span>' +
                        '<span class="text-[11px] font-mono text-emerald-400 shrink-0">' + sim + numberFormatDec(p.precio, dec) + '</span></div>';
            });
            $drop.html(html).removeClass('hidden');
        });

        // mousedown (antes del blur) para que la seleccion no se pierda
        $(document).on('mousedown', '.product-opcion', function(e) {
            e.preventDefault();
            const p = datosProducto($(this).data('id'));
            if (!p) return;
            const $row = $(this).closest('.product-row');

            // SERVICIO elegido desde el buscador: la fila se convierte en el
            // panel de planes (la fila desaparece; máximo un servicio)
            if (p.tipo === 'servicio') {
                const limpiarFila = function() {
                    $row.remove();
                    if ($('#productsList .product-row:not(.hidden)').length === 0) {
                        $('#emptyListMsg').removeClass('hidden');
                    }
                };
                if (servicioActivo) {
                    limpiarFila();
                    Swal.fire({ icon: 'info', title: 'Ya hay un servicio en la cotización',
                        text: 'Una cotización lleva máximo UN servicio. Quite el actual para cambiarlo.',
                        background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#a855f7' });
                    recalculate();
                    return;
                }
                const srv = servicioPorProducto(p.id);
                if (!srv) {
                    limpiarFila();
                    Swal.fire({ icon: 'warning', title: 'Servicio sin planes configurados',
                        text: 'La matriz aún no configura planes activos para este servicio.',
                        background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#a855f7' });
                    recalculate();
                    return;
                }
                limpiarFila();
                activarServicio(srv);
                return;
            }

            $row.find('.product-id').val(p.id);
            // El nombre queda BLOQUEADO tras elegir: para cambiar de producto
            // se elimina la fila (el nombre real siempre lo pone la BD)
            $row.find('.product-buscar').val(p.nombre)
                .prop('readonly', true)
                .addClass('cursor-default text-slate-300')
                .attr('title', 'Para cambiar el producto, elimina la fila y agrega otra');
            $row.find('.product-dropdown').addClass('hidden').empty();
            $row.find('.product-price').val(p.precio);
            $row.find('.moneda-etiqueta').text(p.moneda === 'UF' ? 'UF' : '$');
            pintarBanda($row);

            recalculate();
        });

        $(document).on('blur', '.product-buscar', function() {
            const $drop = $(this).closest('.product-row').find('.product-dropdown');
            setTimeout(function() { $drop.addClass('hidden'); }, 150);
        });

        // 4. Cambios en inputs de fila o descuentos → recalcular
        $(document).on('input change', '.product-qty, .product-price, #discountValue, #discountType', function() {
            recalculate();
        });

        // ── SERVICIO con plan (estilo OPS) ──────────────────────────────────
        // El servicio se elige desde el MISMO autocompletar de productos; al
        // seleccionarlo se abre esta card. Máximo UN servicio por cotización.
        var servicioSeleccionado = null;

        function servicioPorProducto(productoId) {
            for (var i = 0; i < SERVICIOS.length; i++) {
                if (SERVICIOS[i].producto_id == productoId) return SERVICIOS[i];
            }
            return null;
        }
        function planActual() {
            var srv = servicioSeleccionado;
            if (!srv) return null;
            var planId = $('input[name=planServicio]:checked').val();
            for (var i = 0; i < srv.planes.length; i++) if (srv.planes[i].id == planId) return srv.planes[i];
            return null;
        }

        function activarServicio(srv) {
            servicioSeleccionado = srv;
            servicioActivo = true;
            $('#servicioNombre').text(srv.nombre);
            $('#cardServicio').removeClass('hidden');
            pintarServicio();
        }
        $('#btnQuitarServicio').on('click', function() {
            servicioActivo = false;
            servicioSeleccionado = null;
            $('#cardServicio').addClass('hidden');
            $('#cardPreview').addClass('hidden');
            clearTimeout(previewTimer);
            recalculate();
        });

        // ── Vista previa en tiempo real del documento (reusa la plantilla real) ──
        var previewTimer = null;

        function datosServicioParaPreview() {
            if (!servicioActivo || !servicioSeleccionado) return null;
            var planSel = planActual();
            if (!planSel) return null;

            var vInicial = planSel.inicial !== null ? parseFloat($('.plan-inicial[data-plan=' + planSel.id + ']').val() || 0) : '';
            var vMensual = planSel.mensual !== null ? parseFloat($('.plan-mensual[data-plan=' + planSel.id + ']').val() || 0) : '';
            var caracteristicas = [];
            $('#listaCaracteristicas .caracteristica-item').each(function() {
                caracteristicas.push({ titulo: $(this).data('titulo'), desc: $(this).data('desc') || '' });
            });
            var bonos = [];
            $('.chk-bono:checked').each(function() {
                bonos.push({ titulo: $(this).data('titulo'), desc: $(this).data('desc') || '' });
            });

            return {
                lead_id: <?php echo $lead['id']; ?>,
                servicio_id: servicioSeleccionado.id,
                plan_id: planSel.id,
                precio_inicial: vInicial,
                precio_mensual: vMensual,
                cuotas: $('#cuotasServicio').val(),
                descuento_valor: $('#descuentoServicio').val(),
                descuento_tipo: $('#descuentoServicioTipo').val(),
                caracteristicas: caracteristicas,
                bonos: bonos,
                notas: $('#notes').val(),
                vigente_hasta: $('#vigenciaFecha').val()
            };
        }

        function actualizarVistaPrevia() {
            var datos = datosServicioParaPreview();
            var $frame = $('#previewFrame');
            if (!datos || !$frame.length) { $('#cardPreview').addClass('hidden'); return; }

            $('#cardPreview').removeClass('hidden');
            $('#previewEstado').text('Actualizando...');
            $.post('<?php echo APP_URL; ?>/cotizaciones/previsualizar-servicio', datos)
                .done(function(html) {
                    $frame[0].srcdoc = html;
                    $('#previewEstado').text('Actualizado ' + new Date().toLocaleTimeString('es-CL'));
                })
                .fail(function() {
                    $('#previewEstado').text('No se pudo actualizar la vista previa.');
                });
        }

        function programarVistaPrevia() {
            clearTimeout(previewTimer);
            previewTimer = setTimeout(actualizarVistaPrevia, 600);
        }

        $('#btnPreviewNuevaPestana').on('click', function() {
            var datos = datosServicioParaPreview();
            if (!datos) return;
            var $form = $('<form>', { method: 'POST', target: '_blank', action: '<?php echo APP_URL; ?>/cotizaciones/previsualizar-servicio' });
            $.each(datos, function(key, val) {
                if (key === 'caracteristicas' || key === 'bonos') {
                    $.each(val, function(i, item) {
                        $form.append($('<input>', { type: 'hidden', name: key + '[' + i + '][titulo]', value: item.titulo }));
                        $form.append($('<input>', { type: 'hidden', name: key + '[' + i + '][desc]', value: item.desc }));
                    });
                } else {
                    $form.append($('<input>', { type: 'hidden', name: key, value: val }));
                }
            });
            $form.appendTo('body').submit().remove();
        });

        $(document).on('input change', '#notes, #vigenciaFecha', function() { programarVistaPrevia(); });

        // Vigencia SOLO por calendario: el click abre el selector nativo
        // (el tipeo y el pegado están bloqueados en el input)
        $(document).on('click', '#vigenciaFecha', function() {
            if (typeof this.showPicker === 'function') {
                try { this.showPicker(); } catch (e) { /* requiere gesto del usuario */ }
            }
        });
        $(document).on('change', '.chk-bono', function() { programarVistaPrevia(); });

        function pintarServicio() {
            var srv = servicioSeleccionado;
            if (!srv) return;

            // Cards de planes (radio: se elige UNO; el primero queda marcado)
            var html = '';
            srv.planes.forEach(function(p, idx) {
                html += '<label class="plan-card block bg-slate-950 border border-slate-800 rounded-xl p-4 cursor-pointer transition-colors hover:border-purple-500/50">' +
                    '<div class="flex items-center justify-between mb-2">' +
                    '<span class="font-bold text-slate-100 text-sm">' + escaparHtml(p.nombre) + '</span>' +
                    '<input type="radio" name="planServicio" value="' + p.id + '"' + (idx === 0 ? ' checked' : '') + '>' +
                    '</div>' +
                    '<div class="space-y-1.5 text-xs">' +
                    (p.inicial !== null
                        ? '<div><span class="text-slate-500">Pago inicial (' + p.moneda + '):</span> <input type="number" step="0.01" min="0" class="plan-inicial w-24 px-2 py-1 bg-slate-900 border border-slate-800 rounded text-slate-200 text-right font-mono" data-plan="' + p.id + '" value="' + p.inicial + '"><span class="hint-inicial block text-[10px] text-slate-600 mt-0.5"></span></div>'
                        : '<div class="text-slate-600">Sin pago inicial</div>') +
                    (p.mensual !== null
                        ? '<div><span class="text-slate-500">Mensualidad (' + p.moneda + '):</span> <input type="number" step="0.01" min="0" class="plan-mensual w-24 px-2 py-1 bg-slate-900 border border-slate-800 rounded text-slate-200 text-right font-mono" data-plan="' + p.id + '" value="' + p.mensual + '"><span class="hint-mensual block text-[10px] text-slate-600 mt-0.5"></span></div>'
                        : '<div class="text-slate-600">Sin mensualidad</div>') +
                    '</div></label>';
            });
            $('#listaPlanes').html(html);
            pintarCaracteristicas();
            pintarBonos(srv);
            pintarMinimosPlanes();
            recalculate();
            programarVistaPrevia();
        }

        function pintarCaracteristicas() {
            // SOLO LECTURA: se listan tal como vienen del plan, sin checkbox
            // ni edición (la matriz las administra en el configurador)
            var plan = planActual();
            var html = '';
            if (plan) {
                plan.caracteristicas.forEach(function(c, idx) {
                    html += '<div class="caracteristica-item flex items-center gap-2 text-xs text-slate-300" data-titulo="' + escaparHtml(c.titulo).replace(/"/g, '&quot;') + '" data-desc="' + escaparHtml(c.desc).replace(/"/g, '&quot;') + '">' +
                        '<i data-lucide="check" class="w-3.5 h-3.5 text-purple-400 shrink-0"></i>' +
                        '<span>' + escaparHtml(c.titulo) + (c.desc ? ' <span class="text-slate-500">— ' + escaparHtml(c.desc) + '</span>' : '') + '</span></div>';
                });
            }
            $('#listaCaracteristicas').html(html);
            lucide.createIcons();
        }

        function pintarBonos(srv) {
            var html = '';
            srv.bonos.forEach(function(b) {
                html += '<label class="flex items-center gap-2 text-xs text-slate-300 cursor-pointer">' +
                    '<input type="checkbox" class="chk-bono rounded"' + (b.incluido ? ' checked' : '') + ' data-titulo="' + escaparHtml(b.titulo).replace(/"/g, '&quot;') + '" data-desc="' + escaparHtml(b.desc).replace(/"/g, '&quot;') + '">' +
                    '<span>' + escaparHtml(b.titulo) + (b.desc ? ' <span class="text-slate-500">— ' + escaparHtml(b.desc) + '</span>' : '') + '</span></label>';
            });
            $('#listaBonos').html(html);
        }

        // Al cambiar el plan elegido se refrescan características y totales
        $(document).on('change', 'input[name=planServicio]', function() {
            pintarCaracteristicas();
            recalculate();
            programarVistaPrevia();
        });

        // Banda mín-máx del plan validada EN VIVO (mismo patrón pintarBanda)
        function textoRangoPlan(min, max, moneda) {
            if (min === null && max === null) return '';
            var t = 'Permitido: ';
            t += min !== null ? 'desde ' + min : 'sin mínimo';
            t += max !== null ? ' hasta ' + max : '';
            return t + ' ' + moneda;
        }
        function pintarMinimosPlanes() {
            var srv = servicioSeleccionado;
            if (!srv) return;
            srv.planes.forEach(function(p) {
                var $inicial = $('.plan-inicial[data-plan=' + p.id + ']');
                var $mensual = $('.plan-mensual[data-plan=' + p.id + ']');
                if ($inicial.length) {
                    var v = parseFloat($inicial.val() || 0);
                    var $hint = $inicial.closest('div').find('.hint-inicial');
                    if (p.inicial_min !== null && v < p.inicial_min) {
                        $inicial.addClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint.text('⚠ BAJO el mínimo (' + p.inicial_min + ' ' + p.moneda + ')').addClass('text-red-400 font-bold');
                    } else if (p.inicial_max !== null && v > p.inicial_max) {
                        $inicial.addClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint.text('⚠ SUPERA el máximo (' + p.inicial_max + ' ' + p.moneda + ')').addClass('text-red-400 font-bold');
                    } else {
                        $inicial.removeClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint.text(textoRangoPlan(p.inicial_min, p.inicial_max, p.moneda)).removeClass('text-red-400 font-bold');
                    }
                }
                if ($mensual.length) {
                    var v2 = parseFloat($mensual.val() || 0);
                    var $hint2 = $mensual.closest('div').find('.hint-mensual');
                    if (p.mensual_min !== null && v2 < p.mensual_min) {
                        $mensual.addClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint2.text('⚠ BAJO el mínimo (' + p.mensual_min + ' ' + p.moneda + ')').addClass('text-red-400 font-bold');
                    } else if (p.mensual_max !== null && v2 > p.mensual_max) {
                        $mensual.addClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint2.text('⚠ SUPERA el máximo (' + p.mensual_max + ' ' + p.moneda + ')').addClass('text-red-400 font-bold');
                    } else {
                        $mensual.removeClass('border-red-500 ring-1 ring-red-500/40 text-red-300');
                        $hint2.text(textoRangoPlan(p.mensual_min, p.mensual_max, p.moneda)).removeClass('text-red-400 font-bold');
                    }
                }
            });
        }
        $(document).on('input change', '.plan-inicial, .plan-mensual, #cuotasServicio, #descuentoServicio, #descuentoServicioTipo', function() {
            pintarMinimosPlanes();
            recalculate();
            programarVistaPrevia();
        });

        // CARACTERÍSTICAS y BONOS los define la matriz en el configurador del
        // servicio: al cotizar no se agregan manuales (los bonos solo se
        // marcan/desmarcan para incluirlos u omitirlos del documento).

        // Aporte del servicio al subtotal: pago inicial del plan elegido en CLP,
        // menos el descuento del pago inicial. La mensualidad NO entra al total.
        function aporteServicio() {
            if (!servicioActivo) return { setupClp: 0, mensualTexto: '' };
            var plan = planActual();
            if (!plan) return { setupClp: 0, mensualTexto: '' };

            var inicial = plan.inicial !== null ? parseFloat($('.plan-inicial[data-plan=' + plan.id + ']').val() || 0) : 0;
            var mensual = plan.mensual !== null ? parseFloat($('.plan-mensual[data-plan=' + plan.id + ']').val() || 0) : null;
            var setupClp = plan.moneda === 'UF' ? inicial * VALOR_UF : inicial;

            var mensualTexto = '';
            if (mensual !== null && mensual > 0) {
                var mensualClp = plan.moneda === 'UF' ? mensual * VALOR_UF : mensual;
                mensualTexto = 'Mensualidad ' + escaparHtml(plan.nombre) + ': ' +
                    (plan.moneda === 'UF' ? numberFormatDec(mensual, 1) + ' UF' : '$' + numberFormat(mensual)) +
                    ' + IVA (≈ $' + numberFormat(mensualClp * 1.19) + ' IVA incl.) — no entra al total inicial';
            }
            return { setupClp: setupClp, mensualTexto: mensualTexto };
        }

        // 5. Función de Recálculo (los items en UF se convierten a CLP)
        function recalculate() {
            let subtotal = 0;
            let hayUf = false;

            $('#productsList .product-row:not(.hidden)').each(function() {
                const qty = parseInt($(this).find('.product-qty').val() || 1);
                const price = parseFloat($(this).find('.product-price').val() || 0);
                const prod = datosProducto($(this).find('.product-id').val());
                const moneda = prod ? prod.moneda : 'CLP';
                const priceClp = moneda === 'UF' ? price * VALOR_UF : price;
                if (moneda === 'UF') hayUf = true;
                const total = qty * priceClp;

                $(this).find('.item-total').text(numberFormat(total));
                subtotal += total;
            });
            // Aporte del servicio (pago inicial del plan; mensualidad informativa)
            const servicio = aporteServicio();
            subtotal += servicio.setupClp;
            if (servicio.setupClp > 0 && servicioSeleccionado) {
                const planSel = planActual();
                if (planSel && planSel.moneda === 'UF') hayUf = true;
            }
            if (servicio.mensualTexto) {
                $('#lineaMensualidad').html(servicio.mensualTexto).removeClass('hidden');
            } else {
                $('#lineaMensualidad').addClass('hidden');
            }

            $('#lineaUf').toggleClass('hidden', !hayUf);

            // Descuento: con servicio activo, el del panel de servicio aplicado
            // al TOTAL inicial (plan + productos, regla 22-07); sin servicio,
            // el campo general (la UI esta oculta: si no existe, siempre es 0).
            let discountMonto = 0;
            const planDesc = servicioActivo ? planActual() : null;
            if (planDesc) {
                const descValSrv = parseFloat($('#descuentoServicio').val() || 0);
                if (descValSrv > 0) {
                    discountMonto = $('#descuentoServicioTipo').val() === 'porcentaje'
                        ? subtotal * descValSrv / 100
                        : (planDesc.moneda === 'UF' ? descValSrv * VALOR_UF : descValSrv);
                    if (discountMonto > subtotal) discountMonto = subtotal;
                }
            } else {
                const discVal = $('#discountValue').length ? parseFloat($('#discountValue').val() || 0) : 0;
                const discType = $('#discountType').length ? $('#discountType').val() : 'fijo';
                if (discVal > 0) {
                    discountMonto = discType === 'porcentaje' ? subtotal * discVal / 100 : discVal;
                }
            }
            if (discountMonto > 0) {
                $('#discountLine').removeClass('hidden');
                $('#discountVal').text(numberFormat(discountMonto));
            } else {
                $('#discountLine').addClass('hidden');
            }

            // Impuesto (19% IVA)
            const netAmount = subtotal - discountMonto;
            const taxMonto = netAmount * 0.19;
            const totalMonto = netAmount + taxMonto;

            $('#subtotalVal').text(numberFormat(subtotal));
            $('#taxVal').text(numberFormat(taxMonto));
            $('#totalVal').text(numberFormat(totalMonto));
        }

        function numberFormat(val) {
            return new Intl.NumberFormat('es-CL').format(Math.round(val));
        }
        function numberFormatDec(val, dec) {
            return new Intl.NumberFormat('es-CL', { minimumFractionDigits: dec, maximumFractionDigits: dec }).format(val);
        }

        // 6. Submit AJAX (valida la banda min-max antes de enviar)
        $('#submitQuoteBtn').on('click', function() { generarCotizacion(); });

        function generarCotizacion(datosFacturacion) {
            // Vigencia OBLIGATORIA: sin fecha del calendario no se cotiza
            if (!$('#vigenciaFecha').val()) {
                Swal.fire({ icon: 'warning', title: 'Falta la vigencia', text: 'Selecciona en el calendario hasta cuándo estará vigente la cotización.', background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#f59e0b' });
                return;
            }

            const productsData = [];
            const fueraDeBanda = [];

            $('#productsList .product-row:not(.hidden)').each(function() {
                const id = $(this).find('.product-id').val();
                const qty = $(this).find('.product-qty').val();
                const price = parseFloat($(this).find('.product-price').val() || 0);
                const prod = datosProducto(id);

                if (id && qty && prod) {
                    const sim = prod.moneda === 'UF' ? 'UF ' : '$';
                    const dec = prod.moneda === 'UF' ? 2 : 0;
                    if (prod.minimo > 0 && price < prod.minimo) {
                        fueraDeBanda.push(prod.nombre + ': ' + sim + numberFormatDec(price, dec) + ' está BAJO el mínimo (' + sim + numberFormatDec(prod.minimo, dec) + ')');
                    } else if (prod.maximo > 0 && price > prod.maximo) {
                        fueraDeBanda.push(prod.nombre + ': ' + sim + numberFormatDec(price, dec) + ' SUPERA el máximo (' + sim + numberFormatDec(prod.maximo, dec) + ')');
                    }
                    productsData.push({
                        id: id,
                        cantidad: qty,
                        precio: price
                    });
                }
            });

            if (fueraDeBanda.length > 0) {
                Swal.fire({
                    icon: 'warning',
                    title: 'Precio fuera del rango permitido',
                    html: fueraDeBanda.join('<br>'),
                    background: '#1e293b',
                    color: '#f8fafc',
                    confirmButtonColor: '#d97706'
                });
                return;
            }

            // Servicio con plan (si el panel está activo)
            let servicioData = null;
            if (servicioActivo) {
                const planSel = planActual();
                if (!planSel) {
                    Swal.fire({
                        icon: 'warning',
                        title: 'Falta el plan del servicio',
                        text: 'Seleccione uno de los planes del servicio (o quite el servicio).',
                        background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#a855f7'
                    });
                    return;
                }
                // Mínimos del plan validados también antes de enviar
                const vInicial = planSel.inicial !== null ? parseFloat($('.plan-inicial[data-plan=' + planSel.id + ']').val() || 0) : null;
                const vMensual = planSel.mensual !== null ? parseFloat($('.plan-mensual[data-plan=' + planSel.id + ']').val() || 0) : null;
                if (planSel.inicial_min !== null && vInicial !== null && vInicial < planSel.inicial_min) {
                    fueraDeBanda.push(planSel.nombre + ': pago inicial ' + vInicial + ' ' + planSel.moneda + ' está BAJO el mínimo (' + planSel.inicial_min + ')');
                }
                if (planSel.inicial_max !== null && vInicial !== null && vInicial > planSel.inicial_max) {
                    fueraDeBanda.push(planSel.nombre + ': pago inicial ' + vInicial + ' ' + planSel.moneda + ' SUPERA el máximo (' + planSel.inicial_max + ')');
                }
                if (planSel.mensual_min !== null && vMensual !== null && vMensual < planSel.mensual_min) {
                    fueraDeBanda.push(planSel.nombre + ': mensualidad ' + vMensual + ' ' + planSel.moneda + ' está BAJO el mínimo (' + planSel.mensual_min + ')');
                }
                if (planSel.mensual_max !== null && vMensual !== null && vMensual > planSel.mensual_max) {
                    fueraDeBanda.push(planSel.nombre + ': mensualidad ' + vMensual + ' ' + planSel.moneda + ' SUPERA el máximo (' + planSel.mensual_max + ')');
                }
                if (fueraDeBanda.length > 0) {
                    Swal.fire({
                        icon: 'warning',
                        title: 'Precio fuera del rango permitido',
                        html: fueraDeBanda.join('<br>'),
                        background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#d97706'
                    });
                    return;
                }

                const caracteristicas = [];
                $('#listaCaracteristicas .caracteristica-item').each(function() {
                    caracteristicas.push({ titulo: $(this).data('titulo'), desc: $(this).data('desc') || '' });
                });
                const bonos = [];
                $('.chk-bono:checked').each(function() {
                    bonos.push({ titulo: $(this).data('titulo'), desc: $(this).data('desc') || '' });
                });

                servicioData = {
                    servicio_id: servicioSeleccionado.id,
                    plan_id: planSel.id,
                    precio_inicial: vInicial !== null ? vInicial : '',
                    precio_mensual: vMensual !== null ? vMensual : '',
                    cuotas: $('#cuotasServicio').val(),
                    descuento_valor: $('#descuentoServicio').val(),
                    descuento_tipo: $('#descuentoServicioTipo').val(),
                    caracteristicas: caracteristicas,
                    bonos: bonos
                };
            }

            if (productsData.length === 0 && !servicioData) {
                Swal.fire({
                    icon: 'warning',
                    title: 'Formulario Incompleto',
                    text: 'Debe agregar al menos un producto o un servicio válido.',
                    background: '#1e293b',
                    color: '#f8fafc',
                    confirmButtonColor: '#3b82f6'
                });
                return;
            }

            // Deshabilitar botón y mostrar pantalla de carga: crear la
            // cotización incluye el documento en CE y, con servicio, el PDF
            // (Puppeteer) + envío por WhatsApp/correo — puede tardar varios segundos
            $('#submitQuoteBtn').attr('disabled', true).addClass('opacity-80');
            Swal.fire({
                title: 'Generando cotización...',
                html: '<span class="text-sm text-slate-300">Estamos creando el documento, registrándolo en el facturador y preparando el envío.<br>No cierres esta ventana.</span>',
                background: '#1e293b', color: '#f8fafc',
                allowOutsideClick: false, allowEscapeKey: false, showConfirmButton: false,
                didOpen: function() { Swal.showLoading(); }
            });

            const postData = {
                lead_id: <?php echo $lead['id']; ?>,
                productos: productsData,
                descuento_valor: $('#discountValue').length ? $('#discountValue').val() : 0,
                descuento_tipo: $('#discountType').length ? $('#discountType').val() : 'fijo',
                notas: $('#notes').val(),
                vigente_hasta: $('#vigenciaFecha').val()
            };
            if (servicioData) postData.servicio = servicioData;
            if (datosFacturacion) $.extend(postData, datosFacturacion);

            $.ajax({
                url: '<?php echo APP_URL; ?>/cotizaciones/crear',
                type: 'POST',
                data: postData,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        if (response.tipo && response.tipo !== 'productos') {
                            // Servicio: el envío por WhatsApp y correo fue automático.
                            // Si algún canal falló, el título no promete "enviada".
                            const huboFallo = (response.message || '').indexOf('FALLÓ') !== -1;
                            Swal.fire({
                                icon: huboFallo ? 'warning' : 'success',
                                title: huboFallo ? 'Cotización creada, con avisos de envío' : '¡Cotización creada y enviada!',
                                text: response.message,
                                background: '#1e293b',
                                color: '#f8fafc',
                                confirmButtonColor: '#3b82f6'
                            }).then(() => {
                                window.location.href = response.redirect;
                            });
                            return;
                        }
                        // Productos: elegir por dónde enviar la cotización
                        Swal.fire({
                            icon: 'success',
                            title: '¡Cotización Creada!',
                            html: '¿Por dónde quieres enviarla al cliente?',
                            background: '#1e293b',
                            color: '#f8fafc',
                            showDenyButton: true,
                            showCancelButton: true,
                            confirmButtonText: 'Correo y WhatsApp',
                            denyButtonText: 'Solo correo',
                            cancelButtonText: 'Solo WhatsApp',
                            confirmButtonColor: '#3b82f6',
                            denyButtonColor: '#6366f1',
                            cancelButtonColor: '#059669',
                            footer: '<a href="#" id="enviarNinguno" class="text-slate-300 text-xs underline hover:text-slate-100">No enviar por ahora (solo guardar)</a>',
                            didOpen: function() {
                                $('#enviarNinguno').on('click', function(e) {
                                    e.preventDefault();
                                    Swal.close();
                                    window.location.href = response.redirect;
                                });
                            }
                        }).then((eleccion) => {
                            let canales = null;
                            if (eleccion.isConfirmed) canales = ['correo', 'whatsapp'];
                            else if (eleccion.isDenied) canales = ['correo'];
                            else if (eleccion.dismiss === Swal.DismissReason.cancel) canales = ['whatsapp'];
                            if (!canales) { window.location.href = response.redirect; return; }

                            Swal.fire({ title: 'Enviando cotización...', background: '#1e293b', color: '#f8fafc', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
                            $.post('<?php echo APP_URL; ?>/cotizaciones/enviar', { id: response.cotizacion_id, canales: canales }, function(envio) {
                                Swal.fire({
                                    icon: envio.success ? 'success' : 'warning',
                                    title: envio.success ? 'Cotización enviada' : 'Envío con problemas',
                                    text: envio.message,
                                    background: '#1e293b', color: '#f8fafc', confirmButtonColor: '#3b82f6'
                                }).then(() => { window.location.href = response.redirect; });
                            }, 'json').fail(function() {
                                Swal.fire({ icon: 'error', title: 'No se pudo enviar', text: 'La cotización quedó guardada; reintente el envío desde la cotización.', background: '#1e293b', color: '#f8fafc' })
                                    .then(() => { window.location.href = response.redirect; });
                            });
                        });
                    } else if (response.faltan_datos) {
                        // Faltan datos de facturación del cliente: se piden
                        // aquí mismo y se reintenta la generación completa
                        $('#submitQuoteBtn').attr('disabled', false).removeClass('opacity-80');
                        pedirDatosFacturacion(response, function(datos) { generarCotizacion(datos); }, 'Guardar y generar cotización');
                    } else {
                        Swal.fire({
                            icon: 'error',
                            title: 'Fallo al Guardar',
                            text: response.message,
                            background: '#1e293b',
                            color: '#f8fafc',
                            confirmButtonColor: '#3b82f6'
                        });
                        $('#submitQuoteBtn').attr('disabled', false).removeClass('opacity-80');
                    }
                },
                error: function() {
                    Swal.fire({
                        icon: 'error',
                        title: 'Error de servidor',
                        text: 'No se pudo guardar la cotización.',
                        background: '#1e293b',
                        color: '#f8fafc',
                        confirmButtonColor: '#ef4444'
                    });
                    $('#submitQuoteBtn').attr('disabled', false).removeClass('opacity-80');
                }
            });
        }

        // Cargar fila inicial
        addRow();

    });
</script>
<?php // Modal compartido de datos de facturación (se pide AL GENERAR si faltan)
include __DIR__ . '/_datos_facturacion_js.php'; ?>
