window.xbrand = '001'; 
window.xcab = '002';

// main.js - Versi Final Lengkap dengan Perbaikan
import EscPosEncoder from 'https://cdn.jsdelivr.net/npm/esc-pos-encoder@3.0.0/+esm';

const { createApp, reactive } = Vue;

createApp({
    data() {
        return {
            pos: {}, // <--- BARU
            // ... (data lainnya)
            products: [],
            isLoading: true,
            currentView: 'welcome', // welcome, kiosk, cart, success
            customerName: '',
            customerPhone: '',
            lastTransactionId: '',
            searchQuery: '',
            sidebarTab: 'kategori',
            activeCategory: null,
            activeBrand: null,
            isBestSellerActive: false,
            isKeyboardVisible: false,
            keyboardTarget: null,
            cart: [],
            isDetailVisible: false,
            selectedProduct: null,
            modalSelections: {},
            modalSelectedAddons: [],
            modalCondimentChoices: {},
            // BARU: Counter untuk membuat ID unik untuk setiap toping group
            uniqueIdCounter: 0,
            variantLabels: { color: 'Warna', size: 'Ukuran', type: 'Tipe', temp: 'Suhu', storage: 'Penyimpanan', memory: 'Memori', aroma: 'Aroma' },
            keyboardLayout: [
                ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
                ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
                ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
                ['Space','z', 'x', 'c', 'v', 'b', 'n', 'm', 'Backspace', 'Enter'],
                []
            ],
            sidebarState: reactive({}),
        };
    },
    computed: {
        // ... (computed properties)
        flatCategories() {
            if (!this.products || this.products.length === 0) return [];
            // Buat Set untuk mendapatkan nama grup yang unik, dan filter nilai yang kosong
            const groups = new Set(this.products.map(p => p.group_name).filter(Boolean));
            // Ubah Set menjadi array dan urutkan
            return Array.from(groups).sort();
        },
        structuredBrands() {
            const brands = new Set(this.products.map(p => p.brand_name));
            return this.buildHierarchy(brands);
        },
        filteredProducts() {
            let prods = this.products;

            if (this.isBestSellerActive) {
                prods = prods.filter(p => p.is_best_seller);
            } else if (this.activeCategory) {
                // DIUBAH: Filter berdasarkan group_name yang flat
                prods = prods.filter(p => p.group_name === this.activeCategory);
            } else if (this.activeBrand) {
                prods = prods.filter(p => p.brand_name.startsWith(this.activeBrand));
            }

            if (this.searchQuery) {
                const query = this.searchQuery.toLowerCase();
                prods = prods.filter(p => p.name.toLowerCase().includes(query) || p.brand_name.toLowerCase().includes(query) || p.description.toLowerCase().includes(query));
            }
            return prods;
        },
        variantAttributes() {
            if (!this.selectedProduct) return [];
            const keys = new Set();
            this.selectedProduct.variants.forEach(variant => {
                if (variant.attributes && typeof variant.attributes === 'object') {
                    Object.keys(variant.attributes).forEach(key => keys.add(key));
                }
            });
            return Array.from(keys);
        },
        cartTotal() { return this.cart.reduce((total, item) => total + (item.finalPrice * item.quantity), 0); },
        cartItemCount() { return this.cart.reduce((count, item) => count + item.quantity, 0); },
        modalSelectedVariant() {
            if (!this.selectedProduct || !this.modalSelections) {
                return this.selectedProduct?.variants?.[0] || null;
            }
            return this.selectedProduct.variants.find(v =>
                this.variantAttributes.every(key => v.attributes[key] === this.modalSelections[key])
            ) || null;
        },
        modalFinalPrice() {
            if (!this.selectedProduct) return 0;
            const addonTotal = this.modalSelectedAddons.reduce((sum, addon) => sum + addon.price, 0);
            const condimentTotal = Object.values(this.modalCondimentChoices).flat().reduce((sum, choice) => sum + (choice.price || 0), 0);
            return this.selectedProduct.base_price + addonTotal + condimentTotal;
        },
        isModalFormValid() {
            if (!this.selectedProduct || !this.modalSelectedVariant || this.modalSelectedVariant.stock === 0) return false;
            return (this.selectedProduct.condiment_groups || []).every(group => {
                if (!group.is_required) return true;
                const choice = this.modalCondimentChoices[group.uniqueId]; // PERBAIKAN: gunakan uniqueId
                if (group.type === 'radio') return !!choice && Object.keys(choice).length > 0;
                if (group.type === 'checkbox') return choice && choice.length > 0;
                return true;
            });
        }
    },
  
    methods: {

        async loadPosConfig() {
            try {
                // Perintah ambil('pos', 'kode', '', 'zz') untuk mengambil semua data 
                const response = await ambil('pos', 'kode', '', 'zz'); 
                
                if (response && Array.isArray(response) && response.length > 0) {
                    this.pos = {};
                    response.forEach(item => {
                        // Memuat data dengan item.kode sebagai kunci dan item.isi sebagai nilai
                        this.pos[item.kode] = item.isi; 
                    });
                    console.log('✅ Konfigurasi POS berhasil dimuat:', this.pos);
                    
                    // LAKUKAN PENYESUAIAN PRINTER DI SINI (Contoh)
                    // Ambil nama printer dari konfigurasi pos, atau gunakan default
                    this.printerName = this.pos['NAMA_PRINTER'] || 'Nama Printer Kasir Default';
                    this.printerPort = this.pos['PORT_PRINTER'] || 'LPT1';
                    alert(this.pos.nama);

                } else if (response && response.error) {
                     throw new Error(response.error);
                } else {
                    console.warn('⚠️ Tabel pos kosong atau tidak ada data yang dikembalikan.');
                }
            } catch (error) {
                console.error('❌ Gagal memuat konfigurasi POS:', error.message);
            }
        },        
        
        // BARU: Method untuk generate ID unik
        generateUniqueId() {
            return `uid_${Date.now()}_${++this.uniqueIdCounter}_${Math.random().toString(36).substr(2, 9)}`;
        },

        // PERBAIKAN: Method untuk clear search
        clearSearch() {
            this.searchQuery = '';
        },

        // DIUBAH: Mengambil data produk dari API menggunakan this.pos.kiosk_server_data
        async fetchAllProducts() {
            this.isLoading = true;
            // Gunakan konfigurasi dari this.pos, dengan fallback URL
            const apiUrl = this.pos.kiosk_server_data || "http://localhost/bener/kiosk/api_server.php"; 
            
            try {
                // MENGGUNAKAN apiUrl YANG SUDAH DITENTUKAN
                const response = await $.ajax({
                    url: apiUrl,
                    type: "GET",
                    data: { action: 'get_products' },
                    dataType: 'json',
                    timeout: 30000 // 30 detik timeout
                });

                // Handle response format baru
                if (response && response.success && Array.isArray(response.data)) {
                    this.products = response.data;
                    console.log(`Berhasil memuat ${response.count} produk dari ${apiUrl}`);
                } else {
                    throw new Error(response.error || "Format data tidak sesuai");
                }
                
            } catch (error) {
                console.error("Gagal memuat produk:", error);
                
                // Error handling yang lebih baik
                if (error.status === 0) {
                    alert(`Tidak dapat terhubung ke server. Pastikan server API berjalan di: ${apiUrl}`);
                } else {
                    alert(`Error: ${error.responseJSON?.error || error.message || 'Tidak dapat memuat data produk'}`);
                }
                
                this.products = [];
            } finally {
                this.isLoading = false;
            }
        },

        // DIUBAH: Menyimpan transaksi dan memanggil fungsi cetak menggunakan this.pos.kiosk_server_transak
        async submitOrder() {
            this.isLoading = true;
            const transactionData = {
                customerName: this.customerName,
                customerPhone: this.customerPhone,
                items: this.cart,
                total: this.cartTotal
            };
            
            // Gunakan konfigurasi dari this.pos, dengan fallback URL
            const transakApiUrl = this.pos.kiosk_server_transak || "https://bepos.my.id/pos/kiosk/api_server.php"; 

            try {
                // MENGGUNAKAN transakApiUrl YANG SUDAH DITENTUKAN
                const response = await $.ajax({
                    type: "POST",
                    url: transakApiUrl, 
                    data: { 
                        action: 'process_transaction',
                        cartData: JSON.stringify(transactionData)
                    },
                    dataType: 'json',
                    timeout: 30000
                });

                // Handle response format baru
                if (response && response.success) {
                    this.lastTransactionId = response.transaction_code;
                    
                    // Cetak struk - MEMANGGIL DENGAN PRINTER NAME DAN PORT
                    this.printStruk(transactionData, this.lastTransactionId, this.printerPort, this.printerName); 

                    this.currentView = 'success';
                    this.cart = [];
                } else {
                    throw new Error(response.error || 'Terjadi kesalahan di server');
                }

            } catch (error) {
                console.error('Transaction Error:', error);
                
                let errorMessage = 'Gagal memproses pesanan';
                if (error.responseJSON?.error) {
                    errorMessage += ': ' + error.responseJSON.error;
                } else if (error.message) {
                    errorMessage += ': ' + error.message;
                }
                
                alert(errorMessage);
            } finally {
                this.isLoading = false;
            }
        },
        // --- BLOK FUNGSI BARU UNTUK MENCETAK ---
        printStruk(transactionData, transactionCode, port, printerName) { // <--- TAMBAH PARAMETER
            console.log("Mencoba mencetak struk untuk transaksi:", transactionCode);
            const socket = new WebSocket('ws://localhost:8080');
            // ... (Kode printStruk lainnya)
            socket.onerror = (error) => {
                console.error('WebSocket Error:', error);
                alert('Gagal terhubung ke server print. Pastikan aplikasi cetak (cetak.js) sudah berjalan.');
            };

            socket.onopen = () => {
                console.log("Terhubung ke server print.");
                const printData = this.generatePrintData(transactionData, transactionCode);
                const hexData = this.bufferToHex(printData);
                
                // MENGIRIM PRINTER NAME DAN PORT KE SERVER NODE.JS
                socket.send(JSON.stringify({
                    action: 'cetak',
                    printData: hexData,
                    port: port, // <--- PORT DITAMBAHKAN
                    nama_printer: printerName // <--- NAMA PRINTER DITAMBAHKAN
                }));
            };

            socket.onmessage = (event) => {
                const response = JSON.parse(event.data);
                if (response.type === 'success') { // Perhatikan 'type' success/error di cetak.js
                    console.log('Pencetakan berhasil.');
                } else if (response.type === 'error') {
                    console.error('Pencetakan gagal:', response.message);
                    alert(`Gagal mencetak struk: ${response.message}`);
                }
                socket.close();
            };
        },

        // ... (fungsi generatePrintData, bufferToHex, dan fungsi lainnya)
        generatePrintData(transactionData, transactionCode) {
            const encoder = new EscPosEncoder();
            encoder.initialize();
        
            // [DESAIN] Header Struk
            encoder
                .align('center')
                .bold(true)
                .size('wide') // -> Membuat Teks Lebih Lebar & Besar
                .text('NAMA TOKO ANDA')
                .newline()
                .bold(false)
                .size('normal') // -> [FONT] Menggunakan font ukuran normal
                .text('Alamat Toko Anda di Sini')
                .newline()
                .text('No. Telp: 0812-3456-7890')
                .newline()
                .text('==========================================')
                .newline();
        
            // [DESAIN] Informasi Transaksi
            encoder
                .align('left')
                .text(`No. Trans: ${transactionCode}`)
                .newline()
                .text(`Tanggal  : ${new Date().toLocaleString('id-ID', { hour12: false })}`) // Format tanggal lebih rapi
                .newline()
                .text('Kasir    : Kiosk Digital')
                .newline()
                .text('------------------------------------------')
                .newline();
        
            // [DESAIN] Daftar Item yang Ditingkatkan
            transactionData.items.forEach(item => {
                const itemPriceText = this.formatCurrency(item.finalPrice * item.quantity);
                
                // Item utama dibuat tebal
                encoder.bold(true).text(`${item.name} x${item.quantity}`).newline();
                
                // Opsi/condiment dibuat menjorok dan tidak tebal
                if (item.condiments && item.condiments.length > 0) {
                    encoder.bold(false);
                    item.condiments.forEach(cond => {
                         encoder.text(`  - ${cond.name}`).newline();
                    });
                }
                
                // Harga di baris terpisah dan rata kanan
                encoder.align('right').bold(false).text(itemPriceText).newline().align('left');
            });
        
            // [DESAIN] Total
            encoder
                .text('------------------------------------------')
                .newline()
                .align('right')
                .size('wide') // -> Membuat Total lebih menonjol
                .bold(true)
                .text(`TOTAL: ${this.formatCurrency(transactionData.total)}`)
                .newline()
                .newline();
        
            // [DESAIN] Footer
            encoder
                .align('center')
                .size('normal')
                .bold(false)
                .text('Terima Kasih Atas Kunjungan Anda')
                .newline()
                .newline();
        
            // QR Code
            encoder
                .qrcode(transactionCode, 1, 6, 'h')
                .newline()
                // [SPASI] Menambah 3 baris kosong sebelum kertas dipotong
                .newline()
                .newline()
                .newline();
                
            // Perintah potong kertas
            encoder.cut();
        
            return encoder.encode();
        },

        bufferToHex(buffer) {
            return [...new Uint8Array(buffer)]
                .map(b => b.toString(16).padStart(2, '0'))
                .join('');
        },
        // --- AKHIR BLOK FUNGSI CETAK ---
        // ... (Fungsi-fungsi lainnya)
        showProductDetail(product) {
            if (this.isProductOutOfStock(product)) return;
            this.selectedProduct = product;
            this.modalSelectedAddons = [];
            
            // PERBAIKAN: Assign unique ID untuk setiap condiment group
            if (product.condiment_groups && product.condiment_groups.length > 0) {
                product.condiment_groups.forEach(group => {
                    if (!group.uniqueId) {
                        group.uniqueId = this.generateUniqueId();
                    }
                });
            }
            
            const firstAvailableVariant = product.variants.find(v => v.stock > 0) || product.variants[0];
            
            this.modalSelections = this.variantAttributes.reduce((acc, key) => {
                acc[key] = firstAvailableVariant.attributes[key];
                return acc;
            }, {});

            this.modalCondimentChoices = {};
            (product.condiment_groups || []).forEach(group => {
                // PERBAIKAN: Gunakan uniqueId sebagai key
                if (group.type === 'radio') {
                    this.modalCondimentChoices[group.uniqueId] = group.is_required ? group.options[0] : {};
                } else if (group.type === 'checkbox') {
                    this.modalCondimentChoices[group.uniqueId] = [];
                }
            });
            this.isDetailVisible = true;
        },

        toggleSidebarNode(path) {
            const currentState = !!this.sidebarState[path];
            Object.keys(this.sidebarState).forEach(key => {
                if (!path.startsWith(key)) {
                    this.sidebarState[key] = false;
                }
            });
            this.sidebarState[path] = !currentState;
        },
        isSidebarNodeOpen(path) {
            return !!this.sidebarState[path];
        },
        buildHierarchy(itemSet) {
            const hierarchy = {};
            const sortedItems = [...itemSet].sort();
            sortedItems.forEach(itemStr => {
                if (!itemStr) return;
                const parts = itemStr.split(' / ');
                let currentLevel = hierarchy;
                parts.forEach(part => {
                    if (!currentLevel[part]) currentLevel[part] = { _children: {} };
                    currentLevel = currentLevel[part]._children;
                });
            });
            return hierarchy;
        },
        selectHierarchicalFilter(type, path) {
             if (type === 'category') {
                this.activeCategory = path;
                this.activeBrand = null;
                this.isBestSellerActive = false;
                this.sidebarTab = 'kategori';
            } else if (type === 'brand') {
                this.activeBrand = path;
                this.activeCategory = null;
                this.isBestSellerActive = false;
                this.sidebarTab = 'brand';
            }
        },
        // startShopping() { if (this.customerName) { this.currentView = 'kiosk'; this.isKeyboardVisible = false; } },
        startShopping() { if (true) { this.currentView = 'kiosk'; this.isKeyboardVisible = false; } },
        goToCart() { this.currentView = 'cart'; },
        backToKiosk() { this.currentView = 'kiosk'; },
        startNewOrder() {
            this.customerName = '';
            this.customerPhone = '';
            this.lastTransactionId = '';
            this.activeCategory = null;
            this.activeBrand = null;
            this.isBestSellerActive = false;
            this.searchQuery = '';
            this.currentView = 'welcome';
        },
        cancelOrder() {
            if (confirm('Apakah Anda yakin ingin membatalkan transaksi ini? Semua item di keranjang akan dihapus.')) {
                this.startNewOrder();
            }
        },
        formatCurrency(value) { return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 0 }).format(value || 0); },
        selectBestSeller() {
            this.isBestSellerActive = true;
            this.activeCategory = null;
            this.activeBrand = null;
            this.sidebarTab = 'kategori';
        },
        getBrandLogo(brand) {
            if (!brand) return '';
            const domain = brand.split(' / ')[0].toLowerCase().replace(/\s+/g, '').replace('&', '') + '.com';
            return `https://logo.clearbit.com/${domain}?size=40`;
        },
        isProductOutOfStock(product) { return product.variants.every(v => v.stock === 0); },
        isInCart(product) {
            return this.cart.some(item => item.productId === product.id);
        },
        isSimpleProduct(product) {
            return !(
                (product.addons && product.addons.length > 0) || 
                (product.condiment_groups && product.condiment_groups.length > 0) || 
                product.variants.length > 1 || 
                (product.variants[0] && Object.keys(product.variants[0].attributes || {}).length > 0)
            );
        },
        closeDetailModal() { this.isDetailVisible = false; setTimeout(() => {this.selectedProduct = null;}, 300); },
        getAvailableOptions(key, currentAttributeIndex) {
            const relevantVariants = this.selectedProduct.variants.filter(v => {
                for (let i = 0; i < currentAttributeIndex; i++) {
                    const attr = this.variantAttributes[i];
                    if (v.attributes[attr] !== this.modalSelections[attr]) {
                        return false;
                    }
                }
                return true;
            });
            return [...new Set(relevantVariants.map(v => v.attributes[key]).filter(Boolean))];
        },
        isVariantCombinationAvailable(key, option) {
            const tempSelections = { ...this.modalSelections, [key]: option };
            return this.selectedProduct.variants.some(v => {
                return this.variantAttributes.every(attr => tempSelections[attr] === undefined || v.attributes[attr] === tempSelections[attr]);
            });
        },
        selectModalOption(key, option, attributeIndex) {
            this.modalSelections[key] = option;
            for (let i = attributeIndex + 1; i < this.variantAttributes.length; i++) {
                const nextKey = this.variantAttributes[i];
                const availableOptions = this.getAvailableOptions(nextKey, i);
                if (!availableOptions.includes(this.modalSelections[nextKey])) {
                    this.modalSelections[nextKey] = availableOptions[0];
                }
            }
        },
        addProductToCart(event) {
            if (!this.isModalFormValid) return;
            this.animateFlyToCart(event, '.product-detail-modal .detail-image');
            
            setTimeout(() => {
                const product = this.selectedProduct;
                const variant = this.modalSelectedVariant;
                const addons = this.modalSelectedAddons;
                
                // PERBAIKAN: Ambil condiments menggunakan uniqueId
                const condiments = [];
                Object.entries(this.modalCondimentChoices).forEach(([uniqueId, choice]) => {
                    if (Array.isArray(choice)) {
                        // checkbox
                        condiments.push(...choice.filter(c => c && c.name));
                    } else if (choice && choice.name) {
                        // radio
                        condiments.push(choice);
                    }
                });
                
                const cartId = `${product.id}-${variant.id}-${addons.map(a=>a.id).sort().join('-')}-${condiments.map(c=>c.name).sort().join('-')}`;
                
                const existingItem = this.cart.find(item => item.cartId === cartId);
                if (existingItem) existingItem.quantity++;
                else this.cart.push({
                    cartId, productId: product.id, name: product.name, image: variant.image_url, quantity: 1, 
                    finalPrice: this.modalFinalPrice, variant, addons, condiments, note: ''
                });
                this.closeDetailModal();
            }, 100);
        },
        addToCartSimple(product, event) {
            if (this.isProductOutOfStock(product)) return;
            this.animateFlyToCart(event);
            setTimeout(() => {
                const variant = product.variants[0];
                const cartId = `${product.id}-${variant.id}`;
                const existingItem = this.cart.find(item => item.cartId === cartId);
                if (existingItem) existingItem.quantity++;
                else this.cart.push({
                    cartId, productId: product.id, name: product.name, image: variant.image_url, quantity: 1, 
                    finalPrice: product.base_price, variant, addons: [], condiments: [], note: ''
                });
            }, 100);
        },
        removeFromCart(cartId) { this.cart = this.cart.filter(item => item.cartId !== cartId); },
        incrementQuantity(cartId) { const item = this.cart.find(i => i.cartId === cartId); if (item) item.quantity++; },
        decrementQuantity(cartId) {
            const item = this.cart.find(i => i.cartId === cartId);
            if (item && item.quantity > 1) item.quantity--;
            else if (item) this.removeFromCart(cartId);
        },
        showKeyboard(target) { this.keyboardTarget = target; this.isKeyboardVisible = true; },
        hideKeyboard() { this.isKeyboardVisible = false; },
        handleKeyPress(key) {
            let targetModel = this.keyboardTarget;
            if (!targetModel) return;

            if (key === 'Enter') this.hideKeyboard();
            else if (key === 'Backspace') this[targetModel] = this[targetModel].slice(0, -1);
            else if (key === 'Space') this[targetModel] += ' ';
            else if(this[targetModel] !== undefined) this[targetModel] += key;
        },
        getKeyClass(key) {
            if (['Backspace', 'Enter'].includes(key)) return 'key-special';
            if (key === 'Space') return 'key-space';
            return '';
        },
        animateFlyToCart(event, customImageSelector = null) {
            const cartButton = document.querySelector('.cart-button');
            if (!cartButton) return;
            
            let startElement = customImageSelector ? document.querySelector(customImageSelector) : event.target.closest('.product-card').querySelector('.product-image');
            if (!startElement) return;

            const startRect = startElement.getBoundingClientRect();
            const cartRect = cartButton.getBoundingClientRect();
            
            const clone = startElement.cloneNode(true);
            document.body.appendChild(clone);
            clone.style.position = 'fixed';
            clone.style.width = `${startRect.width}px`;
            clone.style.height = `${startRect.height}px`;
            clone.style.top = `${startRect.top}px`;
            clone.style.left = `${startRect.left}px`;
            clone.style.zIndex = '9999';

            const translateX = (cartRect.left + cartRect.width / 2) - (startRect.left + startRect.width / 2);
            const translateY = (cartRect.top + cartRect.height / 2) - (startRect.top + startRect.height / 2);
            clone.style.setProperty('--translate-x', `${translateX}px`);
            clone.style.setProperty('--translate-y', `${translateY}px`);

            requestAnimationFrame(() => {
                clone.classList.add('flying-product-clone');
            });
            
            clone.addEventListener('animationend', () => clone.remove());
        }
    },
    // DIUBAH: mounted hook menjadi async untuk memastikan config dimuat
    async mounted() {
        await this.loadPosConfig(); // Memastikan konfigurasi POS dimuat
        this.fetchAllProducts();
        
    },      

}).mount('#app');