'use client';
import { createContext, useContext, useCallback, useState, useMemo, ReactNode } from 'react';
import type { Product, ProductVariation } from '@/types';

export interface CartItem {
  productId: string;
  variationId?: string;
  name: string;
  variationLabel?: string;
  unitPrice: number;
  quantity: number;
  maxStock: number;
  imageUrl?: string;
}

interface CartContextValue {
  items: CartItem[];
  count: number;
  subtotal: number;
  add: (product: Product, variation: ProductVariation | null, qty?: number) => void;
  updateQty: (key: string, qty: number) => void;
  remove: (key: string) => void;
  clear: () => void;
}

const CartContext = createContext<CartContextValue | null>(null);

function keyOf(item: Pick<CartItem, 'productId' | 'variationId'>) {
  return `${item.productId}::${item.variationId ?? 'base'}`;
}

function variationLabel(v: ProductVariation): string {
  return Object.entries(v.options)
    .map(([k, val]) => `${k}: ${val}`)
    .join(', ');
}

export function CartProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<CartItem[]>([]);

  const add = useCallback(
    (product: Product, variation: ProductVariation | null, qty = 1) => {
      const price =
        variation?.promoPrice ??
        variation?.price ??
        product.promoPrice ??
        product.price;
      const maxStock = variation ? variation.stock : product.stock;
      const newItem: CartItem = {
        productId: product.id,
        variationId: variation?.id,
        name: product.name,
        variationLabel: variation ? variationLabel(variation) : undefined,
        unitPrice: price,
        quantity: qty,
        maxStock,
        imageUrl: variation?.imageUrl ?? product.images[0],
      };
      setItems((prev) => {
        const k = keyOf(newItem);
        const existing = prev.find((i) => keyOf(i) === k);
        if (existing) {
          return prev.map((i) =>
            keyOf(i) === k
              ? { ...i, quantity: Math.min(i.quantity + qty, i.maxStock) }
              : i,
          );
        }
        return [...prev, newItem];
      });
    },
    [],
  );

  const updateQty = useCallback((key: string, qty: number) => {
    setItems((prev) =>
      prev.map((i) =>
        keyOf(i) === key ? { ...i, quantity: Math.max(1, Math.min(qty, i.maxStock)) } : i,
      ),
    );
  }, []);

  const remove = useCallback((key: string) => {
    setItems((prev) => prev.filter((i) => keyOf(i) !== key));
  }, []);

  const clear = useCallback(() => setItems([]), []);

  const value = useMemo<CartContextValue>(() => {
    const count = items.reduce((s, i) => s + i.quantity, 0);
    const subtotal = items.reduce((s, i) => s + i.unitPrice * i.quantity, 0);
    return { items, count, subtotal, add, updateQty, remove, clear };
  }, [items, add, updateQty, remove, clear]);

  return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}

export function useCart() {
  const ctx = useContext(CartContext);
  if (!ctx) throw new Error('useCart deve ser usado dentro de <CartProvider>');
  return ctx;
}

export { keyOf as cartItemKey };
