import { useEffect, useRef, useState } from 'react';
import {
  ICartItem,
  IItemPack,
  IPurchase,
  IPurchaseUnit,
  IStoreItem,
  PurchaseType,
} from '../StoreTypes';

interface IUseStoreCart {
  cartItems: ICartItem[];
  isCartOpen: boolean;
  handleAddToCart: (item: IStoreItem, quantity: number) => void;
  handleRemoveFromCart: (itemKey: string) => void;
  handlePurchase: (onPurchase: (purchase: IPurchase) => void) => void;
  openCart: () => void;
  closeCart: () => void;
  getTotalItems: () => number;
  getTotalPrice: () => number;
}

export const useStoreCart = (): IUseStoreCart => {
  const [cartItems, setCartItems] = useState<ICartItem[]>([]);
  const [isCartOpen, setIsCartOpen] = useState(false);
  const isMounted = useRef(true);

  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  const handleAddToCart = (item: IStoreItem, quantity: number) => {
    setCartItems(prevItems => {
      const existingItem = prevItems.find(
        cartItem => cartItem.item.key === item.key
      );

      if (existingItem) {
        return prevItems.map(cartItem =>
          cartItem.item.key === item.key
            ? {
                ...cartItem,
                quantity: Math.min(cartItem.quantity + quantity, 99),
              }
            : cartItem
        );
      }

      return [...prevItems, { item, quantity }];
    });
  };

  const handleRemoveFromCart = (itemKey: string) => {
    setCartItems(prevItems =>
      prevItems.filter(cartItem => cartItem.item.key !== itemKey)
    );
  };

  const handlePurchase = (onPurchase: (purchase: IPurchase) => void) => {
    const purchaseUnits: IPurchaseUnit[] = cartItems.map(cartItem => {
      const isPack =
        'priceUSD' in cartItem.item &&
        typeof cartItem.item.priceUSD === 'number';

      if (isPack) {
        const packItem = cartItem.item as IStoreItem & IItemPack;
        return {
          purchaseKey: packItem.key,
          qty: cartItem.quantity,
          type: PurchaseType.Pack,
          name: packItem.title,
        };
      }

      return {
        purchaseKey: cartItem.item.key,
        qty: cartItem.quantity,
        type: PurchaseType.Item,
        name: cartItem.item.name,
      };
    });

    const purchase: IPurchase = {
      purchases: purchaseUnits,
    };

    onPurchase(purchase);

    if (isMounted.current) {
      setCartItems([]);
      setIsCartOpen(false);
    }
  };

  const openCart = () => setIsCartOpen(true);
  const closeCart = () => setIsCartOpen(false);

  const getTotalItems = () =>
    cartItems.reduce((sum, item) => sum + item.quantity, 0);

  const getTotalPrice = () =>
    Number(
      cartItems
        .reduce((sum, item) => sum + item.item.price * item.quantity, 0)
        .toFixed(2)
    );

  return {
    cartItems,
    isCartOpen,
    handleAddToCart,
    handleRemoveFromCart,
    handlePurchase,
    openCart,
    closeCart,
    getTotalItems,
    getTotalPrice,
  };
};
