import React, { useEffect, useMemo } from "react";
import PropTypes from "prop-types";
import { DirectChatContainer } from "./DirectChat.styled";
import DirectChatHeaderTitle from "./DirectChatHeaderTitle/DirectChatHeaderTitle";
import DirectChatHeader from "./DirectChatHeader/DirectChatHeader";
import { useDispatch, useSelector } from "react-redux";
import { useLocation, useRouteMatch } from "react-router-dom";
import {
  addNewMessage,
  fetchChats,
  fetchOneChat,
  setOneChat,
} from "../../store/actions/chat/chatActions";
import {
  selectLatestChats,
  selectSelectedChat,
} from "../../store/selectors/chatSelectors";
import DirectChatContent from "./DirectChatContent/DirectChatContent";
import { selectOffer } from "../../store/selectors/offersSelectors";
import { fetchOneOffer } from "../../store/actions/offers/offersActions";
import SkeletonDirectChat from "./SkeletonDirectChat/SkeletonDirectChat";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants";
import { selectUserId } from "../../store/selectors/loginSelectors";
import {
  acceptExchangeSocket,
  addMessageListener,
  removeMessageListener,
} from "../../socket/socket";
import { makeErrorToastMessage } from "../../store/utils/makeToastMessage";
import { useTranslation } from "react-i18next";
import {
  selectExchange,
  selectRequester,
} from "../../store/selectors/exchangeSelector";
import {
  acceptExchange,
  fetchExchange,
  setRequester,
} from "../../store/actions/exchange/exchangeActions";
import { convertLocalDateToUTCDate } from "../../util/helpers/dateHelpers";
import requesterStatus from "../../constants/requesterStatus";
import exchangeStatus from "../../constants/exchangeStatus";
import { NEW_CHAT } from "../../constants/chatConstants";

const DirectChat = () => {
  const chat = useSelector(selectSelectedChat);
  const allChats = useSelector(selectLatestChats);
  const offer = useSelector(selectOffer);
  const routeMatch = useRouteMatch();
  const location = useLocation();
  const dispatch = useDispatch();
  const { t } = useTranslation();
  const exchange = useSelector(selectExchange);
  const requester = useSelector(selectRequester);

  const userId = useSelector(selectUserId);
  const isLoadingDirectChat = useSelector(
    selectIsLoadingByActionType(CHAT_SCOPE)
  );

  const offerObject = useMemo(() => {
    if (location?.state?.offerId) {
      return offer;
    }
    return chat?.offer;
  }, [chat, location.state, offer]);

  const chatObject = useMemo(() => {
    if (location?.state?.offerId) {
      return {};
    }
    return chat;
  }, [chat, location.state]);

  const amIBuyer = useMemo(
    () => exchange.buyer?.user?._id === userId,
    [exchange, userId]
  );

  const exchangeState = useMemo(() => {
    if (exchange?.buyer) {
      let haveIAccepted = amIBuyer
        ? exchange.buyer?.accepted
        : exchange.seller?.accepted;
      let haveinterlocutorAccepted = amIBuyer
        ? exchange.seller?.accepted
        : exchange.buyer?.accepted;
      let haveIReviewed = amIBuyer
        ? exchange.buyer.givenReview
        : exchange.seller.givenReview;
      if (haveIAccepted) {
        if (haveinterlocutorAccepted) {
          if (haveIReviewed) {
            return exchangeStatus.REVIEWED;
          } else {
            return exchangeStatus.ACCEPTED;
          }
        } else {
          return exchangeStatus.I_OFFERED;
        }
      } else {
        if (haveinterlocutorAccepted) {
          return exchangeStatus.I_AM_OFFERED;
        } else {
          return exchangeStatus.INITIAL;
        }
      }
    }
    return exchangeStatus.INITIAL;
  }, [exchange, amIBuyer]);

  const interlocutorObject = useMemo(() => {
    if (location?.state?.offerId) {
      return offer?.user;
    }
    if (chat?.participants) {
      let interlocutor = userId === chat?.participants[0]._id ? 1 : 0;
      return chat?.participants[interlocutor];
    }
    return {};
  }, [chat, location.state, offer]);

  // Fetch chat after it is created
  // (renders after state of location changes)
  useEffect(() => {
    if (routeMatch.params?.chatId) {
      refreshChat();
    }
  }, [routeMatch.params?.chatId, location.state?.offerId]);

  // Listener to socket.IO chat
  useEffect(() => {
    addMessageListener(({ succeed, data }) => {
      if (succeed) {
        if (
          [...allChats].find((item) => {
            return item._id === data.chatId;
          })
        ) {
          dispatch(
            addNewMessage({
              _id: data.chatId,
              message: data.message,
            })
          );
          if (data.message?.isAcceptRequest) {
            dispatch(fetchExchange(exchange?._id));
            if (requester === requesterStatus.NOONE) {
              dispatch(setRequester(requesterStatus.interlocutor));
            }
          }
        } else {
          dispatch(fetchChats());
        }
      } else {
        dispatch(fetchChats());
        dispatch(fetchOneChat(routeMatch.params?.chatId));
        makeErrorToastMessage(t("apiErrors.somethingWentWrong"));
      }
    });
    return () => removeMessageListener();
  }, [allChats, routeMatch, requester]);

  const refreshChat = () => {
    if (routeMatch.params?.chatId === NEW_CHAT) {
      dispatch(fetchOneOffer(location.state.offerId));
      dispatch(setOneChat({}));
    } else {
      dispatch(fetchOneChat(routeMatch.params?.chatId));
    }
  };
  const handleAcceptExchangeSuccess = () => {
    let interlocutor = userId === chat?.participants[0]._id ? 1 : 0;
    acceptExchangeSocket(
      chat?._id,
      userId,
      chat?.participants[interlocutor]._id,
      () => {
        dispatch(
          addNewMessage({
            _id: chat?._id,
            message: {
              user: {
                _id: userId,
              },
              isAcceptRequest: true,
              text: "",
              _created: convertLocalDateToUTCDate(new Date()),
            },
          })
        );
        if (requester === requesterStatus.NOONE) {
          dispatch(setRequester(requesterStatus.ME));
        }
      }
    );
  };
  const handleAcceptExchange = () => {
    console.log("accept salje i prima 1 POZVANA FUNKCIJA");
    dispatch(
      acceptExchange({
        exchangeId: exchange._id,
        handleApiResponseSuccess: handleAcceptExchangeSuccess,
      })
    );
  };
  return (
    <DirectChatContainer>
      {isLoadingDirectChat || isLoadingDirectChat === undefined ? (
        <SkeletonDirectChat />
      ) : (
        <>
          <DirectChatHeaderTitle />
          <DirectChatHeader
            exchangeState={exchangeState}
            offer={offerObject}
            interlocutor={interlocutorObject}
            acceptExchange={handleAcceptExchange}
          />
        </>
      )}

      <DirectChatContent
        chat={chatObject}
        exchangeState={exchangeState}
        interlocutor={interlocutorObject}
        refreshChat={refreshChat}
      />
    </DirectChatContainer>
  );
};

DirectChat.propTypes = {
  children: PropTypes.node,
};

export default DirectChat;
