import {
  useEffect,
  useRef,
  useMemo,
  useState,
  useLayoutEffect,
  FC,
} from "react";
import { createPortal } from "react-dom";
import "../../../../css/ContextMenu.css";

export interface ContextMenuItem {
  id: string;
  label?: string;
  icon?: string;
  shortcut?: string;
  action?: () => void;
  disabled?: boolean;
  separator?: boolean;
  section?: string;
  children?: ContextMenuItem[];
}

interface ContextMenuProps {
  items: ContextMenuItem[];
  position: { x: number; y: number };
  onClose: () => void;
  isVisible: boolean;
}

// ─── Rendu d'un élément de menu (section, séparateur ou entrée cliquable) ───

interface ContextMenuItemRendererProps {
  item: ContextMenuItem;
  isHovered: boolean;
  onHover: (id: string) => void;
  onSubmenuOpen: (id: string | null) => void;
  onItemClick: (item: ContextMenuItem) => void;
}

const ContextMenuItemRenderer: FC<ContextMenuItemRendererProps> = ({
  item,
  isHovered,
  onHover,
  onSubmenuOpen,
  onItemClick,
}) => {
  if (item.section) {
    return (
      <div className="pdfb-context-menu-section" style={{ padding: "2px 6px 1px" }}>
        <div
          className="pdfb-context-menu-section-title"
          style={{
            fontSize: "8px", fontWeight: "600", color: "#64748b",
            textTransform: "uppercase", letterSpacing: "0.5px",
            padding: "0px", marginBottom: "0px",
          }}
        >
          {item.section}
        </div>
      </div>
    );
  }

  if (item.separator) {
    return (
      <div
        className="pdfb-context-menu-separator"
        style={{
          height: "1px",
          background: "linear-gradient(90deg, transparent 0%, #e2e8f0 20%, #e2e8f0 80%, transparent 100%)",
          margin: "1px 0", border: "none",
        }}
      />
    );
  }

  const handleMouseEnter = () => {
    onHover(item.id);
    onSubmenuOpen(item.children?.length ? item.id : null);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter" || e.key === " ") onItemClick(item);
  };

  return (
    <div
      role="menuitem"
      tabIndex={item.disabled ? -1 : 0}
      aria-disabled={item.disabled}
      className={`pdfb-context-menu-item ${item.disabled ? "pdfb-disabled" : ""}`}
      data-item-id={item.id}
      onClick={() => onItemClick(item)}
      onKeyDown={handleKeyDown}
      onMouseEnter={handleMouseEnter}
      style={{
        display: "flex", alignItems: "center", padding: "1px 4px",
        cursor: item.disabled ? "not-allowed" : "pointer",
        userSelect: "none", transition: "all 0.15s cubic-bezier(0.4, 0, 0.2, 1)",
        position: "relative", minHeight: "16px", border: "none",
        background: isHovered ? "#f1f5f9" : "transparent",
        color: item.disabled ? "#94a3b8" : "#334155",
        fontSize: "11px", fontWeight: "500",
      }}
    >
      {item.icon && (
        <span
          className="pdfb-context-menu-item-icon"
          style={{
            width: "10px", height: "10px", marginRight: "3px",
            display: "flex", alignItems: "center", justifyContent: "center",
            color: item.disabled ? "#94a3b8" : "#64748b", fontSize: "9px",
          }}
        >
          {item.icon}
        </span>
      )}
      {item.label && (
        <span
          className="pdfb-context-menu-item-text"
          style={{ flex: "1", fontSize: "10px", fontWeight: "500", color: item.disabled ? "#94a3b8" : "#334155" }}
        >
          {item.label}
        </span>
      )}
      {item.shortcut && (
        <span
          className="pdfb-context-menu-item-shortcut"
          style={{
            fontSize: "8px", fontWeight: "500",
            color: item.disabled ? "#94a3b8" : "#64748b",
            background: "rgba(148, 163, 184, 0.1)",
            padding: "0px 1px", borderRadius: "1px", marginLeft: "3px",
          }}
        >
          {item.shortcut}
        </span>
      )}
      {item.children && item.children.length > 0 && (
        <span className="pdfb-context-menu-submenu-arrow" style={{ marginLeft: "4px", color: "#64748b", fontSize: "8px" }}>
          ▶
        </span>
      )}
    </div>
  );
};

// ─── Composant principal ContextMenu ────────────────────────────────────────

export const ContextMenu: FC<ContextMenuProps> = ({
  items,
  position,
  onClose,
  isVisible,
}) => {
  const menuRef = useRef(null);
  const [hoveredItem, setHoveredItem] = useState<string | null>(null);
  const [openSubmenu, setOpenSubmenu] = useState<string | null>(null);
  const [submenuPosition, setSubmenuPosition] = useState<{
    x: number;
    y: number;
  } | null>(null);
  const closeTimeoutRef = useRef<ReturnType<typeof globalThis.setTimeout> | null>(null);

  // Calculer la position corrigée pour garder le menu à l'écran
  const adjustedPosition = useMemo(() => {
    let adjustedX = position.x;
    let adjustedY = position.y;

    if (globalThis.window !== undefined) {
      // Largeur et hauteur estimées du menu compact
      const menuWidth = 160; // Max width du menu compact

      // Calculer la hauteur réelle en fonction du type d'éléments
      let menuHeight = 0;
      items.forEach((item) => {
        if (item.section) {
          menuHeight += 14; // Hauteur des sections avec padding
        } else if (item.separator) {
          menuHeight += 3; // Hauteur des séparateurs avec margin
        } else {
          menuHeight += 18; // Hauteur des éléments normaux
        }
      });
      menuHeight += 2; // Padding vertical du menu

      // Vérifier si le menu sort à droite
      if (adjustedX + menuWidth > globalThis.innerWidth) {
        adjustedX = globalThis.innerWidth - menuWidth - 10;
      }

      // Vérifier si le menu sort en bas
      if (adjustedY + menuHeight > globalThis.innerHeight) {
        adjustedY = globalThis.innerHeight - menuHeight - 10;
      }

      // Vérifier si le menu sort en haut (après ajustement vers le bas)
      if (adjustedY < 0) {
        adjustedY = 10; // Positionner en haut avec une marge
      }

      // Vérifier les limites à gauche
      if (adjustedX < 0) adjustedX = 10;
    }

    return { x: adjustedX, y: adjustedY };
  }, [position, items]);

  // Nettoyer les timeouts quand le composant se démonte
  useEffect(() => {
    return () => {
      if (closeTimeoutRef.current) {
        clearTimeout(closeTimeoutRef.current);
      }
    };
  }, []);

  // Calculer la position du sous-menu quand il s'ouvre
  useLayoutEffect(() => {
    if (openSubmenu && menuRef.current) {
      const menuElement = menuRef.current as HTMLElement;
      const parentItem = menuElement.querySelector(
        `[data-item-id="${openSubmenu}"]`,
      ) as HTMLElement | null;

      if (parentItem) {
        const menuRect = menuElement.getBoundingClientRect();
        const parentRect = parentItem.getBoundingClientRect();

        let submenuX = menuRect.right - 2; // Positionner à droite du menu parent
        let submenuY = parentRect.top; // Aligner avec l'élément parent

        // Vérifier si le sous-menu sort à droite de l'écran
        const submenuWidth = 160;
        if (submenuX + submenuWidth > globalThis.innerWidth) {
          submenuX = menuRect.left - submenuWidth + 2; // Positionner à gauche
        }

        // Vérifier si le sous-menu sort en bas de l'écran
        const submenuHeight = 200; // Estimation
        if (submenuY + submenuHeight > globalThis.innerHeight) {
          submenuY = window.innerHeight - submenuHeight - 10;
        }

        // Vérifier si le sous-menu sort en haut
        if (submenuY < 0) {
          submenuY = 10;
        }

        setSubmenuPosition((_prev) => ({ x: submenuX, y: submenuY }));
      }
    } else {
      setSubmenuPosition(null);
    }
  }, [openSubmenu]);

  useEffect(() => {
    if (!isVisible) return;

    const handleClickOutside = (event: Event) => {
      // Petite attente pour permettre au menu de s'ouvrir d'abord
      setTimeout(() => {
        if (!menuRef.current) return;

        const mouseEvent = event as unknown as { button?: number };
        // Ne pas fermer si c'est un clic droit (pour éviter de fermer immédiatement)
        if (mouseEvent.button === 2) return;

        // Vérifier si le clic est en dehors du menu
        if (
          !(menuRef.current as HTMLElement).contains(
            event.target as HTMLElement,
          )
        ) {
          onClose();
        }
      }, 10);
    };

    const handleContextMenu = (event: Event) => {
      // Empêcher l'ouverture d'un nouveau menu contextuel sur le menu existant
      if (
        menuRef.current &&
        (menuRef.current as HTMLElement).contains(event.target as HTMLElement)
      ) {
        event.preventDefault();
      }
    };

    const handleEscape = (event: Event) => {
      const keyboardEvent = event as unknown as { key?: string };
      if (keyboardEvent.key === "Escape") {
        onClose();
      }
    };

    // Délai minimal pour permettre au menu de se rendre
    const timer = setTimeout(() => {
      document.addEventListener("mousedown", handleClickOutside, {
        passive: true,
      });
      document.addEventListener("contextmenu", handleContextMenu, {
        passive: true,
      });
      document.addEventListener("keydown", handleEscape, { passive: true });
    }, 50);

    return () => {
      clearTimeout(timer);
      document.removeEventListener("mousedown", handleClickOutside);
      document.removeEventListener("contextmenu", handleContextMenu);
      document.removeEventListener("keydown", handleEscape);
    };
  }, [isVisible, onClose]);

  if (!isVisible) {
    return null;
  }

  const handleItemClick = (item: ContextMenuItem) => {
    // Ne pas exécuter l'action si l'élément a des enfants (c'est un submenu)
    if (!item.disabled && !item.separator && item.action && !item.children?.length) {
      item.action();
      onClose();
    }
  };

  const handleMenuMouseLeave = () => {
    if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
    closeTimeoutRef.current = globalThis.setTimeout(() => {
      setOpenSubmenu(null);
      setHoveredItem(null);
    }, 300);
  };

  const handleMenuMouseEnter = () => {
    if (closeTimeoutRef.current) {
      clearTimeout(closeTimeoutRef.current);
      closeTimeoutRef.current = null;
    }
  };

  const menuStyle: React.CSSProperties = {
    position: "fixed",
    left: `${adjustedPosition.x}px`,
    top: `${adjustedPosition.y}px`,
    opacity: 1,
    visibility: "visible",
    pointerEvents: "auto",
    zIndex: 999999,
    background: "linear-gradient(145deg, #ffffff 0%, #f8fafc 100%)",
    border: "1px solid #e2e8f0",
    WebkitBorderRadius: "8px",
    MozBorderRadius: "8px",
    borderRadius: "8px",
    WebkitBoxShadow: "0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04)",
    MozBoxShadow: "0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04)",
    boxShadow: "0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04)",
    minWidth: "120px",
    maxWidth: "160px",
    padding: "1px 0",
    WebkitTransition: "opacity 0.15s ease-in-out",
    MozTransition: "opacity 0.15s ease-in-out",
    OTransition: "opacity 0.15s ease-in-out",
    transition: "opacity 0.15s ease-in-out",
    WebkitTransformOrigin: "top left",
    MozTransformOrigin: "top left",
    msTransformOrigin: "top left",
    OTransformOrigin: "top left",
    transformOrigin: "top left",
  };

  const menuElement = (
    <div
      ref={menuRef}
      role="menu"
      aria-label="Context menu"
      tabIndex={-1}
      className="pdfb-context-menu"
      onKeyDown={(e) => { if (e.key === "Escape") onClose(); }}
      onMouseLeave={handleMenuMouseLeave}
      onMouseEnter={handleMenuMouseEnter}
      style={menuStyle}
    >
      {items.map((item) => (
        <div key={item.id}>
          <ContextMenuItemRenderer
            item={item}
            isHovered={hoveredItem === item.id}
            onHover={setHoveredItem}
            onSubmenuOpen={setOpenSubmenu}
            onItemClick={handleItemClick}
          />
        </div>
      ))}
    </div>
  );

  const renderSubmenus = () => {
    if (!openSubmenu || !submenuPosition) return null;
    const parentItem = items.find((item) => item.id === openSubmenu);
    if (!parentItem?.children) return null;

    return (
      <div
        role="none"
        onMouseEnter={handleMenuMouseEnter}
        onMouseLeave={handleMenuMouseLeave}
      >
        <ContextMenu
          items={parentItem.children}
          position={submenuPosition}
          onClose={() => setOpenSubmenu(null)}
          isVisible={true}
        />
      </div>
    );
  };

  // Utiliser un Portal pour rendre le menu au niveau du document body
  return createPortal(
    <>
      {menuElement}
      {renderSubmenus()}
    </>,
    document.body,
  );
};
