import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import * as api from "../service/CartService";
import type { CartResponse, CartItem } from "../types/Types";

export const useBulkCart = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: api.bulkCart,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["cart-items"] });
    },
  });
};

export const useIncrementCart = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: api.increment,
    onMutate: async (id: string | number) => {
      await queryClient.cancelQueries({ queryKey: ["cart-items"] });

      const previousCart = queryClient.getQueryData<CartResponse>([
        "cart-items",
      ]);

      if (previousCart?.data) {
        const existingItem = previousCart.data.items.find(
          (item) => item.foodId === String(id)
        );

        if (existingItem) {
          const updatedItems = previousCart.data.items.map((item) => {
            if (item.foodId === String(id)) {
              return {
                ...item,
                quantity: item.quantity + 1,
              };
            }
            return item;
          });

          queryClient.setQueryData<CartResponse>(["cart-items"], {
            ...previousCart,
            data: {
              ...previousCart.data,
              items: updatedItems,
              totalItems: previousCart.data.totalItems + 1,
            },
          });
        }
      }

      return { previousCart };
    },
    onError: (_err, _id, context) => {
      if (context?.previousCart) {
        queryClient.setQueryData(["cart-items"], context.previousCart);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ["cart-items"] });
    },
  });
};

export const useDecrementCart = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: api.decrement,
    onMutate: async (id: string | number) => {
      await queryClient.cancelQueries({ queryKey: ["cart-items"] });

      const previousCart = queryClient.getQueryData<CartResponse>([
        "cart-items",
      ]);

      if (previousCart?.data) {
        const updatedItems = previousCart.data.items
          .map((item: CartItem) => {
            if (item.foodId === String(id)) {
              const newQuantity = item.quantity - 1;
              if (newQuantity <= 0) {
                return null;
              }
              return {
                ...item,
                quantity: newQuantity,
              };
            }
            return item;
          })
          .filter((item: CartItem | null): item is CartItem => item !== null);

        queryClient.setQueryData<CartResponse>(["cart-items"], {
          ...previousCart,
          data: {
            ...previousCart.data,
            items: updatedItems,
            totalItems: Math.max(0, previousCart.data.totalItems - 1),
          },
        });
      }

      return { previousCart };
    },
    onError: (_err, _id, context) => {
      if (context?.previousCart) {
        queryClient.setQueryData(["cart-items"], context.previousCart);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ["cart-items"] });
    },
  });
};

export const useClearCart = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: api.clear,
    onMutate: async () => {
      await queryClient.cancelQueries({ queryKey: ["cart-items"] });

      const previousCart = queryClient.getQueryData<CartResponse>([
        "cart-items",
      ]);

      if (previousCart?.data) {
        queryClient.setQueryData<CartResponse>(["cart-items"], {
          ...previousCart,
          data: {
            ...previousCart.data,
            items: [],
            totalItems: 0,
            subTotal: 0,
            total: 0,
          },
        });
      }

      return { previousCart };
    },
    onError: (_err, _variables, context) => {
      if (context?.previousCart) {
        queryClient.setQueryData(["cart-items"], context.previousCart);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ["cart-items"] });
    },
  });
};

export const useGetCartItems = (enabled = true) => {
  return useQuery({
    queryKey: ["cart-items"],
    queryFn: api.getCartItems,
    enabled,
  });
};

export const useSaveAllMethod = () => {
  return useMutation({
    mutationFn: api.saveAllMethod,
  });
};
