export function menuLabel(text: unknown) {
  return {
    kind: "label",
    text: String(text || ""),
  };
}

export function menuSeparator() {
  return {
    kind: "separator",
  };
}

function isIconPresentation(options: unknown) {
  return String((options as { presentation?: string } | null | undefined)?.presentation || "").trim().toLowerCase() === "icon";
}

function hasExplicitIconPanelLayout(panel: HTMLDivElement | null | undefined) {
  if (!panel?.classList) {
    return false;
  }
  return (
    panel.classList.contains("at-tooltip-icon-stack-panel")
    || panel.classList.contains("at-tooltip-icon-row-panel")
    || panel.classList.contains("at-tooltip-icon-grid-panel")
  );
}

function applyDefaultIconPanelLayout(
  panel: HTMLDivElement | null | undefined,
  items: Array<Record<string, unknown>> | null | undefined,
) {
  if (!panel || hasExplicitIconPanelLayout(panel) || !Array.isArray(items) || items.length <= 0) {
    return;
  }
  const interactiveItems = items.filter((item) => {
    const kind = String(item?.kind || "").trim().toLowerCase();
    return kind === "item" || kind === "submenu";
  });
  if (interactiveItems.length <= 0) {
    return;
  }
  const iconOnlyMenu = interactiveItems.every((item) => isIconPresentation(item?.options));
  if (iconOnlyMenu) {
    panel.classList.add("at-tooltip-icon-stack-panel");
  }
}

function resolveChildPanelLayoutClass(options: {
  presentation?: string;
  layout?: "horizontal" | "vertical";
} | null | undefined) {
  if (options?.layout === "horizontal") {
    return "at-tooltip-icon-row-panel";
  }
  if (options?.layout === "vertical") {
    return "at-tooltip-icon-stack-panel";
  }
  if (isIconPresentation(options)) {
    return "at-tooltip-icon-stack-panel";
  }
  return "";
}

export function menuItem(
  innerHtml: string,
  onSelect: (() => void) | undefined,
  extraClass = "",
  options: {
    disabled?: boolean;
    presentation?: string;
    title?: string;
    ariaLabel?: string;
    layout?: "horizontal" | "vertical";
  } = {},
) {
  return {
    kind: "item",
    innerHtml,
    onSelect,
    extraClass,
    options,
  };
}

export function menuSubmenu(
  innerHtml: string,
  children: Array<Record<string, unknown>> | (() => Array<Record<string, unknown>>),
  extraClass = "",
  options: {
    disabled?: boolean;
    presentation?: string;
    title?: string;
    ariaLabel?: string;
    childPanelClassName?: string;
    layout?: "horizontal" | "vertical";
  } = {},
) {
  return {
    kind: "submenu",
    innerHtml,
    children,
    extraClass,
    options,
  };
}

export function buildPickerMenuItems<T>(
  entries: T[] | null | undefined,
  options: {
    getInnerHtml: (entry: T, index: number) => string;
    onSelect: (entry: T, index: number) => void;
    getExtraClass?: (entry: T, index: number) => string;
    getDisabled?: (entry: T, index: number) => boolean;
  },
) {
  const validEntries = Array.isArray(entries) ? entries : [];
  return validEntries.map((entry, index) => menuItem(
    options.getInnerHtml(entry, index),
    () => options.onSelect(entry, index),
    options.getExtraClass?.(entry, index) || "",
    { disabled: options.getDisabled?.(entry, index) === true },
  ));
}

export function appendContextMenuItems(
  tooltip: {
    makeLabel?: (text: string) => HTMLElement;
    makeItem?: (
      innerHtml: string,
      onClick: () => void,
      extraClass?: string,
      options?: { disabled?: boolean; presentation?: string; title?: string; ariaLabel?: string; layout?: "horizontal" | "vertical" },
    ) => HTMLElement;
    makeSubmenuItem?: (
      innerHtml: string,
      extraClass?: string,
      options?: { disabled?: boolean; presentation?: string; title?: string; ariaLabel?: string; childPanelClassName?: string; layout?: "horizontal" | "vertical" },
    ) => HTMLElement;
    makeSeparator?: () => HTMLElement;
    openChild?: (anchorEl: HTMLElement, builder: (panel: HTMLDivElement) => void, tag?: string) => boolean;
    closeChildren?: (anchorEl: HTMLElement) => boolean;
  } | null | undefined,
  panel: HTMLDivElement,
  items: Array<Record<string, unknown>> | null | undefined,
  menuPath = "root",
) {
  if (!tooltip || !panel || !Array.isArray(items)) {
    return;
  }
  applyDefaultIconPanelLayout(panel, items);
  items.forEach((item) => {
    const kind = String(item?.kind || "").trim().toLowerCase();
    if (kind === "separator") {
      const separatorEl = tooltip.makeSeparator?.();
      if (separatorEl) {
        panel.appendChild(separatorEl);
      }
      return;
    }
    if (kind === "label") {
      const labelEl = tooltip.makeLabel?.(String(item?.text || ""));
      if (labelEl) {
        panel.appendChild(labelEl);
      }
      return;
    }
    if (kind === "item") {
      const itemEl = tooltip.makeItem?.(
        String(item?.innerHtml || ""),
        typeof item?.onSelect === "function" ? item.onSelect as () => void : (() => {}),
        String(item?.extraClass || ""),
        item?.options && typeof item.options === "object"
          ? item.options as { disabled?: boolean; presentation?: string; title?: string; ariaLabel?: string; layout?: "horizontal" | "vertical" }
          : {},
      );
      if (itemEl) {
        const htmlItemEl = itemEl as HTMLButtonElement;
        if (tooltip.closeChildren && !htmlItemEl.disabled) {
          const collapseChildren = () => {
            tooltip.closeChildren?.(htmlItemEl);
          };
          htmlItemEl.addEventListener("mouseenter", collapseChildren);
          htmlItemEl.addEventListener("focus", collapseChildren);
        }
        panel.appendChild(htmlItemEl);
      }
      return;
    }
    if (kind === "submenu") {
      const options = item?.options && typeof item.options === "object"
        ? item.options as {
          disabled?: boolean;
          presentation?: string;
          title?: string;
          ariaLabel?: string;
          childPanelClassName?: string;
          layout?: "horizontal" | "vertical";
        }
        : {};
      const itemEl = tooltip.makeSubmenuItem
        ? tooltip.makeSubmenuItem(
          String(item?.innerHtml || ""),
          String(item?.extraClass || ""),
          options,
        )
        : tooltip.makeItem?.(
          `${String(item?.innerHtml || "")}<span class="at-tooltip-submenu-arrow" aria-hidden="true">›</span>`,
          () => {},
          `has-submenu ${String(item?.extraClass || "")}`.trim(),
          options,
        );
      if (!itemEl) {
        return;
      }
      const childEntries = typeof item?.children === "function"
        ? item.children()
        : (Array.isArray(item?.children) ? item.children : []);
      const htmlItemEl = itemEl as HTMLButtonElement;
      if (!htmlItemEl.disabled && tooltip.openChild) {
        const childTag = `${menuPath}:${String(item?.innerHtml || "").replace(/\s+/g, "-").toLowerCase()}`;
        const openChildMenu = () => {
          tooltip.openChild?.(htmlItemEl, (childPanel) => {
            const extraPanelClassName = String(options.childPanelClassName || "").trim();
            if (extraPanelClassName) {
              childPanel.classList.add(...extraPanelClassName.split(/\s+/).filter(Boolean));
            }
            const childPanelLayoutClass = resolveChildPanelLayoutClass(options);
            if (childPanelLayoutClass) {
              childPanel.classList.add(childPanelLayoutClass);
            }
            appendContextMenuItems(tooltip, childPanel, childEntries, childTag);
          }, childTag);
        };
        htmlItemEl.addEventListener("mouseenter", openChildMenu);
        htmlItemEl.addEventListener("focus", openChildMenu);
        htmlItemEl.addEventListener("click", (event) => {
          event.preventDefault();
          openChildMenu();
        });
      }
      panel.appendChild(htmlItemEl);
    }
  });
}

export function openContextMenuAtPoint(
  tooltip: {
    openAtPoint?: (clientX: number, clientY: number, builder: (panel: HTMLDivElement) => void, tag?: string) => void;
    makeSubmenuItem?: (
      innerHtml: string,
      extraClass?: string,
      options?: { disabled?: boolean; presentation?: string; title?: string; ariaLabel?: string; childPanelClassName?: string; layout?: "horizontal" | "vertical" },
    ) => HTMLElement;
    openChild?: (anchorEl: HTMLElement, builder: (panel: HTMLDivElement) => void, tag?: string) => boolean;
    closeChildren?: (anchorEl: HTMLElement) => boolean;
  } | null | undefined,
  clientX: number,
  clientY: number,
  items: Array<Record<string, unknown>>,
  tag?: string,
) {
  if (!tooltip?.openAtPoint) {
    return false;
  }
  tooltip.openAtPoint(clientX, clientY, (panel) => {
    appendContextMenuItems(tooltip as never, panel, items, tag || "point-menu");
  }, tag);
  return true;
}

export function openContextMenuAtAnchor(
  tooltip: {
    open?: (anchorEl: HTMLElement, builder: (panel: HTMLDivElement) => void, tag?: string) => void;
    makeSubmenuItem?: (
      innerHtml: string,
      extraClass?: string,
      options?: { disabled?: boolean; presentation?: string; title?: string; ariaLabel?: string; childPanelClassName?: string; layout?: "horizontal" | "vertical" },
    ) => HTMLElement;
    openChild?: (anchorEl: HTMLElement, builder: (panel: HTMLDivElement) => void, tag?: string) => boolean;
    closeChildren?: (anchorEl: HTMLElement) => boolean;
  } | null | undefined,
  anchorEl: HTMLElement | null | undefined,
  items: Array<Record<string, unknown>>,
  tag?: string,
) {
  if (!tooltip?.open || !anchorEl) {
    return false;
  }
  tooltip.open(anchorEl, (panel) => {
    appendContextMenuItems(tooltip as never, panel, items, tag || "anchor-menu");
  }, tag);
  return true;
}
