"use client";

import { gql } from "@apollo/client";
import { useMutation, useQuery } from "@apollo/client/react";
import { createContext, useContext, useEffect, useMemo, useState } from "react";

import { cartClient, eateryClient } from "./apollo-clients";
import {
  CartEntity,
  CartItemEntity,
  addMenuItemMutation,
  allEateriesQuery,
  createCartMutation,
  getCartQuery,
} from "./types";

interface CartContextValue {
  items: CartItemEntity[];
  totalItems: number;
  totalPrice: number;
  addToCart: (product: CartItemEntity) => void;
  increaseQty: (id: string) => void;
  decreaseQty: (id: string) => void;
  removeFromCart: (id: string) => void;
  setQuantity: (id: string, quantity: number) => void;
}

const CART_ID = "cartId";
const CartContext = createContext<CartContextValue | null>(null);

const GET_CART_ITEMS = gql`
  query getCart($cartId: String!) {
    getCart(cartId: $cartId) {
      Id
      userId
      eateryId
      items {
        productId
        quantity
        priceAtTimeOfAdding
        subTotal
      }
      totalAmount
      paymentQrUrl
    }
  }
`;

const GET_EATERY = gql`
  query GetEateryMenu {
    allEateries {
      id
    }
  }
`;

const CREATE_CART = gql`
  mutation createCart($eateryId: String!) {
    createCart(eateryId: $eateryId)
  }
`;

const ADD_ITEM = gql`
  mutation addItem(
    $cartId: String!
    $menuItemId: String!
    $quantity: BigInteger!
  ) {
    addItem(cartId: $cartId, menuItemId: $menuItemId, quantity: $quantity) {
      Id
      userId
      eateryId
      items {
        productId
        quantity
        priceAtTimeOfAdding
        subTotal
      }
      totalAmount
      paymentQrUrl
    }
  }
`;

export function CartProvider({ children }: { children: React.ReactNode }) {
  const [cart, setCart] = useState<CartEntity>(null!);
  const [cartId, setCartId] = useState<string | null>(null);

  const { data: eateryData } = useQuery<allEateriesQuery>(GET_EATERY, {
    client: eateryClient,
  });

  const [createCart] = useMutation<createCartMutation>(CREATE_CART, {
    client: cartClient,
  });

  const { data, loading, error } = useQuery<getCartQuery>(GET_CART_ITEMS, {
    client: cartClient,
    variables: { cartId },
  });

  const [addMenuItem] = useMutation<addMenuItemMutation>(ADD_ITEM, {
    client: cartClient,
  });

  useEffect(() => {
    const createCartFunc = async () => {
      if (eateryData && eateryData.allEateries?.length > 0) {
        try {
          const firstEateryId = eateryData.allEateries[0].id;
          const { data: mutationResult } = await createCart({
            variables: { eateryId: firstEateryId },
          });

          const newCartId = mutationResult!.createCart;
          if (newCartId) {
            localStorage.setItem(CART_ID, newCartId);
            setCartId(newCartId);
          }
        } catch (err) {
          console.error("Lỗi khi tạo giỏ hàng:", err);
        }
      }
    };

    if (error) createCartFunc();
    else {
      const localCartId = localStorage.getItem(CART_ID);
      if (localCartId) setCartId(localCartId);
    }
  }, [eateryData, createCart, data, loading, error]);

  useEffect(() => {
    if (data?.getCart) setCart(data.getCart);
  }, [data]);

  const addToCart = async (product: CartItemEntity) => {
    if (!cartId) return;

    const { data: result } = await addMenuItem({
      variables: {
        cartId,
        menuItemId: product.productId!,
        quantity: product.quantity,
      },
    });

    if (result) setCart(result.addItem);
  };

  const setQuantity = async (id: string, quantity: number) => {
    if (!cartId) return;

    const { data: result } = await addMenuItem({
      variables: {
        cartId,
        menuItemId: id,
        quantity,
      },
    });

    if (result) setCart(result.addItem);
  };

  const removeFromCart = (id: string) => setQuantity(id, 0);

  const increaseQty = (id: string) =>
    setQuantity(id, cart.items.find((i) => i.productId == id)!.quantity + 1);

  const decreaseQty = (id: string) =>
    setQuantity(id, cart.items.find((i) => i.productId == id)!.quantity - 1);

  const totalItems = useMemo(
    () => cart?.items.reduce((sum, item) => sum + item.quantity, 0),
    [cart],
  );

  const value = useMemo(
    () => ({
      items: cart?.items,
      totalItems,
      totalPrice: cart?.totalAmount,
      addToCart,
      increaseQty,
      decreaseQty,
      removeFromCart,
      setQuantity,
    }),
    [cart?.items, cart?.totalAmount],
  );

  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 CartProvider");
  }
  return context;
}
