import { type FC, useEffect, useRef } from "react";
import { Popover, type PopoverProps } from "@mantine/core";
import data from "@emoji-mart/data";
import { Picker } from "emoji-mart";

export interface StickerPickerProps {
  /** Whether the picker popover is open. */
  opened: boolean;
  /** Called when the picker should close (click outside, Escape, or after selection). */
  onClose: () => void;
  /** Called with the selected emoji string (native unicode preferred, fallback to shortcode). */
  onSelect: (emoji: string) => void;
  /** Anchor element that opens the popover. */
  target: React.ReactNode;
  /** Color theme for the emoji-mart Picker. Defaults to "dark". */
  theme?: "dark" | "light" | "auto";
  /** Popover placement relative to the anchor. Defaults to "bottom-start". */
  position?: PopoverProps["position"];
}

/**
 * StickerPicker — emoji picker wrapped in a Mantine Popover.
 *
 * Renders an emoji-mart Picker inside a transparent Popover dropdown.
 * The Picker instance is created once on mount and cleaned up on unmount
 * so re-renders caused by parent state changes do not recreate it.
 * onSelect and theme changes are reflected via refs without remounting.
 */
export const StickerPicker: FC<StickerPickerProps> = ({
  opened,
  onClose,
  onSelect,
  target,
  theme = "dark",
  position = "bottom-start",
}) => {
  return (
    <Popover
      opened={opened}
      onChange={(o) => {
        if (!o) onClose();
      }}
      onDismiss={onClose}
      position={position}
      withArrow
      shadow="md"
      withinPortal
      closeOnClickOutside
      closeOnEscape
      trapFocus={false}
    >
      <Popover.Target>{target}</Popover.Target>
      <Popover.Dropdown p={0} style={{ background: "transparent", border: "none" }}>
        <PickerInner
          theme={theme}
          onSelect={(emoji) => {
            onSelect(emoji);
            onClose();
          }}
        />
      </Popover.Dropdown>
    </Popover>
  );
};

// ---------------------------------------------------------------------------
// Internal: mounts emoji-mart Picker once, updates callbacks via refs.
// ---------------------------------------------------------------------------

interface PickerInnerProps {
  onSelect: (emoji: string) => void;
  theme: "dark" | "light" | "auto";
}

function PickerInner({ onSelect, theme }: PickerInnerProps) {
  const ref = useRef<HTMLDivElement | null>(null);
  const instanceRef = useRef<unknown>(null);
  // Keep latest callback in ref so the Picker closure never goes stale.
  const onSelectRef = useRef(onSelect);
  onSelectRef.current = onSelect;
  const themeRef = useRef(theme);
  themeRef.current = theme;

  useEffect(() => {
    if (!ref.current) return;
    instanceRef.current = new Picker({
      data,
      onEmojiSelect: (e: { native?: string; shortcodes?: string }) => {
        const cb = onSelectRef.current;
        if (e.native) cb(e.native);
        else if (e.shortcodes) cb(e.shortcodes);
      },
      theme: themeRef.current,
      previewPosition: "none",
      skinTonePosition: "search",
      autoFocus: true,
      maxFrequentRows: 2,
      ref,
    });
    return () => {
      if (ref.current) ref.current.innerHTML = "";
      instanceRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return <div ref={ref} />;
}
