import type { JSX } from "solid-js";
import { Show, createEffect, onCleanup, splitProps } from "solid-js";
import { createDismiss } from "../../utilities/dismiss/create-dismiss";
import { createFocusTrap } from "../../utilities/focus-trap/create-focus-trap";
import { createScrollLock } from "../../utilities/scroll-lock/create-scroll-lock";
import { useInternalDrawerContext } from "./drawer-context";

/** Props for Drawer.Content. */
export interface DrawerContentProps extends JSX.HTMLAttributes<HTMLDivElement> {
  /** Keep mounted even when closed (for animation control). */
  forceMount?: boolean;
  children?: JSX.Element;
}

/**
 * Drawer content panel. Activates focus trap, scroll lock, and Escape/outside dismiss when open.
 * Sets data-side to indicate which edge the drawer slides from.
 */
export function DrawerContent(props: DrawerContentProps): JSX.Element {
  const [local, rest] = splitProps(props, ["children", "forceMount"]);
  const ctx = useInternalDrawerContext();
  let contentRef: HTMLDivElement | undefined;

  const focusTrap = createFocusTrap(() => contentRef ?? null);
  const scrollLock = createScrollLock();
  const dismiss = createDismiss({
    getContainer: () => contentRef ?? null,
    onDismiss: () => ctx.setOpen(false),
  });

  createEffect(() => {
    if (ctx.isOpen()) {
      focusTrap.activate();
      scrollLock.lock();
      dismiss.attach();
    } else {
      focusTrap.deactivate();
      scrollLock.unlock();
      dismiss.detach();
    }
    onCleanup(() => {
      focusTrap.deactivate();
      scrollLock.unlock();
      dismiss.detach();
    });
  });

  return (
    <Show when={local.forceMount || ctx.isOpen()}>
      <div
        ref={contentRef}
        id={ctx.contentId()}
        role="dialog"
        aria-modal="true"
        aria-labelledby={ctx.titleId() || undefined}
        aria-describedby={ctx.descriptionId() || undefined}
        data-state={ctx.isOpen() ? "open" : "closed"}
        data-side={ctx.side()}
        {...rest}
      >
        {local.children}
      </div>
    </Show>
  );
}
