import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";

import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";

import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import { getContainerId } from "@enact/spotlight/src/container";

import btnPlay from "../../../../assets/images/btn/btn-play-thumb-nor.png";
import defaultLogoImg from "../../../../assets/images/ic-tab-partners-default@3x.png";
import emptyHorImage from "../../../../assets/images/img-home-banner-empty-hor.png";
import emptyVerImage from "../../../../assets/images/img-home-banner-empty-ver.png";
import defaultImageItem from "../../../../assets/images/img-thumb-empty-product@3x.png";
import liveShow from "../../../../assets/images/tag-liveshow.png";
import { setBannerIndex, updateHomeInfo } from "../../../actions/homeActions";
import {
  sendLogTopContents,
  sendLogTotalRecommend,
} from "../../../actions/logActions";
import { pushPanel } from "../../../actions/panelActions";
import { startVideoPlayer } from "../../../actions/playActions";
import CustomImage from "../../../components/CustomImage/CustomImage";
import usePriceInfo from "../../../hooks/usePriceInfo";
import {
  LOG_CONTEXT_NAME,
  LOG_MENU,
  LOG_MESSAGE_ID,
  LOG_TP_NO,
  panel_names,
} from "../../../utils/Config";
import { $L, formatGMTString } from "../../../utils/helperMethods";
import { TEMPLATE_CODE_CONF } from "../HomePanel";
import css from "./RollingUnit.module.less";

const SpottableComponent = Spottable("div");

const Container = SpotlightContainerDecorator(
  { enterTo: "last-focused", preserveId: true },
  "div"
);

const LINK_TYPES = {
  FEATURED_BRANDS: "DSP00501",
  TRENDING_NOW: "DSP00502",
  HOT_PICKS: "DSP00503",
  ON_SALE: "DSP00504",
  CATEGORY: "DSP00505",
  PRODUCT_DETAIL: "DSP00506",
  VOD: "DSP00507",
  SHOW_DETAIL: "DSP00508",
  THEME: "DSP00509",
};

const createPanelInfo = (data, categoryData = {}) => ({
  patnrId: data.patnrId,
  prdtId: data.prdtId,
  curationId: data.lnkCurationId,
  lgCatCd: data.lgCatCd,
  lgCatNm: categoryData.lgCatNm,
  COUNT: categoryData.COUNT,
  currentSpot: null,
  dropDownTab: 0,
  tab: 0,
  focusedContainerId: null,
});

export default function RollingUnit({
  bannerData,
  spotlightId,
  isHorizontal,
  handleItemFocus,
  handleShelfFocus,
}) {
  const rollingData = bannerData.bannerDetailInfos;
  const rollingDataLength = bannerData.bannerDetailInfos.length;

  const dispatch = useDispatch();

  const { curationId, curationTitle } = useSelector((state) => state.home);
  const curtNm = useSelector((state) => state.home?.bannerData?.curtNm);
  const shptmTmplCd = useSelector(
    (state) => state.home?.bannerData?.shptmTmplCd
  );
  const nowMenu = useSelector((state) => state.common.menu.nowMenu);
  const entryMenu = useSelector((state) => state.common.menu.entryMenu);

  const homeCategory = useSelector(
    (state) => state.home.menuData?.data?.homeCategory
  );
  const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd);

  const bannerId = `banner-${bannerData.banrLctnNo}`;
  const savedIndex = useSelector((state) => state.home.bannerIndices[bannerId]);

  const [startIndex, setStartIndex] = useState(
    savedIndex !== undefined ? savedIndex : 0
  );
  const lastIndexRef = useRef(rollingDataLength - 1);
  const doRollingRef = useRef(false);
  const [unitHasFocus, setUnitHasFocus] = useState(false);
  const [contentsFocus, setContentsFocus] = useState(false);
  const [prevFocus, setPrevFocus] = useState(false);
  const [nextFocus, setNextFocus] = useState(false);

  const requestRef = useRef();
  const previousTimeRef = useRef();
  const arrRef = useRef([]);
  const bannerDataRef = useRef(bannerData);
  const rollingDataRef = useRef(rollingData);

  const topContentsLogInfo = useMemo(() => {
    if (rollingDataRef.current) {
      const currentRollingData = rollingDataRef.current[startIndex];

      let contId, contNm;

      switch (currentRollingData?.shptmBanrTpCd) {
        // case: "LIVE" or "VOD"
        case "DSP00301":
        case "DSP00302":
          contId = currentRollingData?.showId;
          contNm = currentRollingData?.showNm;
          break;

        // case: "Image Banner"
        case "DSP00303":
          contId = currentRollingData?.shptmLnkTpCd;
          contNm = currentRollingData?.shptmLnkTpNm;
          break;

        // case: "Today's Deals"
        default:
          contId = currentRollingData?.prdtId;
          contNm = currentRollingData?.prdtNm;
          break;
      }

      if (
        currentRollingData?.shptmLnkTpCd === "DSP00503" || // "Hot Picks"
        currentRollingData?.shptmLnkTpCd === "DSP00509" // "Theme"
      ) {
        contNm = contNm + " | " + currentRollingData?.lnkCurationId;
      }

      return {
        banrNo: `${currentRollingData?.banrDpOrd}`,
        banrTpNm: currentRollingData?.vtctpYn
          ? currentRollingData.vtctpYn === "Y"
            ? "Vertical"
            : "Horizontal"
          : "",
        contId,
        contNm,
        contTpNm: currentRollingData?.shptmBanrTpNm ?? "",
        dspyTpNm: bannerDataRef.current?.shptmDspyTpNm ?? "",
        expsOrd: bannerDataRef.current?.banrLctnNo ?? "",
        linkTpCd: "",
        patncNm: currentRollingData?.patncNm ?? "",
        patnrId: currentRollingData?.patnrId ?? "",
        tmplCd: shptmTmplCd,
      };
    }

    return {};
  }, [shptmTmplCd, startIndex]);
  const sendBannerLog = useCallback(
    (bannerClick) => {
      const data = rollingDataRef.current[startIndex];
      const newParams =
        bannerData.banrLctnNo === "2"
          ? {
              bannerType: "Horizontal",
            }
          : {
              bannerType: "Vertical",
            };
      if (rollingDataRef.current && nowMenu === LOG_MENU.HOME_TOP) {
        const logParams = {
          contextName: LOG_CONTEXT_NAME.HOME,
          messageId: bannerClick
            ? LOG_MESSAGE_ID.BANNER_CLICK
            : LOG_MESSAGE_ID.BANNER,
          curationId: curationId,
          curationTitle: curationTitle,
          contentType: data.shptmBanrTpNm,
          contentId: data.showId,
          contentTitle: data.showNm,
          productId: data.prdtId,
          productTitle: data.prdtNm,
          displayType: "button",
          partner: data.patncNm,
          brand: data.brndNm,
          location: bannerData.banrLctnNo,
          ...newParams,
        };
        dispatch(sendLogTotalRecommend(logParams));
      }
    },
    [nowMenu, rollingDataRef, imageBannerClick]
  );

  useEffect(() => {
    if (savedIndex !== undefined) {
      setStartIndex(savedIndex);
    }
  }, [savedIndex]);

  const animate = useCallback((time) => {
    if (previousTimeRef.current != undefined) {
      const deltaTime = time - previousTimeRef.current;

      if (deltaTime >= 10000 && doRollingRef.current) {
        setStartIndex((prevIndex) =>
          prevIndex === lastIndexRef.current ? 0 : prevIndex + 1
        );
        previousTimeRef.current = time;
      }
    } else {
      previousTimeRef.current = time;
    }

    if (typeof window === "object") {
      requestRef.current = window.requestAnimationFrame(animate);
    }
  }, []);

  // 롤링 이전 버튼
  const handlePrev = useCallback(() => {
    if (startIndex === 0) {
      setStartIndex(lastIndexRef.current);
      return;
    }
    setStartIndex(startIndex - 1);
  }, [startIndex]);

  // 롤링 다음 버튼
  const handleNext = useCallback(() => {
    if (lastIndexRef.current === startIndex) {
      setStartIndex(0);
      return;
    }
    setStartIndex(startIndex + 1);
  }, [startIndex]);

  // 베너 포커스 인
  const onFocus = useCallback(() => {
    if (handleItemFocus) {
      handleItemFocus();
    }
    setUnitHasFocus(true);
  }, [handleItemFocus]);

  // 배너 포커스 아웃
  const onBlur = useCallback(() => {
    setUnitHasFocus(false);
  }, []);

  // 인디케이터 아래키 누를시 [<]
  const prevKeyDown = (event) => {
    if (event.key === "ArrowDown") {
      setNextFocus(true);
      setContentsFocus(true);
    }
  };

  // 인디케이터 아래키 누를시 [>]
  const nextKeyDown = (event) => {
    if (event.key === "ArrowDown") {
      setPrevFocus(true);
      setContentsFocus(true);
    }
  };

  // 인디케이터 포커스
  const indicatorFocus = useCallback(() => {
    if (handleItemFocus) {
      handleItemFocus();
    }

    setNextFocus(false);
    setContentsFocus(false);
    setPrevFocus(false);
    setUnitHasFocus(true);
  }, [handleItemFocus]);

  // 인디케이터 포커스 아웃
  const indicatorBlur = useCallback(() => {
    setUnitHasFocus(false);
    setTimeout(() => {
      setNextFocus(false);
      setContentsFocus(false);
    }, 300);
  }, []);

  const shelfFocus = useCallback(() => {
    if (handleShelfFocus) {
      handleShelfFocus();
    }
  }, [handleShelfFocus]);

  const categoryData = useMemo(() => {
    if (
      Object.keys(rollingData[startIndex]).length > 0 &&
      rollingData[startIndex].shptmLnkTpCd === LINK_TYPES.CATEGORY
    ) {
      if (homeCategory && homeCategory.length > 0) {
        const foundCategory = homeCategory.find(
          (data) => data.lgCatCd === rollingData[startIndex].lgCatCd
        );
        if (foundCategory) {
          return {
            lgCatNm: foundCategory.lgCatNm,
            COUNT: foundCategory.COUNT,
          };
        }
      }
    }
    return {};
  }, [homeCategory, rollingData, startIndex]);

  const { originalPrice, discountedPrice, discountRate, offerInfo } =
    usePriceInfo(rollingData[startIndex].priceInfo) || {};

  const handlePushPanel = useCallback(
    (name, panelInfo) => {
      dispatch(pushPanel({ name, panelInfo }));
    },
    [dispatch]
  );

  const handleStartVideoPlayer = useCallback(
    (playerInfo) => {
      dispatch(startVideoPlayer(playerInfo));
    },
    [dispatch]
  );

  const imageBannerClick = useCallback(() => {
    if (bannerId) {
      dispatch(setBannerIndex(bannerId, startIndex));
    }
    const currentData = rollingData[startIndex];
    const linkType = currentData.shptmLnkTpCd;
    const bannerType = currentData.shptmBanrTpNm;

    if (bannerType === "Today's Deals") {
      handlePushPanel(panel_names.DETAIL_PANEL, createPanelInfo(currentData));
      sendBannerLog(true);
      dispatch(
        sendLogTopContents({
          ...topContentsLogInfo,
          inDt: formatGMTString(new Date()) ?? "",
          logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK,
        })
      );
      return;
    }

    switch (linkType) {
      case LINK_TYPES.FEATURED_BRANDS:
        handlePushPanel(panel_names.FEATURED_BRANDS_PANEL, {
          from: "gnb",
          patnrId: currentData.patnrId,
        });
        break;

      case LINK_TYPES.TRENDING_NOW:
        handlePushPanel(
          panel_names.TRENDING_NOW_PANEL,
          createPanelInfo(currentData)
        );
        break;

      case LINK_TYPES.HOT_PICKS:
        handlePushPanel(
          panel_names.HOT_PICKS_PANEL,
          createPanelInfo(currentData)
        );
        break;

      case LINK_TYPES.ON_SALE:
        handlePushPanel(panel_names.ON_SALE_PANEL, {
          lgCatCd: currentData.lgCatCd,
        });
        break;

      case LINK_TYPES.CATEGORY:
        if (Object.keys(categoryData).length > 0) {
          handlePushPanel(
            panel_names.CATEGORY_PANEL,
            createPanelInfo(currentData, categoryData)
          );
        }
        break;

      case LINK_TYPES.PRODUCT_DETAIL:
      case LINK_TYPES.SHOW_DETAIL:
        handlePushPanel(panel_names.DETAIL_PANEL, createPanelInfo(currentData));
        break;

      case LINK_TYPES.VOD:
        handlePushPanel(panel_names.THEME_CURATION_PANEL, {
          curationId: currentData.lnkCurationId,
        });
        break;

      case LINK_TYPES.THEME:
        handlePushPanel(panel_names.THEME_CURATION_PANEL, {
          curationId: currentData.lnkCurationId,
        });
        break;

      default:
        return;
    }
    sendBannerLog(true);
    dispatch(
      sendLogTopContents({
        ...topContentsLogInfo,
        inDt: formatGMTString(new Date()) ?? "",
        logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK,
      })
    );
  }, [
    rollingData,
    startIndex,
    bannerId,
    dispatch,
    categoryData,
    handlePushPanel,
    sendBannerLog,
    topContentsLogInfo,
  ]);

  const videoClick = useCallback(() => {
    const lastFocusedTargetId = getContainerId(Spotlight.getCurrent());
    const currentSpot = Spotlight.getCurrent();

    if (lastFocusedTargetId) {
      dispatch(
        updateHomeInfo({
          name: panel_names.HOME_PANEL,
          panelInfo: {
            lastFocusedTargetId,
            focusedContainerId: TEMPLATE_CODE_CONF.TOP,
            currentSpot: currentSpot?.getAttribute("data-spotlight-id"),
          },
        })
      );
    }

    if (bannerId) {
      dispatch(setBannerIndex(bannerId, startIndex));
    }

    const currentData = rollingData[startIndex];

    handleStartVideoPlayer({
      showUrl: currentData.showUrl,
      patnrId: currentData.patnrId,
      showId: currentData.showId,
      shptmBanrTpNm: currentData.showId ? currentData.shptmBanrTpNm : "MEDIA",
      lgCatCd: currentData.lgCatCd,
      chanId: currentData.brdcChnlId,
      modal: false,
      modalContainerId: null,
      modalClassName: css.videoModal,
    });

    sendBannerLog();
    dispatch(
      sendLogTopContents({
        ...topContentsLogInfo,
        inDt: formatGMTString(new Date()) ?? "",
        logTpNo: LOG_TP_NO.TOP_CONTENTS.CLICK,
      })
    );
  }, [
    rollingData,
    startIndex,
    bannerId,
    dispatch,
    handleStartVideoPlayer,
    topContentsLogInfo,
  ]);

  // 10초 롤링
  useEffect(() => {
    // 데이터가 1개인 경우 및 포커스 있는 경우 롤링 하지 않음
    lastIndexRef.current = rollingDataLength - 1;
    previousTimeRef.current = undefined;
    if (rollingDataLength <= 1 || unitHasFocus) {
      doRollingRef.current = false;
      if (typeof window === "object") {
        window.cancelAnimationFrame(requestRef.current);
      }
      return;
    }

    doRollingRef.current = true;
    if (typeof window === "object") {
      requestRef.current = window.requestAnimationFrame(animate);
    }

    return () => {
      doRollingRef.current = false;
      if (typeof window === "object") {
        window.cancelAnimationFrame(requestRef.current);
      }
    };
  }, [rollingDataLength, unitHasFocus]);

  useEffect(() => {
    let _nowMenu = nowMenu;
    let _entryMenu = entryMenu;

    if (nowMenu === LOG_MENU.HOME_TOP) {
      const params = {
        ...topContentsLogInfo,
        entryMenu: _entryMenu,
        inDt: formatGMTString(new Date()) ?? "",
        logTpNo: LOG_TP_NO.TOP_CONTENTS.VIEW,
        nowMenu: _nowMenu,
      };

      return () => {
        if (arrRef.current.every((number) => number !== startIndex)) {
          dispatch(sendLogTopContents(params));
          arrRef.current.push(startIndex);
        }
      };
    }
  }, [dispatch, entryMenu, nowMenu, startIndex, topContentsLogInfo]);

  useEffect(() => {
    sendBannerLog();
  }, [rollingDataRef, nowMenu, startIndex]);

  useEffect(() => {
    if (nowMenu !== LOG_MENU.HOME_TOP) {
      arrRef.current = [];
    }
  }, [nowMenu]);

  return (
    <Container
      className={classNames(
        css.rollingWrap,
        isHorizontal && css.isHorizontalWrap
      )}
      spotlightId={`container-${spotlightId}`}
      onFocus={shelfFocus}
    >
      {rollingDataLength !== 1 ? (
        <SpottableComponent
          className={classNames(css.arrow, css.leftBtn)}
          onClick={handlePrev}
          onFocus={indicatorFocus}
          onBlur={indicatorBlur}
          spotlightId={spotlightId + "Prev"}
          spotlightDisabled={prevFocus}
          onKeyDown={prevKeyDown}
          aria-label="Move to left Button"
        />
      ) : null}

      {rollingData &&
      rollingData[startIndex].shptmBanrTpNm === "Image Banner" ? (
        <SpottableComponent
          className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
          onClick={imageBannerClick}
          onFocus={onFocus}
          onBlur={onBlur}
          spotlightId={spotlightId}
          spotlightDisabled={contentsFocus}
          aria-label={
            rollingData[startIndex].prdtNm
              ? rollingData[startIndex].prdtNm
              : rollingData[startIndex].tmnlImgNm
          }
        >
          <div className={css.imgBanner}>
            <img src={rollingData[startIndex].tmnlImgPath} />
          </div>
        </SpottableComponent>
      ) : rollingData[startIndex].shptmBanrTpNm === "LIVE" ? (
        <SpottableComponent
          className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
          onClick={videoClick}
          onFocus={onFocus}
          onBlur={onBlur}
          spotlightId={spotlightId}
          spotlightDisabled={contentsFocus}
          aria-label={"LIVE " + rollingData[startIndex].showNm}
        >
          <p className={css.liveIcon}>
            <CustomImage
              delay={0}
              src={liveShow}
              animationSpeed="fast"
              ariaLabel="LIVE icon"
            />
          </p>

          <div
            className={classNames(
              css.itemBox,
              isHorizontal && css.isHorizontal
            )}
          >
            {rollingData[startIndex].tmnlImgPath == null ? (
              <CustomImage
                delay={0}
                src={
                  rollingData[startIndex].vtctpYn === "Y"
                    ? emptyVerImage
                    : emptyHorImage
                }
                ariaLabel={rollingData[startIndex].tmnlImgNm}
                fallbackSrc={isHorizontal ? emptyHorImage : emptyVerImage}
              />
            ) : (
              <CustomImage
                delay={0}
                src={rollingData[startIndex].tmnlImgPath}
                ariaLabel={rollingData[startIndex].tmnlImgNm}
                fallbackSrc={isHorizontal ? emptyHorImage : emptyVerImage}
              />
            )}

            <div className={css.btnPlay}>
              {rollingData[startIndex].tmnlImgPath == null ? (
                ""
              ) : (
                <CustomImage
                  delay={0}
                  src={btnPlay}
                  ariaLabel="Play video Button"
                />
              )}
            </div>
          </div>

          <p className={css.brandIcon}>
            <CustomImage
              delay={0}
              src={rollingData[startIndex].patncLogoPath}
              fallbackSrc={defaultLogoImg}
              animationSpeed="fast"
              ariaLabel={rollingData[startIndex].brdcChnlId}
            />
          </p>
        </SpottableComponent>
      ) : rollingData[startIndex].shptmBanrTpNm === "VOD" ? (
        <SpottableComponent
          className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
          onClick={videoClick}
          onFocus={onFocus}
          onBlur={onBlur}
          spotlightId={spotlightId}
          spotlightDisabled={contentsFocus}
          aria-label={rollingData[startIndex].showNm}
        >
          <div
            className={classNames(
              css.itemBox,
              isHorizontal && css.isHorizontal
            )}
          >
            {rollingData[startIndex].tmnlImgPath == null ? (
              <CustomImage
                delay={0}
                src={
                  rollingData[startIndex].vtctpYn === "Y"
                    ? emptyVerImage
                    : emptyHorImage
                }
                ariaLabel={rollingData[startIndex].tmnlImgNm}
              />
            ) : (
              <CustomImage
                delay={0}
                src={rollingData[startIndex].tmnlImgPath}
                ariaLabel={rollingData[startIndex].tmnlImgNm}
              />
            )}

            <div className={css.btnPlay}>
              {rollingData[startIndex].tmnlImgPath == null ? (
                ""
              ) : (
                <CustomImage
                  delay={0}
                  src={btnPlay}
                  ariaLabel="Play video Button"
                />
              )}
            </div>

            {rollingData[startIndex]?.patncLogoPath && (
              <p className={css.brandIcon}>
                <CustomImage
                  delay={0}
                  src={rollingData[startIndex].patncLogoPath}
                  fallbackSrc={defaultLogoImg}
                  animationSpeed="fast"
                  ariaLabel={rollingData[startIndex].brdcChnlId}
                />
              </p>
            )}
          </div>
        </SpottableComponent>
      ) : rollingData[startIndex].shptmBanrTpNm === "Today's Deals" ? (
        <SpottableComponent
          className={classNames(
            css.itemBox,
            css.todaysDeals,
            countryCode === "RU" ? css.ru : "",
            countryCode === "DE" ? css.de : "",
            isHorizontal && css.isHorizontal
          )}
          onClick={imageBannerClick}
          onFocus={onFocus}
          onBlur={onBlur}
          spotlightId={spotlightId}
          spotlightDisabled={contentsFocus}
          aria-label={
            rollingData[startIndex].prdtNm
              ? rollingData[startIndex].prdtNm
              : rollingData[startIndex].tmnlImgNm
          }
        >
          <div className={css.productInfo}>
            <div className={css.todaysDealTitle}>{$L("TODAY's DEALS")}</div>
            <div
              className={css.textBox}
              dangerouslySetInnerHTML={{
                __html: `${rollingData[startIndex].prdtNm}`,
              }}
            />
            <div className={css.accBox}>
              {parseFloat(originalPrice?.replace("$", "")) === 0
                ? rollingData[startIndex].offerInfo
                : discountRate
                  ? discountedPrice
                  : originalPrice}
              {discountRate && !isHorizontal && (
                <span className={css.saleAccBox}>{originalPrice}</span>
              )}
            </div>
            {isHorizontal &&
              parseFloat(originalPrice?.replace("$", "")) !== 0 && (
                <span className={css.saleAccBox}>{originalPrice}</span>
              )}
          </div>

          <div className={css.itemImgBox}>
            <CustomImage
              alt=""
              delay={0}
              animationSpeed="fast"
              src={rollingData[startIndex].tmnlImgPath}
              fallbackSrc={defaultImageItem}
              ariaLabel={rollingData[startIndex].tmnlImgNm}
            />
          </div>
        </SpottableComponent>
      ) : null}

      {rollingDataLength !== 1 ? (
        <SpottableComponent
          className={classNames(css.arrow, css.rightBtn)}
          onClick={handleNext}
          onFocus={indicatorFocus}
          onBlur={indicatorBlur}
          spotlightId={spotlightId + "Next"}
          spotlightDisabled={nextFocus}
          onKeyDown={nextKeyDown}
          aria-label="Move to right Button"
        />
      ) : null}
    </Container>
  );
}
