import type { JSX } from "solid-js";
import { Show, createEffect, onCleanup, splitProps } from "solid-js";
import { createDismiss } from "../../utilities/dismiss/create-dismiss";
import { useInternalSelectContext } from "./select-context";

export interface SelectContentProps extends JSX.HTMLAttributes<HTMLDivElement> {
  /** Keep mounted when closed. @default false */
  forceMount?: boolean;
  children?: JSX.Element;
}

/**
 * Floating dropdown content for Select. Contains the listbox with items.
 * Handles dismiss (outside click) and keyboard navigation.
 */
export function SelectContent(props: SelectContentProps): JSX.Element {
  const [local, rest] = splitProps(props, ["children", "forceMount"]);
  const ctx = useInternalSelectContext();

  const dismiss = createDismiss({
    getContainer: () => ctx.contentRef(),
    onDismiss: () => ctx.close(),
    dismissOnEscape: false,
  });

  createEffect(() => {
    if (ctx.isOpen()) {
      dismiss.attach();
    } else {
      dismiss.detach();
    }
    onCleanup(() => dismiss.detach());
  });

  const handleKeyDown: JSX.EventHandler<HTMLDivElement, KeyboardEvent> = (e) => {
    if (e.key === "Escape") {
      e.preventDefault();
      ctx.close();
      ctx.triggerRef()?.focus();
      return;
    }
    if (e.key === "Tab") {
      ctx.close();
      return;
    }
    ctx.navigation.containerProps.onKeyDown(e);
  };

  return (
    <Show when={local.forceMount || ctx.isOpen()}>
      <div
        ref={(el) => ctx.setContentRef(el)}
        id={ctx.contentId}
        role="listbox"
        aria-orientation="vertical"
        aria-activedescendant={ctx.navigation.containerProps["aria-activedescendant"]}
        aria-labelledby={ctx.triggerId}
        data-state={ctx.isOpen() ? "open" : "closed"}
        style={ctx.floatingStyle()}
        tabIndex={-1}
        onKeyDown={handleKeyDown}
        onPointerLeave={() => ctx.navigation.clearHighlight()}
        {...rest}
      >
        {local.children}
      </div>
    </Show>
  );
}
