import { Select } from "antd";
import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import "./shop-info.section-navigator.styles.scss";

const HIGHLIGHT_CLASS = "shop-info-section-navigator__target--active";

export default function ShopInfoSectionNavigator({ tabsRef, activeTabKey }) {
  const { t } = useTranslation();
  const targetMapRef = useRef(new Map());
  const highlightedTargetRef = useRef(null);
  const [options, setOptions] = useState([]);
  const [selectedSection, setSelectedSection] = useState(undefined);

  useEffect(() => {
    const tabsContainer = tabsRef.current;
    if (!tabsContainer) return undefined;

    let animationFrameId = 0;

    const refreshOptions = () => {
      const activePane = tabsContainer.querySelector(".ant-tabs-tabpane-active");
      if (!activePane) {
        targetMapRef.current = new Map();
        setOptions([]);
        return;
      }

      const nextTargetMap = new Map();
      const nextOptions = Array.from(activePane.querySelectorAll(".imex-form-row"))
        .filter((card) => {
          return shouldIncludeCardInNavigator(card, activePane);
        })
        .map((card, index) => {
          const { title, depth, searchLabel } = getCardNavigatorInfo(card, activePane);
          const value = `${activeTabKey}-shop-info-section-${index}`;

          nextTargetMap.set(value, card);

          return {
            label: renderNavigatorOptionLabel(title, depth),
            labelText: title,
            searchLabel,
            depth,
            value
          };
        });

      targetMapRef.current = nextTargetMap;
      setOptions((currentOptions) => (areOptionsEqual(currentOptions, nextOptions) ? currentOptions : nextOptions));
    };

    const scheduleRefresh = () => {
      cancelAnimationFrame(animationFrameId);
      animationFrameId = requestAnimationFrame(refreshOptions);
    };

    scheduleRefresh();

    const observer = new MutationObserver(scheduleRefresh);
    observer.observe(tabsContainer, {
      childList: true,
      subtree: true,
      characterData: true,
      attributes: true,
      attributeFilter: ["class"]
    });

    return () => {
      cancelAnimationFrame(animationFrameId);
      observer.disconnect();
    };
  }, [activeTabKey, tabsRef]);

  useEffect(() => {
    clearHighlightedTarget(highlightedTargetRef);
    setSelectedSection(undefined);
  }, [activeTabKey]);

  const handleSectionChange = (value) => {
    setSelectedSection(value);

    clearHighlightedTarget(highlightedTargetRef);
    if (!value) return;

    const target = targetMapRef.current.get(value);
    if (target) {
      target.classList.add(HIGHLIGHT_CLASS);
      highlightedTargetRef.current = target;
      target.scrollIntoView({
        behavior: "smooth",
        block: "start"
      });
    }

    window.setTimeout(() => {
      setSelectedSection(undefined);
    }, 0);
  };

  return (
    <div className="shop-info-section-navigator">
      <Select
        allowClear
        showSearch
        value={selectedSection}
        placeholder={t("bodyshop.labels.jump_to_section")}
        options={options}
        popupMatchSelectWidth={false}
        disabled={options.length === 0}
        filterOption={(input, option) => option?.searchLabel?.toLowerCase().includes(input.toLowerCase())}
        onChange={handleSectionChange}
      />
    </div>
  );
}

function getOwnCardTitleNode(card) {
  const headNode = Array.from(card.children).find((child) => child.classList?.contains("ant-card-head"));
  return headNode?.querySelector(".ant-card-head-title");
}

function getOwnCardTitle(card) {
  return getOwnCardTitleNode(card)?.textContent?.trim();
}

function getAncestorCards(card, activePane) {
  const ancestors = [];
  let currentCard = card.parentElement?.closest(".imex-form-row");

  while (currentCard && activePane.contains(currentCard)) {
    ancestors.push(currentCard);
    currentCard = currentCard.parentElement?.closest(".imex-form-row");
  }

  return ancestors.reverse();
}

function getCardDepth(card, activePane) {
  return getAncestorCards(card, activePane).length;
}

function isVisibleCard(card) {
  return card.offsetParent !== null;
}

function isNavigatorEligibleSubsection(card) {
  return (
    !card.classList.contains("imex-form-row--compact") &&
    !card.classList.contains("imex-form-row--title-only") &&
    !card.querySelector(":scope > .ant-card-actions")
  );
}

function shouldIncludeCardInNavigator(card, activePane) {
  const title = getOwnCardTitle(card);
  if (!title || !isVisibleCard(card)) return false;

  const depth = getCardDepth(card, activePane);
  if (depth === 0) return true;
  if (depth === 1) return isNavigatorEligibleSubsection(card);

  return false;
}

function getCardNavigatorInfo(card, activePane) {
  const title = getOwnCardTitle(card);
  const ancestors = getAncestorCards(card, activePane);
  const depth = ancestors.length;
  const parentTitle = depth === 1 ? getOwnCardTitle(ancestors[0]) : null;

  return {
    title,
    depth,
    searchLabel: parentTitle ? `${parentTitle} ${title}` : title
  };
}

function renderNavigatorOptionLabel(title, depth) {
  return (
    <span
      className={[
        "shop-info-section-navigator__option",
        depth > 0 ? "shop-info-section-navigator__option--subsection" : null
      ]
        .filter(Boolean)
        .join(" ")}
    >
      <span className="shop-info-section-navigator__option-label">{title}</span>
    </span>
  );
}

function clearHighlightedTarget(highlightedTargetRef) {
  if (highlightedTargetRef.current) {
    highlightedTargetRef.current.classList.remove(HIGHLIGHT_CLASS);
    highlightedTargetRef.current = null;
  }
}

function areOptionsEqual(currentOptions, nextOptions) {
  if (currentOptions.length !== nextOptions.length) return false;

  return currentOptions.every((option, index) => {
    const nextOption = nextOptions[index];
    return (
      option.labelText === nextOption.labelText &&
      option.searchLabel === nextOption.searchLabel &&
      option.depth === nextOption.depth &&
      option.value === nextOption.value
    );
  });
}
