import React, { useEffect, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
  closePopup,
  openPopup,
  togglePopup,
} from "../../slices/localVariablesSlice";

/**
 * align: "auto" | "left" | "right"
 * boundaryRef: optional ref to the drawer/container element to use as boundary
 */
const HoverPopup = ({
  id,
  title,
  content,
  children,
  className = "",
  Mode = "hover",
  align = "auto",
  boundaryRef = null,
}) => {
  const dispatch = useDispatch();
  const visible = useSelector((s) => s.localVariables.popups[id] || false);

  const triggerRef = useRef(null);
  const popupRef = useRef(null);

  const handleMouseEnter = () => {
    if (Mode === "hover") dispatch(openPopup(id));
  };
  const handleMouseLeave = () => {
    if (Mode === "hover") dispatch(closePopup(id));
  };
  const handleClick = (e) => {
    if (Mode === "click") {
      e.stopPropagation();
      dispatch(togglePopup(id));
    }
  };

  // Close on outside click when using click mode
  useEffect(() => {
    if (Mode !== "click" || !visible) return;

    const handler = (e) => {
      if (
        popupRef.current &&
        !popupRef.current.contains(e.target) &&
        triggerRef.current &&
        !triggerRef.current.contains(e.target)
      ) {
        dispatch(closePopup(id));
      }
    };

    document.addEventListener("click", handler);
    return () => document.removeEventListener("click", handler);
  }, [Mode, visible, dispatch, id]);

  // Positioning effect: respects align prop and stays inside boundary (drawer)
  useEffect(() => {
    if (!visible || !popupRef.current || !triggerRef.current) return;

    // run in next frame so DOM/layout settles
    requestAnimationFrame(() => {
      const popup = popupRef.current;

      // choose boundary: provided boundaryRef or nearest positioned parent (popup.parentElement)
      const boundaryEl =
        (boundaryRef && boundaryRef.current) || popup.parentElement;
      if (!boundaryEl) return;

      const boundaryRect = boundaryEl.getBoundingClientRect();
      const triggerRect = triggerRef.current.getBoundingClientRect();

      // reset styles first
      popup.style.left = "";
      popup.style.right = "";
      popup.style.transform = "";
      popup.style.top = "";

      const popupRect = popup.getBoundingClientRect();
      const parentRect = boundaryRect; // alias

      // Convert trigger center to parent coordinates
      const triggerCenterX =
        triggerRect.left + triggerRect.width / 2 - parentRect.left;

      // preferred left so popup center aligns to trigger center:
      const preferredLeft = triggerCenterX - popupRect.width / 2;

      // Helpers to set styles in parent's coordinate system:
      const setLeft = (leftPx) => {
        popup.style.left = `${leftPx}px`;
        popup.style.right = "auto";
        popup.style.transform = "none";
      };
      const setRight = (rightPx) => {
        popup.style.left = "auto";
        popup.style.right = `${rightPx}px`;
        popup.style.transform = "none";
      };

      // If user forced align:
      if (align === "left") {
        // align popup's left to parent's left (0)
        setLeft(0);
        return;
      }
      if (align === "right") {
        // align popup's right to parent's right (0)
        setRight(0);
        return;
      }
      if (align === "center") {
        popup.style.left = "50%";
        popup.style.right = "auto";
        popup.style.transform = "translateX(-50%)";
        return;
      }

      // align === "auto": try preferred centered position, but flip fully if overflow
      // clamp preferredLeft to boundaries so it doesn't render partially outside
      const leftIfCentered = Math.max(
        0,
        Math.min(preferredLeft, parentRect.width - popupRect.width)
      );

      // if centered fits, use it
      if (leftIfCentered === preferredLeft) {
        setLeft(leftIfCentered);
        return;
      }

      // if centering would overflow right -> stick popup fully to left (left=0)
      if (preferredLeft > parentRect.width - popupRect.width) {
        // place popup so its right aligns to parent's right
        // i.e., left = parent width - popup width
        setLeft(parentRect.width - popupRect.width);
        return;
      }

      // if centering would overflow left -> stick popup fully to left=0
      if (preferredLeft < 0) {
        setLeft(0);
        return;
      }

      // fallback center
      setLeft(leftIfCentered);
    });
  }, [visible, align, boundaryRef]);

  return (
    <div
      className="d-inline-block "
      style={{
        maxWidth: "calc(700px - 100px)",
        width: "100%",
        wordWrap: "break-word",
        overflow: "hidden",
      }}
    >
      <div
        className="d-inline-block"
        ref={triggerRef}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
        onClick={handleClick}
        style={{ cursor: "pointer" }}
      >
        {children}
      </div>

      {visible && (
        <div
          ref={popupRef}
          // position absolute; it should be inside a positioned parent (the drawer)
          className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
          style={{
            zIndex: 2000,
            top: "100%", // open below trigger
            // left/right will be set by effect in parent coordinates
            width: "max-content",
            minWidth: "120px",
          }}
          onClick={(e) => e.stopPropagation()}
        >
          {title && <h6 className="fw-semibold mb-2">{title}</h6>}
          <div>{content}</div>
        </div>
      )}
    </div>
  );
};

export default HoverPopup;
