// /home/Autopartes/pos/static/js/pos.js
/**
 * POS Frontend: sale processing, F-key shortcuts, payment modal, ticket printing.
 *
 * Communicates with:
 *   - /pos/api/sales (pos_bp)
 *   - /pos/api/quotations (pos_bp)
 *   - /pos/api/layaways (pos_bp)
 *   - /pos/api/customers (customers_bp)
 *   - /pos/api/register (cashregister_bp)
 *   - /pos/api/inventory/items (inventory_bp) — for item search
 *   - /pos/api/catalog/search (catalog_bp) — for catalog search
 */
const POS = (() => {
    // ─── State ───────────────────────────
    let token = localStorage.getItem('pos_token') || '';
    let cart = [];
    let selectedRow = -1;
    let currentCustomer = null;
    let currentRegister = null;
    let paymentMethod = 'efectivo';
    let canViewCost = false;
    let employeeMaxDiscount = 100;
    let lastSaleId = sessionStorage.getItem('pos_last_sale_id') || null;
    let lastSaleData = null;
    let searchTimeout = null;
    let customerSearchTimeout = null;
    let canCancel = false;
    let canDiscount = false;
    let canEditPrice = false;
    let canCreateWorkshopOrder = false;
    let canCreateLayaway = false;
    let receiptConfig = {};

    // Currency-aware formatter: reads pos_currency from localStorage
    const _posCurrency = localStorage.getItem('pos_currency') || 'MXN';
    const _currSymbols = { MXN: '$', USD: 'US$' };
    const _currLocale = _posCurrency === 'USD' ? 'en-US' : 'es-MX';
    const fmt = (n) => (_currSymbols[_posCurrency] || '$') + parseFloat(n || 0).toLocaleString(_currLocale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });

    function headers() {
        return { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token };
    }

    async function api(url, options = {}) {
        options.headers = headers();
        const res = await fetch(url, options);
        const data = await res.json();
        if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
        return data;
    }

    function showToast(msg) {
        const container = document.getElementById('toastContainer');
        if (!container) return;
        const el = document.createElement('div');
        el.className = 'toast';
        el.textContent = msg;
        container.appendChild(el);
        setTimeout(() => el.remove(), 2100);
    }

    // ─── Permission-based UI toggles ─────
    function applyPermissionsUI() {
        function hide(selector) {
            const el = document.querySelector(selector);
            if (el) el.style.display = 'none';
        }
        if (!canCancel) {
            hide('#btnCancelSale');
            hide('#fkeyEsc');
        }
        if (!canDiscount) hide('[onclick="POS.applyDiscount()"]');
        if (!canEditPrice) hide('[onclick="POS.modifyPrice()"]');
        if (!canCreateWorkshopOrder) {
            hide('[onclick="POS.createServiceOrder()"]');
            hide('[title="Orden de servicio"]');
        }
        if (!canCreateLayaway) hide('[onclick="POS.createLayaway()"]');
    }

    // ─── Init ────────────────────────────
    async function init() {
        // Parse JWT to get employee info
        try {
            const payload = JSON.parse(atob(token.split('.')[1]));
            document.getElementById('employeeName').textContent = payload.name || 'Empleado';
            document.getElementById('branchName').textContent = payload.branch_name || '';
            const perms = payload.permissions || [];
            canViewCost = perms.includes('pos.view_cost');
            canCancel = perms.includes('pos.cancel');
            canDiscount = perms.includes('pos.discount');
            canEditPrice = perms.includes('config.edit_prices');
            canCreateWorkshopOrder = perms.includes('workshop.edit');
            canCreateLayaway = perms.includes('pos.sell');
            employeeMaxDiscount = payload.max_discount_pct || 100;

            // Show cost/margin columns and toggle button if permission
            if (canViewCost) {
                document.getElementById('thCost').style.display = '';
                document.getElementById('thMargin').style.display = '';
                const costToggle = document.getElementById('costToggle');
                if (costToggle) costToggle.style.display = '';
            }

            // Set avatar initials
            const avatar = document.querySelector('.status-bar__user-avatar');
            if (avatar && payload.name) {
                const parts = payload.name.split(' ');
                avatar.textContent = parts.map(p => p[0]).join('').substring(0, 2).toUpperCase();
            }

            applyPermissionsUI();
        } catch (e) {
            console.warn('Could not parse token:', e);
        }

        // Load cart from localStorage (from catalog or quotation edit/convert)
        const catalogCart = localStorage.getItem('pos_cart');
        const editQuoteId = localStorage.getItem('pos_edit_quote_id');
        const convertQuoteId = localStorage.getItem('pos_convert_quote_id');
        if (catalogCart) {
            try {
                const items = JSON.parse(catalogCart);
                for (const item of items) {
                    addToCart(item);
                }
                localStorage.removeItem('pos_cart');
            } catch (e) { console.warn('Could not load catalog cart:', e); }
        }
        if (editQuoteId) {
            showToast(`Modo edicion: Cotizacion #${editQuoteId}. Guardar actualizara la cotizacion.`);
        }
        if (convertQuoteId) {
            showToast(`Modo conversion: Cotizacion #${convertQuoteId}. El pago convertira la cotizacion en venta.`);
        }

        // Load current register and receipt config
        await loadRegister();
        await loadReceiptConfig();

        // Setup event listeners
        setupKeyboard();
        setupSearch();
        setupCustomerSearch();
    }

    // ─── Register ────────────────────────
    async function loadRegister() {
        try {
            const data = await api('/pos/api/register/current');
            if (data.register) {
                currentRegister = data.register;
                document.getElementById('registerInfo').innerHTML =
                    `<span>Caja #${data.register.register_number}</span>`;
            } else {
                currentRegister = null;
                document.getElementById('registerInfo').innerHTML =
                    '<span style="color:var(--color-error);cursor:pointer;" onclick="POS.showOpenRegisterModal()" title="Clic para abrir caja">&#x26A0; Sin caja abierta — Clic para abrir</span>';
                // Force open register modal on first load
                showOpenRegisterModal();
            }
        } catch (e) {
            console.warn('Register check failed:', e);
        }
    }

    async function loadReceiptConfig() {
        try {
            receiptConfig = await api('/pos/api/config/receipt');
        } catch (e) {
            console.warn('Could not load receipt config:', e);
            receiptConfig = {};
        }
    }

    function rc(key, fallback) {
        const v = receiptConfig[key];
        return v !== undefined && v !== null && v !== '' ? v : fallback;
    }

    function showOpenRegisterModal() {
        document.getElementById('openRegisterModal').classList.add('open');
        document.getElementById('registerOpenResult').innerHTML = '';
    }
    function closeOpenRegisterModal() {
        document.getElementById('openRegisterModal').classList.remove('open');
        document.getElementById('registerOpenResult').innerHTML = '';
    }
    async function openRegister() {
        const number = parseInt(document.getElementById('regNumber').value);
        const amount = parseFloat(document.getElementById('regOpeningAmount').value) || 0;
        if (!number || number < 1) {
            document.getElementById('registerOpenResult').innerHTML = '<span style="color:var(--color-error);">Numero de caja invalido</span>';
            return;
        }
        try {
            const data = await api('/pos/api/register/open', {
                method: 'POST',
                body: JSON.stringify({ register_number: number, opening_amount: amount })
            });
            if (data.error) {
                document.getElementById('registerOpenResult').innerHTML = '<span style="color:var(--color-error);">' + (data.error || 'Error') + '</span>';
                return;
            }
            currentRegister = data;
            document.getElementById('registerInfo').innerHTML = `<span>Caja #${data.register_number}</span>`;
            closeOpenRegisterModal();
            showToast(`Caja #${data.register_number} abierta con $${amount.toFixed(2)}`);
        } catch (e) {
            document.getElementById('registerOpenResult').innerHTML = '<span style="color:var(--color-error);">Error de red</span>';
        }
    }

    // ─── Cut X / Z (Close Register) ──────
    function showCutZModal() {
        document.getElementById('cutZModal').classList.add('open');
        document.getElementById('cutZResult').innerHTML = '';
        loadCutX();
    }
    function closeCutZModal() {
        document.getElementById('cutZModal').classList.remove('open');
        document.getElementById('cutZResult').innerHTML = '';
    }
    async function loadCutX() {
        const el = document.getElementById('cutZSummary');
        try {
            const data = await api('/pos/api/register/cut-x');
            if (data.error) {
                el.innerHTML = '<p style="color:var(--color-error);">' + data.error + '</p>';
                return;
            }
            let html = '<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3);font-size:var(--text-body-sm);">';
            html += '<div><span style="color:var(--color-text-muted);">Efectivo inicial</span><br/><strong>' + fmt(data.opening_amount) + '</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Ventas totales</span><br/><strong>' + fmt(data.total_sales) + '</strong> (' + data.total_sales_count + ')</div>';
            html += '<div><span style="color:var(--color-text-muted);">Efectivo en ventas</span><br/><strong>' + fmt(data.cash_from_sales) + '</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Cambio entregado</span><br/><strong>-' + fmt(data.change_given) + '</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Entradas de efectivo</span><br/><strong>+' + fmt(data.cash_movements_in) + '</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Salidas de efectivo</span><br/><strong>-' + fmt(data.cash_movements_out) + '</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Cancelaciones</span><br/><strong>' + data.cancelled_count + ' (' + fmt(data.cancelled_amount) + ')</strong></div>';
            html += '<div><span style="color:var(--color-text-muted);">Efectivo esperado</span><br/><strong style="color:var(--color-accent);font-size:1.1em;">' + fmt(data.expected_cash) + '</strong></div>';
            html += '</div>';
            if (data.sales_by_method && Object.keys(data.sales_by_method).length) {
                html += '<div style="margin-top:var(--space-3);padding-top:var(--space-3);border-top:1px solid var(--color-border);">';
                html += '<span style="color:var(--color-text-muted);font-size:var(--text-caption);">Por metodo de pago:</span><br/>';
                for (const [method, info] of Object.entries(data.sales_by_method)) {
                    html += '<span style="font-size:var(--text-body-sm);margin-right:var(--space-3);">' + method + ': ' + fmt(info.amount) + ' (' + info.count + ')</span>';
                }
                html += '</div>';
            }
            if (data.movement_detail && data.movement_detail.length) {
                html += '<div style="margin-top:var(--space-3);padding-top:var(--space-3);border-top:1px solid var(--color-border);">';
                html += '<span style="color:var(--color-text-muted);font-size:var(--text-caption);">Movimientos de caja:</span><br/>';
                data.movement_detail.forEach(function(m) {
                    html += '<div style="font-size:var(--text-body-sm);">' + m.type + ' ' + fmt(m.amount) + ' — ' + (m.reason || '') + '</div>';
                });
                html += '</div>';
            }
            el.innerHTML = html;
            document.getElementById('cutZClosingAmount').value = data.expected_cash.toFixed(2);
        } catch (e) {
            el.innerHTML = '<p style="color:var(--color-error);">Error cargando resumen</p>';
        }
    }
    async function confirmCutZ() {
        const amount = parseFloat(document.getElementById('cutZClosingAmount').value) || 0;
        try {
            const data = await api('/pos/api/register/cut-z', {
                method: 'POST',
                body: JSON.stringify({ closing_amount: amount })
            });
            if (data.error) {
                document.getElementById('cutZResult').innerHTML = '<span style="color:var(--color-error);">' + data.error + '</span>';
                return;
            }
            const diffColor = data.difference > 0 ? 'var(--color-success)' : (data.difference < 0 ? 'var(--color-error)' : 'var(--color-text-muted)');
            document.getElementById('cutZResult').innerHTML = '<span style="color:var(--color-success);">Caja cerrada correctamente</span>';
            document.getElementById('registerInfo').innerHTML = '<span style="color:var(--color-text-muted);" onclick="POS.showOpenRegisterModal()">Sin caja abierta</span>';
            currentRegister = null;
            closeCutZModal();
            showToast('Corte Z completado. Diferencia: $' + data.difference.toFixed(2));
        } catch (e) {
            document.getElementById('cutZResult').innerHTML = '<span style="color:var(--color-error);">Error de red</span>';
        }
    }

    // ─── Cart ────────────────────────────
    function addToCart(item) {
        const existing = cart.find(c => c.inventory_id === item.inventory_id);
        if (existing) {
            existing.quantity += (item.quantity || 1);
            renderCart();
            if (window.BarcodeFeedback) BarcodeFeedback.success();
            return;
        }

        cart.push({
            inventory_id: item.inventory_id || item.id,
            part_number: item.part_number || '',
            name: item.name || '',
            quantity: item.quantity || 1,
            unit_price: parseFloat(item.unit_price || item.price_1 || 0),
            unit_cost: parseFloat(item.cost || 0),
            discount_pct: parseFloat(item.discount_pct || 0),
            tax_rate: parseFloat(item.tax_rate || 0.16),
            stock: item.stock || 0,
            price_1: parseFloat(item.price_1 || 0),
            price_2: parseFloat(item.price_2 || 0),
            price_3: parseFloat(item.price_3 || 0),
        });

        renderCart();
        showToast(`${item.name || 'Articulo'} agregado`);
    }

    function removeFromCart(index) {
        cart.splice(index, 1);
        if (selectedRow >= cart.length) selectedRow = cart.length - 1;
        renderCart();
    }

    function clearCart() {
        cart.length = 0;
        selectedRow = -1;
        renderCart();
    }

    function openCancelModal() {
        if (!canCancel) { showToast('No tienes permiso para cancelar'); return; }
        const overlay = document.getElementById('overlay-cancelar-venta');
        const dialog = document.getElementById('modal-cancelar-venta');
        if (overlay) overlay.classList.add('active');
        if (dialog) dialog.classList.add('active');
    }

    function closeCancelModal() {
        const overlay = document.getElementById('overlay-cancelar-venta');
        const dialog = document.getElementById('modal-cancelar-venta');
        if (overlay) overlay.classList.remove('active');
        if (dialog) dialog.classList.remove('active');
    }

    function changeQuantity() {
        if (selectedRow < 0 || selectedRow >= cart.length) {
            showToast('Selecciona un articulo primero', 'warn');
            return;
        }
        const q = prompt('Nueva cantidad:', cart[selectedRow].quantity);
        if (q !== null) {
            const n = parseInt(q);
            if (n > 0) {
                cart[selectedRow].quantity = n;
                renderCart();
            }
        }
    }

    function applyDiscount() {
        if (!canDiscount) { showToast('No tienes permiso para aplicar descuentos'); return; }
        if (selectedRow < 0 || selectedRow >= cart.length) {
            showToast('Selecciona un articulo primero', 'warn');
            return;
        }
        const d = prompt('Descuento %:', cart[selectedRow].discount_pct);
        if (d !== null) {
            const n = parseFloat(d);
            if (n >= 0 && n <= 100) {
                cart[selectedRow].discount_pct = n;
                renderCart();
            }
        }
    }

    function modifyPrice() {
        if (!canEditPrice) { showToast('No tienes permiso para modificar precios'); return; }
        if (selectedRow < 0 || selectedRow >= cart.length) {
            showToast('Selecciona un articulo primero', 'warn');
            return;
        }
        const p = prompt('Nuevo precio unitario:', cart[selectedRow].unit_price);
        if (p !== null) {
            const n = parseFloat(p);
            if (n >= 0) {
                cart[selectedRow].unit_price = n;
                renderCart();
            }
        }
    }

    // Wire confirm-cancel button
    document.addEventListener('DOMContentLoaded', function() {
        var btn = document.getElementById('btnConfirmCancel');
        if (btn) {
            btn.addEventListener('click', function() {
                clearCart();
                closeCancelModal();
            });
        }
    });

    function renderCart() {
        const tbody = document.getElementById('cartBody');
        const table = document.getElementById('cartTable');
        const empty = document.getElementById('cartEmpty');

        if (cart.length === 0) {
            table.style.display = 'none';
            empty.style.display = 'flex';
            updateTotals();
            return;
        }

        table.style.display = '';
        empty.style.display = 'none';

        let html = '';
        cart.forEach((item, i) => {
            const lineGross = item.unit_price * item.quantity;
            const lineDiscount = lineGross * item.discount_pct / 100;
            const lineSubtotal = lineGross - lineDiscount;

            const costHtml = canViewCost ? `<td class="num" style="text-align:right;padding:var(--space-2);font-family:var(--font-mono);color:var(--color-text-muted);font-size:var(--text-caption);">${fmt(item.unit_cost)}</td>` : '';
            let marginHtml = '';
            if (canViewCost) {
                const effectivePrice = item.unit_price * (1 - item.discount_pct / 100);
                const marginPct = effectivePrice > 0
                    ? ((effectivePrice - item.unit_cost) / effectivePrice * 100).toFixed(1)
                    : '0.0';
                const marginVal = parseFloat(marginPct);
                const cls = marginVal > 30 ? 'margin-high' : marginVal > 15 ? 'margin-mid' : 'margin-low';
                const color = marginVal > 30 ? 'var(--color-success)' : marginVal > 15 ? 'var(--color-warning)' : 'var(--color-error)';
                marginHtml = `<td style="text-align:center;padding:var(--space-2);"><span style="font-family:var(--font-mono);font-size:var(--text-caption);font-weight:var(--font-weight-bold);color:${color};">${marginPct}%</span></td>`;
            }

            html += `<tr style="border-bottom:1px solid var(--color-border);cursor:pointer;${i === selectedRow ? 'background:var(--color-primary-muted);' : ''}" onclick="POS.selectRow(${i})">
                <td style="padding:var(--space-2);color:var(--color-text-muted);">${i + 1}</td>
                <td style="padding:var(--space-2);">
                    <div style="font-weight:var(--font-weight-semibold);color:var(--color-text-primary);">${item.name}</div>
                    <div style="font-family:var(--font-mono);font-size:var(--text-caption);color:var(--color-text-muted);">${item.part_number} | Stock: ${item.stock}</div>
                </td>
                <td style="text-align:center;padding:var(--space-2);"><input type="number" style="width:50px;text-align:center;font-family:var(--font-mono);background:var(--color-bg-base);color:var(--color-text-primary);border:1px solid var(--color-border);border-radius:var(--radius-sm);padding:2px 4px;" value="${item.quantity}" min="1"
                    onchange="POS.updateQty(${i}, this.value)" onclick="event.stopPropagation()"></td>
                <td style="text-align:right;padding:var(--space-2);font-family:var(--font-mono);">${fmt(item.unit_price)}</td>
                <td style="text-align:center;padding:var(--space-2);"><input type="number" style="width:45px;text-align:center;font-family:var(--font-mono);background:var(--color-bg-base);color:var(--color-text-primary);border:1px solid var(--color-border);border-radius:var(--radius-sm);padding:2px 4px;" value="${item.discount_pct}" min="0" max="100" step="0.5"
                    onchange="POS.updateDiscount(${i}, this.value)" onclick="event.stopPropagation()">%</td>
                <td style="text-align:right;padding:var(--space-2);font-family:var(--font-mono);font-weight:var(--font-weight-bold);">${fmt(lineSubtotal)}</td>
                ${costHtml}
                ${marginHtml}
                <td style="text-align:center;"><button style="background:transparent;border:1px solid var(--color-border);border-radius:var(--radius-sm);width:24px;height:24px;cursor:pointer;color:var(--color-text-muted);font-size:14px;" onclick="event.stopPropagation(); POS.removeFromCart(${i})">&times;</button></td>
            </tr>`;
        });
        tbody.innerHTML = html;
        updateTotals();
        updateAvgMargin();
    }

    function updateQty(index, val) {
        const qty = Math.max(1, parseInt(val) || 1);
        cart[index].quantity = qty;
        renderCart();
    }

    function updateDiscount(index, val) {
        let disc = Math.max(0, Math.min(100, parseFloat(val) || 0));
        if (disc > employeeMaxDiscount) {
            alert(`Descuento maximo permitido: ${employeeMaxDiscount}%`);
            disc = employeeMaxDiscount;
        }
        cart[index].discount_pct = disc;
        renderCart();
    }

    function selectRow(index) {
        selectedRow = index;
        renderCart();
    }

    function updateTotals() {
        let subtotal = 0, discountTotal = 0, taxTotal = 0;

        cart.forEach(item => {
            const lineGross = item.unit_price * item.quantity;
            const lineDiscount = lineGross * item.discount_pct / 100;
            const lineAfterDiscount = lineGross - lineDiscount;
            const lineTax = lineAfterDiscount * item.tax_rate;
            subtotal += lineAfterDiscount;
            discountTotal += lineDiscount;
            taxTotal += lineTax;
        });

        const total = subtotal + taxTotal;

        document.getElementById('dispSubtotal').textContent = fmt(subtotal);
        document.getElementById('dispTax').textContent = fmt(taxTotal);
        document.getElementById('dispTotal').textContent = fmt(total);

        if (discountTotal > 0) {
            document.getElementById('discountRow').style.display = '';
            document.getElementById('dispDiscount').textContent = '-' + fmt(discountTotal);
        } else {
            document.getElementById('discountRow').style.display = 'none';
        }
    }

    function updateAvgMargin() {
        const avgEl = document.getElementById('avgMargin');
        if (!avgEl || !canViewCost) return;
        let totalRevenue = 0, totalCost = 0;
        cart.forEach(item => {
            if (item.unit_cost > 0) {
                const effectivePrice = item.unit_price * (1 - item.discount_pct / 100);
                totalRevenue += effectivePrice * item.quantity;
                totalCost += item.unit_cost * item.quantity;
            }
        });
        if (totalRevenue > 0) {
            const avg = ((totalRevenue - totalCost) / totalRevenue * 100);
            avgEl.textContent = avg.toFixed(1) + '%';
            avgEl.style.color = avg > 30 ? 'var(--color-success)' : avg > 15 ? 'var(--color-warning)' : 'var(--color-error)';
        } else {
            avgEl.textContent = '--';
        }
    }

    function getTotal() {
        let subtotal = 0, taxTotal = 0;
        cart.forEach(item => {
            const lineGross = item.unit_price * item.quantity;
            const lineDiscount = lineGross * item.discount_pct / 100;
            const lineAfterDiscount = lineGross - lineDiscount;
            const lineTax = lineAfterDiscount * item.tax_rate;
            subtotal += lineAfterDiscount;
            taxTotal += lineTax;
        });
        return Math.round((subtotal + taxTotal) * 100) / 100;
    }

    function getItemCount() {
        return cart.reduce((sum, item) => sum + item.quantity, 0);
    }

    // ─── Search ──────────────────────────
    function setupSearch() {
        const input = document.getElementById('itemSearch');
        if (!input) return;
        input.addEventListener('input', () => {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => searchItems(input.value.trim()), 300);
        });
        input.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                e.preventDefault();
                searchItems(input.value.trim());
            }
            if (e.key === 'Escape') {
                input.value = '';
                hideSearchResults();
            }
        });
    }

    async function searchItems(q) {
        if (!q || q.length < 2) { hideSearchResults(); return; }

        try {
            const data = await api(`/pos/api/inventory/items?q=${encodeURIComponent(q)}&per_page=20`);
            const container = document.getElementById('searchResults');
            const totals = document.getElementById('totalsPanel');

            if (data.data.length === 0) {
                container.innerHTML = '<div style="padding:20px;text-align:center;color:var(--color-text-muted);">Sin resultados</div>';
                if (window.BarcodeFeedback) BarcodeFeedback.error();
            } else if (data.data.length === 1 && q.length >= 8) {
                // Auto-select single result on barcode scan (long codes)
                const item = data.data[0];
                let price = item.price_1;
                if (currentCustomer) {
                    const tier = currentCustomer.price_tier || 1;
                    price = tier === 3 ? item.price_3 : tier === 2 ? item.price_2 : item.price_1;
                }
                addFromSearch(item, price);
                input.value = '';
                hideSearchResults();
                return;
            } else {
                let html = '';
                data.data.forEach(item => {
                    let price = item.price_1;
                    if (currentCustomer) {
                        const tier = currentCustomer.price_tier || 1;
                        price = tier === 3 ? item.price_3 : tier === 2 ? item.price_2 : item.price_1;
                    }
                    html += `<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--color-border);cursor:pointer;display:flex;justify-content:space-between;align-items:center;transition:var(--transition-fast);" onmouseover="this.style.background='var(--color-primary-muted)'" onmouseout="this.style.background=''" onclick='POS.addFromSearch(${JSON.stringify(item).replace(/'/g, "&#39;")}, ${price})'>
                        <div>
                            <div style="font-weight:var(--font-weight-semibold);">${item.name}</div>
                            <div style="font-family:var(--font-mono);font-size:var(--text-caption);color:var(--color-text-muted);">${item.part_number} | ${item.brand || ''}</div>
                            <div style="font-size:var(--text-caption);color:${item.stock <= 0 ? 'var(--color-error)' : 'var(--color-text-muted)'};">Stock: ${item.stock}</div>
                        </div>
                        <div style="font-family:var(--font-mono);font-weight:var(--font-weight-bold);color:var(--color-primary);">${fmt(price)}</div>
                    </div>`;
                });
                container.innerHTML = html;
            }

            container.style.display = '';
            totals.style.display = 'none';
        } catch (e) {
            console.error('Search error:', e);
        }
    }

    function addFromSearch(item, price) {
        addToCart({
            inventory_id: item.id,
            part_number: item.part_number,
            name: item.name,
            unit_price: price,
            cost: item.cost,
            tax_rate: item.tax_rate,
            stock: item.stock,
            price_1: item.price_1,
            price_2: item.price_2,
            price_3: item.price_3,
        });
        if (window.BarcodeFeedback) BarcodeFeedback.success();
        hideSearchResults();
        document.getElementById('itemSearch').value = '';
        document.getElementById('itemSearch').focus();
    }

    function hideSearchResults() {
        const sr = document.getElementById('searchResults');
        const tp = document.getElementById('totalsPanel');
        if (sr) sr.style.display = 'none';
        if (tp) tp.style.display = '';
    }

    // ─── Customer Search ─────────────────
    function setupCustomerSearch() {
        const input = document.getElementById('customerSearch');
        if (!input) return;
        input.addEventListener('input', () => {
            clearTimeout(customerSearchTimeout);
            customerSearchTimeout = setTimeout(() => searchCustomers(input.value.trim()), 300);
        });
        input.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') {
                input.value = '';
                document.getElementById('customerAutocomplete').style.display = 'none';
            }
        });
    }

    async function searchCustomers(q) {
        if (!q || q.length < 2) {
            document.getElementById('customerAutocomplete').style.display = 'none';
            return;
        }

        try {
            const data = await api(`/pos/api/customers?q=${encodeURIComponent(q)}&per_page=10`);
            const ac = document.getElementById('customerAutocomplete');

            if (data.data.length === 0) {
                ac.innerHTML = '<div style="padding:var(--space-3);color:var(--color-text-muted);">Sin resultados</div>';
            } else {
                let html = '';
                data.data.forEach(c => {
                    const tiers = { 1: 'Mostrador', 2: 'Taller', 3: 'Mayoreo' };
                    html += `<div style="padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--color-border);cursor:pointer;transition:var(--transition-fast);" onmouseover="this.style.background='var(--color-primary-muted)'" onmouseout="this.style.background=''" onclick='POS.selectCustomer(${JSON.stringify(c).replace(/'/g, "&#39;")})'>
                        <div style="font-weight:var(--font-weight-semibold);">${c.name}</div>
                        <div style="font-size:var(--text-caption);color:var(--color-text-muted);">${c.rfc || ''} | ${c.phone || ''} | ${tiers[c.price_tier] || 'P1'} | Credito: ${fmt(c.credit_balance)}/${fmt(c.credit_limit)}</div>
                    </div>`;
                });
                ac.innerHTML = html;
            }
            ac.style.display = 'block';
        } catch (e) {
            console.error('Customer search error:', e);
        }
    }

    function recalcCartPrices() {
        const tier = currentCustomer ? (currentCustomer.price_tier || 1) : 1;
        cart.forEach(item => {
            if (item.price_1 > 0) {
                item.unit_price = tier === 3 ? item.price_3 : tier === 2 ? item.price_2 : item.price_1;
            }
        });
    }

    async function selectCustomer(customer) {
        currentCustomer = customer;
        document.getElementById('customerAutocomplete').style.display = 'none';
        document.getElementById('customerSearchWrap').querySelector('input').style.display = 'none';

        recalcCartPrices();

        const tiers = { 1: 'P1 Mostrador', 2: 'P2 Taller', 3: 'P3 Mayoreo' };
        document.getElementById('customerName').textContent = customer.name;
        document.getElementById('customerTier').textContent = tiers[customer.price_tier] || 'P1';
        document.getElementById('customerCredit').textContent =
            `Credito: ${fmt(customer.credit_balance)} / ${fmt(customer.credit_limit)}`;
        document.getElementById('customerSelected').style.display = '';

        // Show vehicle info banner
        if (customer.vehicle_info && customer.vehicle_info.length > 0) {
            const v = customer.vehicle_info[0];
            document.getElementById('vehicleInfo').textContent =
                `${v.make || ''} ${v.model || ''} ${v.year || ''} ${v.plates ? '(' + v.plates + ')' : ''}`;
            document.getElementById('vehicleBanner').classList.add('visible');
        }

        // Fetch full customer detail
        try {
            const detail = await api(`/pos/api/customers/${customer.id}`);
            if (detail.recent_purchases && detail.recent_purchases.length > 0) {
                const last = detail.recent_purchases[0];
                const daysAgo = Math.floor((Date.now() - new Date(last.created_at).getTime()) / 86400000);
                const daysText = daysAgo === 0 ? 'hoy' : daysAgo === 1 ? 'hace 1 dia' : `hace ${daysAgo} dias`;
                document.getElementById('lastPurchaseInfo').textContent =
                    `${fmt(last.total)} ${daysText}`;
                document.getElementById('vehicleBanner').classList.add('visible');
            }
        } catch (e) {
            console.warn('Could not fetch customer detail:', e);
        }

        // Update CFDI hint
        const cfdiHint = document.getElementById('cfdiHint');
        if (cfdiHint && customer.rfc) {
            cfdiHint.textContent = `RFC: ${customer.rfc}`;
            document.getElementById('cfdiCheck').checked = !!customer.rfc;
        }

        renderCart();
    }

    function clearCustomer() {
        currentCustomer = null;
        document.getElementById('customerSelected').style.display = 'none';
        const searchInput = document.getElementById('customerSearch');
        if (searchInput) {
            searchInput.style.display = '';
            searchInput.value = '';
        }
        document.getElementById('vehicleBanner').classList.remove('visible');
        const cfdiHint = document.getElementById('cfdiHint');
        if (cfdiHint) cfdiHint.textContent = '';
        renderCart();
    }

    // ─── New Customer Modal ──────────────
    function showNewCustomerModal() {
        document.getElementById('newCustomerModal').classList.add('open');
        setTimeout(() => document.getElementById('ncName').focus(), 100);
    }

    function closeNewCustomerModal() {
        document.getElementById('newCustomerModal').classList.remove('open');
    }

    async function saveNewCustomer() {
        const name = document.getElementById('ncName').value.trim();
        if (!name) { alert('Nombre es requerido'); return; }

        const vehicle_info = [];
        const make = document.getElementById('ncVehMake').value.trim();
        if (make) {
            vehicle_info.push({
                make: make,
                model: document.getElementById('ncVehModel').value.trim(),
                year: document.getElementById('ncVehYear').value.trim(),
                plates: document.getElementById('ncVehPlates').value.trim(),
            });
        }

        const body = {
            name: name,
            rfc: document.getElementById('ncRfc').value.trim() || null,
            razon_social: document.getElementById('ncRazonSocial').value.trim() || null,
            regimen_fiscal: document.getElementById('ncRegimenFiscal').value || null,
            uso_cfdi: document.getElementById('ncUsoCfdi').value || 'G03',
            phone: document.getElementById('ncPhone').value.trim() || null,
            email: document.getElementById('ncEmail').value.trim() || null,
            price_tier: parseInt(document.getElementById('ncPriceTier').value) || 1,
            credit_limit: parseFloat(document.getElementById('ncCreditLimit').value) || 0,
            vehicle_info: vehicle_info.length > 0 ? vehicle_info : null,
        };

        try {
            const result = await api('/pos/api/customers', {
                method: 'POST',
                body: JSON.stringify(body),
            });

            selectCustomer({
                id: result.id,
                name: body.name,
                rfc: body.rfc,
                phone: body.phone,
                price_tier: body.price_tier,
                credit_limit: body.credit_limit,
                credit_balance: 0,
                vehicle_info: body.vehicle_info,
            });

            closeNewCustomerModal();
            showToast('Cliente creado');
        } catch (e) {
            alert('Error al crear cliente: ' + e.message);
        }
    }

    // ─── Payment ─────────────────────────
    function checkout() {
        if (cart.length === 0) { showToast('Carrito vacio'); return; }
        if (!currentRegister) { showOpenRegisterModal(); return; }

        paymentMethod = 'efectivo';
        const total = getTotal();

        // Populate modal
        document.getElementById('modalTotal').textContent = fmt(total);
        document.getElementById('modalItemCount').textContent = `${getItemCount()} productos`;
        document.getElementById('modalCustomerName').textContent =
            currentCustomer ? currentCustomer.name : 'Publico General';

        // Reset inputs
        document.getElementById('cashReceived').value = '';
        document.getElementById('changeDisplay').textContent = '$0.00';
        document.getElementById('changeDisplay').className = 'cambio-amount positive';
        const payRef = document.getElementById('paymentRef');
        if (payRef) payRef.value = '';

        // Populate quick amounts
        const quickContainer = document.getElementById('quickAmounts');
        if (quickContainer) {
            const rounded = Math.ceil(total);
            const amounts = [rounded, Math.ceil(total / 100) * 100, Math.ceil(total / 500) * 500, Math.ceil(total / 1000) * 1000];
            const unique = [...new Set(amounts)].slice(0, 4);
            quickContainer.innerHTML = unique.map(a =>
                `<button class="quick-btn" onclick="document.getElementById('cashReceived').value=${a};POS.updateChange();">${fmt(a)}</button>`
            ).join('');
        }

        // Set ref amount
        const refAmount = document.getElementById('refAmount');
        if (refAmount) refAmount.value = fmt(total);

        // Reset payment tabs
        document.querySelectorAll('.pago-tab').forEach(t => t.classList.remove('active'));
        document.querySelector('.pago-tab[data-method="efectivo"]').classList.add('active');
        document.getElementById('cashPayment').classList.add('active');
        document.getElementById('cashPayment').style.display = '';
        document.getElementById('refPayment').classList.remove('active');
        document.getElementById('refPayment').style.display = 'none';
        document.getElementById('mixedPayment').classList.remove('active');
        document.getElementById('mixedPayment').style.display = 'none';

        // Reset confirm button
        const confirmBtn = document.getElementById('btnConfirmPayment');
        confirmBtn.disabled = false;
        confirmBtn.textContent = `Confirmar Pago — ${fmt(total)}`;

        document.getElementById('paymentModal').classList.add('open');
        setTimeout(() => document.getElementById('cashReceived').focus(), 100);
    }

    function selectPaymentMethod(method, btn) {
        paymentMethod = method;

        // Update tabs
        document.querySelectorAll('.pago-tab').forEach(t => t.classList.remove('active'));
        if (btn) btn.classList.add('active');

        // Show/hide tab content
        const tabs = {
            efectivo: 'cashPayment',
            transferencia: 'refPayment',
            tarjeta: 'refPayment',
            mixto: 'mixedPayment',
        };

        ['cashPayment', 'refPayment', 'mixedPayment'].forEach(id => {
            const el = document.getElementById(id);
            if (el) {
                const isActive = el.id === tabs[method];
                el.classList.toggle('active', isActive);
                el.style.display = isActive ? '' : 'none';
            }
        });

        if (method === 'efectivo') document.getElementById('cashReceived').focus();
        if (method === 'transferencia' || method === 'tarjeta') {
            const ref = document.getElementById('paymentRef');
            if (ref) ref.focus();
        }
    }

    function updateChange() {
        const total = getTotal();
        const received = parseFloat(document.getElementById('cashReceived').value) || 0;
        const change = received - total;
        const el = document.getElementById('changeDisplay');
        if (change >= 0) {
            el.textContent = fmt(change);
            el.className = 'cambio-amount positive';
        } else {
            el.textContent = '-' + fmt(Math.abs(change));
            el.className = 'cambio-amount negative';
        }
    }

    function updateMixedTotal() {
        const total = getTotal();
        let sum = 0;
        document.querySelectorAll('.mixed-amount').forEach(input => {
            sum += parseFloat(input.value) || 0;
        });
        const remaining = total - sum;
        const el = document.getElementById('mixedRemaining');
        el.textContent = remaining > 0 ? `Faltante: ${fmt(remaining)}` : `Cubierto (${fmt(sum)})`;
        el.style.color = remaining > 0 ? 'var(--color-error)' : 'var(--color-success)';
    }

    function closePaymentModal() {
        document.getElementById('paymentModal').classList.remove('open');
    }

    async function confirmPayment() {
        const total = getTotal();
        let amountPaid = 0;
        let paymentDetails = [];
        let reference = '';

        if (paymentMethod === 'efectivo') {
            amountPaid = parseFloat(document.getElementById('cashReceived').value) || 0;
            if (amountPaid < total) { alert(`Monto insuficiente. Total: ${fmt(total)}`); return; }
        } else if (paymentMethod === 'transferencia' || paymentMethod === 'tarjeta') {
            amountPaid = total;
            reference = document.getElementById('paymentRef').value.trim();
        } else if (paymentMethod === 'mixto') {
            const rows = document.querySelectorAll('.mixed-row');
            rows.forEach(row => {
                const method = row.querySelector('select').value;
                const amount = parseFloat(row.querySelector('.mixed-amount').value) || 0;
                const ref = row.querySelectorAll('input')[1]?.value || '';
                if (amount > 0) {
                    paymentDetails.push({ method, amount, reference: ref });
                    amountPaid += amount;
                }
            });
            if (amountPaid < total) { alert(`Monto total insuficiente. Falta: ${fmt(total - amountPaid)}`); return; }
        }

        const saleData = {
            items: cart.map(item => ({
                inventory_id: item.inventory_id,
                quantity: item.quantity,
                unit_price: item.unit_price,
                discount_pct: item.discount_pct,
                tax_rate: item.tax_rate,
            })),
            customer_id: currentCustomer ? currentCustomer.id : null,
            payment_method: paymentMethod,
            sale_type: 'cash',
            register_id: currentRegister ? currentRegister.id : null,
            amount_paid: amountPaid,
            payment_details: paymentDetails,
            reference: reference,
            generate_cfdi: document.getElementById('cfdiCheck').checked,
        };

        const confirmBtn = document.getElementById('btnConfirmPayment');
        confirmBtn.disabled = true;
        confirmBtn.textContent = 'Procesando...';

        try {
            const convertQuoteId = localStorage.getItem('pos_convert_quote_id');
            let sale;
            if (convertQuoteId) {
                const convertData = {
                    register_id: currentRegister ? currentRegister.id : null,
                    payment_method: paymentMethod,
                    sale_type: 'cash',
                    amount_paid: amountPaid,
                    payment_details: paymentDetails,
                };
                sale = await api('/pos/api/quotations/' + convertQuoteId + '/convert', {
                    method: 'POST',
                    body: JSON.stringify(convertData),
                });
                localStorage.removeItem('pos_convert_quote_id');
                showToast(`Cotizacion #${convertQuoteId} convertida a venta #${sale.id}`);
            } else {
                sale = await api('/pos/api/sales', {
                    method: 'POST',
                    body: JSON.stringify(saleData),
                });
                showToast(`Venta #${sale.id} completada`);
            }

            lastSaleId = sale.id;
            lastSaleData = sale;
            try { sessionStorage.setItem('pos_last_sale_id', sale.id); } catch(e) {}
            closePaymentModal();
            showTicket(sale);

            // Clear cart
            cart = [];
            selectedRow = -1;
            clearCustomer();
            renderCart();
        } catch (e) {
            alert('Error al procesar venta: ' + e.message);
        } finally {
            confirmBtn.disabled = false;
            confirmBtn.textContent = 'Confirmar Pago';
        }
    }

    // ─── Credit Sale ─────────────────────
    async function creditSale() {
        if (cart.length === 0) { alert('Carrito vacio'); return; }
        if (!currentCustomer) { alert('Seleccione un cliente para venta a credito'); return; }
        if (!currentRegister) { alert('No hay caja abierta.'); return; }

        const total = getTotal();
        const available = (currentCustomer.credit_limit || 0) - (currentCustomer.credit_balance || 0);

        if (currentCustomer.credit_limit > 0 && total > available) {
            if (!confirm(`Credito insuficiente. Disponible: ${fmt(available)}, Total: ${fmt(total)}. Continuar?`)) {
                return;
            }
        }

        const saleData = {
            items: cart.map(item => ({
                inventory_id: item.inventory_id,
                quantity: item.quantity,
                unit_price: item.unit_price,
                discount_pct: item.discount_pct,
                tax_rate: item.tax_rate,
            })),
            customer_id: currentCustomer.id,
            payment_method: 'credito',
            sale_type: 'credit',
            register_id: currentRegister ? currentRegister.id : null,
            amount_paid: 0,
        };

        try {
            const sale = await api('/pos/api/sales', {
                method: 'POST',
                body: JSON.stringify(saleData),
            });

            lastSaleId = sale.id;
            lastSaleData = sale;
            try { sessionStorage.setItem('pos_last_sale_id', sale.id); } catch(e) {}
            showTicket(sale);
            cart = [];
            selectedRow = -1;
            clearCustomer();
            renderCart();
        } catch (e) {
            alert('Error: ' + e.message);
        }
    }

    // ─── Quotation ───────────────────────
    async function saveQuotation() {
        if (cart.length === 0) { showToast('Carrito vacio'); return; }

        const body = {
            items: cart.map(item => ({
                inventory_id: item.inventory_id,
                quantity: item.quantity,
                unit_price: item.unit_price,
                discount_pct: item.discount_pct,
                tax_rate: item.tax_rate,
            })),
            customer_id: currentCustomer ? currentCustomer.id : null,
        };

        const editQuoteId = localStorage.getItem('pos_edit_quote_id');

        try {
            if (editQuoteId) {
                const result = await api('/pos/api/quotations/' + editQuoteId, {
                    method: 'PUT',
                    body: JSON.stringify(body),
                });
                localStorage.removeItem('pos_edit_quote_id');
                localStorage.removeItem('pos_edit_quote_customer_id');
                localStorage.removeItem('pos_edit_quote_notes');
                showToast(`Cotizacion #${editQuoteId} actualizada. Total: ${fmt(result.total)}`);
            } else {
                const result = await api('/pos/api/quotations', {
                    method: 'POST',
                    body: JSON.stringify(body),
                });
                showToast(`Cotizacion #${result.id} guardada. Total: ${fmt(result.total)}`);
            }
        } catch (e) {
            alert('Error: ' + e.message);
        }
    }

    // ─── Layaway ─────────────────────────
    async function createLayaway() {
        if (!canCreateLayaway) { showToast('No tienes permiso para crear apartados'); return; }
        if (cart.length === 0) { alert('Carrito vacio'); return; }
        if (!currentCustomer) { alert('Seleccione un cliente para apartado'); return; }

        const total = getTotal();
        const initialPayment = prompt(`Total: ${fmt(total)}\nIngrese monto del anticipo:`);
        if (!initialPayment) return;

        const amount = parseFloat(initialPayment);
        if (isNaN(amount) || amount <= 0) { alert('Monto invalido'); return; }
        if (amount > total) { alert('El anticipo no puede exceder el total'); return; }

        const body = {
            items: cart.map(item => ({
                inventory_id: item.inventory_id,
                quantity: item.quantity,
                unit_price: item.unit_price,
                discount_pct: item.discount_pct,
                tax_rate: item.tax_rate,
            })),
            customer_id: currentCustomer.id,
            initial_payment: amount,
            payment_method: 'efectivo',
            register_id: currentRegister ? currentRegister.id : null,
        };

        try {
            const result = await api('/pos/api/layaways', {
                method: 'POST',
                body: JSON.stringify(body),
            });
            showToast(`Apartado #${result.id} creado. Restante: ${fmt(result.remaining)}`);
            cart = [];
            selectedRow = -1;
            clearCustomer();
            renderCart();
        } catch (e) {
            alert('Error: ' + e.message);
        }
    }

    // ─── Service Order from POS ──────────
    function createServiceOrder() {
        if (!canCreateWorkshopOrder) { showToast('No tienes permiso para ordenes de taller'); return; }
        if (cart.length === 0) { showToast('Carrito vacio'); return; }
        const custInput = document.getElementById('soCustomer');
        if (custInput) custInput.value = currentCustomer ? currentCustomer.name : 'Publico General';
        document.getElementById('serviceOrderModal').classList.add('open');
    }

    function closeServiceOrderModal() {
        document.getElementById('serviceOrderModal').classList.remove('open');
    }

    async function confirmServiceOrder() {
        const customerId = currentCustomer ? currentCustomer.id : null;
        if (!customerId) { alert('Seleccione un cliente para la orden de servicio'); return; }

        const vehicleText = document.getElementById('soVehicle').value.trim();
        const delivery = document.getElementById('soDelivery').value;
        const notes = document.getElementById('soNotes').value.trim();
        const isDirect = document.getElementById('soDirect').checked;

        const items = cart.map(item => ({
            inventory_id: item.inventory_id,
            part_number: item.part_number,
            name: item.name,
            quantity: item.quantity,
            unit_price: item.unit_price,
            status: 'pending'
        }));

        try {
            const order = await api('/pos/api/service-orders/from-pos', {
                method: 'POST',
                body: JSON.stringify({
                    customer_id: customerId,
                    priority: 'normal',
                    reception_notes: (vehicleText ? 'Vehiculo: ' + vehicleText + '. ' : '') + (notes || ''),
                    delivery_method: delivery || null,
                    is_direct: isDirect,
                    items: items
                })
            });

            showToast(`Orden de servicio ${order.order_number} creada`);
            closeServiceOrderModal();
            cart = [];
            selectedRow = -1;
            renderCart();
            showServiceOrderTicket(order);
        } catch (e) {
            alert('Error: ' + e.message);
        }
    }

    function showServiceOrderTicket(order) {
        const dateStr = new Date(order.created_at).toLocaleString('es-MX', {
            year: 'numeric', month: 'short', day: 'numeric',
            hour: '2-digit', minute: '2-digit'
        });

        const customerName = order.customer_name || (currentCustomer ? currentCustomer.name : 'Publico General');
        let itemsHtml = '';
        (order.items || []).forEach(item => {
            const itemTotal = item.unit_price * item.quantity;
            itemsHtml += `
                <div class="item-line-wide ticket-line">
                    <span class="qty">${item.quantity}</span>
                    <span class="name">${item.name || ''}</span>
                    <span class="price">${fmt(item.unit_price)}</span>
                    <span class="subtotal">${fmt(itemTotal)}</span>
                </div>`;
        });

        const ticketHtml = `
            <div class="store-name">NEXUS AUTOPARTS</div>
            <div class="store-tagline">Orden de servicio</div>
            <div class="store-info">
                Sucursal: ${currentRegister ? currentRegister.branch_name || '' : ''}<br>
                RFC: NAU210315XX1
            </div>
            <hr class="divider-double">
            <div class="folio-line">
                <span>ORDEN: ${order.order_number}</span>
                <span>${dateStr}</span>
            </div>
            <div class="ticket-row" style="font-size: 9px; color: #555; margin-bottom: 4px;">
                <span>Cliente: ${customerName}</span>
            </div>
            <hr class="divider">
            <div class="item-line-wide" style="font-weight: bold; font-size: 9px; color: #555; text-transform: uppercase;">
                <span class="qty">Cant</span>
                <span class="name">Descripcion</span>
                <span class="price">P. Unit</span>
                <span class="subtotal">Importe</span>
            </div>
            <hr class="divider" style="margin: 2px 0;">
            ${itemsHtml}
            <hr class="divider-double">
            <div class="total-section">
                <div class="total-line">
                    <span>Refacciones:</span><span>${fmt(order.total_parts || 0)}</span>
                </div>
                <div class="total-line">
                    <span>Mano de obra:</span><span>${fmt(order.total_labor || 0)}</span>
                </div>
                <div class="total-line grand">
                    <span>TOTAL:</span><span>${fmt(order.total || 0)}</span>
                </div>
            </div>
            <hr class="divider">
            <div class="footer-section">
                <div class="thanks">Gracias por su preferencia!</div>
                <div>Conserve su ticket como comprobante.</div>
            </div>
        `;

        const printArea = document.getElementById('ticketContent');
        if (printArea) printArea.innerHTML = ticketHtml;
        const preview = document.getElementById('ticketPreviewContent');
        if (preview) preview.innerHTML = ticketHtml;
        const modalHeader = document.querySelector('#ticketModal .modal-header h3');
        if (modalHeader) modalHeader.textContent = 'Ticket de Orden de Servicio';
        document.getElementById('ticketModal').classList.add('open');
    }

    // ─── Ticket ──────────────────────────
    function showTicket(sale) {
        const dateStr = new Date(sale.created_at).toLocaleString('es-MX', {
            year: 'numeric', month: 'short', day: 'numeric',
            hour: '2-digit', minute: '2-digit'
        });

        const customerName = currentCustomer ? currentCustomer.name : 'Publico General';
        const customerRfc = currentCustomer && currentCustomer.rfc ? currentCustomer.rfc : '';

        let itemsHtml = '';
        (sale.items || []).forEach(item => {
            const itemTotal = (item.unit_price * item.quantity * (1 - (item.discount_pct || 0) / 100));
            itemsHtml += `
                <div class="item-line-wide ticket-line">
                    <span class="qty">${item.quantity}</span>
                    <span class="name">${item.name || ''}</span>
                    <span class="price">${fmt(item.unit_price)}</span>
                    <span class="subtotal">${fmt(item.subtotal || itemTotal)}</span>
                </div>`;
        });

        const cfg = receiptConfig || {};
        const showLogo = cfg.show_logo && cfg.logo;
        const showRfc = cfg.show_rfc !== false;
        const showAddress = cfg.show_address;
        const showPhone = cfg.show_phone;
        const showIva = cfg.show_iva_breakdown !== false;
        const showPayment = cfg.show_payment_details !== false;
        const showEmployee = cfg.show_employee;
        const storeName = rc('store_name', 'NEXUS AUTOPARTS');
        const storeTagline = rc('tagline', 'Tu conexion con las refacciones');
        const storeRfc = rc('rfc', 'NAU210315XX1');
        const storeAddress = rc('address', '');
        const storePhone = rc('phone', '');
        const thanksMsg = rc('thanks_message', 'Gracias por su compra!');
        const footerMsg = rc('footer', 'Conserve su ticket como comprobante.');

        let storeInfoLines = [];
        if (currentRegister && currentRegister.branch_name) storeInfoLines.push(`Sucursal: ${currentRegister.branch_name}`);
        if (showEmployee && sale.employee_name) storeInfoLines.push(`Atendió: ${sale.employee_name}`);
        if (showRfc && storeRfc) storeInfoLines.push(`RFC: ${storeRfc}`);
        if (showAddress && storeAddress) storeInfoLines.push(storeAddress);
        if (showPhone && storePhone) storeInfoLines.push(`Tel: ${storePhone}`);

        const logoHtml = showLogo ? `<div class="ticket-logo-wrap"><img src="${cfg.logo}" alt="Logo" class="ticket-logo" style="max-width:140px;max-height:70px;object-fit:contain;"></div>` : '';

        const ticketHtml = `
            ${logoHtml}
            <div class="store-name">${storeName}</div>
            ${storeTagline ? `<div class="store-tagline">${storeTagline}</div>` : ''}
            <div class="store-info">
                ${storeInfoLines.join('<br>')}
            </div>
            <hr class="divider-double">
            <div class="folio-line">
                <span>VENTA: V-${sale.id}</span>
                <span>${dateStr}</span>
            </div>
            <div class="ticket-row" style="font-size: 9px; color: #555; margin-bottom: 4px;">
                <span>Cliente: ${customerName}</span>
                ${customerRfc ? `<span>RFC: ${customerRfc}</span>` : ''}
            </div>
            <hr class="divider">
            <div class="item-line-wide" style="font-weight: bold; font-size: 9px; color: #555; text-transform: uppercase;">
                <span class="qty">Cant</span>
                <span class="name">Descripcion</span>
                <span class="price">P. Unit</span>
                <span class="subtotal">Importe</span>
            </div>
            <hr class="divider" style="margin: 2px 0;">
            ${itemsHtml}
            <hr class="divider-double">
            <div class="total-section">
                <div class="total-line">
                    <span>Subtotal:</span><span>${fmt(sale.subtotal)}</span>
                </div>
                ${sale.discount_total > 0 ? `<div class="total-line"><span>Descuento:</span><span>-${fmt(sale.discount_total)}</span></div>` : ''}
                ${showIva ? `<div class="total-line"><span>IVA:</span><span>${fmt(sale.tax_total)}</span></div>` : ''}
                <div class="total-line grand">
                    <span>TOTAL:</span><span>${fmt(sale.total)}</span>
                </div>
            </div>
            ${showPayment ? `
            <hr class="divider">
            <div class="payment-section">
                <div class="ticket-row">
                    <span>Forma de pago:</span><span>${sale.payment_method || paymentMethod}</span>
                </div>
                ${sale.payment_method === 'efectivo' ? `
                <div class="ticket-row">
                    <span>Recibido:</span><span>${fmt(sale.amount_paid)}</span>
                </div>
                <div class="ticket-row" style="font-weight: bold;">
                    <span>Cambio:</span><span>${fmt(sale.change_given || 0)}</span>
                </div>` : ''}
            </div>` : ''}
            <hr class="divider">
            <div class="footer-section">
                <div class="thanks">${thanksMsg}</div>
                ${footerMsg ? `<div>${footerMsg}</div>` : ''}
            </div>
        `;

        // Set both print area and preview
        const printArea = document.getElementById('ticketContent');
        if (printArea) printArea.innerHTML = ticketHtml;
        const preview = document.getElementById('ticketPreviewContent');
        if (preview) preview.innerHTML = ticketHtml;
        const modalHeader = document.querySelector('#ticketModal .modal-header h3');
        if (modalHeader) modalHeader.textContent = 'Ticket de Venta';

        document.getElementById('ticketModal').classList.add('open');
    }

    function closeTicketModal() {
        document.getElementById('ticketModal').classList.remove('open');
    }

    function printTicket() {
        // Make print area visible for @media print
        const area = document.getElementById('ticketPrintArea');
        if (area) area.style.display = 'block';
        window.print();
        setTimeout(() => { if (area) area.style.display = 'none'; }, 500);
    }

    // ─── Thermal Printing ─────────────────

    async function connectThermal() {
        if (!window.NexusPrinter) { showToast('Printer module not loaded'); return; }
        const result = await NexusPrinter.connect();
        if (result.ok) {
            showToast('Impresora conectada: ' + (result.name || result.type));
            _updatePrinterButtons();
        } else {
            showToast(result.error || 'No se pudo conectar la impresora');
        }
    }

    async function thermalPrint() {
        if (!window.NexusPrinter || !NexusPrinter.isConnected()) {
            showToast('Conecte una impresora termica primero');
            return;
        }
        if (!lastSaleId) { showToast('No hay venta para imprimir'); return; }
        const ok = await NexusPrinter.printSale(lastSaleId);
        if (ok) {
            showToast('Ticket enviado a impresora termica');
        } else {
            showToast('Error al imprimir. Reconecte la impresora.');
        }
    }

    function _updatePrinterButtons() {
        const connectBtn = document.getElementById('btnConnectPrinter');
        const thermalBtn = document.getElementById('btnThermalPrint');
        if (window.NexusPrinter && NexusPrinter.isConnected()) {
            if (connectBtn) connectBtn.style.display = 'none';
            if (thermalBtn) thermalBtn.style.display = '';
        } else {
            if (connectBtn) connectBtn.style.display = '';
            if (thermalBtn) thermalBtn.style.display = 'none';
        }
    }

    // ─── Last Sale ───────────────────────
    async function showLastSale() {
        if (!lastSaleId) { showToast('No hay venta reciente'); return; }
        try {
            const sale = await api(`/pos/api/sales/${lastSaleId}`);
            showTicket(sale);
        } catch (e) {
            alert('Error: ' + e.message);
        }
    }

    // ─── Drawer ──────────────────────────
    function openDrawer() {
        showToast('Comando enviado al cajon de efectivo.');
    }

    // ─── Keyboard Shortcuts ──────────────
    function setupKeyboard() {
        document.addEventListener('keydown', (e) => {
            const tag = e.target.tagName;
            const inInput = tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';

            switch (e.key) {
                case 'F1':
                    e.preventDefault();
                    document.getElementById('itemSearch').focus();
                    break;
                case 'F2':
                    e.preventDefault();
                    document.getElementById('customerSearch').focus();
                    document.getElementById('customerSearch').style.display = '';
                    document.getElementById('customerSelected').style.display = 'none';
                    break;
                case 'F3':
                    e.preventDefault();
                    checkout();
                    break;
                case 'F4':
                    e.preventDefault();
                    saveQuotation();
                    break;
                case 'F5':
                    e.preventDefault();
                    showLastSale();
                    break;
                case 'F6':
                    e.preventDefault();
                    openDrawer();
                    break;
                case 'F7':
                    e.preventDefault();
                    createServiceOrder();
                    break;
                case 'Escape':
                    e.preventDefault();
                    if (document.getElementById('paymentModal').classList.contains('open')) {
                        closePaymentModal();
                    } else if (document.getElementById('newCustomerModal').classList.contains('open')) {
                        closeNewCustomerModal();
                    } else if (document.getElementById('ticketModal').classList.contains('open')) {
                        closeTicketModal();
                    } else if (document.getElementById('serviceOrderModal').classList.contains('open')) {
                        closeServiceOrderModal();
                    } else if (document.querySelector('.confirm-overlay.active')) {
                        // Close cancel modal
                        const overlay = document.getElementById('overlay-cancelar-venta');
                        const dialog = document.getElementById('modal-cancelar-venta');
                        if (overlay && overlay.classList.contains('active')) {
                            overlay.classList.remove('active');
                            dialog.classList.remove('active');
                        }
                    } else {
                        hideSearchResults();
                    }
                    break;
                case 'Delete':
                    if (!inInput && selectedRow >= 0 && selectedRow < cart.length) {
                        e.preventDefault();
                        removeFromCart(selectedRow);
                    }
                    break;
                case '+':
                    if (!inInput && selectedRow >= 0 && selectedRow < cart.length) {
                        e.preventDefault();
                        cart[selectedRow].quantity++;
                        renderCart();
                    }
                    break;
                case '-':
                    if (!inInput && selectedRow >= 0 && selectedRow < cart.length) {
                        e.preventDefault();
                        if (cart[selectedRow].quantity > 1) {
                            cart[selectedRow].quantity--;
                            renderCart();
                        }
                    }
                    break;
                case '*':
                    if (!inInput && selectedRow >= 0 && selectedRow < cart.length) {
                        e.preventDefault();
                        const disc = prompt('Descuento %:', cart[selectedRow].discount_pct);
                        if (disc !== null) {
                            updateDiscount(selectedRow, disc);
                        }
                    }
                    break;
                case 'ArrowUp':
                    if (!inInput && cart.length > 0) {
                        e.preventDefault();
                        selectedRow = Math.max(0, selectedRow - 1);
                        renderCart();
                    }
                    break;
                case 'ArrowDown':
                    if (!inInput && cart.length > 0) {
                        e.preventDefault();
                        selectedRow = Math.min(cart.length - 1, selectedRow + 1);
                        renderCart();
                    }
                    break;
                case 'Enter':
                    if (e.target.id === 'cashReceived') {
                        e.preventDefault();
                        confirmPayment();
                    }
                    break;
            }
        });
    }

    // Register Cmd+K items
    if (typeof registerCmdKItem === "function") {
        registerCmdKItem({ group: "Principal", label: "POS Ventas", href: "/pos/sale", icon: "🛒" });
        registerCmdKItem({ group: "Principal", label: "Catálogo", href: "/pos/catalog", icon: "📁" });
        registerCmdKItem({ group: "Principal", label: "Clientes", href: "/pos/customers", icon: "👤" });
        registerCmdKItem({ group: "Principal", label: "Dashboard", href: "/pos/dashboard", icon: "📊" });
    }

    // ─── Public API ──────────────────────
    init();

    return {
        addToCart, removeFromCart, clearCart, selectRow,
        updateQty, updateDiscount,
        addFromSearch, hideSearchResults,
        selectCustomer, clearCustomer,
        showNewCustomerModal, closeNewCustomerModal, saveNewCustomer,
        checkout, confirmPayment, closePaymentModal,
        selectPaymentMethod, updateChange, updateMixedTotal,
        creditSale, saveQuotation, createLayaway,
        createServiceOrder, closeServiceOrderModal, confirmServiceOrder, showServiceOrderTicket,
        showLastSale, openDrawer,
        showTicket, closeTicketModal, printTicket,
        connectThermal, thermalPrint,
        showOpenRegisterModal, closeOpenRegisterModal, openRegister,
        showCutZModal, closeCutZModal, loadCutX, confirmCutZ,
        openCancelModal, closeCancelModal, changeQuantity, applyDiscount, modifyPrice,
    };

})();
