import { defineStore } from 'pinia'
import axios from 'axios'
import { db } from '../db'
import { useNetworkStore } from './network'

export const usePosStore = defineStore('pos', {
    state: () => ({
        activeSession: null,
        cart: [],
        products: [],
        categories: [],
        loading: false,
        error: null,
        receivedAmount: 0,
        paymentMethod: 'cash',
        paymentField: '',
        todayStats: { count: 0, total: 0, store_name: null, store_photo: null },
        customerSuggestions: [],
        cachedCustomers: JSON.parse(localStorage.getItem('pos_cached_customers') || '[]'),
        posSessions: [],
        posSessionsCount: 0,
        posSessionsPage: 1,
        isOfflineMode: false,
        lastSync: localStorage.getItem('pos_last_sync') || null,
    }),

    getters: {
        totalAmount: (state) => {
            return state.cart.reduce((sum, item) => sum + (item.total_price || 0), 0)
        },
        changeAmount: (state) => {
            return Math.max(0, state.receivedAmount - state.totalAmount)
        },
        itemsCount: (state) => {
            return state.cart.reduce((count, item) => count + (item.quantity || 0), 0)
        }
    },

    actions: {
        async fetchProducts(accessKey = null, storeHash = null) {
            this.loading = true
            try {
                // Try Local DB first if offline
                if (this.isOfflineMode) {
                    const localProducts = await db.products.toArray()
                    if (localProducts.length > 0) {
                        this.products = localProducts
                        this.loading = false
                        return
                    }
                }

                const params = {}
                if (accessKey) params.access_key = accessKey
                if (storeHash) params.store_hash = storeHash
                if (this.activeSession) params.session_hash = this.activeSession.hashkey

                const response = await axios.post('/Market/Products/List', params)
                this.products = response.data || []
                
                // Save to local DB for next time
                if (this.products.length > 0) {
                    await db.products.clear()
                    await db.products.bulkPut(this.products)
                    this.lastSync = new Date().toISOString()
                    localStorage.setItem('pos_last_sync', this.lastSync)
                }

                // Extract unique categories
                const cats = new Set(this.products.map(p => p.category).filter(Boolean))
                this.categories = Array.from(cats)
            } catch (error) {
                console.error('Failed to fetch products:', error)
                // Fallback to local DB on network error
                const localProducts = await db.products.toArray()
                if (localProducts.length > 0) {
                   this.products = localProducts
                } else if (this.products.length === 0) {
                   // Only surface the error if nothing is already showing
                   this.error = 'Failed to load products'
                }
            } finally {
                this.loading = false
            }
        },

        async startNewSession(storeHash, customerName = '', accessKey = null) {
            if (this.loading) return
            this.loading = true
            try {
                const networkStore = useNetworkStore()
                
                const payload = {
                    customer_name: customerName
                }

                if (!networkStore.isOnline) {
                    const savedRaw = localStorage.getItem('pos_cart_session')
                    const saved = savedRaw ? JSON.parse(savedRaw) : null
                    if (saved?.offline && saved.cart?.length > 0) {
                        this.activeSession = { hashkey: saved.sessionHashkey, offline: true, transactions: [] }
                        this.cart = saved.cart
                    } else {
                        this.activeSession = {
                            hashkey: 'offline-' + Date.now(),
                            customer_name: customerName,
                            offline: true,
                            transactions: []
                        }
                        this.cart = []
                    }
                    return
                }

                if (accessKey) payload.access_key = accessKey
                if (storeHash) payload.store_hash = storeHash

                const response = await axios.post('/api/pos/start', payload)
                if (response.data && response.data.success) {
                    await this.loadSession(response.data.data.hashkey)
                }
            } catch (error) {
                console.error('Failed to start session:', error)
                const serverMessage = error?.response?.data?.message
                this.error = serverMessage || 'Failed to start session'
            } finally {
                this.loading = false
            }
        },

        async loadSession(hashkey = null, accessKey = null) {
            this.loading = true
            try {
                const params = {}
                if (hashkey) params.target = hashkey
                if (accessKey) params.access_key = accessKey

                const response = await axios.post('/api/pos/session', params)
                if (response.data && response.data.success) {
                    this.activeSession = response.data.data
                    this.cart = this.activeSession.transactions || []
                    if (this.cart.length === 0) {
                        this._restoreCartFromStorage(this.activeSession.hashkey)
                    }
                } else {
                    this.error = 'Session not found or invalid'
                }
            } catch (error) {
                console.error('Failed to load session:', error)
                this.error = 'Failed to load session'
            } finally {
                this.loading = false
            }
        },

        async addToCart(productHash, quantity = 1, customPrice = null) {
            if (!this.activeSession && !this.isOfflineMode) return

            // Offline Fallback
            if (this.isOfflineMode || !navigator.onLine) {
                const product = this.products.find(p => p.hashkey === productHash);
                if (!product) return;

                const price = customPrice !== null ? customPrice : (product.price || 0);
                const existingIndex = this.cart.findIndex(item => item.product?.hashkey === productHash);
                
                if (existingIndex !== -1) {
                    if (quantity <= 0) {
                        this.cart.splice(existingIndex, 1);
                    } else {
                        const item = this.cart[existingIndex];
                        item.quantity = quantity;
                        item.price_at_sale = price;
                        item.total_price = item.quantity * item.price_at_sale;
                    }
                } else if (quantity > 0) {
                    this.cart.push({
                        id: 'local-' + Date.now(),
                        product: product,
                        quantity: quantity,
                        price_at_sale: price,
                        total_price: price * quantity
                    });
                }
                this._saveCartToStorage()
                return;
            }

            try {
                const payload = {
                    session_hash: this.activeSession.hashkey,
                    product_hash: productHash,
                    quantity: quantity
                }
                if (customPrice !== null) payload.price = customPrice

                const response = await axios.post('/api/pos/add-item', payload)
                if (response.data && response.data.success) {
                    // Update session state directly from the response
                    this.activeSession = response.data.data
                    this.cart = this.activeSession.transactions || []
                    this._saveCartToStorage()
                }
            } catch (error) {
                console.error('Failed to add item:', error)
                this.error = 'Failed to add item to cart'
            }
        },

        async removeFromCart(transactionId) {
            if (!this.activeSession) return

            if (this.isOfflineMode || !navigator.onLine) {
                this.cart = this.cart.filter(item => item.id !== transactionId);
                return;
            }

            try {
                const response = await axios.post('/api/pos/remove-item', {
                    session_hash: this.activeSession.hashkey,
                    transaction_id: transactionId
                })
                if (response.data && response.data.success) {
                    // Update session state directly from the response
                    this.activeSession = response.data.data
                    this.cart = this.activeSession.transactions || []
                }
            } catch (error) {
                console.error('Failed to remove item:', error)
            }
        },

        async completeTransaction(customerName = '') {
            if (!this.activeSession || this.loading) return

            this.loading = true
            try {
                const response = await axios.post('/api/pos/complete', {
                    session_hash: this.activeSession.hashkey,
                    received_amount: this.receivedAmount,
                    payment_method: this.paymentMethod,
                    payment_field: this.paymentField,
                    customer_name: customerName
                })
                if (response.data && response.data.success) {
                    this.activeSession = response.data.data
                    this._clearCartStorage()

                    // Add customer to cache if provided
                    if (customerName) {
                        this.updateCustomerCache([{
                            name: customerName,
                            hashkey: 'new-' + Date.now() // Temporary hash until next fetch
                        }]);
                    }

                    return true
                }
            } catch (error) {
                console.error('Failed to complete transaction:', error)
                this.error = 'Payment failed'
            } finally {
                this.loading = false
            }
            return false
        },

        _saveCartToStorage() {
            if (!this.activeSession) return
            try {
                localStorage.setItem('pos_cart_session', JSON.stringify({
                    sessionHashkey: this.activeSession.hashkey,
                    offline: this.activeSession.offline || false,
                    cart: this.cart
                }))
            } catch {}
        },

        _restoreCartFromStorage(sessionHashkey) {
            try {
                const raw = localStorage.getItem('pos_cart_session')
                if (!raw) return false
                const saved = JSON.parse(raw)
                if (saved.sessionHashkey === sessionHashkey && saved.cart?.length > 0) {
                    this.cart = saved.cart
                    return true
                }
            } catch {}
            return false
        },

        _clearCartStorage() {
            localStorage.removeItem('pos_cart_session')
        },

        resetSession() {
            this.activeSession = null
            this.cart = []
            this.receivedAmount = 0
            this.paymentField = ''
            this._clearCartStorage()
            // Keep the access key as it defines the terminal session
        },

        async fetchTodayStats(storeHash = null) {
            try {
                const response = await axios.post('/api/pos/stats', {
                    store_hash: storeHash
                })
                if (response.data && response.data.success) {
                    this.todayStats = response.data.data
                }
            } catch (error) {
                console.error('Failed to fetch today stats:', error)
            }
        },

        async fetchCustomerSuggestions(query = '', storeHash = null) {
            // 1. Show cached results immediately if available
            if (this.cachedCustomers.length > 0) {
                const q = query.toLowerCase();
                this.customerSuggestions = query 
                    ? this.cachedCustomers.filter(c => c.name.toLowerCase().includes(q)).slice(0, 10)
                    : this.cachedCustomers.slice(-3).reverse(); // Show last 3 most recent if no query
            }

            // 2. Background fetch to get current/complete list
            try {
                const response = await axios.post('/api/pos/get-customers', {
                    query: query,
                    store_hash: storeHash
                })
                if (response.data && response.data.success) {
                    const newSuggestions = response.data.data;
                    this.customerSuggestions = newSuggestions;
                    
                    // Update persistent cache
                    this.updateCustomerCache(newSuggestions);
                }
            } catch (error) {
                console.error('Failed to fetch customer suggestions:', error)
            }
        },

        updateCustomerCache(newCustomers) {
            const merged = [...this.cachedCustomers];
            newCustomers.forEach(newCust => {
                const index = merged.findIndex(c => c.name.toLowerCase() === newCust.name.toLowerCase());
                if (index === -1) {
                    merged.push(newCust);
                } else {
                    // Update existing if new one has real hashkey
                    if (!merged[index].hashkey.startsWith('new-') || newCust.hashkey) {
                        merged[index] = newCust;
                    }
                }
            });
            
            // Limit cache to 200 most recent
            this.cachedCustomers = merged.slice(-200);
            localStorage.setItem('pos_cached_customers', JSON.stringify(this.cachedCustomers));
        },

        async fetchPosSessions(storeHash, page = 1) {
            this.loading = true
            try {
                const response = await axios.post('/api/pos/sessions/list', {
                    store_hash: storeHash,
                    page: page,
                    per_page: 10
                })
                if (response.data && response.data.success) {
                    const { sessions, total_count, page: currentPage } = response.data.data
                    if (page === 1) {
                        this.posSessions = sessions
                    } else {
                        // Avoid duplicates
                        const existingHashes = new Set(this.posSessions.map(s => s.hashkey))
                        const newSessions = sessions.filter(s => !existingHashes.has(s.hashkey))
                        this.posSessions = [...this.posSessions, ...newSessions]
                    }
                    this.posSessionsCount = total_count
                    this.posSessionsPage = currentPage
                }
            } catch (error) {
                console.error('Failed to fetch POS sessions:', error)
                this.error = 'Failed to load POS history'
            } finally {
                this.loading = false
            }
        },

        syncFromSSE(data) {
            // 1. Sync Today's Stats
            if (data.pos_stats) {
                // Merge into existing stats to preserve store_name/photo if SSE payload is partial
                this.todayStats = {
                    ...this.todayStats,
                    ...data.pos_stats
                };
            }

            // 2. Sync Customers (Merge into search suggestions and persistent cache)
            if (data.customers && data.customers.length > 0) {
                this.updateCustomerCache(data.customers);
                
                // If currently showing recent customers, refresh the view
                if (!this.loading && this.customerSuggestions.length > 0) {
                     // Minor delay to avoid flickering if user is typing
                     const recent = this.cachedCustomers.slice(-3).reverse();
                     this.customerSuggestions = recent;
                }
            }

            // 3. Sync Inventory Deltas (Stock/Price changes + newly assigned products)
            if (data.inventory_deltas && data.inventory_deltas.length > 0) {
                let hasNewProduct = false;
                data.inventory_deltas.forEach(delta => {
                    const index = this.products.findIndex(p => p.hashkey === delta.hashkey || p.id === delta.id);
                    if (index !== -1) {
                        this.products[index] = {
                            ...this.products[index],
                            ...delta
                        };
                    } else if (this.products.length > 0) {
                        // Product not in list — newly assigned to this store
                        hasNewProduct = true;
                    }
                });
                // Trigger a full reload so store-specific price/available are fetched correctly.
                // Requires an active session so the backend resolves the correct store.
                if (hasNewProduct && this.activeSession) {
                    this.fetchProducts();
                }
            }
        }
    }
})

