"use client"; import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from "react"; import type { ShopCurrency, ShopProduct } from "@/lib/shopCatalog"; const CART_KEY = "cyberlux-cart-v1"; export type CartLine = { productId: string; qty: number; name: string; price: number; currency: ShopCurrency; }; type CartContextValue = { lines: CartLine[]; itemCount: number; hydrated: boolean; addToCart: (product: ShopProduct, qty?: number) => void; removeLine: (productId: string) => void; setLineQty: (productId: string, qty: number) => void; clearCart: () => void; }; const CartContext = createContext(undefined); function loadRaw(): CartLine[] { if (typeof window === "undefined") return []; try { const raw = localStorage.getItem(CART_KEY); if (!raw) return []; const v = JSON.parse(raw) as CartLine[]; if (!Array.isArray(v)) return []; return v.filter( (row) => row && typeof row.productId === "string" && typeof row.qty === "number" && row.qty > 0 && typeof row.name === "string" && typeof row.price === "number" && row.currency && ["BTC", "ETH", "USD", "XMR"].includes(row.currency), ); } catch { return []; } } function persist(lines: CartLine[]) { if (typeof window === "undefined") return; localStorage.setItem(CART_KEY, JSON.stringify(lines)); } export function CartProvider({ children }: { children: ReactNode }) { const [lines, setLines] = useState([]); const [hydrated, setHydrated] = useState(false); useEffect(() => { setLines(loadRaw()); setHydrated(true); }, []); const flush = useCallback((next: CartLine[]) => { persist(next); setLines(next); }, []); const addToCart = useCallback((product: ShopProduct, qty = 1) => { const q = Math.max(1, Math.min(99, qty)); const cur = loadRaw(); const i = cur.findIndex((l) => l.productId === product.id); let next: CartLine[]; if (i >= 0) { next = [...cur]; next[i] = { ...next[i]!, qty: Math.min(99, next[i]!.qty + q) }; } else { next = [ ...cur, { productId: product.id, qty: q, name: product.name, price: product.price, currency: product.currency, }, ]; } persist(next); setLines(next); }, []); const removeLine = useCallback((productId: string) => { const next = loadRaw().filter((l) => l.productId !== productId); persist(next); setLines(next); }, []); const setLineQty = useCallback((productId: string, qty: number) => { const q = Math.floor(qty); if (q < 1) { const next = loadRaw().filter((l) => l.productId !== productId); persist(next); setLines(next); return; } const capped = Math.min(99, q); const next = loadRaw().map((l) => (l.productId === productId ? { ...l, qty: capped } : l)); persist(next); setLines(next); }, []); const clearCart = useCallback(() => { persist([]); setLines([]); }, []); const itemCount = useMemo(() => lines.reduce((s, l) => s + l.qty, 0), [lines]); const value = useMemo( () => ({ lines, itemCount, hydrated, addToCart, removeLine, setLineQty, clearCart, }), [lines, itemCount, hydrated, addToCart, removeLine, setLineQty, clearCart], ); return {children}; } export function useCart(): CartContextValue { const ctx = useContext(CartContext); if (!ctx) throw new Error("useCart must be used within CartProvider"); return ctx; }