import {
  ICartItem as IBaseCartItem,
  IPurchase,
  IPurchaseUnit,
  IStoreItem,
  MetadataType,
  PurchaseType
} from '@rpg-engine/shared';
import { useEffect, useRef, useState } from 'react';
import { useStoreMetadata } from './useStoreMetadata';

// Extend the base cart item to include metadata
interface ICartItem extends IBaseCartItem {
  metadata?: Record<string, any>;
}

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

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

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

  const { collectMetadata, isCollectingMetadata } = useStoreMetadata();

  const handleAddToCart = async (item: IStoreItem, quantity: number, preselectedMetadata?: Record<string, any>) => {
    // If metadata is already provided (from inline selection), use it directly
    if (preselectedMetadata) {
      setCartItems(prevItems => {
        return [
          ...prevItems,
          {
            item,
            quantity,
            metadata: preselectedMetadata,
          },
        ];
      });
      return;
    }
    
    // If item requires metadata but none was provided, collect it before adding to cart
    if (item.metadataType && item.metadataType !== MetadataType.None) {
      const metadata = await collectMetadata(item);
      if (!metadata) return; // User cancelled

      // Add item with metadata
      setCartItems(prevItems => {
        // Create new cart item with metadata
        return [
          ...prevItems,
          {
            item,
            quantity,
            metadata,
          },
        ];
      });
    } else {
      // Existing add to cart logic for items without metadata
      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 => ({
      purchaseKey: cartItem.item.key,
      qty: cartItem.quantity,
      type: getPurchaseType(cartItem.item),
      name: cartItem.item.name,
      metadata: cartItem.metadata || cartItem.item.metadataConfig, // Use collected metadata if available
    }));

    const purchase: IPurchase = {
      _id: uuidv4(),
      userId: '1',
      status: 'pending',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      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,
    isCollectingMetadata,
  };
};

// Helper functions
function getPurchaseType(item: IStoreItem): PurchaseType {
  // Check if the item comes from a pack based on naming convention or other property
  if (item.key.startsWith('pack_')) {
    return PurchaseType.Pack;
  } else {
    return PurchaseType.Item;
  }
}

function uuidv4(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = (Math.random() * 16) | 0,
      v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

