// static/js/pos_grid.js — SwiftPOS Grid POS V2
// Depends on: product-cache.js (swiftposLoadProducts, swiftposRefreshProducts)
// Depends on: order-sync.js (setupOrderSubmit, syncPendingOrders)
// Uses the same IndexedDB cart as pos-cart.js via swiftposOpenDB

'use strict';

(function () {

    /* ── State ─────────────────────────────────────────── */
    let allProducts   = [];      // all loaded products
    let filteredProds = [];      // currently shown
    let cartItems     = [];      // [{id, productId, name, price, quantity, image}]
    let recentProdIds = [];      // last 8 added (in session)
    let currentCat    = 'all';
    let searchQuery   = '';
    let longPressTimer = null;
    let longPressProduct = null;
    let db = null;

    const SYM = window.swiftposCurrencySymbol || '₦';
    const VAT = window.swiftposVatRate || 0;
    const DP  = window.swiftposDecimalPlaces || 2;

    /* ── DOM refs ──────────────────────────────────────── */
    const grid         = document.getElementById('gpos-grid');
    const catsBar      = document.getElementById('gpos-cats');
    const searchInput  = document.getElementById('gpos-search');
    const cartEl       = document.getElementById('gpos-cart-items');
    const emptyCart    = document.getElementById('gpos-empty-cart');
    const cartCount    = document.getElementById('gpos-cart-count');
    const stickyCount  = document.getElementById('gpos-sticky-count');
    const totalEl      = document.getElementById('gpos-total');
    const subtotalEl   = document.getElementById('gpos-subtotal');
    const vatEl        = document.getElementById('gpos-vat');
    const stickyTotal  = document.getElementById('gpos-sticky-total');
    const submitBtn    = document.getElementById('gpos-submit-btn');
    const clearBtn     = document.getElementById('gpos-clear-cart');
    const payStatus    = document.getElementById('gpos-pay-status');
    const amtGroup     = document.getElementById('gpos-amount-paid-group');
    const refreshBtn   = document.getElementById('gpos-refresh-btn');
    const offlineBann  = document.getElementById('gpos-offline-banner');
    const recentWrap   = document.getElementById('gpos-recent-wrap');
    const recentRow    = document.getElementById('gpos-recent-row');

    const USE_COMMA = window.swiftposUseCommaSeparator || false;

    /* ── Format price ──────────────────────────────────── */
    function fmt(val) {
        let num = Number(val).toFixed(DP);
        if (USE_COMMA) {
            let parts = num.split(".");
            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
            num = parts.join(".");
        }
        return SYM + num;
    }

    /* ── Resolve price (base vs wholesale) ─────────────── */
    function resolveItemPrice(item) {
        const base = parseFloat(item.basePrice) || 0;
        const wsP  = parseFloat(item.wholesalePrice) || 0;
        const wsQ  = parseInt(item.wholesaleMinQty) || 0;
        if (wsP > 0 && wsQ > 0 && item.quantity >= wsQ) {
            return wsP;
        }
        return base;
    }

    /* ── IndexedDB cart persistence (reuse pos-cart.js stores) ─── */
    async function getDB() {
        if (db) return db;
        db = await window.swiftposOpenDB();
        return db;
    }

    async function saveCartoDB() {
        const d = await getDB();
        return new Promise(resolve => {
            const tx = d.transaction(['cart_items','cart_totals'],'readwrite');
            const si = tx.objectStore('cart_items');
            const st = tx.objectStore('cart_totals');
            si.clear();
            cartItems.forEach(item => si.put(item));
            const totals = calcTotals();
            st.put({ id: 'current', ...totals });
            tx.oncomplete = () => resolve();
        });
    }

    async function loadCartFromDB() {
        const d = await getDB();
        return new Promise(resolve => {
            const tx = d.transaction('cart_items','readonly');
            const req = tx.objectStore('cart_items').getAll();
            req.onsuccess = () => resolve(req.result || []);
        });
    }

    /* ── Cart logic ────────────────────────────────────── */
    function calcTotals() {
        let subtotal = 0;
        cartItems.forEach(i => {
            i.price = resolveItemPrice(i);  // re-resolve wholesale on every recalc
            subtotal += i.price * i.quantity;
        });
        const promoDisc = window.gposPromoDiscount || 0;
        const discountedSub = Math.max(0, subtotal - promoDisc);
        const vatAmt = parseFloat((discountedSub * VAT / 100).toFixed(DP));
        const grand  = parseFloat((discountedSub + vatAmt).toFixed(DP));
        
        // Expose original subtotal vs discounted if needed
        return { id:'current', subtotal, discount: promoDisc, tax: vatAmt, grandTotal: grand };
    }


    function renderCart() {
        const totals = calcTotals();
        const count  = cartItems.reduce((s,i) => s + i.quantity, 0);

        // counts
        if (cartCount)   cartCount.textContent   = count;
        if (stickyCount) stickyCount.textContent  = count;

        // totals
        if (subtotalEl)  subtotalEl.textContent  = fmt(totals.subtotal);
        if (vatEl)       vatEl.textContent        = fmt(totals.tax);
        if (totalEl)     totalEl.textContent      = fmt(totals.grandTotal);
        if (stickyTotal) stickyTotal.textContent  = fmt(totals.grandTotal);

        // submit btn
        if (submitBtn) submitBtn.disabled = cartItems.length === 0;

        // cart rows
        if (cartEl) {
            if (cartItems.length === 0) {
                cartEl.innerHTML = `
                    <div id="gpos-empty-cart" class="text-center py-5 text-muted">
                        <i class="fas fa-shopping-cart fa-2x opacity-25 d-block mb-2"></i>
                        <small>Tap a product to add it</small>
                    </div>`;
                return;
            }

            cartEl.innerHTML = cartItems.map(item => `
                <div class="gpos-cart-item" data-id="${item.productId}">
                    <div class="gpos-ci-name">${item.name}</div>
                    <div class="gpos-ci-qty">
                        <button type="button" class="gpos-qty-btn" data-action="dec" data-product-id="${item.productId}" title="Decrease">−</button>
                        <span>${item.quantity}</span>
                        <button type="button" class="gpos-qty-btn" data-action="inc" data-product-id="${item.productId}" title="Increase">+</button>
                    </div>
                    <div class="gpos-ci-price">${fmt(item.price * item.quantity)}</div>
                    <button type="button" class="gpos-ci-del" data-action="remove" data-product-id="${item.productId}" title="Remove">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
            `).join('');
        }

        // hidden payload
        const payload = document.getElementById('cart-payload-field');
        if (payload) {
            payload.value = JSON.stringify({ items: cartItems, totals });
        }
    }
    window.gposRenderCart = renderCart;

    async function _coreAddToCart(product, qty = 1) {
        const cartId = product._cart_id || product.id; // Use variant-specific ID if provided
        const existing = cartItems.find(i => i.productId === cartId);
        if (existing) {
            existing.quantity += qty;
            existing.price = resolveItemPrice(existing);  // re-check wholesale
        } else {
            const basePrice       = parseFloat(product.price) || 0;
            const wholesalePrice  = parseFloat(product.wholesale_price || product.wholesalePrice || 0);
            const wholesaleMinQty = parseInt(product.wholesale_min_quantity || product.wholesale_min_qty  || product.wholesaleMinQty  || 0);
            const newItem = {
                id: cartId,
                productId: cartId, // string or int
                parentProductId: product.id,
                variantId: product.variant_id || null,
                name: product.name,
                basePrice,
                wholesalePrice,
                wholesaleMinQty,
                price: basePrice,   // will be resolved below
                quantity: qty,
                image: product.image || ''
            };
            newItem.price = resolveItemPrice(newItem);
            cartItems.push(newItem);
        }
        // Track recent (always by parent product id)
        recentProdIds = [product.parentProductId || product.id, ...recentProdIds.filter(x => x !== (product.parentProductId || product.id))].slice(0, 8);
        renderRecentRow();
        renderCart();
        await saveCartoDB();

        // Flash card
        const card = grid.querySelector(`[data-product-id="${product.parentProductId || product.id}"]`);
        if (card) {
            card.classList.add('just-added');
            setTimeout(() => card.classList.remove('just-added'), 350);
        }
    }

    async function addToCart(product, qty = 1) {
        // If product has variants, intercept and show the picker first
        if (product.has_variants && product.variants && product.variants.length > 0 && window.swiftVariantPicker) {
            window.swiftVariantPicker.open(product, async function(chosen) {
                var vp = Object.assign({}, product, {
                    _cart_id: product.id + '-' + chosen.id,
                    parentProductId: product.id,
                    variant_id: chosen.id,
                    name: product.name + ' (' + chosen.display_label + ')',
                    price: chosen.price,
                    stock_quantity: chosen.stock_quantity
                });
                await _coreAddToCart(vp, qty);
            });
        } else {
            await _coreAddToCart(product, qty);
        }
    }

    window.gposChangeQty = async function(productId, delta) {
        // kept for external use; internally the cart uses event delegation
        const item = cartItems.find(i => String(i.productId) === String(productId));
        if (!item) return;
        item.quantity = Math.max(1, item.quantity + delta);
        item.price = resolveItemPrice(item);
        renderCart();
        await saveCartoDB();
    };

    window.gposRemove = async function(productId) {
        cartItems = cartItems.filter(i => String(i.productId) !== String(productId));
        renderCart();
        await saveCartoDB();
    };

    /* ── Cart event delegation (same pattern as classic POS) ── */
    function setupCartDelegation() {
        const el = document.getElementById('gpos-cart-items');
        if (!el) return;
        el.addEventListener('click', async function(e) {
            // qty +/- buttons
            const qtyBtn = e.target.closest('.gpos-qty-btn');
            if (qtyBtn) {
                e.preventDefault();
                const pid   = qtyBtn.dataset.productId;
                const delta = qtyBtn.dataset.action === 'inc' ? 1 : -1;
                const item  = cartItems.find(i => String(i.productId) === String(pid));
                if (item) {
                    item.quantity = Math.max(1, item.quantity + delta);
                    item.price = resolveItemPrice(item);
                    renderCart();
                    await saveCartoDB();
                }
                return;
            }
            // remove button
            const delBtn = e.target.closest('.gpos-ci-del');
            if (delBtn) {
                e.preventDefault();
                const pid = delBtn.dataset.productId;
                cartItems = cartItems.filter(i => String(i.productId) !== String(pid));
                renderCart();
                await saveCartoDB();
            }
        });
    }

    async function clearCart() {
        cartItems = [];
        renderCart();
        await saveCartoDB();
    }

    /* ── Product grid rendering ────────────────────────── */
    function renderGrid(products) {
        if (!grid) return;
        if (products.length === 0) {
            grid.innerHTML = `<div class="col-span-full text-center py-5 text-muted" style="grid-column:1/-1;">
                <i class="fas fa-box-open fa-2x opacity-25 d-block mb-2"></i>
                <small>No products found</small>
            </div>`;
            return;
        }

        grid.innerHTML = products.map(p => {
            const stock = Number(p.stock_quantity);
            const UNLIMITED = window.swiftposUnlimitedStock || false;
            const isOutOfStock = !UNLIMITED && stock === 0;
            const isLow = !UNLIMITED && stock > 0 && stock <= 5;
            const imgHtml = p.image
                ? `<img class="gpos-card-img" src="${p.image}" alt="${p.name}" loading="lazy">`
                : `<div class="gpos-card-img-placeholder"><i class="fas fa-box"></i></div>`;
            const wsPrice  = parseFloat(p.wholesale_price || 0);
            const wsMinQty = parseInt(p.wholesale_min_quantity || p.wholesale_min_qty || 0);
            const wsNote   = wsPrice > 0 && wsMinQty > 0
                ? `<div class="gpos-card-ws" title="Wholesale: ${SYM}${wsPrice.toFixed(DP)} for ${wsMinQty}+">WS: ${SYM}${wsPrice.toFixed(DP)} @ ${wsMinQty}+</div>`
                : '';
            
            const hasVariants = p.has_variants && p.variants && p.variants.length > 0;
            const variantBadge = hasVariants ? `<span class="gpos-stock-badge" style="background:#6366f1; left:auto; right: 0.8rem; top: 0.8rem;" title="Has Variants"><i class="fas fa-layer-group"></i> Variants</span>` : '';
            
            const stockDisplay = UNLIMITED ? '∞ Unlimited' : `Stock: ${stock}`;

            return `
                <div class="gpos-card ${isOutOfStock ? 'out-of-stock' : ''}"
                     data-product-id="${p.id}"
                     data-cat="${(p.category || '').toLowerCase()}"
                     title="${p.name}">
                    ${isLow ? '<span class="gpos-stock-badge low">Low</span>' : UNLIMITED ? '<span class="gpos-stock-badge ok" style="background:#8b5cf6">∞</span>' : '<span class="gpos-stock-badge ok">✓</span>'}
                    ${variantBadge}
                    ${imgHtml}
                    <div class="gpos-card-name">${p.name}</div>
                    <div class="gpos-card-price">${fmt(p.price)}</div>
                    ${wsNote}
                    <div class="gpos-card-stock">${stockDisplay}</div>
                    <button class="gpos-add-btn" onclick="event.stopPropagation();" title="Add">+</button>
                </div>
            `;
        }).join('');

        // Bind events
        grid.querySelectorAll('.gpos-card').forEach(card => {
            const pid   = parseInt(card.dataset.productId);
            const prod  = products.find(p => p.id === pid);
            if (!prod) return;

            // Tap = instant add
            card.addEventListener('click', () => addToCart(prod, 1));

            // Long-press = quantity modal
            card.addEventListener('pointerdown', () => {
                longPressTimer = setTimeout(() => {
                    card.classList.add('long-pressing');
                    openQtyModal(prod);
                }, 600);
            });
            card.addEventListener('pointerup',    cancelLongPress);
            card.addEventListener('pointerleave', cancelLongPress);
        });

        // Add button (prevent double-fire)
        grid.querySelectorAll('.gpos-add-btn').forEach(btn => {
            btn.addEventListener('click', e => {
                e.stopPropagation();
                const card = btn.closest('.gpos-card');
                const pid  = parseInt(card.dataset.productId);
                const prod = products.find(p => p.id === pid);
                if (prod) addToCart(prod, 1);
            });
        });
    }

    function cancelLongPress() {
        clearTimeout(longPressTimer);
        grid.querySelectorAll('.gpos-card.long-pressing').forEach(c => c.classList.remove('long-pressing'));
    }

    /* ── Category chips ─────────────────────────────────── */
    function buildCategoryChips(products) {
        const cats = ['all', ...new Set(products.map(p => p.category).filter(Boolean))];
        if (!catsBar) return;
        catsBar.innerHTML = cats.map(cat => {
            const catLower = cat.toLowerCase();
            return `<button type="button" class="gpos-cat-btn ${catLower === currentCat ? 'active' : ''}" data-cat="${catLower}">
                ${cat === 'all' ? '🏷 All' : cat}
            </button>`;
        }).join('');
        catsBar.querySelectorAll('.gpos-cat-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                currentCat = btn.dataset.cat; // already lowercase from data-cat
                catsBar.querySelectorAll('.gpos-cat-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                applyFilters();
            });
        });
    }

    /* ── Search + filter ────────────────────────────────── */
    function applyFilters() {
        let products = allProducts;
        if (currentCat !== 'all') {
            products = products.filter(p => (p.category || '').toLowerCase() === currentCat);
        }
        if (searchQuery.trim()) {
            const q = searchQuery.toLowerCase();
            products = products.filter(p =>
                p.name.toLowerCase().includes(q) ||
                (p.sku || '').toLowerCase().includes(q) ||
                (p.barcode || '').toLowerCase().includes(q)
            );
        }
        filteredProds = products;
        renderGrid(filteredProds);
    }

    /* ── Recent row ─────────────────────────────────────── */
    function renderRecentRow() {
        if (!recentRow || !recentWrap) return;
        if (recentProdIds.length === 0) { recentWrap.style.display = 'none'; return; }
        recentWrap.style.display = '';
        recentRow.innerHTML = recentProdIds.map(id => {
            const p = allProducts.find(x => x.id === id);
            if (!p) return '';
            return `<div class="gpos-recent-chip" onclick="gposRecentAdd(${p.id})">
                <i class="fas fa-history fa-xs"></i>${p.name}
            </div>`;
        }).join('');
    }

    window.gposRecentAdd = async function(pid) {
        const prod = allProducts.find(p => p.id === pid);
        if (prod) await addToCart(prod, 1);
    };

    /* ── Long-press quantity modal ───────────────────────── */
    let qtyModalProduct = null;

    function openQtyModal(product) {
        qtyModalProduct = product;
        const nameEl = document.getElementById('gpos-modal-product-name');
        const qtyEl  = document.getElementById('gpos-modal-qty');
        if (nameEl) nameEl.textContent = product.name;
        if (qtyEl)  qtyEl.value = 1;

        const modalEl = document.getElementById('gposQtyModal');
        if (modalEl && window.bootstrap) {
            // Use getOrCreateInstance to avoid stacking backdrops
            const modal = bootstrap.Modal.getOrCreateInstance(modalEl);
            modal.show();
        }
    }

    /* ── Load products ──────────────────────────────────── */
    async function loadGridProducts(forceRefresh = false) {
        grid.innerHTML = '<div class="gpos-skeleton"></div>'.repeat(8);
        try {
            const products = forceRefresh
                ? await window.swiftposRefreshProducts()
                : await window.swiftposLoadProducts();
            allProducts = products || [];
            buildCategoryChips(allProducts);
            applyFilters();
        } catch (err) {
            console.error('GPOS: error loading products', err);
            grid.innerHTML = `<div style="grid-column:1/-1" class="text-center text-muted py-4">
                <small>Error loading products. Check connection.</small>
            </div>`;
        }
    }

    /* ── Init ───────────────────────────────────────────── */
    document.addEventListener('DOMContentLoaded', async function () {
        // Load persisted cart or preloaded cart from repeat sale
        if (window.gposPreloadCart) {
            cartItems = window.gposPreloadCart;
            window.gposPreloadCart = null;
            await saveCartoDB();
        } else {
            cartItems = await loadCartFromDB();
        }
        renderCart();
        setupCartDelegation(); // attach delegated cart click handler

        // Load products
        await loadGridProducts(false);

        // Search
        if (searchInput) {
            searchInput.addEventListener('input', () => {
                searchQuery = searchInput.value;
                applyFilters();
            });
        }

        // Refresh
        if (refreshBtn) refreshBtn.addEventListener('click', () => loadGridProducts(true));

        // Clear cart
        if (clearBtn) clearBtn.addEventListener('click', clearCart);

        // Offline banner
        function updateOffline() {
            if (offlineBann) offlineBann.classList.toggle('d-none', navigator.onLine);
        }
        updateOffline();
        window.addEventListener('online',  () => { updateOffline(); loadGridProducts(true); });
        window.addEventListener('offline', updateOffline);

        // Payment status → amount paid visibility
        if (payStatus) {
            payStatus.addEventListener('change', () => {
                if (amtGroup) amtGroup.classList.toggle('d-none', payStatus.value === 'full');
            });
        }

        // Qty modal: confirm
        const confirmBtn = document.getElementById('gpos-modal-confirm');
        const minusBtn   = document.getElementById('gpos-modal-minus');
        const plusBtn    = document.getElementById('gpos-modal-plus');
        const qtyIn      = document.getElementById('gpos-modal-qty');

        if (confirmBtn) {
            confirmBtn.addEventListener('click', async () => {
                if (!qtyModalProduct || !qtyIn) return;
                const qty = Math.max(1, parseInt(qtyIn.value || '1'));
                await addToCart(qtyModalProduct, qty);
                const modalEl = document.getElementById('gposQtyModal');
                bootstrap.Modal.getOrCreateInstance(modalEl)?.hide();
            });
        }
        if (minusBtn && qtyIn) minusBtn.addEventListener('click', () => qtyIn.value = Math.max(1, parseInt(qtyIn.value) - 1));
        if (plusBtn  && qtyIn) plusBtn.addEventListener('click',  () => qtyIn.value = parseInt(qtyIn.value) + 1);

        // Sync pending offline orders
        if (window.swiftposSyncOrders) await window.swiftposSyncOrders();

        // Expose clearCart for order-sync.js
        if (!window.swiftposCart) window.swiftposCart = {};
        window.swiftposCart.clearCart = clearCart;
        window.swiftposCart.loadCartFromDB = loadCartFromDB;
    });

    // Auto-refresh when online
    window.addEventListener('online', () => loadGridProducts(true));

})();
