// /home/Autopartes/pos/static/js/catalog.js
// Catalog UI: TecDoc vehicle navigation with local stock enrichment, cart, detail panel.

(function () {
    'use strict';

    var API = '/pos/api/catalog';
    var token = localStorage.getItem('pos_token');
    if (!token) { window.location.href = '/pos/login'; return; }

    var headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' };

    // ─── DOM refs ───
    var breadcrumb    = document.getElementById('breadcrumb');
    var searchInput   = document.getElementById('searchInput');
    var searchDropdown = document.getElementById('searchDropdown');
    var levelTitle    = document.getElementById('levelTitle');
    var levelFilter   = document.getElementById('levelFilter');
    var loading       = document.getElementById('loading');
    var emptyState    = document.getElementById('emptyState');
    var emptyTitle    = document.getElementById('emptyTitle');
    var emptySubtitle = document.getElementById('emptySubtitle');
    var navGrid       = document.getElementById('navGrid');
    var partsGrid     = document.getElementById('partsGrid');
    var paginationNav = document.getElementById('pagination');
    var pageBody      = document.getElementById('pageBody');
    // Detail panel
    var detailPanel   = document.getElementById('detailPanel');
    var detailOverlay = document.getElementById('detailOverlay');
    var detailBody    = document.getElementById('detailBody');
    var detailFooter  = document.getElementById('detailFooter');
    var detailClose   = document.getElementById('detailClose');
    var qtyMinus      = document.getElementById('qtyMinus');
    var qtyPlus       = document.getElementById('qtyPlus');
    var qtyDisplay    = document.getElementById('qtyDisplay');
    var addToCartBtn  = document.getElementById('addToCartBtn');
    // Cart
    var cartSidebar   = document.getElementById('cartSidebar');
    var cartOverlay   = document.getElementById('cartOverlay');
    var cartItemsEl   = document.getElementById('cartItems');
    var cartEmptyEl   = document.getElementById('cartEmpty');
    var cartSubtotalEl= document.getElementById('cartSubtotal');
    var cartTaxEl     = document.getElementById('cartTax');
    var cartTotalEl   = document.getElementById('cartTotal');
    var cartBadge     = document.getElementById('cartBadge');
    var checkoutBtn   = document.getElementById('checkoutBtn');
    var cartFab       = document.getElementById('cartFab');
    var cartCloseBtn  = document.getElementById('cartCloseBtn');
    // Supplier prices upload
    var uploadPricesBtn  = document.getElementById('uploadPricesBtn');
    var uploadPricesModal= document.getElementById('uploadPricesModal');
    var uploadPricesFile = document.getElementById('uploadPricesFile');
    var uploadPricesStatus=document.getElementById('uploadPricesStatus');

    // ─── Navigation State ───
    var nav = {
        level: 'brands',  // brands|models|years|engines|categories|groups|part_types|parts
        brand: null,       // {id, name}
        model: null,       // {id, name}
        year: null,        // {id, year}
        engine: null,      // {id_mye, name}

        // OEM mode (TecDoc) navigation state — integer IDs
        category: null,    // {id, name}
        group: null,       // {id, name}
        partType: null,    // {slug, name}  ← 3rd-level subcategory (Nexpart-style)

        // Local mode (Nexpart) navigation state — string slugs.
        // These live in parallel with category/group/partType so transitioning
        // between modes doesn't trash the other branch's state.
        nxGroup: null,     // {slug, name}  ← top-level Nexpart group (14 total)
        nxSubgroup: null,  // {slug, name}  ← Nexpart subgroup
        nxPartType: null,  // {slug, name}  ← Nexpart part type (3rd level)
    };

    // ─── Catalog mode (OEM / Local) ───
    // OEM catalog is disabled until fully completed — force local mode
    var catalogMode = 'local';
    localStorage.setItem('catalog_mode', 'local');

    function updateModeToggleUI() {
        var btns = document.querySelectorAll('#modeToggle button');
        btns.forEach(function (b) {
            if (b.getAttribute('data-mode') === catalogMode) {
                b.classList.add('is-active');
            } else {
                b.classList.remove('is-active');
            }
        });
    }

    function setCatalogMode(mode) {
        if (mode !== 'oem' && mode !== 'local' && mode !== 'supplies') return;
        if (mode === 'oem') {
            // OEM catalog is disabled until fully completed
            alert('Catálogo OEM próximamente. Por favor usa el modo Local o Shop Supplies.');
            return;
        }
        if (mode === catalogMode) return;
        catalogMode = mode;
        localStorage.setItem('catalog_mode', mode);
        updateModeToggleUI();

        // Clear category-and-below state regardless of mode
        nav.category = nav.group = nav.partType = null;
        nav.nxGroup = nav.nxSubgroup = nav.nxPartType = null;
        currentPage = 1;

        if (mode === 'supplies') {
            // Supplies mode skips the vehicle chain entirely.
            // Clear the vehicle state for visual clarity and go directly
            // to the Shop Supplies top-level group list.
            try { vsClearAll(); } catch (e) {}
            nav.brand = nav.model = nav.year = nav.engine = null;
            nav.level = 'categories';
            loadShopSuppliesGroups();
            return;
        }

        // OEM/Local: smart reset — if the user already picked a vehicle,
        // stay at the categories level. Otherwise reset to brand selection.
        var hasVehicle = !!(nav.engine && nav.engine.id_mye);
        if (hasVehicle) {
            nav.level = 'categories';
            loadCategoriesForMode();
            return;
        }

        try { vsClearAll(); } catch (e) {}
        nav.level = 'brands';
        nav.brand = nav.model = nav.year = nav.engine = null;
        loadBrands();
    }

    var currentPage = 1;
    var currentDetailPart = null;
    var detailQty = 1;
    var isOffline = false;
    var skipPush = false; // flag to avoid pushing state on popstate

    // ─── Browser History Management ───
    function pushNavState() {
        if (skipPush) return;
        var s = JSON.parse(JSON.stringify(nav));
        s.page = currentPage;
        history.pushState(s, '', '/pos/catalog');
    }

    window.addEventListener('popstate', function (e) {
        if (e.state) {
            skipPush = true;
            nav.level = e.state.level || 'brands';
            nav.brand = e.state.brand;
            nav.model = e.state.model;
            nav.year = e.state.year;
            nav.engine = e.state.engine;
            nav.category = e.state.category;
            nav.group = e.state.group;
            nav.partType = e.state.partType || null;
            nav.nxGroup = e.state.nxGroup || null;
            nav.nxSubgroup = e.state.nxSubgroup || null;
            nav.nxPartType = e.state.nxPartType || null;
            currentPage = e.state.page || 1;

            // Reload the correct level
            if (nav.level === 'brands') loadBrands();
            else if (nav.level === 'models') loadModels();
            else if (nav.level === 'years') loadYears();
            else if (nav.level === 'engines') loadEngines();
            // When restoring from history, dispatch between OEM and Nexpart
            // based on which branch of state is populated — this survives
            // toggle changes made mid-session.
            else if (nav.level === 'categories') loadCategoriesForMode();
            else if (nav.level === 'groups') {
                if (nav.nxGroup) loadNexpartSubgroups(); else loadGroups();
            }
            else if (nav.level === 'part_types') {
                if (nav.nxSubgroup) loadNexpartPartTypes(); else loadPartTypes();
            }
            else if (nav.level === 'parts') loadParts(currentPage);
            else loadBrands();

            skipPush = false;
        }
    });

    // Push initial state
    history.replaceState(JSON.parse(JSON.stringify(nav)), '', '/pos/catalog');

    // ─── Cart State ───
    var cartItems = JSON.parse(localStorage.getItem('pos_cart') || '[]');

    // ─── API helper ───
    var currentAbort = null;

    function apiFetch(url) {
        // Cancel previous navigation/search GETs to avoid race conditions
        if (currentAbort) {
            currentAbort.abort();
            currentAbort = null;
        }
        var opts = { headers: headers };
        var isCatalogNav = url.indexOf('/pos/api/') === 0 && (
            url.indexOf('mode=') !== -1 ||
            url.indexOf('/years') !== -1 ||
            url.indexOf('/brands') !== -1 ||
            url.indexOf('/models') !== -1 ||
            url.indexOf('/engines') !== -1 ||
            url.indexOf('/categories') !== -1 ||
            url.indexOf('/groups') !== -1 ||
            url.indexOf('/part-types') !== -1 ||
            url.indexOf('/parts') !== -1 ||
            url.indexOf('/search') !== -1
        );
        if (isCatalogNav) {
            currentAbort = new AbortController();
            opts.signal = currentAbort.signal;
        }
        return fetch(url, opts)
            .then(function (resp) {
                if (resp.status === 401) {
                    localStorage.removeItem('pos_token');
                    window.location.href = '/pos/login';
                    return null;
                }
                return resp.json();
            })
            .catch(function (e) {
                if (e.name === 'AbortError') return null;
                console.error('API error:', e);
                return null;
            });
    }

    // ─── UI helpers ───
    function showLoading() { loading.classList.add('is-visible'); navGrid.innerHTML = ''; partsGrid.style.display = 'none'; partsGrid.innerHTML = ''; emptyState.classList.remove('is-visible'); paginationNav.innerHTML = ''; var dl = document.getElementById('diagLink'); if (dl && nav.level !== 'categories') dl.style.display = 'none'; }
    function hideLoading() { loading.classList.remove('is-visible'); }

    function showEmpty(title, subtitle) {
        emptyTitle.textContent = title;
        emptySubtitle.textContent = subtitle || '';
        emptyState.classList.add('is-visible');
        navGrid.innerHTML = '';
        partsGrid.style.display = 'none';
    }

    function fmt(n) { return (parseFloat(n) || 0).toFixed(2); }

    function esc(s) {
        if (!s) return '';
        var d = document.createElement('div');
        d.textContent = s;
        return d.innerHTML.replace(/"/g, '&quot;');
    }

    // ─── Breadcrumb ───
    function updateBreadcrumb() {
        var parts = [];
        parts.push({ label: 'Catalogo', action: 'loadBrands' });

        if (nav.brand) parts.push({ label: nav.brand.name, action: 'loadModels' });
        if (nav.model) parts.push({ label: nav.model.name, action: 'loadYears' });
        if (nav.year) parts.push({ label: String(nav.year.year), action: 'loadEngines' });
        if (nav.engine) parts.push({ label: nav.engine.name, action: 'loadCategories' });

        // The category/group/part_type trio is rendered from EITHER the Nexpart
        // branch (nxGroup/nxSubgroup/nxPartType) or the OEM branch (category/
        // group/partType), depending on which is populated. Only one branch
        // should be active at a time after a navigation reset.
        if (nav.nxGroup) parts.push({ label: nav.nxGroup.name, action: 'loadNxSubgroups' });
        else if (nav.category) parts.push({ label: nav.category.name, action: 'loadGroups' });

        if (nav.nxSubgroup) parts.push({ label: nav.nxSubgroup.name, action: 'loadNxPartTypes' });
        else if (nav.group) parts.push({ label: nav.group.name, action: 'loadPartTypes' });

        if (nav.nxPartType) parts.push({ label: nav.nxPartType.name, action: null });
        else if (nav.partType) parts.push({ label: nav.partType.name, action: null });

        //Botón para retroceder
        var backAction = null;
        if (parts.length > 1) {
            var prev = parts[parts.length - 2];
            backAction = prev ? prev.action : 'loadBrands';
        }

        var html = '';
        //Botón para retroceder
        if (backAction) {
            html += '<button class="breadcrumb__back" data-bc-action="' + backAction + '">&#8592; Atr&aacute;s</button>';
            html += '<span class="breadcrumb__sep" aria-hidden="true">|</span>';
        }
        //--------
        for (var i = 0; i < parts.length; i++) {
            if (i > 0) html += '<span class="breadcrumb__sep" aria-hidden="true">/</span>';
            if (i < parts.length - 1 && parts[i].action) {
                html += '<a class="breadcrumb__link" data-bc-action="' + parts[i].action + '">' + esc(parts[i].label) + '</a>';
            } else {
                html += '<span class="breadcrumb__current">' + esc(parts[i].label) + '</span>';
            }
        }
        breadcrumb.innerHTML = html;

        // Wire breadcrumb clicks
        breadcrumb.querySelectorAll('[data-bc-action]').forEach(function (el) {
            el.addEventListener('click', function () {
                var action = this.dataset.bcAction;
                if (action === 'loadBrands') { resetNav(); loadBrands(); }
                else if (action === 'loadModels') { resetNavFrom('models'); loadModels(); }
                else if (action === 'loadYears') { resetNavFrom('years'); loadYears(); }
                else if (action === 'loadEngines') { resetNavFrom('engines'); loadEngines(); }
                else if (action === 'loadCategories') { resetNavFrom('categories'); loadCategoriesForMode(); }
                else if (action === 'loadGroups') { resetNavFrom('groups'); loadGroups(); }
                else if (action === 'loadPartTypes') { resetNavFrom('part_types'); loadPartTypes(); }
                // Nexpart-branch breadcrumb actions
                else if (action === 'loadNxSubgroups') { resetNavFrom('groups'); loadNexpartSubgroups(); }
                else if (action === 'loadNxPartTypes') { resetNavFrom('part_types'); loadNexpartPartTypes(); }
            });
        });

    }

    function resetNav() {
        nav.level = 'brands';
        nav.brand = nav.model = nav.year = nav.engine = nav.category = nav.group = nav.partType = null;
        nav.nxGroup = nav.nxSubgroup = nav.nxPartType = null;
        pushNavState();
    }

    function resetNavFrom(level) {
        var levels = ['brands', 'models', 'years', 'engines', 'categories', 'groups', 'part_types', 'parts'];
        var idx = levels.indexOf(level);
        if (idx <= 0) { resetNav(); return; }
        nav.level = level;
        // For each level, the corresponding state key(s) to clear.
        // In Local mode, 'categories' clears nxGroup, 'groups' clears nxSubgroup, etc.
        // We clear BOTH mode-specific keys at each level so a mode switch mid-navigation
        // is always clean.
        var keys = [
            null,                             // brands (nothing to clear above)
            ['model'],                        // models
            ['year'],                         // years
            ['engine'],                       // engines
            ['category', 'nxGroup'],          // categories  ← both OEM + Nexpart
            ['group', 'nxSubgroup'],          // groups       ← both OEM + Nexpart
            ['partType', 'nxPartType'],       // part_types   ← both OEM + Nexpart
            null,                             // parts
        ];
        for (var i = idx; i < keys.length; i++) {
            if (!keys[i]) continue;
            var ks = keys[i];
            for (var j = 0; j < ks.length; j++) nav[ks[j]] = null;
        }
    }

    // ─── Level filter ───
    function setupLevelFilter(show) {
        if (!show) { levelFilter.style.display = 'none'; levelFilter.value = ''; return; }
        levelFilter.style.display = '';
        levelFilter.value = '';
        levelFilter.oninput = function () {
            var q = this.value.toLowerCase();
            var cards = navGrid.querySelectorAll('.nav-card');
            cards.forEach(function (card) {
                var text = card.textContent.toLowerCase();
                card.style.display = text.indexOf(q) >= 0 ? '' : 'none';
            });
        };
    }

    // ─── LEVEL LOADERS ───

    function loadBrands() {
        nav.level = 'brands';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = 'Selecciona una marca';
        setupLevelFilter(true);
        showLoading();

        var cacheKey = 'nexus:brands:' + catalogMode;
        var cached = sessionStorage.getItem(cacheKey);
        if (cached) {
            try {
                hideLoading();
                var data = JSON.parse(cached);
                renderBrands(data);
                return;
            } catch (e) {
                sessionStorage.removeItem(cacheKey);
            }
        }

        apiFetch(API + '/brands?mode=' + catalogMode).then(function (data) {
            hideLoading();
            if (data && data.data) sessionStorage.setItem(cacheKey, JSON.stringify(data));
            if (!data || !data.data || !data.data.length) {
                if (!data) {
                    enterOfflineMode();
                    return;
                }
                showEmpty('Sin marcas', 'El catalogo no tiene marcas con partes disponibles.');
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (b) {
                return '<div class="nav-card" role="listitem" data-brand-id="' + b.id_brand + '" data-name="' + esc(b.name_brand) + '">' +
                    '<div class="nav-card__name">' + esc(b.name_brand) + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.brand = { id: parseInt(this.dataset.brandId), name: this.dataset.name };
                    loadModels();
                });
            });
        });
    }

    function renderBrands(data) {
        if (!data || !data.data || !data.data.length) {
            if (!data) {
                enterOfflineMode();
                return;
            }
            showEmpty('Sin marcas', 'El catalogo no tiene marcas con partes disponibles.');
            return;
        }
        navGrid.className = 'nav-grid';
        navGrid.innerHTML = data.data.map(function (b) {
            return '<div class="nav-card" role="listitem" data-brand-id="' + b.id_brand + '" data-name="' + esc(b.name_brand) + '">' +
                '<div class="nav-card__name">' + esc(b.name_brand) + '</div>' +
                '</div>';
        }).join('');

        navGrid.querySelectorAll('.nav-card').forEach(function (card) {
            card.addEventListener('click', function () {
                nav.brand = { id: parseInt(this.dataset.brandId), name: this.dataset.name };
                loadModels();
            });
        });
    }

    function modelIdsParam(model) {
        if (!model) return '';
        if (model.variant_ids && model.variant_ids.length) return model.variant_ids.join(',');
        return String(model.id);
    }

    function loadModels() {
        nav.level = 'models';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = 'Modelos de ' + nav.brand.name;
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/models?brand_id=' + nav.brand.id).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin modelos', 'No hay modelos con partes para ' + nav.brand.name); return; }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (m) {
                return '<div class="nav-card" role="listitem" data-model-id="' + m.id_model + '" data-variant-ids="' + esc((m.variant_ids || [m.id_model]).join(',')) + '" data-name="' + esc(m.display_name || m.name_model) + '">' +
                    '<div class="nav-card__name">' + esc(m.display_name || m.name_model) + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    var variantIds = (this.dataset.variantIds || this.dataset.modelId).split(',').map(function(x){ return parseInt(x); });
                    nav.model = { id: parseInt(this.dataset.modelId), name: this.dataset.name, variant_ids: variantIds };
                    loadYears();
                });
            });
        });
    }

    function loadYears() {
        nav.level = 'years';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.brand.name + ' ' + nav.model.name + ' — Anios';
        setupLevelFilter(false);
        showLoading();

        apiFetch(API + '/years?model_id=' + modelIdsParam(nav.model)).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin anios', 'No hay anios con partes para este modelo.'); return; }
            navGrid.className = 'nav-grid nav-grid--years';
            navGrid.innerHTML = data.data.map(function (y) {
                return '<div class="nav-card nav-card--year" role="listitem" data-year-id="' + y.id_year + '" data-year="' + y.year_car + '">' +
                    '<div class="nav-card__name">' + y.year_car + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.year = { id: parseInt(this.dataset.yearId), year: parseInt(this.dataset.year) };
                    loadEngines();
                });
            });
        });
    }

    function loadEngines() {
        nav.level = 'engines';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.brand.name + ' ' + nav.model.name + ' ' + nav.year.year + ' — Motor';
        setupLevelFilter(false);
        showLoading();

        apiFetch(API + '/engines?model_id=' + modelIdsParam(nav.model) + '&year_id=' + nav.year.id).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin motores', 'No hay configuraciones de motor para esta combinacion.'); return; }

            // Helper: avoid showing raw "N/A" as engine name
            function engineLabel(e) {
                var name = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
                return name + (e.trim_level ? ' — ' + e.trim_level : '');
            }

            // If only one engine, auto-select it
            if (data.data.length === 1) {
                var e = data.data[0];
                nav.engine = { id_mye: e.id_mye, name: engineLabel(e) };
                loadCategoriesForMode();
                return;
            }

            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (e) {
                var name = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
                var label = name + (e.trim_level ? ' — ' + e.trim_level : '');
                return '<div class="nav-card" role="listitem" data-mye-id="' + e.id_mye + '" data-name="' + esc(label) + '">' +
                    '<div class="nav-card__name">' + esc(name) + '</div>' +
                    (e.trim_level ? '<div class="nav-card__sub">' + esc(e.trim_level) + '</div>' : '') +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.engine = { id_mye: parseInt(this.dataset.myeId), name: this.dataset.name };
                    loadCategoriesForMode();
                });
            });
        });
    }

    function loadCategories() {
        nav.level = 'categories';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = 'Categorias de partes';
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/categories?mye_id=' + nav.engine.id_mye).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin categorias', 'No hay partes catalogadas para este vehiculo.'); return; }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (c) {
                return '<div class="nav-card" role="listitem" data-cat-id="' + c.id_part_category + '" data-name="' + esc(c.name) + '">' +
                    '<div class="nav-card__name">' + esc(c.name) + '</div>' +
                    '<div class="nav-card__count">' + c.part_count + ' partes</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.category = { id: parseInt(this.dataset.catId), name: this.dataset.name };
                    loadGroups();
                });
            });
        });
    }

    function loadGroups() {
        nav.level = 'groups';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.category.name;
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/groups?mye_id=' + nav.engine.id_mye + '&category_id=' + nav.category.id).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin subcategorias', 'No hay subcategorias para ' + nav.category.name); return; }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (g) {
                return '<div class="nav-card" role="listitem" data-group-id="' + g.id_part_group + '" data-name="' + esc(g.name) + '">' +
                    '<div class="nav-card__name">' + esc(g.name) + '</div>' +
                    '<div class="nav-card__count">' + g.part_count + ' partes</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.group = { id: parseInt(this.dataset.groupId), name: this.dataset.name };
                    nav.partType = null; // reset deeper levels
                    loadPartTypes();
                });
            });
        });
    }

    // ─── Part Types (3rd subcategory level — Nexpart-style) ───
    function loadPartTypes() {
        nav.level = 'part_types';
        nav.partType = null;
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.group.name;
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/part-types?mye_id=' + nav.engine.id_mye + '&group_id=' + nav.group.id).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                // No part types? Skip directly to all parts in the group.
                loadParts(1);
                return;
            }
            // Single part type? Skip the picker — go straight to parts.
            if (data.data.length === 1) {
                var only = data.data[0];
                nav.partType = { slug: only.slug, name: only.name };
                loadParts(1);
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (pt) {
                var img = pt.sample_image
                    ? '<img src="' + esc(pt.sample_image) + '" alt="" style="width:32px;height:32px;object-fit:contain;margin-right:8px;vertical-align:middle;" onerror="this.style.display=\'none\'">'
                    : '';
                return '<div class="nav-card" role="listitem" data-pt-slug="' + esc(pt.slug) + '" data-pt-name="' + esc(pt.name) + '">' +
                    '<div class="nav-card__name">' + img + esc(pt.name) + '</div>' +
                    '<div class="nav-card__count">' + pt.variant_count + ' variante' + (pt.variant_count > 1 ? 's' : '') + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.partType = { slug: this.dataset.ptSlug, name: this.dataset.ptName };
                    loadParts(1);
                });
            });
        });
    }

    // ═══════════════════════════════════════════════════════════════════
    // NEXPART (Local mode) — parallel navigation functions
    // ═══════════════════════════════════════════════════════════════════
    // These run in parallel to loadCategories / loadGroups / loadPartTypes
    // and are only invoked when catalogMode === 'local'. They share the
    // same DOM hooks (navGrid, breadcrumb, levelTitle) but fetch from the
    // Nexpart-filtered endpoints and store state in nav.nxGroup / nxSubgroup
    // / nxPartType instead of nav.category / group / partType.

    function loadCategoriesForMode() {
        // Dispatcher — called by every place that used to call loadCategories()
        if (catalogMode === 'local') {
            loadNexpartCategories();
        } else {
            loadCategories();
        }
    }

    function loadNexpartCategories() {
        nav.level = 'categories';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = 'Categorias (Local)';
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/categories?mode=local&mye_id=' + nav.engine.id_mye).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin categorias Local', 'Ninguna parte de este vehiculo mapea al catalogo Local.');
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (c) {
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(c.slug) + '" data-name="' + esc(c.name) + '">' +
                    '<div class="nav-card__name">' + esc(c.name) + '</div>' +
                    '<div class="nav-card__count">' + c.part_count + ' partes</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxGroup = { slug: this.dataset.slug, name: this.dataset.name };
                    // Reset deeper Nexpart state so a re-click always goes to
                    // a clean subgroup list.
                    nav.nxSubgroup = null;
                    nav.nxPartType = null;
                    loadNexpartSubgroups();
                });
            });
        });
    }

    function loadNexpartSubgroups() {
        nav.level = 'groups';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.nxGroup.name;
        setupLevelFilter(true);
        showLoading();

        var url = API + '/groups?mode=local&mye_id=' + nav.engine.id_mye
                + '&category_slug=' + encodeURIComponent(nav.nxGroup.slug);

        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin subcategorias', 'No hay subcategorias en ' + nav.nxGroup.name);
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (s) {
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(s.slug) + '" data-name="' + esc(s.name) + '">' +
                    '<div class="nav-card__name">' + esc(s.name) + '</div>' +
                    '<div class="nav-card__count">' + s.part_count + ' partes</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxSubgroup = { slug: this.dataset.slug, name: this.dataset.name };
                    nav.nxPartType = null;
                    loadNexpartPartTypes();
                });
            });
        });
    }

    function loadNexpartPartTypes() {
        nav.level = 'part_types';
        nav.nxPartType = null;
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.nxSubgroup.name;
        setupLevelFilter(true);
        showLoading();

        var url = API + '/part-types?mode=local&mye_id=' + nav.engine.id_mye
                + '&group_slug=' + encodeURIComponent(nav.nxGroup.slug)
                + '&subgroup_slug=' + encodeURIComponent(nav.nxSubgroup.slug);

        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin tipos de parte', 'No hay tipos de parte en ' + nav.nxSubgroup.name);
                return;
            }
            // Single part type? Auto-drill-down to parts (UX shortcut).
            if (data.data.length === 1) {
                var only = data.data[0];
                nav.nxPartType = { slug: only.slug, name: only.name };
                loadParts(1);
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (pt) {
                var img = pt.sample_image
                    ? '<img src="' + esc(pt.sample_image) + '" alt="" style="width:32px;height:32px;object-fit:contain;margin-right:8px;vertical-align:middle;" onerror="this.style.display=\'none\'">'
                    : '';
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(pt.slug) + '" data-name="' + esc(pt.name) + '">' +
                    '<div class="nav-card__name">' + img + esc(pt.name) + '</div>' +
                    '<div class="nav-card__count">' + pt.variant_count + ' variante' + (pt.variant_count > 1 ? 's' : '') + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxPartType = { slug: this.dataset.slug, name: this.dataset.name };
                    loadParts(1);
                });
            });
        });
    }

    // ═══════════════════════════════════════════════════════════════════
    // SHOP SUPPLIES (Supplies mode) — vehicle-independent
    // ═══════════════════════════════════════════════════════════════════
    // Uses nav.nxGroup / nav.nxSubgroup / nav.nxPartType for state (reuses
    // the Nexpart slot because Supplies is a subset of the Nexpart taxonomy)
    // but calls a different set of endpoints (/shop-supplies/*) that don't
    // require an mye_id.

    function loadShopSuppliesGroups() {
        nav.level = 'categories';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = 'Shop Supplies (sin vehiculo)';
        setupLevelFilter(true);
        showLoading();

        apiFetch(API + '/shop-supplies/groups').then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin supplies', 'No hay grupos de Shop Supplies disponibles.');
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (g) {
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(g.slug) + '" data-name="' + esc(g.name) + '">' +
                    '<div class="nav-card__name">' + esc(g.name) + '</div>' +
                    '<div class="nav-card__count">' + g.subgroup_count + ' subgrupos</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxGroup = { slug: this.dataset.slug, name: this.dataset.name };
                    nav.nxSubgroup = null;
                    nav.nxPartType = null;
                    loadShopSuppliesSubgroups();
                });
            });
        });
    }

    function loadShopSuppliesSubgroups() {
        nav.level = 'groups';
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.nxGroup.name;
        setupLevelFilter(true);
        showLoading();

        var url = API + '/shop-supplies/subgroups?group_slug=' + encodeURIComponent(nav.nxGroup.slug);
        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin subgrupos', 'No hay subgrupos con partes disponibles.');
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (s) {
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(s.slug) + '" data-name="' + esc(s.name) + '">' +
                    '<div class="nav-card__name">' + esc(s.name) + '</div>' +
                    '<div class="nav-card__count">' + s.part_count + ' partes</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxSubgroup = { slug: this.dataset.slug, name: this.dataset.name };
                    nav.nxPartType = null;
                    loadShopSuppliesPartTypes();
                });
            });
        });
    }

    function loadShopSuppliesPartTypes() {
        nav.level = 'part_types';
        nav.nxPartType = null;
        pushNavState();
        updateBreadcrumb();
        levelTitle.textContent = nav.nxSubgroup.name;
        setupLevelFilter(true);
        showLoading();

        var url = API + '/shop-supplies/part-types'
                + '?group_slug=' + encodeURIComponent(nav.nxGroup.slug)
                + '&subgroup_slug=' + encodeURIComponent(nav.nxSubgroup.slug);

        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin tipos', 'No hay tipos de parte en este subgrupo.');
                return;
            }
            // Single part type? Skip the picker.
            if (data.data.length === 1) {
                var only = data.data[0];
                nav.nxPartType = { slug: only.slug, name: only.name };
                loadShopSuppliesParts(1);
                return;
            }
            navGrid.className = 'nav-grid';
            navGrid.innerHTML = data.data.map(function (pt) {
                var img = pt.sample_image
                    ? '<img src="' + esc(pt.sample_image) + '" alt="" style="width:32px;height:32px;object-fit:contain;margin-right:8px;vertical-align:middle;" onerror="this.style.display=\'none\'">'
                    : '';
                return '<div class="nav-card" role="listitem" ' +
                    'data-slug="' + esc(pt.slug) + '" data-name="' + esc(pt.name) + '">' +
                    '<div class="nav-card__name">' + img + esc(pt.name) + '</div>' +
                    '<div class="nav-card__count">' + pt.variant_count + ' variante' + (pt.variant_count > 1 ? 's' : '') + '</div>' +
                    '</div>';
            }).join('');

            navGrid.querySelectorAll('.nav-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    nav.nxPartType = { slug: this.dataset.slug, name: this.dataset.name };
                    loadShopSuppliesParts(1);
                });
            });
        });
    }

    function loadShopSuppliesParts(page) {
        nav.level = 'parts';
        pushNavState();
        currentPage = page || 1;
        updateBreadcrumb();
        levelTitle.textContent = nav.nxPartType.name;
        setupLevelFilter(false);
        showLoading();
        navGrid.innerHTML = '';

        var url = API + '/shop-supplies/parts'
                + '?group_slug=' + encodeURIComponent(nav.nxGroup.slug)
                + '&subgroup_slug=' + encodeURIComponent(nav.nxSubgroup.slug)
                + '&part_type_slug=' + encodeURIComponent(nav.nxPartType.slug)
                + '&page=' + currentPage + '&per_page=30';

        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) {
                showEmpty('Sin partes', 'No hay partes en este tipo.');
                return;
            }

            // Reuse the same aftermarket-styled rendering as Local mode.
            partsGrid.style.display = '';
            partsGrid.innerHTML = data.data.map(function (p) {
                var stockBadge;
                if (p.in_stock_network || p.bodega_count > 0) {
                    stockBadge = '<span class="stock-badge stock-badge--bodega">' + p.bodega_count + ' bodega' + (p.bodega_count > 1 ? 's' : '') + '</span>';
                } else {
                    stockBadge = '<span class="stock-badge stock-badge--none">Sin stock</span>';
                }

                var imgHtml = p.image_url
                    ? '<img src="' + esc(p.image_url) + '" alt="' + esc(p.name) + '" loading="lazy" decoding="async">'
                    : '<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 7h8M8 12h8M8 17h5"/></svg>';

                var tierClass = p.priority_tier === 1 ? ' part-card--tier1' : (p.priority_tier === 2 ? ' part-card--tier2' : '');
                var manuBadge = '';
                if (p.manufacturer) {
                    var tierStar = p.priority_tier === 1 ? '<span class="manu-tier">★</span>' : '';
                    manuBadge = '<div class="part-card__manu"><span class="manu-name">' + esc(p.manufacturer) + '</span>' + tierStar + '</div>';
                }
                var skuLine = p.part_number
                    ? esc(p.part_number) + '<span class="part-card__oem-sub"> · OEM: ' + esc(p.oem_part_number || '') + '</span>'
                    : esc(p.oem_part_number || '');

                return '<article class="part-card' + tierClass + '" role="listitem" data-part-id="' + p.id_part + '">' +
                    '<div class="part-card__image">' + imgHtml + '</div>' +
                    '<div class="part-card__body">' +
                    manuBadge +
                    '<div class="part-card__oem">' + skuLine + '</div>' +
                    '<div class="part-card__name">' + esc(p.name) + '</div>' +
                    '</div>' +
                    '<div class="part-card__footer">' +
                    '<span class="part-card__price" style="color:var(--color-text-muted);">Sin precio</span>' +
                    stockBadge +
                    '</div>' +
                    '</article>';
            }).join('');

            partsGrid.querySelectorAll('.part-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    var pid = this.dataset.partId;
                    var src = this.dataset.source || '';
                    if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
                        return;
                    }
                    if (src === 'supplier_catalog' || (typeof pid === 'string' && pid.indexOf('sc:') === 0)) {
                        openSupplierDetail(pid.replace('sc:', ''));
                        return;
                    }
                    openPartDetail(parseInt(pid));
                });
            });

            if (data.pagination) renderPagination(data.pagination);
        });
    }

    function loadParts(page) {
        nav.level = 'parts';
        pushNavState();
        currentPage = page || 1;
        updateBreadcrumb();

        // Title: Nexpart part type > TecDoc part type > TecDoc group
        if (nav.nxPartType) {
            levelTitle.textContent = nav.nxPartType.name;
        } else if (nav.partType) {
            levelTitle.textContent = nav.partType.name;
        } else if (nav.group) {
            levelTitle.textContent = nav.group.name;
        } else {
            levelTitle.textContent = 'Partes';
        }

        setupLevelFilter(false);
        showLoading();
        navGrid.innerHTML = '';

        // Build the URL based on which navigation branch the user took.
        // Nexpart branch uses slug-based params; OEM branch uses integer ids.
        var url;
        if (nav.nxGroup && nav.nxSubgroup && nav.nxPartType) {
            url = API + '/parts?mode=local'
                + '&mye_id=' + nav.engine.id_mye
                + '&page=' + currentPage + '&per_page=30'
                + '&nexpart_group=' + encodeURIComponent(nav.nxGroup.slug)
                + '&nexpart_subgroup=' + encodeURIComponent(nav.nxSubgroup.slug)
                + '&nexpart_part_type=' + encodeURIComponent(nav.nxPartType.slug);
        } else {
            var ptParam = nav.partType ? '&part_type=' + encodeURIComponent(nav.partType.slug) : '';
            url = API + '/parts?mye_id=' + nav.engine.id_mye
                + '&group_id=' + nav.group.id
                + '&page=' + currentPage + '&per_page=30'
                + '&mode=' + catalogMode
                + ptParam;
        }

        apiFetch(url).then(function (data) {
            hideLoading();
            if (!data || !data.data || !data.data.length) { showEmpty('Sin partes', 'No hay partes en este grupo.'); return; }

            var isLocal = (catalogMode === 'local');

            partsGrid.style.display = '';
            partsGrid.innerHTML = data.data.map(function (p) {
                // Stock badge — prefer tenant stock, then warehouse network, else fallback
                var stockBadge;
                var isSupplier = p.source === 'supplier_catalog' || (typeof p.id_part === 'string' && p.id_part.indexOf('sc:') === 0);
                if (isSupplier) {
                    stockBadge = '<span class="stock-badge stock-badge--none" style="background:#f59e0b;color:#fff;">Cat. Proveedor</span>';
                } else if (p.local_stock > 0) {
                    stockBadge = '<span class="stock-badge stock-badge--local">En stock: ' + p.local_stock + '</span>';
                } else if (p.in_stock_network || p.bodega_count > 0) {
                    stockBadge = '<span class="stock-badge stock-badge--bodega">' + p.bodega_count + ' bodega' + (p.bodega_count > 1 ? 's' : '') + '</span>';
                } else {
                    stockBadge = '<span class="stock-badge stock-badge--none">Sin stock</span>';
                }
                // Source badge for local inventory or supplier catalog
                var sourceBadge = '';
                if (p.source === 'local_inventory') {
                    sourceBadge = '<span class="stock-badge stock-badge--local" style="margin-left:4px;background:#4f46e5;">Stock Local</span>';
                } else if (isSupplier) {
                    sourceBadge = '<span class="stock-badge stock-badge--local" style="margin-left:4px;background:#f59e0b;color:#fff;">Cat. Proveedor</span>';
                }

                var imgHtml = p.image_url
                    ? '<img src="' + esc(p.image_url) + '" alt="' + esc(p.name) + '" loading="lazy" decoding="async">'
                    : '<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 7h8M8 12h8M8 17h5"/></svg>';

                // Local-mode extras: manufacturer badge + priority tier indicator
                var manuBadge = '';
                var tierClass = '';
                if (isLocal && p.manufacturer) {
                    var tierLabel = '';
                    if (p.priority_tier === 1) { tierClass = ' part-card--tier1'; tierLabel = '★'; }
                    else if (p.priority_tier === 2) { tierClass = ' part-card--tier2'; tierLabel = ''; }
                    manuBadge = '<div class="part-card__manu"><span class="manu-name">' + esc(p.manufacturer) + '</span>' +
                                (tierLabel ? '<span class="manu-tier">' + tierLabel + '</span>' : '') + '</div>';
                }

                // SKU to show: aftermarket part_number in local mode, OEM number otherwise
                var skuLine = isLocal && p.part_number
                    ? esc(p.part_number) + '<span class="part-card__oem-sub"> · OEM: ' + esc(p.oem_part_number) + '</span>'
                    : esc(p.oem_part_number);

                return '<article class="part-card' + tierClass + '" role="listitem" data-part-id="' + p.id_part + '" data-source="' + (p.source || '') + '">' +
                    '<div class="part-card__image">' + imgHtml + '</div>' +
                    '<div class="part-card__body">' +
                    manuBadge +
                    sourceBadge +
                    '<div class="part-card__oem">' + skuLine + '</div>' +
                    '<div class="part-card__name">' + esc(p.name) + '</div>' +
                    '</div>' +
                    '<div class="part-card__footer">' +
                    (p.local_price ? '<span class="part-card__price">$' + fmt(p.local_price) + '</span>' : '<span class="part-card__price" style="color:var(--color-text-muted);">Sin precio</span>') +
                    (p.supplier_price ? '<span class="part-card__price" style="color:#2d7d46;font-size:0.85em;">Prov: $' + fmt(p.supplier_price) + '</span>' : '') +
                    stockBadge +
                    '</div>' +
                    '</article>';
            }).join('');

            // Wire part card clicks → open detail panel (skip local-inventory items)
            partsGrid.querySelectorAll('.part-card').forEach(function (card) {
                card.addEventListener('click', function () {
                    var pid = this.dataset.partId;
                    var src = this.dataset.source || '';
                    if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
                        // local-inventory item: info already visible on card
                        return;
                    }
                    if (src === 'supplier_catalog' || (typeof pid === 'string' && pid.indexOf('sc:') === 0)) {
                        openSupplierDetail(pid.replace('sc:', ''));
                        return;
                    }
                    openPartDetail(parseInt(pid));
                });
            });

            // Pagination
            if (data.pagination) renderPagination(data.pagination);
        });
    }

    // ─── PAGINATION ───
    function renderPagination(pg) {
        if (!pg || pg.total_pages <= 1) { paginationNav.innerHTML = ''; return; }
        var html = '';

        if (pg.page <= 1) {
            html += '<button class="page-item page-item--wide is-disabled" disabled>Anterior</button>';
        } else {
            html += '<button class="page-item page-item--wide" data-page="' + (pg.page - 1) + '">Anterior</button>';
        }

        var pages = buildPageNumbers(pg.page, pg.total_pages);
        pages.forEach(function (p) {
            if (p === '...') {
                html += '<span style="padding:0 4px;color:var(--color-text-muted);">...</span>';
            } else if (p === pg.page) {
                html += '<button class="page-item is-active">' + p + '</button>';
            } else {
                html += '<button class="page-item" data-page="' + p + '">' + p + '</button>';
            }
        });

        if (pg.page >= pg.total_pages) {
            html += '<button class="page-item page-item--wide is-disabled" disabled>Siguiente</button>';
        } else {
            html += '<button class="page-item page-item--wide" data-page="' + (pg.page + 1) + '">Siguiente</button>';
        }

        paginationNav.innerHTML = html;

        paginationNav.querySelectorAll('[data-page]').forEach(function (btn) {
            btn.addEventListener('click', function () {
                pageBody.scrollTo({ top: 0, behavior: 'smooth' });
                loadParts(parseInt(this.dataset.page));
            });
        });
    }

    function buildPageNumbers(current, total) {
        if (total <= 7) { var a = []; for (var i = 1; i <= total; i++) a.push(i); return a; }
        var p = [1];
        if (current > 3) p.push('...');
        for (var j = Math.max(2, current - 1); j <= Math.min(total - 1, current + 1); j++) p.push(j);
        if (current < total - 2) p.push('...');
        p.push(total);
        return p;
    }

    // ─── DETAIL PANEL ───
    function openPartDetail(partId) {
        detailBody.innerHTML = '<div class="loading is-visible"><div class="spinner"></div></div>';
        detailFooter.style.display = 'none';
        detailPanel.classList.add('is-open');
        detailOverlay.classList.add('is-visible');
        detailQty = 1;
        qtyDisplay.textContent = '1';

        apiFetch(API + '/part/' + partId).then(function (data) {
            if (!data || data.error) {
                detailBody.innerHTML = '<p style="color:var(--color-error);padding:var(--space-4);">Error al cargar detalle.</p>';
                return;
            }

            currentDetailPart = data;
            var p = data.part;
            var local = data.local;
            var bodegas = data.bodegas || [];
            var alts = data.alternatives || [];

            var html = '';

            // Part info
            html += '<div class="detail-section">';
            if (p.category_name) html += '<div style="font-size:var(--text-caption);color:var(--color-text-muted);margin-bottom:var(--space-1);">' + esc(p.category_name) + ' > ' + esc(p.group_name) + '</div>';
            html += '<div class="detail-oem">' + esc(p.oem_part_number) + '</div>';
            html += '<div class="detail-name">' + esc(p.name) + '</div>';
            if (p.description) html += '<div class="detail-desc">' + esc(p.description) + '</div>';
            if (p.image_url) html += '<div style="margin-top:var(--space-3);text-align:center;"><img src="' + esc(p.image_url) + '" alt="" loading="lazy" decoding="async" style="max-width:100%;max-height:200px;object-fit:contain;border-radius:var(--radius-sm);"></div>';
            html += '</div>';

            // Local stock
            html += '<div class="detail-section">';
            html += '<div class="detail-section__title">Mi stock</div>';
            if (local && local.stock > 0) {
                html += '<div class="stock-row"><span class="stock-label">Cantidad</span><span class="stock-value stock-value--ok">' + local.stock + ' ' + (local.unit || 'PZA') + '</span></div>';
                html += '<div class="stock-row"><span class="stock-label">Precio publico</span><span class="stock-value">$' + fmt(local.price_1) + '</span></div>';
                if (local.price_2) html += '<div class="stock-row"><span class="stock-label">Precio mayoreo</span><span class="stock-value">$' + fmt(local.price_2) + '</span></div>';
                if (local.price_3) html += '<div class="stock-row"><span class="stock-label">Precio taller</span><span class="stock-value">$' + fmt(local.price_3) + '</span></div>';
                if (local.location) html += '<div class="stock-row"><span class="stock-label">Ubicacion</span><span class="stock-value">' + esc(local.location) + '</span></div>';
            } else {
                html += '<div style="color:var(--color-text-muted);font-size:var(--text-body-sm);">No tienes esta parte en inventario.</div>';
            }
            html += '</div>';

            // Bodegas
            if (bodegas.length) {
                html += '<div class="detail-section">';
                html += '<div class="detail-section__title">Disponible en bodegas</div>';
                html += '<table class="bodega-table"><thead><tr><th>Bodega</th><th>Precio</th><th>Stock</th></tr></thead><tbody>';
                bodegas.forEach(function (b) {
                    html += '<tr><td>' + esc(b.business_name) + '</td><td>' + (b.price ? '$' + fmt(b.price) : '--') + '</td><td>' + b.stock + '</td></tr>';
                });
                html += '</tbody></table></div>';
            }

            // Alternatives
            if (alts.length) {
                html += '<div class="detail-section">';
                html += '<div class="detail-section__title">Alternativas / Cross-references</div>';
                alts.forEach(function (a) {
                    var stockLabel = a.local_stock > 0
                        ? '<span class="stock-badge stock-badge--local">Stock: ' + a.local_stock + '</span>'
                        : (a.bodega_count > 0 ? '<span class="stock-badge stock-badge--bodega">' + a.bodega_count + ' bod.</span>' : '');
                    html += '<div class="alt-item">' +
                        '<div><div class="alt-item__pn">' + esc(a.part_number) + '</div>' +
                        '<div class="alt-item__mfr">' + esc(a.manufacturer) + (a.name ? ' — ' + esc(a.name) : '') + '</div></div>' +
                        '<div class="alt-item__stock">' + stockLabel + '</div>' +
                        '</div>';
                });
                html += '</div>';
            }

            detailBody.innerHTML = html;

            // Show footer only if we have local stock
            if (local && local.stock > 0) {
                detailFooter.style.display = '';
            } else {
                detailFooter.style.display = 'none';
            }
        });
    }

    function openSupplierDetail(supplierId) {
        detailBody.innerHTML = '<div class="loading is-visible"><div class="spinner"></div></div>';
        detailFooter.style.display = 'none';
        detailPanel.classList.add('is-open');
        detailOverlay.classList.add('is-visible');

        apiFetch('/pos/api/supplier-catalog/items/' + supplierId).then(function (data) {
            if (!data || data.error) {
                detailBody.innerHTML = '<p style="color:var(--color-error);padding:var(--space-4);">Error al cargar detalle.</p>';
                return;
            }
            var p = data;
            var html = '';

            html += '<div class="detail-section">';
            html += '<div style="font-size:var(--text-caption);color:var(--color-text-muted);margin-bottom:var(--space-1);">' + esc(p.supplier_name) + ' &gt; ' + esc(p.category || '') + '</div>';
            html += '<div class="detail-oem">' + esc(p.sku) + '</div>';
            html += '<div class="detail-name">' + esc((p.name || '').replace(/\\n/g, ' ')) + '</div>';
            if (p.description) html += '<div class="detail-desc">' + esc(p.description) + '</div>';
            if (p.image_url) html += '<div style="margin-top:var(--space-3);text-align:center;"><img src="' + esc(p.image_url) + '" alt="" loading="lazy" decoding="async" style="max-width:100%;max-height:200px;object-fit:contain;border-radius:var(--radius-sm);"></div>';
            html += '</div>';

            // Interchanges
            if (p.interchanges && p.interchanges.length) {
                html += '<div class="detail-section">';
                html += '<div class="detail-section__title">Intercambios OEM</div>';
                var seen = {};
                p.interchanges.forEach(function(ix) {
                    var key = (ix.brand || '') + '|' + (ix.interchange_number || '');
                    if (seen[key]) return;
                    seen[key] = true;
                    html += '<div style="display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--color-border);">' +
                        '<span style="font-weight:600;">' + esc(ix.brand || '') + '</span>' +
                        '<span style="color:var(--color-text-muted);font-family:monospace;">' + esc(ix.interchange_number || '') + '</span>' +
                        '</div>';
                });
                html += '</div>';
            }

// Compatibilities — deduplicate by (make, model, year, engine)
            if (p.compatibilities && p.compatibilities.length) {
                var seenCompat = {};
                var uniqCompat = [];
                p.compatibilities.forEach(function(c) {
                    var key = (c.make || '') + '|' + (c.model || '') + '|' + (c.year || '') + '|' + (c.engine || '');
                    if (seenCompat[key]) return;
                    seenCompat[key] = true;
                    uniqCompat.push(c);
                });
                html += '<div class="detail-section">';
                html += '<div class="detail-section__title">Vehiculos compatibles</div>';
                html += '<div id="compat-list"></div>';
                html += '<div id="compat-pager" class="compat-pager"></div>';
                html += '</div>';
                compatFullList = uniqCompat;
            } else {
                compatFullList = [];
            }

            detailBody.innerHTML = html;

            if (compatFullList.length) {
                renderCompatPage(1);
            }
        });
    }

    // --- Pagination for "Vehiculos compatibles" ---
    var compatFullList = [];
    var compatPageSize = 15;
    var compatCurrentPage = 1;

    function renderCompatPage(page) {
        var listEl = document.getElementById('compat-list');
        var pagerEl = document.getElementById('compat-pager');
        if (!listEl || !pagerEl) return;

        var totalItems = compatFullList.length;
        var totalPages = Math.max(1, Math.ceil(totalItems / compatPageSize));
        page = Math.min(Math.max(1, page), totalPages);
        compatCurrentPage = page;

        var start = (page - 1) * compatPageSize;
        var pageItems = compatFullList.slice(start, start + compatPageSize);

        var listHtml = '';
        var currentMake = '';
        pageItems.forEach(function(c) {
            if (c.make !== currentMake) {
                currentMake = c.make;
                listHtml += '<div style="font-weight:600;margin-top:8px;">' + esc(c.make) + '</div>';
            }
            listHtml += '<div style="padding-left:12px;color:var(--color-text-muted);font-size:var(--text-body-sm);">' +
                esc(c.model) + ' ' + c.year + ' ' + esc(c.engine || '') + '</div>';
        });
        listEl.innerHTML = listHtml;

        if (totalPages > 1) {
            pagerEl.innerHTML =
                '<button type="button" id="compat-prev" class="compat-pager__btn"' + (page <= 1 ? ' disabled' : '') + '>&lsaquo; Anterior</button>' +
                '<span class="compat-pager__info">Pagina ' + page + ' de ' + totalPages + ' (' + totalItems + ' vehiculos)</span>' +
                '<button type="button" id="compat-next" class="compat-pager__btn"' + (page >= totalPages ? ' disabled' : '') + '>Siguiente &rsaquo;</button>';

            var prevBtn = document.getElementById('compat-prev');
            var nextBtn = document.getElementById('compat-next');
            if (prevBtn) prevBtn.addEventListener('click', function () { renderCompatPage(compatCurrentPage - 1); });
            if (nextBtn) nextBtn.addEventListener('click', function () { renderCompatPage(compatCurrentPage + 1); });
        } else {
            pagerEl.innerHTML = '';
        }
    }

    function closeDetail() {
        detailPanel.classList.remove('is-open');
        detailOverlay.classList.remove('is-visible');
        currentDetailPart = null;
    }

    detailClose.addEventListener('click', closeDetail);
    detailOverlay.addEventListener('click', closeDetail);

    qtyMinus.addEventListener('click', function () { if (detailQty > 1) { detailQty--; qtyDisplay.textContent = detailQty; } });
    qtyPlus.addEventListener('click', function () { detailQty++; qtyDisplay.textContent = detailQty; });

    addToCartBtn.addEventListener('click', function () {
        if (!currentDetailPart) return;
        var p = currentDetailPart.part;
        var local = currentDetailPart.local;
        if (!local) return;

        addToCart({
            id: p.id_part,
            part_number: p.oem_part_number,
            name: p.name,
            brand: '',
            price: local.price_1,
            tax_rate: local.tax_rate || 0.16,
            unit: local.unit || 'PZA',
            stock: local.stock,
            source: 'local',
            inventory_id: local.inventory_id,
        }, detailQty);
        closeDetail();
    });

    // ─── SMART SEARCH ───
    var searchTimeout = null;

    // ═══════════════════════════════════════════════════════════════════
    // SMART SEARCH — auto-detect VIN / plate / part number / keyword
    // ═══════════════════════════════════════════════════════════════════
    // Returns: 'vin' | 'plate' | 'part_number' | 'keyword'

    function detectQueryType(raw) {
        if (!raw) return 'keyword';
        var q = raw.trim();

        // Strip common separators for detection (VINs/parts rarely contain spaces)
        var compact = q.replace(/[\s\-]/g, '').toUpperCase();

        // VIN: exactly 17 chars alphanumeric, no I/O/Q
        if (/^[A-HJ-NPR-Z0-9]{17}$/.test(compact)) return 'vin';

        // Mexican license plate: 3 letters + 3-4 digits (with/without hyphen)
        if (/^[A-Z]{3}[-\s]?\d{3,4}$/.test(q.toUpperCase())) return 'plate';

        // Part-number heuristic. Rules designed to avoid false positives on
        // natural-language Spanish/English queries:
        //  1. Original query must NOT contain lowercase letters. Real part
        //     numbers are always uppercase ("4G0-857-951-A"); keywords aren't.
        //  2. No natural-language words allowed (para, de, con, for, the, etc.)
        //  3. Either has a dash/slash separator, or is a solid alphanumeric blob.
        var hasLowercase = /[a-z]/.test(q);
        if (hasLowercase) return 'keyword';

        // Block queries that contain a year-like 4-digit number alongside
        // other tokens — those are "PART 2018" style vehicle refs, not parts.
        var tokens = q.split(/\s+/);
        var hasYear = tokens.some(function (t) { return /^(19|20)\d{2}$/.test(t); });
        if (hasYear && tokens.length > 1) return 'keyword';

        var qUpper = q.toUpperCase();
        // Dashed/slashed part number: "4G0-857-951-A", "BP-1234"
        if (/^[A-Z0-9]{2,}[\-\/][A-Z0-9]{2,}([\-\/][A-Z0-9]+)*$/.test(qUpper) && compact.length >= 6) {
            return 'part_number';
        }
        // Space-separated part number (rare but real, e.g. BOSCH "0 986 4B7 013")
        if (tokens.length >= 2 && tokens.every(function (t) { return /^[A-Z0-9]{1,}$/.test(t); }) && compact.length >= 6) {
            return 'part_number';
        }
        // Solid alphanumeric blob 8+ chars with both letters+digits
        if (/^[A-Z0-9]{8,}$/.test(compact) && /[A-Z]/.test(compact) && /\d/.test(compact)) {
            return 'part_number';
        }

        return 'keyword';
    }

    // Hint badge shown next to the search input. Injected lazily so we don't
    // need to touch the HTML.
    var searchHint = null;
    function ensureSearchHint() {
        if (searchHint) return searchHint;
        searchHint = document.createElement('div');
        searchHint.id = 'searchHint';
        searchHint.style.cssText =
            'position:absolute;top:100%;left:0;margin-top:4px;padding:3px 10px;' +
            'background:var(--color-primary-muted);color:var(--color-text-accent);' +
            'font-size:var(--text-caption);font-weight:var(--font-weight-semibold);' +
            'border:1px dashed var(--color-border-accent);border-radius:var(--radius-sm);' +
            'white-space:nowrap;pointer-events:none;z-index:10;display:none;';
        searchInput.parentElement.appendChild(searchHint);
        return searchHint;
    }

    function updateSearchHint(type) {
        var hint = ensureSearchHint();
        var labels = {
            vin: '🚗 VIN detectado — decodificando',
            plate: '🔖 Placa detectada — consultando registro',
            part_number: '🔩 Numero de parte detectado',
            keyword: null,
        };
        var label = labels[type];
        if (!label) {
            hint.style.display = 'none';
        } else {
            hint.textContent = label;
            hint.style.display = '';
        }
    }

    // Smart dispatcher — decides which endpoint to call based on input type.
    function runSmartSearch(q) {
        var type = detectQueryType(q);

        if (type === 'vin') {
            // Use the existing VIN decoder flow
            try { decodeVinWithValue(q); } catch (e) { runSearch(q); }
            return;
        }

        if (type === 'plate') {
            // Use the existing plate lookup flow — assume default state MX
            try { lookupPlateWithValue(q); } catch (e) { runSearch(q); }
            return;
        }

        // For part_number and keyword, both go through the existing /search
        // endpoint (which supports full-text + OEM number search).
        runSearch(q);
    }

    // Thin wrappers around existing VIN/plate handlers — they usually read
    // from their own input fields; these set the field and trigger.
    function decodeVinWithValue(vin) {
        var vinInput = document.getElementById('vinInput');
        if (vinInput) {
            vinInput.value = vin;
            if (typeof decodeVin === 'function') decodeVin();
            else runSearch(vin);
        } else {
            runSearch(vin);  // fallback
        }
    }

    function lookupPlateWithValue(plate) {
        var plateInput = document.getElementById('plateInput');
        if (plateInput) {
            plateInput.value = plate.toUpperCase();
            if (typeof lookupPlate === 'function') lookupPlate();
            else runSearch(plate);
        } else {
            runSearch(plate);  // fallback
        }
    }

    searchInput.addEventListener('input', function () {
        clearTimeout(searchTimeout);
        var q = this.value.trim();
        // Live type detection for the hint (runs on every keystroke)
        updateSearchHint(q.length >= 3 ? detectQueryType(q) : null);

        if (q.length < 2) { searchDropdown.classList.remove('is-visible'); return; }
        // For keyword queries, keep the debounced dropdown preview.
        // For VIN/plate/part-number, wait for Enter — they're one-shot lookups.
        var type = detectQueryType(q);
        if (type === 'keyword') {
            searchTimeout = setTimeout(function () { runSearch(q); }, 350);
        }
    });

    searchInput.addEventListener('keydown', function (e) {
        if (e.key === 'Enter') {
            e.preventDefault();
            clearTimeout(searchTimeout);
            var q = this.value.trim();
            if (q.length >= 2) runSmartSearch(q);
        }
        if (e.key === 'Escape') {
            searchDropdown.classList.remove('is-visible');
            updateSearchHint(null);
        }
    });

    // Close dropdown on outside click
    document.addEventListener('click', function (e) {
        if (!searchDropdown.contains(e.target) && e.target !== searchInput) {
            searchDropdown.classList.remove('is-visible');
        }
    });

    function runSearch(q) {
        var url = API + '/search?q=' + encodeURIComponent(q) + '&limit=20';
        if (nav.engine && nav.engine.id_mye) {
            url += '&mye_id=' + nav.engine.id_mye;
        }
        apiFetch(url).then(function (data) {
            if (!data || !data.data || !data.data.length) {
                searchDropdown.innerHTML = '<div style="padding:var(--space-4);color:var(--color-text-muted);font-size:var(--text-body-sm);">Sin resultados para "' + esc(q) + '"</div>';
                searchDropdown.classList.add('is-visible');
                return;
            }
            searchDropdown.innerHTML = data.data.map(function (r) {
                var isLocal = r.source === 'local_inventory' || (typeof r.id_part === 'string' && r.id_part.indexOf('inv:') === 0);
                var isSupplier = r.source === 'supplier_catalog' || (typeof r.id_part === 'string' && r.id_part.indexOf('sc:') === 0);
                var stockLabel = r.local_stock > 0
                    ? '<span class="stock-badge stock-badge--local" style="margin-left:auto;">Stock: ' + r.local_stock + '</span>'
                    : '';
                var sourceBadge = '';
                if (isLocal) {
                    sourceBadge = '<span class="stock-badge stock-badge--local" style="margin-right:4px;background:#4f46e5;">Stock Local</span>';
                } else if (isSupplier) {
                    sourceBadge = '<span class="stock-badge stock-badge--local" style="margin-right:4px;background:#f59e0b;color:#fff;">Cat. Proveedor</span>';
                }
                var oemNum = isLocal ? (r.oem_part_number || r.part_number || '') : (r.oem_part_number || '');
                var cleanName = (r.name || '').replace(/\\n/g, ' ');
                return '<div class="search-result-item" data-part-id="' + r.id_part + '" data-name="' + esc(cleanName) + '" data-pn="' + esc(oemNum) + '" data-price="' + (r.local_price || '') + '" data-stock="' + (r.local_stock || 0) + '" data-source="' + (r.source || '') + '">' +
                    '<div style="flex:1;">' +
                    '<div class="search-result__oem">' + sourceBadge + esc(oemNum) + '</div>' +
                    '<div class="search-result__name">' + esc(cleanName) + '</div>' +
                    (r.vehicle_info ? '<div class="search-result__vehicle">' + esc(r.vehicle_info) + '</div>' : '') +
                    '</div>' +
                    stockLabel +
                    '</div>';
            }).join('');
            searchDropdown.classList.add('is-visible');

            searchDropdown.querySelectorAll('.search-result-item').forEach(function (el) {
                el.addEventListener('click', function () {
                    searchDropdown.classList.remove('is-visible');
                    var pid = this.dataset.partId;
                    var src = this.dataset.source || '';
                    if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
                        var info = '💠 Stock Local\n\n' +
                            'Parte: ' + (this.dataset.pn || 'N/A') + '\n' +
                            'Nombre: ' + (this.dataset.name || '') + '\n' +
                            'Precio: $' + (this.dataset.price || '—') + '\n' +
                            'Stock: ' + (this.dataset.stock || 0) + ' pzas';
                        alert(info);
                        return;
                    }
                    if (src === 'supplier_catalog' || (typeof pid === 'string' && pid.indexOf('sc:') === 0)) {
                        openSupplierDetail(pid.replace('sc:', ''));
                        return;
                    }
                    openPartDetail(parseInt(pid));
                });
            });
        });
    }

    // ─── CART ───
    function addToCart(item, qty) {
        qty = qty || 1;
        var existing = cartItems.find(function (c) { return c.id === item.id; });
        if (existing) {
            existing.quantity += qty;
        } else {
            cartItems.push({
                id: item.id,
                part_number: item.part_number,
                name: item.name,
                brand: item.brand || '',
                price: item.price,
                tax_rate: item.tax_rate || 0.16,
                unit: item.unit || 'PZA',
                stock: item.stock,
                source: item.source || 'local',
                inventory_id: item.inventory_id,
                quantity: qty,
            });
        }
        saveCart();
        renderCart();
        if (!cartSidebar.classList.contains('open')) toggleCart();
    }

    function removeFromCart(index) {
        cartItems.splice(index, 1);
        saveCart();
        renderCart();
    }

    function updateQuantity(index, qty) {
        qty = parseInt(qty);
        if (qty <= 0) { removeFromCart(index); return; }
        cartItems[index].quantity = qty;
        saveCart();
        renderCart();
    }

    function clearCart() {
        cartItems = [];
        saveCart();
        renderCart();
    }

    function saveCart() { localStorage.setItem('pos_cart', JSON.stringify(cartItems)); }

    function renderCart() {
        var total = cartItems.reduce(function (s, c) { return s + c.quantity; }, 0);
        if (cartBadge) {
            cartBadge.textContent = total;
            cartBadge.style.display = total > 0 ? 'flex' : 'none';
        }

        if (!cartItems.length) {
            cartItemsEl.innerHTML = '';
            cartEmptyEl.style.display = 'block';
            if (checkoutBtn) checkoutBtn.disabled = true;
            cartSubtotalEl.textContent = '$0.00';
            cartTaxEl.textContent = '$0.00';
            cartTotalEl.textContent = '$0.00';
            return;
        }

        cartEmptyEl.style.display = 'none';
        if (checkoutBtn) checkoutBtn.disabled = false;

        var subtotal = 0;
        var tax = 0;
        cartItemsEl.innerHTML = cartItems.map(function (c, i) {
            var lineTotal = c.price * c.quantity;
            var lineTax = lineTotal * c.tax_rate;
            subtotal += lineTotal;
            tax += lineTax;
            return '<div class="cart-item">' +
                '<div style="flex:1;">' +
                '<div style="font-weight:600;font-size:0.85rem;color:var(--color-text-primary);">' + esc(c.name) + '</div>' +
                '<div style="font-size:0.75rem;color:var(--color-text-muted);">' + esc(c.part_number) + '</div>' +
                '<div style="margin-top:4px;display:flex;align-items:center;gap:6px;">' +
                '<button data-cart-action="dec" data-idx="' + i + '" style="width:24px;height:24px;border:1px solid var(--color-border);background:var(--color-bg-base);border-radius:var(--radius-sm);cursor:pointer;color:var(--color-text-primary);">-</button>' +
                '<span style="font-weight:600;color:var(--color-text-primary);">' + c.quantity + '</span>' +
                '<button data-cart-action="inc" data-idx="' + i + '" style="width:24px;height:24px;border:1px solid var(--color-border);background:var(--color-bg-base);border-radius:var(--radius-sm);cursor:pointer;color:var(--color-text-primary);">+</button>' +
                '</div></div>' +
                '<div style="text-align:right;">' +
                '<div style="font-weight:600;color:var(--color-text-primary);">$' + fmt(lineTotal) + '</div>' +
                '<button data-cart-action="remove" data-idx="' + i + '" style="font-size:0.75rem;color:var(--color-error,#ef4444);background:none;border:none;cursor:pointer;margin-top:4px;">Quitar</button>' +
                '</div></div>';
        }).join('');

        cartSubtotalEl.textContent = '$' + fmt(subtotal);
        cartTaxEl.textContent = '$' + fmt(tax);
        cartTotalEl.textContent = '$' + fmt(subtotal + tax);

    }

    // Event delegation for cart buttons (attached once)
    cartItemsEl.addEventListener('click', function (e) {
        var btn = e.target.closest('[data-cart-action]');
        if (!btn) return;
        var idx = parseInt(btn.dataset.idx);
        var action = btn.dataset.cartAction;
        if (action === 'dec') updateQuantity(idx, cartItems[idx].quantity - 1);
        else if (action === 'inc') updateQuantity(idx, cartItems[idx].quantity + 1);
        else if (action === 'remove') removeFromCart(idx);
    });

    function toggleCart() {
        var isOpen = cartSidebar.classList.toggle('open');
        cartOverlay.classList.toggle('open', isOpen);
    }

    function goToCheckout() {
        if (!cartItems.length) return;
        localStorage.setItem('pos_cart', JSON.stringify(cartItems));
        window.location.href = '/pos/sale';
    }

    cartFab.addEventListener('click', toggleCart);
    cartCloseBtn.addEventListener('click', toggleCart);
    cartOverlay.addEventListener('click', toggleCart);
    checkoutBtn.addEventListener('click', goToCheckout);

    // ─── OFFLINE FALLBACK ───
    function enterOfflineMode() {
        isOffline = true;
        document.getElementById('offlineBanner').style.display = '';
        document.getElementById('offlineBannerText').innerHTML = '<strong>Modo offline</strong> — Mostrando solo tu inventario local.';
        levelTitle.textContent = 'Inventario local';
        setupLevelFilter(false);
        // TODO: load local inventory via legacy /pos/api/catalog/search endpoint
        showEmpty('Sin conexion al catalogo', 'Verifica tu conexion. El catalogo TecDoc requiere acceso al servidor central.');
    }

    // ─── BARCODE SCANNER ───
    var barcodeBuffer = '';
    var barcodeTimeout = null;

    document.addEventListener('keydown', function (e) {
        // F1 → focus search
        if (e.key === 'F1') { e.preventDefault(); searchInput.focus(); return; }
        // Escape → close panels
        if (e.key === 'Escape') {
            closeDetail();
            if (cartSidebar.classList.contains('open')) toggleCart();
            return;
        }
        // Barcode scanner detection
        if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return;
        if (e.key === 'Enter' && barcodeBuffer.length >= 4) {
            var code = barcodeBuffer.trim();
            barcodeBuffer = '';
            // Search for the barcode
            searchInput.value = code;
            runSearch(code);
            return;
        }
        if (e.key.length === 1) {
            barcodeBuffer += e.key;
            clearTimeout(barcodeTimeout);
            barcodeTimeout = setTimeout(function () { barcodeBuffer = ''; }, 200);
        }
    });

    // ─── THEME SWITCHER ───
    document.querySelectorAll('[data-theme-switch]').forEach(function (btn) {
        btn.addEventListener('click', function () {
            var theme = this.dataset.themeSwitch;
            document.documentElement.setAttribute('data-theme', theme);
            localStorage.setItem('pos_theme', theme);
            document.querySelectorAll('[data-theme-switch]').forEach(function (b) {
                b.classList.remove('is-active');
                b.setAttribute('aria-pressed', 'false');
            });
            this.classList.add('is-active');
            this.setAttribute('aria-pressed', 'true');
        });
        // Set initial active state
        var current = localStorage.getItem('pos_theme') || 'industrial';
        if (btn.dataset.themeSwitch === current) {
            btn.classList.add('is-active');
            btn.setAttribute('aria-pressed', 'true');
        } else {
            btn.classList.remove('is-active');
            btn.setAttribute('aria-pressed', 'false');
        }
    });

    // ─── VEHICLE SELECTOR (dropdown bar) ───
    var vsYear = document.getElementById('vsYear');
    var vsBrand = document.getElementById('vsBrand');
    var vsModel = document.getElementById('vsModel');
    var vsEngine = document.getElementById('vsEngine');
    var vsClear = document.getElementById('vsClear');

    // Load years on init
    function vsLoadYears() {
        var cacheKey = 'nexus:years-all';
        var cached = sessionStorage.getItem(cacheKey);
        if (cached) {
            try {
                var data = JSON.parse(cached);
                var years = data.data || data || [];
            } catch (e) {
                sessionStorage.removeItem(cacheKey);
                var years = [];
            }
            if (!years.length) {
                years = [];
                for (var y = 2026; y >= 1990; y--) years.push({ id_year: y, year_car: y });
            }
            vsYear.innerHTML = '<option value="">Año...</option>' +
                years.map(function (y) {
                    return '<option value="' + y.id_year + '">' + y.year_car + '</option>';
                }).join('');
            return;
        }

        apiFetch(API + '/years-all').then(function (data) {
            if (!data) return;
            var years = data.data || data;
            // If endpoint doesn't exist, generate from 1990-2026
            if (!years || !years.length) {
                years = [];
                for (var y = 2026; y >= 1990; y--) years.push({ id_year: y, year_car: y });
            }
            sessionStorage.setItem(cacheKey, JSON.stringify(data));
            vsYear.innerHTML = '<option value="">Año...</option>' +
                years.map(function (y) {
                    return '<option value="' + y.id_year + '">' + y.year_car + '</option>';
                }).join('');
        }).catch(function () {
            // Fallback: generate years statically
            var fallbackYears = [];
            for (var y = 2026; y >= 1990; y--) fallbackYears.push(y);
            vsYear.innerHTML = '<option value="">Año...</option>' +
                fallbackYears.map(function (y) {
                    return '<option value="' + y + '">' + y + '</option>';
                }).join('');
        });
    }


    function vsYearChanged() {
        var yearId = vsYear.value;
        vsClear.style.display = (yearId || vsBrand.value || vsModel.value) ? '' : 'none';

        // Resetear marca solo si no hay nada seleccionado en ella
        vsBrand.disabled = false;
        vsEngine.innerHTML = '<option value="">Motor...</option>';
        vsEngine.disabled = true;

        if (!yearId) {
            //carga todo
            vsLoadAllBrands();
            return;
        }
        // Filtrar marcas por año
        apiFetch(API + '/brands?year_id=' + yearId + '&mode=' + catalogMode).then(function (data) {
            var brands = data.data || data;
            if (!brands) return;
            vsBrand.innerHTML = '<option value="">Marca...</option>' +
                brands.map(function (b) {
                    return '<option value="' + b.id_brand + '">' + esc(b.name_brand) + '</option>';
                }).join('');
            // si hay marca seleccionada despliega modelos
            if (vsBrand.value) vsBrandChanged();
        });
    }
    function vsLoadAllBrands() {
        apiFetch(API + '/brands?mode=' + catalogMode).then(function (data) {
            var brands = data.data || data;
            if (!brands) return;
            var current = vsBrand.value;
            vsBrand.innerHTML = '<option value="">Marca...</option>' +
                brands.map(function (b) {
                    return '<option value="' + b.id_brand + '">' + esc(b.name_brand) + '</option>';
                }).join('');
            if (current) vsBrand.value = current;
        });
    }

    function vsBrandChanged() {
        var brandId = vsBrand.value;
        var yearId = vsYear.value;
        vsClear.style.display = (yearId || brandId) ? '' : 'none';

        vsModel.innerHTML = '<option value="">Modelo...</option>';
        vsEngine.innerHTML = '<option value="">Motor...</option>';
        vsModel.disabled = false;  // cambio
        vsEngine.disabled = true;

        if (!brandId) {
            vsModel.disabled = true;
            return;
        }

        // Cargar modelos con o sin año
        apiFetch(API + '/models?brand_id=' + brandId + (yearId ? '&year_id=' + yearId : '')).then(function (data) {
            var models = data.data || data;
            if (!models) return;
            vsModel.innerHTML = '<option value="">Modelo...</option>' +
                models.map(function (m) {
                    var variants = (m.variant_ids || [m.id_model]).join(',');
                    return '<option value="' + m.id_model + '" data-variant-ids="' + esc(variants) + '">' + esc(m.display_name || m.name_model) + '</option>';
                }).join('');
            // si hay modelo seleccionado despliega año
            if (vsModel.value) vsModelChanged();
        });
    }


    function vsModelChanged() {
        var modelId = vsModel.value;
        var yearVal = vsYear.value;
        var selectedOption = vsModel.options[vsModel.selectedIndex];
        var variantIds = selectedOption && selectedOption.dataset.variantIds
            ? selectedOption.dataset.variantIds.split(',').map(function(x){ return parseInt(x); })
            : (modelId ? [parseInt(modelId)] : []);

        vsEngine.innerHTML = '<option value="">Motor...</option>';
        vsEngine.disabled = true;

        if (!modelId || !variantIds.length) return;

        // Si hay año carga motores usando todas las variantes del modelo
        if (yearVal) {
            vsEngine.disabled = false;
            apiFetch(API + '/engines?model_id=' + variantIds.join(',') + '&year_id=' + yearVal).then(function (data) {
                var engines = data.data || data;
                if (!engines) return;
                vsEngine.innerHTML = '<option value="">Motor...</option>' +
                    engines.map(function (e) {
                        var name = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
                        var label = name + (e.trim_level ? ' (' + e.trim_level + ')' : '');
                        return '<option value="' + e.id_mye + '">' + esc(label) + '</option>';
                    }).join('');
                if (engines.length === 1) {
                    vsEngine.value = engines[0].id_mye;
                    vsEngineChanged();
                }
            });
        } else {
            // Sin año: cargar categorías a nivel modelo
            var brandId = vsBrand.value;
            if (!brandId) return;
            nav.brand = { id: parseInt(brandId), name: vsBrand.options[vsBrand.selectedIndex].text };
            nav.model = { id: parseInt(modelId), name: vsModel.options[vsModel.selectedIndex].text };
            nav.year = null;
            nav.engine = null;
            nav.level = 'categories';
            pushNavState();
            loadCategoriesForMode();
            setTimeout(function () {
                var body = document.getElementById('pageBody');
                if (body) body.scrollIntoView({ behavior: 'smooth', block: 'start' });
            }, 300);
        }
    }

    function vsEngineChanged() {
        var myeId = vsEngine.value;
        if (!myeId) return;

        // Update state and load categories
        var yearText = vsYear.options[vsYear.selectedIndex].text;
        var brandText = vsBrand.options[vsBrand.selectedIndex].text;
        var modelText = vsModel.options[vsModel.selectedIndex].text;
        var engineText = vsEngine.options[vsEngine.selectedIndex].text;

        var selectedModelOption = vsModel.options[vsModel.selectedIndex];
        var modelVariantIds = selectedModelOption && selectedModelOption.dataset.variantIds
            ? selectedModelOption.dataset.variantIds.split(',').map(function(x){ return parseInt(x); })
            : [parseInt(vsModel.value)];
        nav.brand = { id: parseInt(vsBrand.value), name: brandText };
        nav.model = { id: parseInt(vsModel.value), name: modelText, variant_ids: modelVariantIds };
        nav.year = { id: parseInt(vsYear.value), year: yearText };
        nav.engine = { id_mye: parseInt(myeId), name: engineText };
        nav.level = 'categories';
        pushNavState();

        loadCategoriesForMode();

        // Scroll to catalog content
        setTimeout(function () {
            var body = document.getElementById('pageBody');
            if (body) body.scrollIntoView({ behavior: 'smooth', block: 'start' });
        }, 300);
    }

    function vsClearAll() {
        vsYear.value = '';
        vsBrand.innerHTML = '<option value="">Marca...</option>';
        vsModel.innerHTML = '<option value="">Modelo...</option>';
        vsEngine.innerHTML = '<option value="">Motor...</option>';
        vsBrand.disabled = true;
        vsModel.disabled = true;
        vsEngine.disabled = true;
        vsClear.style.display = 'none';

        nav.level = 'brands'; nav.brand = null; nav.model = null; nav.year = null; nav.engine = null; nav.category = null; nav.group = null; nav.partType = null;
        nav.nxGroup = null; nav.nxSubgroup = null; nav.nxPartType = null;
        currentPage = 1;
        pushNavState();
        loadBrands();
    }

    // ─── EXPOSE GLOBALS (for backward compat) ───
    // ─── BARCODE CAMERA SCAN ───
    function startBarcodeScan() {
        if (!window.NexusNative) {
            alert('El modulo de escaneo no esta cargado.');
            return;
        }
        window.NexusNative.scanBarcode().then(function (code) {
            if (code) {
                searchInput.value = code;
                runSearch(code);
            }
        });
    }

    // ─── PLATE LOOKUP ───
    var plateInputWrap = document.getElementById('plateInputWrap');
    var plateInput = document.getElementById('plateInput');
    var plateStatus = document.getElementById('plateStatus');
    var plateToggle = document.getElementById('plateToggle');

    function togglePlate() {
        var isVisible = plateInputWrap.style.display !== 'none';
        plateInputWrap.style.display = isVisible ? 'none' : '';
        plateToggle.textContent = isVisible ? 'Tienes las placas?' : 'Ocultar placas';
        if (!isVisible && plateInput) plateInput.focus();
    }

    function showPlateStatus(msg, isError) {
        plateStatus.style.display = msg ? '' : 'none';
        plateStatus.textContent = msg;
        plateStatus.style.color = isError ? 'var(--color-error)' : 'var(--color-text-muted)';
    }

    function lookupPlate() {
        var plate = (plateInput.value || '').trim().toUpperCase();
        if (!plate || plate.length < 5) {
            showPlateStatus('Ingresa una placa valida (Ej: ABC-1234).', true);
            return;
        }
        showPlateStatus('Buscando placa...', false);

        apiFetch(API + '/plate/' + encodeURIComponent(plate)).then(function (data) {
            if (!data) {
                showPlateStatus('Error de conexion al buscar placa.', true);
                return;
            }
            if (data.error) {
                showPlateStatus(data.error, true);
                return;
            }
            if (!data.found) {
                plateStatus.style.display = '';
                plateStatus.innerHTML = 'Placa no registrada. <a href="/pos/customers" style="color:var(--color-primary);">Registrar vehiculo</a>';
                plateStatus.style.color = 'var(--color-warning, #e6a700)';
                return;
            }

            var parts = [];
            if (data.year) parts.push(data.year);
            if (data.make) parts.push(data.make);
            if (data.model) parts.push(data.model);
            var label = parts.join(' ') || 'Vehiculo encontrado';

            // If we got a catalog match, auto-fill the dropdowns
            var match = data.catalog_match;
            if (match && match.brand_id) {
                showPlateStatus(label + ' — Cargando catalogo...', false);
                _autoFillFromVin(match, data);
            } else {
                showPlateStatus(label + ' — No encontrado en el catalogo TecDoc.', false);
            }
        });
    }

    if (plateInput) {
        plateInput.addEventListener('keydown', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                lookupPlate();
            }
        });
    }

    // ─── VIN DECODER ───
    var vinInputWrap = document.getElementById('vinInputWrap');
    var vinInput = document.getElementById('vinInput');
    var vinStatus = document.getElementById('vinStatus');
    var vinToggle = document.getElementById('vinToggle');

    function toggleVin() {
        var isVisible = vinInputWrap.style.display !== 'none';
        vinInputWrap.style.display = isVisible ? 'none' : '';
        vinToggle.textContent = isVisible ? 'Tienes el VIN?' : 'Ocultar VIN';
        if (!isVisible && vinInput) vinInput.focus();
    }

    function decodeVin() {
        var vin = (vinInput.value || '').trim().toUpperCase();
        if (vin.length !== 17) {
            showVinStatus('El VIN debe tener exactamente 17 caracteres.', true);
            return;
        }
        showVinStatus('Decodificando VIN...', false);

        apiFetch(API + '/vin/' + encodeURIComponent(vin)).then(function (data) {
            if (!data) {
                showVinStatus('Error de conexion al decodificar VIN.', true);
                return;
            }
            if (data.error && !data.make) {
                showVinStatus(data.error, true);
                return;
            }

            var parts = [];
            if (data.year) parts.push(data.year);
            if (data.make) parts.push(data.make);
            if (data.model) parts.push(data.model);
            if (data.engine) parts.push(data.engine);
            var label = parts.join(' ') || 'Vehiculo no reconocido';

            // If we got a catalog match, auto-fill the dropdowns
            var match = data.catalog_match;
            if (match && match.brand_id) {
                showVinStatus(label + ' — Encontrado en catalogo, cargando...', false);
                _autoFillFromVin(match, data);
            } else {
                showVinStatus(label + ' — No encontrado en el catalogo TecDoc.', false);
            }
        });
    }

    function _autoFillFromVin(match, vinData) {
        // Set year dropdown
        if (match.year_id) {
            vsYear.value = String(match.year_id);
            // Trigger brand load
            apiFetch(API + '/brands?year_id=' + match.year_id).then(function (brandData) {
                var brands = brandData && (brandData.data || brandData);
                if (!brands) return;
                vsBrand.innerHTML = '<option value="">Marca...</option>' +
                    brands.map(function (b) {
                        return '<option value="' + b.id_brand + '">' + esc(b.name_brand) + '</option>';
                    }).join('');
                vsBrand.disabled = false;
                vsClear.style.display = '';

                if (match.brand_id) {
                    vsBrand.value = String(match.brand_id);
                    // Load models
                    apiFetch(API + '/models?brand_id=' + match.brand_id + '&year_id=' + match.year_id).then(function (modelData) {
                        var models = modelData && (modelData.data || modelData);
                        if (!models) return;
                        vsModel.innerHTML = '<option value="">Modelo...</option>' +
                            models.map(function (m) {
                                var variants = (m.variant_ids || [m.id_model]).join(',');
                                return '<option value="' + m.id_model + '" data-variant-ids="' + esc(variants) + '">' + esc(m.display_name || m.name_model) + '</option>';
                            }).join('');
                        vsModel.disabled = false;

                        if (match.model_id) {
                            // The VIN match may point to a variant that is now grouped under
                            // a canonical model; select the option whose variants include it.
                            var matchedOption = Array.from(vsModel.options).find(function (opt) {
                                if (!opt.value) return false;
                                var vids = (opt.dataset.variantIds || opt.value).split(',').map(function(x){ return parseInt(x); });
                                return vids.indexOf(match.model_id) !== -1;
                            });
                            if (matchedOption) {
                                vsModel.value = matchedOption.value;
                            } else {
                                vsModel.value = String(match.model_id);
                            }
                            var selectedVariantIds = vsModel.selectedIndex >= 0 && vsModel.options[vsModel.selectedIndex].dataset.variantIds
                                ? vsModel.options[vsModel.selectedIndex].dataset.variantIds.split(',').map(function(x){ return parseInt(x); })
                                : [match.model_id];
                            // Load engines
                            apiFetch(API + '/engines?model_id=' + selectedVariantIds.join(',') + '&year_id=' + match.year_id).then(function (engData) {
                                var engines = engData && (engData.data || engData);
                                if (!engines) return;
                                vsEngine.innerHTML = '<option value="">Motor...</option>' +
                                    engines.map(function (e) {
                                        var ename = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
                                        var elabel = ename + (e.trim_level ? ' (' + e.trim_level + ')' : '');
                                        return '<option value="' + e.id_mye + '">' + esc(elabel) + '</option>';
                                    }).join('');
                                vsEngine.disabled = false;

                                // Auto-select engine if only one or if match specifies it
                                if (match.id_mye) {
                                    vsEngine.value = String(match.id_mye);
                                    vsEngineChanged();
                                    showVinStatus('Vehiculo cargado desde VIN.', false);
                                } else if (engines.length === 1) {
                                    vsEngine.value = engines[0].id_mye;
                                    vsEngineChanged();
                                    showVinStatus('Vehiculo cargado desde VIN.', false);
                                } else {
                                    showVinStatus('Selecciona el motor para continuar.', false);
                                }
                            });
                        }
                    });
                }
            });
        }
    }

    function showVinStatus(msg, isError) {
        vinStatus.style.display = msg ? '' : 'none';
        vinStatus.textContent = msg;
        vinStatus.style.color = isError ? 'var(--color-error)' : 'var(--color-text-muted)';
    }

    // Allow Enter key in VIN input to trigger decode
    if (vinInput) {
        vinInput.addEventListener('keydown', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                decodeVin();
            }
        });
    }

    // ─── Supplier prices upload ─────────────────────────────────────────────
    function openUploadPricesModal() {
        if (uploadPricesModal) uploadPricesModal.style.display = 'flex';
        if (uploadPricesStatus) uploadPricesStatus.innerHTML = '';
        if (uploadPricesFile) uploadPricesFile.value = '';
    }
    function closeUploadPricesModal() {
        if (uploadPricesModal) uploadPricesModal.style.display = 'none';
    }
    async function submitUploadPrices() {
        if (!uploadPricesFile || !uploadPricesFile.files || !uploadPricesFile.files[0]) {
            if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-error);">Selecciona un archivo primero.</span>';
            return;
        }
        var form = new FormData();
        form.append('file', uploadPricesFile.files[0]);
        if (uploadPricesStatus) uploadPricesStatus.innerHTML = 'Subiendo...';
        try {
            var res = await fetch('/pos/api/supplier-catalog/prices/upload', {
                method: 'POST',
                headers: { 'Authorization': 'Bearer ' + token },
                body: form
            });
            var data = await res.json();
            if (res.ok && data.success) {
                if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-success);">✓ Precios actualizados: ' + data.processed + ' (insertados: ' + data.inserted + ', actualizados: ' + data.updated + ')</span>';
                uploadPricesFile.value = '';
            } else {
                var msg = data.error || 'Error al subir precios';
                var details = (data.details || []).join('<br>');
                if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-error);">' + esc(msg) + '</span>' + (details ? '<div style="margin-top:4px;font-size:0.9em;">' + details + '</div>' : '');
            }
        } catch (e) {
            if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-error);">Error de red: ' + esc(e.message) + '</span>';
        }
    }

    async function downloadPriceTemplate() {
        try {
            var res = await fetch('/pos/api/supplier-catalog/prices/template', {
                headers: { 'Authorization': 'Bearer ' + token }
            });
            if (!res.ok) {
                var data = await res.json().catch(function() { return {}; });
                if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-error);">' + esc(data.error || 'Error al descargar plantilla') + '</span>';
                return;
            }
            var blob = await res.blob();
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = 'supplier_prices_template.csv';
            document.body.appendChild(a);
            a.click();
            a.remove();
            URL.revokeObjectURL(url);
            if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-success);">✓ Plantilla descargada.</span>';
        } catch (e) {
            if (uploadPricesStatus) uploadPricesStatus.innerHTML = '<span style="color:var(--color-error);">Error de red: ' + esc(e.message) + '</span>';
        }
    }

    function shouldShowUploadPricesButton() {
        try {
            var user = JSON.parse(localStorage.getItem('pos_employee') || '{}');
            return user.role === 'owner' || user.role === 'admin';
        } catch (e) { return false; }
    }
    if (uploadPricesBtn && shouldShowUploadPricesButton()) {
        uploadPricesBtn.style.display = 'inline-flex';
    }

    window.CatalogApp = {
        toggleCart: toggleCart,
        goToCheckout: goToCheckout,
        addToCart: addToCart,
        removeFromCart: removeFromCart,
        updateQty: updateQuantity,
        clearCart: clearCart,
        loadPage: function (p) { loadParts(p); },
        vsYearChanged: vsYearChanged,
        vsBrandChanged: vsBrandChanged,
        vsModelChanged: vsModelChanged,
        vsEngineChanged: vsEngineChanged,
        vsClear: vsClearAll,
        startBarcodeScan: startBarcodeScan,
        toggleVin: toggleVin,
        decodeVin: decodeVin,
        togglePlate: togglePlate,
        lookupPlate: lookupPlate,
        setMode: setCatalogMode,
        openUploadPricesModal: openUploadPricesModal,
        closeUploadPricesModal: closeUploadPricesModal,
        submitUploadPrices: submitUploadPrices,
        downloadPriceTemplate: downloadPriceTemplate,
    };

    // ─── INIT ───
    renderCart();
    updateModeToggleUI();
    vsLoadYears();
    loadBrands();

})();
