import { useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";

/**
 * Height Memory Wrapper
 * @param children
 * @param maxHeight
 * @param setMaxHeight
 * @param override - Override the minHeight style from being set
 * @param itemKey - Unique key to preserve height for items with the same key
 * @returns {JSX.Element}
 */
const HeightMemoryWrapper = ({ children, maxHeight, setMaxHeight, override, itemKey }) => {
  const ref = useRef(null);
  const heightMapRef = useRef(new Map());
  const [localMaxHeight, setLocalMaxHeight] = useState(maxHeight);
  const [devicePixelRatio, setDevicePixelRatio] = useState(window.devicePixelRatio);

  useEffect(() => {
    const currentRef = ref.current;
    const updateHeight = () => {
      const currentHeight = currentRef?.firstChild?.clientHeight || 0;
      if (itemKey) {
        const keyHeight = heightMapRef.current.get(itemKey) || 0;
        const newHeight = Math.max(keyHeight, currentHeight);
        heightMapRef.current.set(itemKey, newHeight);
        setLocalMaxHeight(newHeight);
      } else {
        setLocalMaxHeight((prevHeight) => Math.max(prevHeight, currentHeight));
      }
      setMaxHeight((prevHeight) => Math.max(prevHeight, currentHeight));
    };

    const resizeObserver = new ResizeObserver(updateHeight);

    if (currentRef?.firstChild) {
      resizeObserver.observe(currentRef.firstChild);
    }

    const resizeHandler = () => {
      if (Math.abs(window.devicePixelRatio - devicePixelRatio) > 0.1) {
        // Threshold to detect significant zoom level change
        heightMapRef.current.clear(); // Clearing the height memory as zoom level has changed significantly
        setLocalMaxHeight(0); // Reset local max height
        setDevicePixelRatio(window.devicePixelRatio); // Update the recorded device pixel ratio
      }
      updateHeight();
    };

    window.addEventListener("resize", resizeHandler);

    return () => {
      if (currentRef?.firstChild) {
        resizeObserver.unobserve(currentRef.firstChild);
      }
      window.removeEventListener("resize", resizeHandler);
    };
  }, [itemKey, setMaxHeight, devicePixelRatio]);

  useEffect(() => {
    if (itemKey && heightMapRef.current.has(itemKey)) {
      setLocalMaxHeight(heightMapRef.current.get(itemKey));
    }
  }, [itemKey]);

  const style = override ? {} : { minHeight: localMaxHeight };

  return (
    <div ref={ref} style={style}>
      {children}
    </div>
  );
};

HeightMemoryWrapper.propTypes = {
  children: PropTypes.node.isRequired,
  maxHeight: PropTypes.number.isRequired,
  setMaxHeight: PropTypes.func.isRequired,
  override: PropTypes.bool,
  itemKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};

export default HeightMemoryWrapper;
