/** @typedef {{ productId: string; slug: string; name: string; price: number; image?: string | null; category?: string | null; quantity: number }} CartItem */ const STORAGE_KEY = "kikomiko-cart-v1"; /** @type {CartItem[]} */ let items = []; let hydrated = false; const listeners = new Set(); function notify() { for (const fn of listeners) fn(getSnapshot()); } function persist() { if (!hydrated) return; try { localStorage.setItem(STORAGE_KEY, JSON.stringify(items)); } catch { /* ignore */ } } export function hydrateCart() { if (hydrated) return; try { const raw = localStorage.getItem(STORAGE_KEY); items = raw ? JSON.parse(raw) : []; if (!Array.isArray(items)) items = []; } catch { items = []; } hydrated = true; notify(); } export function subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); } export function getSnapshot() { const itemCount = items.reduce((n, i) => n + i.quantity, 0); const subtotal = items.reduce((n, i) => n + i.price * i.quantity, 0); return { items: [...items], itemCount, subtotal, hydrated }; } export function addItem(item) { hydrateCart(); const qty = Math.max(1, item.quantity ?? 1); const existing = items.find((i) => i.productId === item.productId); if (existing) { existing.quantity += qty; if (item.category && !existing.category) existing.category = item.category; if (item.image && !existing.image) existing.image = item.image; } else { items.push({ productId: item.productId, slug: item.slug, name: item.name, price: item.price, image: item.image ?? null, category: item.category ?? null, quantity: qty, }); } persist(); notify(); } export function updateQuantity(productId, quantity) { hydrateCart(); if (quantity <= 0) { items = items.filter((i) => i.productId !== productId); } else { const row = items.find((i) => i.productId === productId); if (row) row.quantity = quantity; } persist(); notify(); } export function removeItem(productId) { hydrateCart(); items = items.filter((i) => i.productId !== productId); persist(); notify(); } export function clearCart() { hydrateCart(); items = []; persist(); notify(); } export function formatPrice(price) { const amount = Number.isFinite(price) ? Math.round(price) : 0; return `${new Intl.NumberFormat("fa-IR", { maximumFractionDigits: 0, }).format(amount)} تومان`; }