import React, {
  useCallback,
  useEffect,
  useRef,
} from 'react';

import classNames from 'classnames';
import { useDispatch } from 'react-redux';

import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator
  from '@enact/spotlight/SpotlightContainerDecorator';
import { setContainerLastFocusedElement } from '@enact/spotlight/src/container';

import {
  sendLogGNB,
  sendLogTotalRecommend,
} from '../../actions/logActions';
import { getTop20Show } from '../../actions/mainActions';
import {
  pushPanel,
  updatePanel,
} from '../../actions/panelActions';
import { finishVideoPreview } from '../../actions/playActions';
import { getBestSeller } from '../../actions/productActions';
import SectionTitle from '../../components/SectionTitle/SectionTitle';
import TBody from '../../components/TBody/TBody';
import TButton, { TYPES } from '../../components/TButton/TButton';
import { removeDotAndColon } from '../../components/TItemCard/TItemCard';
import TItemCardNew from '../../components/TItemCard/TItemCard.new';
import TPanel from '../../components/TPanel/TPanel';
import TVerticalPagenator
  from '../../components/TVerticalPagenator/TVerticalPagenator';
import useWhyDidYouUpdate from '../../hooks/useWhyDidYouUpdate';
import {
  LOG_CONTEXT_NAME,
  LOG_MENU,
  LOG_MESSAGE_ID,
  panel_names,
} from '../../utils/Config';
import { $L } from '../../utils/helperMethods';
import { SpotlightIds } from '../../utils/SpotlightIds';
import PopularShowIndicator from './PopularShow/PopularShowIndicator';
import css from './TrendingNowPanel.module.less';

const Container = SpotlightContainerDecorator(
  { enterTo: "last-focused" },
  "div"
);
const BestSellerContainer = SpotlightContainerDecorator(
  { enterTo: "last-focused" },
  "div"
);
const STRING_CONF = {
  POPULAR_SHOW: "POPULAR SHOW",
  BEST_SELLER: "BEST SELLER",
};

const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
  const dispatch = useDispatch();
  const { USE_SELECTOR, USE_STATE } = useWhyDidYouUpdate(spotlightId, {
    panelInfo,
    isOnTop,
    ...rest,
  });

  const topInfos = USE_SELECTOR(
    "topInfos",
    (state) => state.main.top20ShowData?.topInfos
  );
  const bestSeller = USE_SELECTOR(
    "bestSeller",
    (state) => state.product?.bestSellerData?.bestSeller
  );

  const [showButton, setShowButton] = USE_STATE("showButton", true);
  const [selectedIndex, setSelectedIndex] = USE_STATE("selectedIndex", 0);

  const cbChangePageRef = useRef(null);
  const isInitialRef = useRef(true);
  const currentSentMenuRef = useRef(null);
  const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId);

  // effect: data fetching when no data exists in the store
  useEffect(() => {
    if (!topInfos) dispatch(getTop20Show());
    if (!bestSeller) dispatch(getBestSeller());
  }, []);

  // effect: focus handling on initial render
  useEffect(() => {
    if (isInitialRef.current && !panelInfo?.currentSpot) {
      if (topInfos && bestSeller) {
        let target;
        switch (panelInfo?.pageName) {
          case "PS":
            target = SpotlightIds.TRENDING_NOW_POPULAR_SHOW;
            break;
          case "BS":
            target = SpotlightIds.TRENDING_NOW_BEST_SELLER;
            break;
        }

        Spotlight.focus(target ?? spotlightId);
        isInitialRef.current = false;
      }
    }
  }, [topInfos, bestSeller]);

  // effect: set the index when returning to the details or entering through a deep-link
  useEffect(() => {
    if (panelInfo?.selectedIndex) setSelectedIndex(panelInfo.selectedIndex);
  }, []);

  // effect: focus recovery when returning to the details
  useEffect(() => {
    if (isOnTop && panelInfo?.currentSpot) {
      Spotlight.focus(panelInfo.currentSpot);
    }
  }, [isOnTop]);

  // effect: for the GNB log
  useEffect(() => {
    if (isOnTop) {
      let menu;
      // case: entering through a deep link or the Home, and returning from the player or details
      if (panelInfo?.focusedContainerId) {
        menu =
          panelInfo.focusedContainerId !==
          SpotlightIds.TRENDING_NOW_POPULAR_SHOW
            ? LOG_MENU.TRENDING_NOW_BEST_SELLER
            : LOG_MENU.TRENDING_NOW_POPULAR_SHOWS;
      }
      // case: entering through the GNB
      else {
        menu = LOG_MENU.TRENDING_NOW_POPULAR_SHOWS;
      }

      if (menu) dispatch(sendLogGNB(menu));
    }
  }, [isOnTop]);

  const onFocusedContainerId = useCallback((containerId) => {
    focusedContainerIdRef.current = containerId;
  }, []);

  const handleScroll = useCallback((e) => {
    setShowButton(e.scrollTop === 0);

    if (e.scrollTop !== 0) dispatch(finishVideoPreview());
  }, []);

  const handleSpotlight = useCallback(
    (spotlightId) => (e) => {
      e.stopPropagation();
      if (spotlightId) Spotlight.focus(spotlightId);
    },
    []
  );

  const handleIndicatorClick = useCallback(
    (direction) => () => {
      if (!topInfos) return;

      const isPrev = direction === "prev";
      const isNext = direction === "next";
      const isEdgeIndex =
        (isPrev && selectedIndex === 1) ||
        (isNext && selectedIndex === topInfos.length - 2);

      if (isEdgeIndex) Spotlight.focus(SpotlightIds.TRENDING_NOW_POPULAR_VIDEO);

      setSelectedIndex((prev) => prev + (isPrev ? -1 : isNext ? 1 : 0));
      setContainerLastFocusedElement(null, [
        SpotlightIds.TRENDING_NOW_POPULAR_GRID_LIST,
      ]);
    },
    [selectedIndex, topInfos]
  );

  const handleBestSellerClick = useCallback(
    ({ patnrId, prdtId }) =>
      () => {
        const currentSpot =
          Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null;

        dispatch(
          updatePanel({
            name: panel_names.TRENDING_NOW_PANEL,
            panelInfo: {
              currentSpot,
              focusedContainerId: focusedContainerIdRef.current,
              selectedIndex,
            },
          })
        );

        dispatch(
          pushPanel({
            name: panel_names.DETAIL_PANEL,
            panelInfo: { patnrId, prdtId },
          })
        );
      },
    [selectedIndex]
  );

  const handleBestSellerFocus = useCallback(() => {
    handleItemFocus(LOG_MENU.TRENDING_NOW_BEST_SELLER, STRING_CONF.BEST_SELLER);
  }, [handleItemFocus]);

  const handleItemClick = useCallback(() => {
    const currentSpot =
      Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null;

    dispatch(
      updatePanel({
        name: panel_names.TRENDING_NOW_PANEL,
        panelInfo: {
          currentSpot,
          focusedContainerId: focusedContainerIdRef.current,
          selectedIndex,
        },
      })
    );
  }, [selectedIndex]);

  const handleItemFocus = useCallback(
    (nowMenu, currentShelf) => {
      setTimeout(() => dispatch(sendLogGNB(nowMenu)));

      if (nowMenu !== currentSentMenuRef.current) {
        let order;
        let spotlightId;
        switch (currentShelf) {
          case STRING_CONF.POPULAR_SHOW:
            order = 1;
            spotlightId = SpotlightIds.TRENDING_NOW_POPULAR_SHOW;
            break;
          case STRING_CONF.BEST_SELLER:
            order = 2;
            spotlightId = SpotlightIds.TRENDING_NOW_BEST_SELLER;
            break;
        }

        if (order && spotlightId) {
          const params = {
            contextName: LOG_CONTEXT_NAME.TRENDING_NOW,
            messageId: LOG_MESSAGE_ID.SHELF,
            shelfLocation: order,
            shelfId: spotlightId,
            shelfTitle: currentShelf,
          };
          dispatch(sendLogTotalRecommend(params));

          currentSentMenuRef.current = nowMenu;
        }
      }
    },
    [currentSentMenuRef]
  );

  const handleTopButtonClick = useCallback(() => {
    if (cbChangePageRef.current) {
      cbChangePageRef.current(0, true);
    }

    let target = SpotlightIds.TRENDING_NOW_POPULAR_VIDEO;

    if (topInfos.length === 0 && bestSeller && bestSeller.length > 0) {
      target = `spotlightId-bestSeller-${bestSeller[0]?.prdtId}`;
    }
    Spotlight.focus(target);
    setContainerLastFocusedElement(null, [
      SpotlightIds.TRENDING_NOW_BEST_SELLER,
    ]);
  }, [bestSeller, topInfos]);

  const getFirstLabel = useCallback((rankOrder) => {
    switch (rankOrder) {
      case 1:
        return `${rankOrder}st,`;
      case 2:
        return `${rankOrder}nd,`;
      case 3:
        return `${rankOrder}rd,`;
      default:
        return `${rankOrder}th,`;
    }
  }, []);

  return (
    <div className={css.trendingNowWrap}>
      {isOnTop && selectedIndex >= 1 && showButton && (
        <TButton
          className={classNames(css.button, css.prevBtn)}
          onClick={handleIndicatorClick("prev")}
          onSpotlightRight={handleSpotlight(
            SpotlightIds.TRENDING_NOW_POPULAR_VIDEO
          )}
          onSpotlightDown={handleSpotlight(
            SpotlightIds.TRENDING_NOW_BEST_SELLER
          )}
          spotlightId={SpotlightIds.TRENDING_NOW_PREV_INDICATOR}
          ariaLabel="Move to left"
        />
      )}
      <TPanel spotlightId={spotlightId}>
        <TBody
          className={css.trendingNow}
          scrollable={false}
          spotlightDisabled={!isOnTop}
        >
          <TVerticalPagenator
            className={css.tVerticalPagenator}
            spotlightId={SpotlightIds.TRENDING_NOW_VERTICAL_PAGINATOR}
            defaultContainerId={panelInfo?.focusedContainerId}
            onScroll={handleScroll}
            onFocusedContainerId={onFocusedContainerId}
            cbChangePageRef={cbChangePageRef}
            topMargin={36}
          >
            {topInfos && topInfos?.length > 0 && (
              <Container
                className={css.popularContainer}
                spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_SHOW}
                data-wheel-point={true}
              >
                <SectionTitle
                  title={$L(STRING_CONF.POPULAR_SHOW)}
                  label="POPULAR SHOW, Heading1"
                />
                <PopularShowIndicator
                  topInfos={topInfos}
                  selectedIndex={selectedIndex}
                  onSpotlightDown={handleSpotlight(
                    SpotlightIds.TRENDING_NOW_BEST_SELLER
                  )}
                  onSpotlightRight={handleSpotlight(
                    SpotlightIds.TRENDING_NOW_NEXT_INDICATOR
                  )}
                  handleItemFocus={handleItemFocus}
                  handleItemClick={handleItemClick}
                  isOnTop={isOnTop}
                  currentShelf={STRING_CONF.POPULAR_SHOW}
                />
              </Container>
            )}
            {bestSeller && bestSeller?.length > 0 && (
              <BestSellerContainer
                className={css.bestContainer}
                spotlightId={SpotlightIds.TRENDING_NOW_BEST_SELLER}
                data-wheel-point
              >
                <SectionTitle
                  title={$L(STRING_CONF.BEST_SELLER)}
                  data-title-index="TNBestSellerTitle"
                />
                <div className={css.itemList}>
                  {bestSeller.map((item, index) => (
                    <TItemCardNew
                      className={css.trendingBestItem}
                      contextName={LOG_CONTEXT_NAME.TRENDING_NOW}
                      messageId={LOG_MESSAGE_ID.SHELF_CLICK}
                      shelfLocation={2}
                      shelfTitle={STRING_CONF.BEST_SELLER}
                      shelfId={SpotlightIds.TRENDING_NOW_BEST_SELLER}
                      order={item.rankOrd}
                      catNm={item.lgCatNm}
                      patnerName={item.patncNm}
                      brandName={item.brndNm}
                      data-wheel-point={index >= 5}
                      firstLabel={getFirstLabel(item.rankOrd)}
                      imageAlt={item.prdtId}
                      imageSource={item.imgUrl}
                      key={item.prdtId}
                      isBestSeller
                      label={index * 1 + 1 + " of " + bestSeller.length}
                      lastLabel=" go to detail, button"
                      offerInfo={item.offerInfo}
                      onFocus={handleBestSellerFocus}
                      onClick={handleBestSellerClick(item)}
                      priceInfo={item.priceInfo}
                      productName={item.prdtNm}
                      productId={item.prdtId}
                      rank={item.rankOrd}
                      spotlightId={
                        "spotlightId-" +
                        "bestSeller-" +
                        removeDotAndColon(item.prdtId)
                      }
                      euEnrgLblInfos={item.euEnrgLblInfos}
                    />
                  ))}
                </div>
              </BestSellerContainer>
            )}
            <Container>
              {((topInfos && topInfos?.length > 0) ||
                (bestSeller && bestSeller?.length > 10)) && (
                <TButton
                  onClick={handleTopButtonClick}
                  size={null}
                  spotlightId={SpotlightIds.TRENDING_NOW_TOP_BUTTON}
                  ariaLabel="Move to Top"
                  data-wheel-point
                  type={TYPES.topButton}
                />
              )}
            </Container>
          </TVerticalPagenator>
        </TBody>
      </TPanel>
      {isOnTop && topInfos &&
        topInfos?.length > 0 &&
        selectedIndex !== topInfos?.length - 1 &&
        showButton && (
          <TButton
            className={classNames(css.button, css.nextBtn)}
            onClick={handleIndicatorClick("next")}
            onSpotlightDown={handleSpotlight(
              SpotlightIds.TRENDING_NOW_BEST_SELLER
            )}
            spotlightId={SpotlightIds.TRENDING_NOW_NEXT_INDICATOR}
            ariaLabel="Move to right"
          />
        )}
    </div>
  );
};
const propsAreEqual = (prev, next) => {
  const keys = Object.keys(prev);
  const nextKeys = Object.keys(next);
  // if (!next.isOnTop) {
  //   //ignore event on background
  //   return true;
  // }
  if (keys.length !== nextKeys.length) {
    return false;
  }
  for (let i = 0; i < keys.length; i++) {
    if (prev[keys[i]] !== next[keys[i]]) {
      return false;
    }
  }
  return true;
};
export default React.memo(TrendingNowPanel, propsAreEqual);
