import { useNavigate } from "react-router-dom";
import styles from "./styles.module.scss";
import { ChangeEvent, useCallback, useEffect, useRef, useState } from "react";
import Loader, { LoaderColor } from "@/components/Loader";
import ChatHeader from "./components/ChatHeader";
import InputMessage from "./components/InputMessage";
import routes from "@/routes";
import Message from "./components/Message";
import LoaderDots from "./components/LoaderDots";
import StartInfo from "./components/StartInfo";
import RefillCreditsModal from "./components/RefillCreditsModal";
import useChatSocket from "@/hooks/chatsSocket/useChatsSocket";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import BottomModal from "../../components/BottomModal";
import OutOfCreditsModal from "./components/OutOfCreditsModal";
import RefillProductsModal from "./components/RefillProductsModal";
import { Products, useApi, useApiCall } from "@/api";
import { usePaywall } from "@/hooks/paywall/usePaywall";
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
import { useAuth } from "@/auth";
import { ResponsePost } from "@/api/resources/SinglePayment";
import { createSinglePayment } from "@/services/singlePayment";
import Modal from "@/components/Modal";
import Title from "@/components/Title";
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
import { getPriceCentsToDollars } from "@/services/price";
import { IMessage } from "@/api/resources/ChatMessages";

const returnUrl = `${window.location.protocol}//${
  window.location.host
}${routes.client.chatsExpert()}`;

function ExpertChat() {
  const api = useApi();
  const dispatch = useDispatch();
  const navigate = useNavigate();
  const assistant = useSelector(selectors.selectCurrentAssistant);
  const chatId = useSelector(selectors.selectCurrentChatId);
  const userId = useSelector(selectors.selectUserId);
  const [messageText, setMessageText] = useState("");
  const [textareaRows, setTextareaRows] = useState(1);
  // const [isLoadingLatestMessages, setIsLoadingLatestMessages] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const [isShowRefillCreditsModal, setIsShowRefillCreditsModal] =
    useState(false);
  const [isShowOutOfCreditsModal, setIsShowOutOfCreditsModal] = useState(false);
  const [isShowRefillProductsModal, setIsShowRefillProductsModal] =
    useState(false);

  const {
    isLoading,
    isLoadingSelfMessage,
    isLoadingAdvisorMessage,
    messages,
    isAvailableChatting,
    messagesAfterEnd,
    initialBalance,
    sendMessage,
    readMessage,
  } = useChatSocket(userId, chatId);

  // Payment
  const { user: userFromStore } = useAuth();
  const tokenFromStore = useSelector(selectors.selectToken);
  const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
  const [isLoadingPayment, setIsLoadingPayment] = useState(false);
  const [isError, setIsError] = useState(false);
  const [currentProduct, setCurrentProduct] = useState<IPaywallProduct | null>(
    null
  );

  const isPayedFirstPurchase = useSelector(
    selectors.selectIsPayedFirstPurchase
  );

  const checkIsPayedFirstPurchase = useCallback(async () => {
    if (isPayedFirstPurchase) return;
    const isPayed = await api.checkProductPurchased({
      token: tokenFromStore,
      productKey: "credits.100",
    });
    if (isPayed && "active" in isPayed && isPayed.active) {
      dispatch(actions.chat.updateIsPayedFirstPurchase(true));
    }
    return isPayed;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    api,
    dispatch,
    isPayedFirstPurchase,
    tokenFromStore,
    isAvailableChatting,
  ]);

  const { data: isPayedFirstPurchaseResponse } = useApiCall<
    Products.ResponseGet | undefined
  >(checkIsPayedFirstPurchase);

  const { products } = usePaywall({
    placementKey: EPlacementKeys["aura.placement.chat"],
  });

  const scrollToBottom = () => {
    setTimeout(() => {
      messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
    }, 100);
  };

  useEffect(() => {
    if (!isLoading && !!messages.length) scrollToBottom();
  }, [messages, isLoading]);

  const handleChangeMessageText = (e: ChangeEvent<HTMLTextAreaElement>) => {
    const { scrollHeight, clientHeight, value } = e.target;
    if (
      scrollHeight > clientHeight &&
      textareaRows < 5 &&
      value.length > messageText.length
    ) {
      setTextareaRows((prev) => prev + 1);
    }
    if (
      scrollHeight === clientHeight &&
      textareaRows > 1 &&
      value.length < messageText.length
    ) {
      setTextareaRows((prev) => prev - 1);
    }
    setMessageText(e.target.value);
  };

  const getIsSelfMessage = (role: string) => role === "user";

  const deleteDataFromMessage = (messageText: string) => {
    const splittedText = messageText?.split("#");
    if (splittedText?.length > 2) {
      return splittedText?.slice(2).join("#");
    }
    return messageText;
  };

  const endChat = () => {
    navigate(routes.client.chatsCategories());
  };

  const handleRefillModalClickButton = () => {
    createPayment("credits.100");
  };

  const handleOutOfCreditsModalClickButton = () => {
    createPayment("credits.80");
  };

  const handleRefillProductsModalClickButton = (productKey: string) => {
    createPayment(productKey);
  };

  const handleSendMessage = (messageText: string) => {
    if (!isAvailableChatting) {
      showModals();
    }
    setMessageText("");
    sendMessage(messageText);
  };

  const closeModals = useCallback(() => {
    setIsShowRefillProductsModal(false);
    setIsShowOutOfCreditsModal(false);
    setIsShowRefillCreditsModal(false);
  }, []);

  const createPayment = useCallback(
    async (productKey: string) => {
      try {
        if (!userFromStore || !productKey.length) return;
        const currentProduct =
          products?.find((product) => product.key === productKey) || null;
        if (!currentProduct) return;
        setCurrentProduct(currentProduct);
        setIsLoadingPayment(true);
        const { _id, key } = currentProduct;
        const paymentInfo = {
          productId: _id,
          key,
        };
        const paymentIntent = await createSinglePayment(
          userFromStore,
          paymentInfo,
          tokenFromStore,
          userFromStore.email,
          userFromStore.profile.full_name,
          userFromStore.profile.birthday,
          returnUrl,
          api
        );
        setPaymentIntent(paymentIntent);
        if ("payment" in paymentIntent) {
          if (paymentIntent.payment.status === "paid") return closeModals();
          return setIsError(true);
        }
      } catch (error) {
        console.log(error);

        setIsError(true);
      } finally {
        setIsLoadingPayment(false);
      }
    },
    [api, closeModals, products, tokenFromStore, userFromStore]
  );

  const showModals = useCallback(() => {
    if (isPayedFirstPurchase) {
      return setIsShowOutOfCreditsModal(true);
    }

    if (
      isPayedFirstPurchase ||
      !isPayedFirstPurchaseResponse ||
      !("active" in isPayedFirstPurchaseResponse) ||
      !isPayedFirstPurchaseResponse
    ) {
      return setIsShowOutOfCreditsModal(true);
    }

    return setIsShowRefillCreditsModal(true);
  }, [isPayedFirstPurchase, isPayedFirstPurchaseResponse]);

  useEffect(() => {
    if (isAvailableChatting && !isLoading) {
      closeModals();
    }
  }, [closeModals, isAvailableChatting, isLoading]);

  useEffect(() => {
    if (initialBalance !== null && !isLoading && !initialBalance) {
      showModals();
    }
  }, [initialBalance, isLoading, showModals]);

  const isBlurMessage = (message: IMessage) => {
    return (
      !!messagesAfterEnd.find((item) => item.id === message.id) &&
      message.role === "assistant"
    );
  };

  return (
    <section className={`${styles.page} page`}>
      {!isLoading &&
        paymentIntent &&
        "paymentIntent" in paymentIntent &&
        !!tokenFromStore.length &&
        currentProduct && (
          <>
            <Modal
              open={!!paymentIntent}
              onClose={() => setPaymentIntent(null)}
              containerClassName={styles.modal}
            >
              <Title variant="h1" className={styles["modal-title"]}>
                {getPriceCentsToDollars(currentProduct.price || 0)}$
              </Title>
              <PaymentForm
                isLoadingPayment={isLoadingPayment}
                stripePublicKey={paymentIntent.paymentIntent.data.public_key}
                clientSecret={paymentIntent.paymentIntent.data.client_secret}
                returnUrl={returnUrl}
              />
            </Modal>
          </>
        )}
      {isLoading && (
        <Loader color={LoaderColor.Red} className={styles.loader} />
      )}
      {!isLoading && (
        <ChatHeader
          name={assistant?.name || ""}
          avatar={assistant?.image || ""}
          classNameContainer={styles["header-container"]}
          clickBackButton={endChat}
          isTimerGoing={isAvailableChatting}
          hasBackButton={false}
        />
      )}
      {!isLoading && !!messages.length && (
        <div className={styles["messages-container"]}>
          {messages.map((message) => (
            <Message
              avatar={assistant?.image || ""}
              text={deleteDataFromMessage(message.text)}
              isVisible={deleteDataFromMessage(message.text) !== " HI"}
              advisorName={assistant?.name || ""}
              backgroundTextColor={
                getIsSelfMessage(message.role) ? "#0080ff" : "#c9c9c9"
              }
              textColor={getIsSelfMessage(message.role) ? "#fff" : "#000"}
              isSelf={getIsSelfMessage(message.role)}
              key={message.id}
              isRead={message.isRead}
              readMessage={readMessage}
              messageId={message.id}
              isBlur={isBlurMessage(message)}
              onClickBlur={() => showModals()}
            />
          ))}
          {isLoadingAdvisorMessage && !isLoadingSelfMessage && (
            <Message
              avatar={assistant?.image || ""}
              text={<LoaderDots />}
              isSelf={false}
              backgroundTextColor={"#c9c9c9"}
              textColor={"#000"}
            />
          )}
          {/* <div className={styles["loader-container"]}>
            {isLoadingLatestMessages && <Loader color={LoaderColor.Red} />}
          </div> */}
        </div>
      )}

      {!messages.length && !isLoading && <StartInfo />}

      <div ref={messagesEndRef} />
      {!isLoading && (
        <InputMessage
          placeholder="Text message"
          messageText={messageText}
          textareaRows={textareaRows}
          disabledTextArea={isLoadingAdvisorMessage || isLoadingSelfMessage}
          disabledButton={!messageText.length}
          classNameContainer={styles["input-container"]}
          handleChangeMessageText={handleChangeMessageText}
          isLoading={isLoadingSelfMessage}
          submitForm={handleSendMessage}
          description={`The cost of chat is ${assistant?.price} credits/min`}
        />
      )}
      {!isLoading && (
        <>
          {isShowRefillCreditsModal && (
            <BottomModal handleClose={() => setIsShowRefillCreditsModal(false)}>
              <RefillCreditsModal
                isError={isError}
                isLoading={isLoadingPayment}
                products={products}
                handleClickButton={handleRefillModalClickButton}
              />
            </BottomModal>
          )}
          {isShowOutOfCreditsModal && (
            <BottomModal handleClose={() => setIsShowOutOfCreditsModal(false)}>
              <OutOfCreditsModal
                isError={isError}
                isLoading={isLoadingPayment}
                products={products}
                handleClickButton={handleOutOfCreditsModalClickButton}
                handleClickNotWant={endChat}
                timerLeft={() => {
                  if (isLoadingPayment) return;
                  setIsShowOutOfCreditsModal(false);
                  setIsShowRefillProductsModal(true);
                }}
              />
            </BottomModal>
          )}
          {isShowRefillProductsModal && (
            <BottomModal
              handleClose={() => setIsShowRefillProductsModal(false)}
            >
              <RefillProductsModal
                isError={isError}
                isLoading={isLoadingPayment}
                products={products}
                handleClickButton={handleRefillProductsModalClickButton}
              />
            </BottomModal>
          )}
        </>
      )}
    </section>
  );
}

export default ExpertChat;
