"use client";

import { useState, useRef } from "react";
import { fetchHandler } from "../fetch-handler";
import { GUEST_CART_ID, GUEST_CART_TOKEN, IS_GUEST } from "@/utils/constants";
import { encodeJWT, decodeJWT } from "@/utils/jwt-cookie";
import { setCookie, deleteCookie, getCookie } from "@/utils/cookie-tools";
import { CREATE_CART_TOKEN } from "@/graphql";

// ---------------------------
// Main Hook
// ---------------------------
export const useGuestCartToken = () => {

  const [token, setToken] = useState(() => {
      const cookieToken = getCookie(GUEST_CART_TOKEN);
      let guestCartToken: string | null = null;

      if (cookieToken) {

        const isGuest = getCookie(IS_GUEST) !== "false";
        const decoded = decodeJWT<{
          sessionToken: string;
          cartId: number;
          isGuest: boolean;
        }>(cookieToken, isGuest);

        if (decoded) {
          guestCartToken = decoded.sessionToken;
        }
      }
      return guestCartToken;
  });
  const [cartId, setCartId] = useState(() => {
    const cookieToken = getCookie(GUEST_CART_TOKEN);
    let guestCartId: number | null = null;
    if (cookieToken) {

      const isGuest = getCookie(IS_GUEST) !== "false";
      const decoded = decodeJWT<{
        sessionToken: string;
        cartId: number;
        isGuest: boolean;
      }>(cookieToken, isGuest);

      if (decoded) {
        guestCartId = decoded.cartId;
      }
    }
    return guestCartId;
  });
  // const [isReady, setIsReady] = useState(true);

  const isResettingRef = useRef(false);
  const tokenCreatedRef = useRef(false);
  const tokenPromiseRef = useRef<Promise<string | null> | null>(null);

  const createGuestToken = async (): Promise<string | null> => {
    if (tokenPromiseRef.current) return tokenPromiseRef.current;

    tokenPromiseRef.current = (async () => {
      if (tokenCreatedRef.current) {
        // Return existing raw token from cookie
        const cookieVal = getCookie(GUEST_CART_TOKEN);
        if (cookieVal) {
          const isGuest = getCookie(IS_GUEST) !== "false";
          const decoded = decodeJWT<{ sessionToken: string }>(cookieVal, isGuest);
          return decoded?.sessionToken ?? null;
        }
        return null;
      }
      tokenCreatedRef.current = true;

      try {
        const query = CREATE_CART_TOKEN;
        const queryString = typeof query === "string" ? query : (query.loc?.source?.body ?? "");
        const res = await fetchHandler({
          url: "graphql",
          method: "POST",
          body: { operationName: "CreateCart",query: queryString },
          contentType: true,
        });

        const cart = res?.data?.createCartToken?.cartToken;
        if (!cart) {
          tokenCreatedRef.current = false;
          return null;
        }

        const newToken = encodeJWT({
          sessionToken: cart.sessionToken,
          cartId: cart.id,
          isGuest: cart.isGuest,
        });
        const newCartId = Number(cart.id);

        setCookie(GUEST_CART_TOKEN, newToken,{encode: false});
        setCookie(GUEST_CART_ID, String(newCartId));
        setCookie(IS_GUEST, String(cart?.isGuest));

        // State and return should be the RAW token
        setToken(cart.sessionToken);
        setCartId(newCartId);
        return cart.sessionToken;
      } catch (e) {
        console.error("Error creating guest token:", e);
        tokenCreatedRef.current = false;
        return null;
      } finally {
        tokenPromiseRef.current = null;
      }
    })();

    return tokenPromiseRef.current;


  };

  const resetGuestToken = async () => {
    if (isResettingRef.current) return;
    isResettingRef.current = true;

    tokenCreatedRef.current = false;

    // delete old
    deleteCookie(GUEST_CART_TOKEN);
    deleteCookie(GUEST_CART_ID);

    await createGuestToken();

    isResettingRef.current = false;
  };


  return {
    token,
    cartId,
    // isReady,
    createGuestToken,
    resetGuestToken,
    deleteCookie,
  };
};
