"use client"; import { create } from "zustand"; import { persist } from "zustand/middleware"; import { Product } from "../data/products"; import { orderService } from "../services/orderService"; import api from "../services/api"; export interface CartItem { product: Product; quantity: number; calculatedDose?: { quantity: number; unit: string; }; } interface Order { id: string; date: string; items: CartItem[]; total: number; charityDonation?: number; status: 'processing' | 'shipped' | 'delivered'; petId?: string; trackingNumber: string; } interface CartStore { items: CartItem[]; isSubscribed: boolean; charityDonation: number; coupon: { code: string; discount: number } | null; orders: Order[]; addItem: (product: Product, quantity: number, dose?: { quantity: number; unit: string }) => void; removeItem: (productId: string) => void; updateQuantity: (productId: string, quantity: number) => void; toggleSubscription: () => void; setCharityDonation: (amount: number) => void; applyCoupon: (code: string) => Promise; addOrder: (order: Omit) => Promise; clearCart: () => void; removeCoupon: () => void; setOrders: (orders: any[]) => void; getTotalItems: () => number; getSubtotal: () => number; getDiscount: () => number; getTotal: () => number; } export const useCartStore = create()( persist( (set, get) => ({ items: [], isSubscribed: false, charityDonation: 0, coupon: null, orders: [], addItem: (product, quantity, dose) => { const items = get().items; const existing = items.find((i) => i.product.id === product.id); if (existing) { set({ items: items.map((i) => i.product.id === product.id ? { ...i, quantity: i.quantity + quantity } : i ), }); } else { set({ items: [...items, { product, quantity, calculatedDose: dose }] }); } }, removeItem: (productId) => { set({ items: get().items.filter((i) => i.product.id !== productId) }); }, updateQuantity: (productId, quantity) => { if (quantity <= 0) { get().removeItem(productId); return; } set({ items: get().items.map((i) => i.product.id === productId ? { ...i, quantity } : i ), }); }, toggleSubscription: () => set({ isSubscribed: !get().isSubscribed }), setCharityDonation: (amount) => set({ charityDonation: amount }), applyCoupon: async (code) => { try { const cleanCode = code.toUpperCase().trim(); // Assuming API returns { discountValue: number } or similar const response = await api.post('/cart/apply-coupon', { code: cleanCode }); if (response.data && response.data.discountValue) { set({ coupon: { code: cleanCode, discount: response.data.discountValue } }); return true; } return false; } catch (error) { console.error("Failed to apply coupon:", error); return false; } }, addOrder: async (orderData) => { const payload = { petId: orderData.petId, items: orderData.items.map(i => ({ productId: i.product.id, quantity: i.quantity })) }; try { const backendOrder = await orderService.createOrder(payload); const newOrder: Order = { ...orderData, id: backendOrder.id, date: backendOrder.createdAt, total: Number(backendOrder.totalAmount), charityDonation: Number(backendOrder.charityDonation), status: backendOrder.status as any, trackingNumber: backendOrder.trackingNumber || `CN-${Math.floor(Math.random() * 90000) + 10000}` }; set({ orders: [newOrder, ...get().orders] }); return backendOrder.id; } catch (error: any) { console.error("Order creation failed on backend:", error); throw error; } }, clearCart: () => set({ items: [], coupon: null }), removeCoupon: () => set({ coupon: null }), setOrders: (backendOrders) => { const mappedOrders: Order[] = backendOrders.map(bo => ({ id: bo.id, date: bo.createdAt, items: bo.orderItems?.map((oi: any) => ({ product: oi.product, quantity: oi.quantity })) || [], total: Number(bo.totalAmount), charityDonation: Number(bo.charityDonation), status: bo.status, trackingNumber: bo.trackingNumber || `CN-${Math.floor(Math.random() * 90000) + 10000}` })); set({ orders: mappedOrders }); }, getTotalItems: () => get().items.reduce((acc, item) => acc + item.quantity, 0), getSubtotal: () => get().items.reduce((acc, item) => acc + item.product.priceValue * item.quantity, 0), getDiscount: () => { const subtotal = get().getSubtotal(); let discount = get().isSubscribed ? subtotal * 0.05 : 0; if (get().coupon) { const c = get().coupon!; if (c.discount < 1) { discount += subtotal * c.discount; } else { discount += c.discount; } } return Math.min(discount, subtotal); }, getTotal: () => get().getSubtotal() - get().getDiscount() + get().charityDonation, }), { name: "canina-cart" } ) );