// src/components/DropdownPortal.jsx
// ✅ EXACTLY like your sample: Portal + outside pointerdown close + ESC + stopPropagation
// ✅ One dropdown open at a time (shared state via menu + setMenu)
// ✅ Reusable anywhere

import React, { useEffect, useLayoutEffect, useMemo, useRef, useState, useCallback } from "react";
import { createPortal } from "react-dom";
import { TbChevronDown } from "react-icons/tb";

/* ---------------- helpers ---------------- */
function cn(...a) {
  return a.filter(Boolean).join(" ");
}

function clamp(n, min, max) {
  return Math.max(min, Math.min(max, n));
}

function useOutsidePointerDown(ref, handler, when = true) {
  useEffect(() => {
    if (!when) return;

    const onDown = (e) => {
      if (!ref.current) return;
      if (ref.current.contains(e.target)) return;
      handler?.(e);
    };

    document.addEventListener("pointerdown", onDown);
    return () => document.removeEventListener("pointerdown", onDown);
  }, [ref, handler, when]);
}

/* ---------------- Portal Container (SAME AS SAMPLE) ---------------- */
export function ActionMenuPortal({ open, rect, onClose, children, width = 280, offset = 8 }) {
  const menuRef = useRef(null);
  const [pos, setPos] = useState({ top: 0, left: 0 });

  useOutsidePointerDown(menuRef, () => onClose?.(), open);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose?.();
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open, onClose]);

  useLayoutEffect(() => {
    if (!open || !rect) return;

    const calc = () => {
      const vh = window.innerHeight;
      const vw = window.innerWidth;

      const menuW = width;
      const menuH = menuRef.current?.offsetHeight || 240;

      let top = rect.bottom + offset;
      let left = rect.right - menuW;

      if (top + menuH > vh - 8) top = rect.top - menuH - offset;

      top = clamp(top, 8, vh - menuH - 8);
      left = clamp(left, 8, vw - menuW - 8);

      setPos({ top: top + window.scrollY, left: left + window.scrollX });
    };

    calc();
    window.addEventListener("resize", calc);
    window.addEventListener("scroll", calc, true);
    return () => {
      window.removeEventListener("resize", calc);
      window.removeEventListener("scroll", calc, true);
    };
  }, [open, rect, width, offset]);

  if (!open || !rect) return null;

  return createPortal(
    <div
      ref={menuRef}
      style={{ position: "absolute", top: pos.top, left: pos.left, width }}
      className="pointer-events-auto z-[999999] rounded-2xl shadow-xl border border-black/5 dark:border-white/10 bg-[#f2f2f2] dark:bg-[#001F3F]"
      onPointerDown={(e) => e.stopPropagation()}
      onClick={(e) => e.stopPropagation()}
    >
      <div className="p-2">{children}</div>
    </div>,
    document.body
  );
}

/* ---------------- Menu Button (SAME AS SAMPLE) ---------------- */
export const MenuBtn = ({ onAction, active = false, children }) => (
  <button
    type="button"
    className={cn(
      "w-full flex gap-2 items-center text-right rounded-xl text-sm font-semibold px-3 py-2 transition",
      active
        ? "bg-[#A1E3F980] dark:bg-white/10 text-black dark:text-white"
        : "dark:text-white text-black hover:bg-[#A1E3F980] dark:hover:bg-white/10"
    )}
    onPointerDown={(e) => {
      e.preventDefault();
      e.stopPropagation();
    }}
    onClick={(e) => {
      e.preventDefault();
      e.stopPropagation();
      onAction?.();
    }}
  >
    {children}
  </button>
);

/* ---------------- Reusable Dropdown ----------------
Props:
- id: unique id for this dropdown
- menu, setMenu: shared state to ensure only one open
- value: current value
- options: [{value,label}] or any shape but must have value + label
- onChange: (value, option) => void
- label: optional prefix in button like "وضعیت: ..."
- width, offset
- buttonClassName, menuClassName: optional styling overrides
- renderOption: optional custom renderer
----------------------------------------------------- */
export default function DropdownPortal({
  id,
  menu,
  setMenu,
  value,
  options = [],
  onChange,
  label,
  width = 260,
  offset = 8,
  buttonClassName = "",
  menuClassName = "",
  renderOption,
}) {
  const isOpen = String(menu?.id) === String(id);

  const current = useMemo(() => {
    if (!Array.isArray(options) || options.length === 0) return null;
    return options.find((o) => String(o.value) === String(value)) || options[0];
  }, [options, value]);

  const close = useCallback(() => setMenu?.({ id: null, rect: null }), [setMenu]);

  const toggle = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const rect = e.currentTarget.getBoundingClientRect();

    setMenu?.((prev) =>
      String(prev?.id) === String(id) ? { id: null, rect: null } : { id, rect }
    );
  };

  return (
    <div className="relative">
      <button
        type="button"
        className={cn(
          "h-[45.6px] px-3 rounded-xl shadow border border-black/10 dark:border-white/10",
          "bg-[#A1E3F980] dark:bg-[#A1E3F919]",
          "inline-flex items-center justify-between gap-2 w-full sm:w-auto text-sm",
          buttonClassName
        )}
        onPointerDown={(e) => {
          // ✅ دقیقا مثل نمونه: فقط stopPropagation + preventDefault
          e.preventDefault();
          e.stopPropagation();
        }}
        onClick={toggle}
      >
        <span className="truncate">
          {label ? `${label}: ${current?.label ?? "-"}` : current?.label ?? "-"}
        </span>
        <TbChevronDown
          className={cn("w-4 h-4 opacity-80 transition-transform", isOpen ? "rotate-180" : "")}
        />
      </button>

      <ActionMenuPortal open={isOpen} rect={menu?.rect} onClose={close} width={width} offset={offset}>
        <div className={cn("flex flex-col gap-1", menuClassName)}>
          {(options || []).map((opt) => {
            const active = String(opt.value) === String(value);
            return (
              <MenuBtn
                key={String(opt.value)}
                active={active}
                onAction={() => {
                  onChange?.(opt.value, opt);
                  close();
                }}
              >
                {renderOption ? renderOption(opt, active) : <span className="truncate w-full">{opt.label}</span>}
              </MenuBtn>
            );
          })}
        </div>
      </ActionMenuPortal>
    </div>
  );
}
