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

    /* ── Format price ──────────────────────────────────── */
    function fmt(val) {
        return SYM + Number(val).toFixed(DP);
    }

    /* ── 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 => subtotal += i.price * i.quantity);
        const vatAmt = parseFloat((subtotal * VAT / 100).toFixed(DP));
        const grand  = parseFloat((subtotal + vatAmt).toFixed(DP));
        return { id:'current', subtotal, discount:0, 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 onclick="gposChangeQty(${item.productId}, -1)">−</button>
                        <span>${item.quantity}</span>
                        <button onclick="gposChangeQty(${item.productId}, 1)">+</button>
                    </div>
                    <div class="gpos-ci-price">${fmt(item.price * item.quantity)}</div>
                    <button class="gpos-ci-del" onclick="gposRemove(${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 });
        }
    }

    async function addToCart(product, qty = 1) {
        const existing = cartItems.find(i => i.productId === product.id);
        if (existing) {
            existing.quantity += qty;
        } else {
            cartItems.push({
                id: product.id,
                productId: product.id,
                name: product.name,
                price: parseFloat(product.price),
                quantity: qty,
                image: product.image || ''
            });
        }
        // Track recent
        recentProdIds = [product.id, ...recentProdIds.filter(x => x !== product.id)].slice(0, 8);
        renderRecentRow();
        renderCart();
        await saveCartoDB();

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

    window.gposChangeQty = async function(productId, delta) {
        const item = cartItems.find(i => i.productId === productId);
        if (!item) return;
        item.quantity = Math.max(1, item.quantity + delta);
        renderCart();
        await saveCartoDB();
    };

    window.gposRemove = async function(productId) {
        cartItems = cartItems.filter(i => i.productId !== productId);
        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 isLow = 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>`;

            return `
                <div class="gpos-card ${stock === 0 ? '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>' : '<span class="gpos-stock-badge ok">✓</span>'}
                    ${imgHtml}
                    <div class="gpos-card-name">${p.name}</div>
                    <div class="gpos-card-price">${fmt(p.price)}</div>
                    <div class="gpos-card-stock">Stock: ${stock}</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 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
        cartItems = await loadCartFromDB();
        renderCart();

        // 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));

})();
