import { createContext, useContext, useEffect, useMemo, useReducer } from 'react';

const CartContext = createContext(undefined);

const initialState = {
  items: [],
};

function cartReducer(state, action) {
  switch (action.type) {
    case 'HYDRATE':
      return { ...state, items: action.payload };
    case 'ADD_ITEM': {
      const { item } = action.payload;
      const existing = state.items.find((entry) => entry.id === item.id);
      if (!existing) {
        return { ...state, items: [...state.items, item] };
      }
      const updated = state.items.map((entry) =>
        entry.id === item.id ? { ...entry, quantity: item.quantity, limit: item.limit } : entry
      );
      return { ...state, items: updated };
    }
    case 'UPDATE_QUANTITY': {
      const { id, quantity } = action.payload;
      const updated = state.items
        .map((entry) => (entry.id === id ? { ...entry, quantity } : entry))
        .filter((entry) => entry.quantity > 0);
      return { ...state, items: updated };
    }
    case 'REMOVE_ITEM': {
      const { id } = action.payload;
      return { ...state, items: state.items.filter((entry) => entry.id !== id) };
    }
    case 'CLEAR':
      return { ...state, items: [] };
    default:
      return state;
  }
}

const STORAGE_KEY = 'fullmoon.cart';

export function CartProvider({ children }) {
  const [state, dispatch] = useReducer(cartReducer, initialState);

  useEffect(() => {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (!raw) return;
      const parsed = JSON.parse(raw);
      if (Array.isArray(parsed)) {
        dispatch({ type: 'HYDRATE', payload: parsed });
      }
    } catch (error) {
      console.warn('Cart hydration failed', error);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state.items));
  }, [state.items]);

  const itemCount = useMemo(
    () => state.items.reduce((sum, entry) => sum + entry.quantity, 0),
    [state.items]
  );

  const subtotal = useMemo(
    () => state.items.reduce((sum, entry) => sum + entry.price * entry.quantity, 0),
    [state.items]
  );

  const addItem = (product) => {
    if (!product?.id) return;
    const price = Number(product.price || 0);
    const maxPerOrder = Number(product.max_per_order || 0) > 0 ? Number(product.max_per_order) : Infinity;
    const inventoryLimit =
      typeof product.inventory_quantity === 'number' && product.inventory_quantity >= 0
        ? product.inventory_quantity
        : Infinity;
    const limit = Math.min(maxPerOrder, inventoryLimit);
    if (limit <= 0) return;

    const numericLimit = Number.isFinite(limit) ? limit : Infinity;
    const existing = state.items.find((entry) => entry.id === product.id);
    const nextQuantity = existing ? Math.min(existing.quantity + 1, numericLimit) : 1;

    dispatch({
      type: 'ADD_ITEM',
      payload: {
        item: {
          id: product.id,
          slug: product.slug,
          name: product.name,
          price,
          quantity: nextQuantity,
          imageUrl: product.imageUrl,
          limit: Number.isFinite(limit) ? limit : null,
        },
      },
    });
  };

  const updateQuantity = (id, quantity) => {
    if (quantity < 0) return;
    const entry = state.items.find((item) => item.id === id);
    if (!entry) return;
    const limit = Number.isFinite(entry.limit) ? entry.limit : Infinity;
    const clamped = Math.min(quantity, limit);
    dispatch({ type: 'UPDATE_QUANTITY', payload: { id, quantity: clamped } });
  };

  const removeItem = (id) => dispatch({ type: 'REMOVE_ITEM', payload: { id } });
  const clearCart = () => dispatch({ type: 'CLEAR' });

  const value = useMemo(
    () => ({
      items: state.items,
      addItem,
      updateQuantity,
      removeItem,
      clearCart,
      itemCount,
      subtotal,
    }),
    [state.items, itemCount, subtotal]
  );

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

export function useCart() {
  const context = useContext(CartContext);
  if (!context) {
    throw new Error('useCart must be used within a CartProvider');
  }
  return context;
}
