import { useAllProducts } from '@/src/hooks/prominent-api-hooks';
import { useCentralSlotStore } from '@/src/store/centralSlotStore';
import { Alert } from 'react-native';
import { useQuery, useMutation, useQueryClient, UseQueryResult, UseMutationResult } from '@tanstack/react-query';
import { StorageServiceCasual } from 'common-ui/src/services/StorageServiceCasual';

// Cart type definition
export type CartType = "regular" | "flash";

const getCartStorageKey = (cartType: CartType = "regular"): string => {
  return cartType === "flash" ? "flash_cart_items" : "cart_items";
};

interface LocalCartItem {
  id: number;
  productId: number;
  quantity: number;
  slotId: number;
  addedAt: string;
}

interface ProductSummary {
  id: number;
  price: string;
  incrementStep: number;
  isOutOfStock: boolean;
  isFlashAvailable: boolean;
  name?: string;
  flashPrice?: string | null;
  images?: string[];
  productQuantity?: number;
  unitNotation?: string;
  marketPrice?: string | null;
}

export interface CartItem {
  id: number;
  productId: number;
  quantity: number;
  addedAt: string;
  subtotal: number;
  slotId: number;
}

interface CartData {
  items: CartItem[];
  totalItems: number;
  totalAmount: number;
}

interface UseGetCartOptions {
  refetchOnWindowFocus?: boolean;
  enabled?: boolean;
}

interface UseGetCartReturn {
  data: CartData | undefined;
  isLoading: boolean;
  error: Error | null;
  refetch: () => Promise<UseQueryResult<CartData, Error>>;
  cartItems: CartItem[];
  totalItems: number;
  totalPrice: number;
  isEmpty: boolean;
  hasItems: boolean;
}

interface AddToCartVariables {
  productId: number;
  quantity: number;
  slotId: number;
}

interface UpdateCartVariables {
  itemId: number;
  quantity: number;
}

interface RemoveCartVariables {
  itemId: number;
}

interface MutationOptions<TData, TVariables> {
  onSuccess?: (data: TData, variables: TVariables) => void;
  onError?: (error: Error) => void;
  showSuccessAlert?: boolean;
  showErrorAlert?: boolean;
  refetchCart?: boolean;
}

interface UseAddToCartReturn {
  mutate: UseMutationResult<LocalCartItem[], Error, AddToCartVariables>['mutate'];
  mutateAsync: UseMutationResult<LocalCartItem[], Error, AddToCartVariables>['mutateAsync'];
  isLoading: boolean;
  error: Error | null;
  data: LocalCartItem[] | undefined;
  addToCart: (productId: number, quantity?: number, slotId?: number, onSettled?: (data: LocalCartItem[] | undefined, error: Error | null) => void) => void;
  addToCartAsync: (productId: number, quantity?: number, slotId?: number) => Promise<LocalCartItem[]>;
}

interface UseUpdateCartItemReturn {
  mutate: UseMutationResult<LocalCartItem[], Error, UpdateCartVariables>['mutate'];
  mutateAsync: UseMutationResult<LocalCartItem[], Error, UpdateCartVariables>['mutateAsync'];
  isLoading: boolean;
  error: Error | null;
  data: LocalCartItem[] | undefined;
  updateCartItem: (itemId: number, quantity: number) => void;
  updateCartItemAsync: (itemId: number, quantity: number) => Promise<LocalCartItem[]>;
}

interface UseRemoveFromCartReturn {
  mutate: UseMutationResult<LocalCartItem[], Error, RemoveCartVariables>['mutate'];
  mutateAsync: UseMutationResult<LocalCartItem[], Error, RemoveCartVariables>['mutateAsync'];
  isLoading: boolean;
  error: Error | null;
  data: LocalCartItem[] | undefined;
  removeFromCart: (itemId: number) => void;
  removeFromCartAsync: (itemId: number) => Promise<LocalCartItem[]>;
}

const getLocalCart = async (cartType: CartType = "regular"): Promise<LocalCartItem[]> => {
  const key = getCartStorageKey(cartType);
  const data = await StorageServiceCasual.getItem(key);
  return data ? JSON.parse(data) : [];
};

const saveLocalCart = async (items: LocalCartItem[], cartType: CartType = "regular"): Promise<void> => {
  const key = getCartStorageKey(cartType);
  await StorageServiceCasual.setItem(key, JSON.stringify(items));
  await getLocalCart(cartType);
};

const getNextCartItemId = (items: LocalCartItem[]): number => {
  const maxId = items.length > 0 ? Math.max(...items.map(item => item.id)) : 0;
  return maxId + 1;
};

const addToLocalCart = async (productId: number, quantity: number, slotId: number | undefined, cartType: CartType = "regular"): Promise<LocalCartItem[]> => {
  const items = await getLocalCart(cartType);
  const existingIndex = items.findIndex(item => item.productId === productId);

  if (existingIndex >= 0) {
    items[existingIndex].quantity += quantity;
    if (slotId !== undefined) {
      items[existingIndex].slotId = slotId;
    }
  } else {
    const newId = getNextCartItemId(items);
    const cartItem: LocalCartItem = {
      id: newId,
      productId,
      quantity,
      slotId: slotId ?? 0,
      addedAt: new Date().toISOString(),
    };

    items.push(cartItem);
  }
  
  await saveLocalCart(items, cartType);
  return items;
};

const updateLocalCartItem = async (itemId: number, quantity: number, cartType: CartType = "regular"): Promise<LocalCartItem[]> => {
  const items = await getLocalCart(cartType);
  const item = items.find(i => i.id === itemId);
  if (item) {
    item.quantity = quantity;
    await saveLocalCart(items, cartType);
  }
  return items;
};

const removeFromLocalCart = async (itemId: number, cartType: CartType = "regular"): Promise<LocalCartItem[]> => {
  const items = await getLocalCart(cartType);
  const filtered = items.filter(i => i.id !== itemId);
  await saveLocalCart(filtered, cartType);
  return filtered;
};

const clearLocalCart = async (cartType: CartType = "regular"): Promise<void> => {
  const key = getCartStorageKey(cartType);
  await StorageServiceCasual.setItem(key, JSON.stringify([]));
};

export function useGetCart(options: UseGetCartOptions = {}, cartType: CartType = "regular"): UseGetCartReturn {
  const { data: products } = useAllProducts();
  const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap);
  
  const query: UseQueryResult<CartData, Error> = useQuery({
    queryKey: [`local-cart-${cartType}`],
    queryFn: async (): Promise<CartData> => {
      const cartItems = await getLocalCart(cartType);

      const productMap: Record<number, Omit<ProductSummary, 'isOutOfStock' | 'isFlashAvailable'>> = Object.fromEntries(
        products?.products?.map((p) => [
          p.id,
          {
            id: p.id,
            price: String(p.price),
            incrementStep: p.incrementStep,
            marketPrice: p.marketPrice === null || p.marketPrice === undefined ? null : String(p.marketPrice),
            name: p.name,
            flashPrice: p.flashPrice,
            images: p.images,
            productQuantity: p.productQuantity,
            unitNotation: p.unitNotation,
          },
        ]) ?? []
      );

      const items: CartItem[] = cartItems
        .map((cartItem): CartItem | null => {
          const productBasic = productMap[cartItem.productId];
          const productAvailability = productSlotsMap[cartItem.productId];

          if (!productBasic || !productAvailability) return null;
          
          return {
            id: cartItem.id,
            productId: cartItem.productId,
            quantity: cartItem.quantity,
            addedAt: cartItem.addedAt, 
            subtotal: Number(productBasic.price) * cartItem.quantity,
            slotId: cartItem.slotId,
          };
        })
        .filter((item): item is CartItem => item !== null);
        
      const totalAmount = items.reduce((sum, item) => sum + item.subtotal, 0);

      return {
        items,
        totalItems: items.length,
        totalAmount,
      };
    },
    refetchOnWindowFocus: options?.refetchOnWindowFocus ?? true,
    enabled: (options?.enabled ?? true) && !!products,
  });
  
  return {
    data: query.data,
    isLoading: query.isLoading,
    error: query.error,
    refetch: query.refetch,
    cartItems: query.data?.items ?? [],
    totalItems: query.data?.totalItems ?? 0,
    totalPrice: query.data?.totalAmount ?? 0,
    isEmpty: !(query.data?.items?.length ?? 0),
    hasItems: Boolean(query.data?.items?.length),
  };
}

export function useAddToCart(options: MutationOptions<LocalCartItem[], AddToCartVariables> = {}, cartType: CartType = "regular"): UseAddToCartReturn {
  const queryClient = useQueryClient();

  const mutation: UseMutationResult<LocalCartItem[], Error, AddToCartVariables> = useMutation({
    mutationFn: async ({ productId, quantity, slotId }: AddToCartVariables): Promise<LocalCartItem[]> => {
      return await addToLocalCart(productId, quantity, slotId, cartType);
    },
    onSuccess: (data: LocalCartItem[], variables: AddToCartVariables) => {
      queryClient.invalidateQueries({ queryKey: [`local-cart-${cartType}`] });
      if (options?.showSuccessAlert !== false) {
        Alert.alert("Success", "Item added to cart!");
      }
      options?.onSuccess?.(data, variables);
    },
    onError: (error: Error) => {
      if (options?.showErrorAlert !== false) {
        Alert.alert("Error", error.message || "Failed to add item to cart");
      }
      options?.onError?.(error);
    },
  });

  const addToCart = (productId: number, quantity = 1, slotId?: number, onSettled?: (data: LocalCartItem[] | undefined, error: Error | null) => void): void => {
    if (slotId == null) {
      throw new Error('slotId is required for adding to cart');
    }
    mutation.mutate({ productId, quantity, slotId }, {
      onSettled: (data: LocalCartItem[] | undefined, error: Error | null) => {
        onSettled?.(data, error);
      }
    });
  };

  return {
    mutate: mutation.mutate,
    mutateAsync: mutation.mutateAsync,
    isLoading: mutation.isPending,
    error: mutation.error,
    data: mutation.data,
    addToCart,
    addToCartAsync: (productId: number, quantity = 1, slotId?: number): Promise<LocalCartItem[]> => {
      if (slotId == null) {
        throw new Error('slotId is required for adding to cart');
      }
      return mutation.mutateAsync({ productId, quantity, slotId });
    },
  };
}

export function useUpdateCartItem(options: MutationOptions<LocalCartItem[], UpdateCartVariables> = {}, cartType: CartType = "regular"): UseUpdateCartItemReturn {
  const queryClient = useQueryClient();

  const mutation: UseMutationResult<LocalCartItem[], Error, UpdateCartVariables> = useMutation({
    mutationFn: async ({ itemId, quantity }: UpdateCartVariables): Promise<LocalCartItem[]> => {
      return await updateLocalCartItem(itemId, quantity, cartType);
    },
    onSuccess: (data: LocalCartItem[], variables: UpdateCartVariables) => {
      queryClient.invalidateQueries({ queryKey: [`local-cart-${cartType}`] });
      if (options?.showSuccessAlert !== false) {
        Alert.alert("Success", "Cart item updated!");
      }
      options?.onSuccess?.(data, variables);
    },
    onError: (error: Error) => {
      if (options?.showErrorAlert !== false) {
        Alert.alert("Error", error.message || "Failed to update cart item");
      }
      options?.onError?.(error);
    },
  });

  return {
    mutate: mutation.mutate,
    mutateAsync: mutation.mutateAsync,
    isLoading: mutation.isPending,
    error: mutation.error,
    data: mutation.data,
    updateCartItem: (itemId: number, quantity: number): void =>
      mutation.mutate({ itemId, quantity }),
    updateCartItemAsync: (itemId: number, quantity: number): Promise<LocalCartItem[]> =>
      mutation.mutateAsync({ itemId, quantity }),
  };
}

export function useRemoveFromCart(options: MutationOptions<LocalCartItem[], RemoveCartVariables> = {}, cartType: CartType = "regular"): UseRemoveFromCartReturn {
  const queryClient = useQueryClient();

  const mutation: UseMutationResult<LocalCartItem[], Error, RemoveCartVariables> = useMutation({
    mutationFn: async ({ itemId }: RemoveCartVariables): Promise<LocalCartItem[]> => {
      return await removeFromLocalCart(itemId, cartType);
    },
    onSuccess: (data: LocalCartItem[], variables: RemoveCartVariables) => {
      queryClient.invalidateQueries({ queryKey: [`local-cart-${cartType}`] });
      if (options?.showSuccessAlert !== false) {
        Alert.alert("Success", "Item removed from cart!");
      }
      options?.onSuccess?.(data, variables);
    },
    onError: (error: Error) => {
      if (options?.showErrorAlert !== false) {
        Alert.alert("Error", error.message || "Failed to remove item from cart");
      }
      options?.onError?.(error);
    },
  });

  return {
    mutate: mutation.mutate,
    mutateAsync: mutation.mutateAsync,
    isLoading: mutation.isPending,
    error: mutation.error,
    data: mutation.data,
    removeFromCart: (itemId: number): void =>
      mutation.mutate({ itemId }),
    removeFromCartAsync: (itemId: number): Promise<LocalCartItem[]> =>
      mutation.mutateAsync({ itemId }),
  };
}

// Export clear cart function for direct use
export { clearLocalCart };
