import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
import { RelatedStrip } from "../components/RelatedStrip";
import { TableView } from "../components/TableView";
import { useOnlyDiff } from "../hooks/useOnlyDiff";
import { useTable } from "../hooks/useTable";
import { TableHeading } from "../components/TableHeading";
import { getConfig, isOverlay, text } from "../lib/config";
import { PopupHeader } from "./PopupHeader";
import { useFocusTrap } from "./useFocusTrap";

const NO_IDS = [];

/** Exit animation length; keep in sync with the CSS transition. */
const EXIT_MS = 180;

/**
 * The comparison dialog: backdrop, header and the scrollable table.
 * Esc, the close button and a backdrop click call `onRequestClose`; the
 * controller then sets `closing`, the exit animation plays and `onClosed`
 * runs.
 */
export function Popup({ closing = false, onRequestClose, onClosed }) {
  const dialogRef = useRef(null);
  const closeRef = useRef(null);
  const [visible, setVisible] = useState(false);
  const table = useTable({ ids: NO_IDS, fields: NO_IDS, context: "popup" });
  const animation = getConfig().popup_animation || "fade";
  const overlay = isOverlay();
  const [onlyDiff, toggleOnlyDiff] = useOnlyDiff(
    Boolean(table.data && table.data.only_diff_default),
  );
  const canToggle =
    getConfig().table.show_only_differences_toggle !== false &&
    Boolean(table.data && table.data.products.length > 1);

  // Enter: force a style flush, then add `is-open` so the transition runs.
  // (No requestAnimationFrame: it never fires in background tabs.)
  useLayoutEffect(() => {
    dialogRef.current?.getBoundingClientRect();
    setVisible(true);
  }, []);

  // Exit: remove `is-open`, then tell the controller when it's done.
  useEffect(() => {
    if (!closing) {
      return undefined;
    }

    setVisible(false);
    const reduced = window.matchMedia(
      "(prefers-reduced-motion: reduce)",
    ).matches;
    const timer = setTimeout(
      onClosed,
      animation === "none" || reduced ? 0 : EXIT_MS,
    );

    return () => clearTimeout(timer);
  }, [closing, animation, onClosed]);

  useFocusTrap(dialogRef, { onEscape: onRequestClose, initial: closeRef });

  return (
    <div
      className={`pcfw-popup pcfw-popup--${animation}${overlay ? " pcfw-popup--overlay" : ""}${visible ? " is-open" : ""}`}
    >
      <div
        className="pcfw-popup__backdrop"
        aria-hidden="true"
        onClick={onRequestClose}
      />
      <div
        ref={dialogRef}
        className="pcfw-popup__dialog"
        role="dialog"
        aria-modal="true"
        aria-labelledby="pcfw-popup-title"
        tabIndex={-1}
      >
        <PopupHeader
          data={table.data}
          closeRef={closeRef}
          onClose={onRequestClose}
          onlyDiff={canToggle ? onlyDiff : null}
          onToggleOnlyDiff={toggleOnlyDiff}
          compact={overlay}
        />
        <div className="pcfw-popup__body">
          <TableView
            {...table}
            layout="auto"
            onlyDiff={canToggle && onlyDiff}
            fromList
            heading={
              overlay ? (
                <TableHeading
                  id="pcfw-popup-title"
                  title={text("popupTitle", "Compare products")}
                />
              ) : null
            }
          />
          <RelatedStrip data={table.data} />
        </div>
      </div>
    </div>
  );
}
