import React, { useEffect, useRef, useCallback } from 'react'

let emojiMartPromise = null

function ensureEmojiMart() {
  if (!emojiMartPromise) {
    emojiMartPromise = import('emoji-mart')
  }
  return emojiMartPromise
}

export default function EmojiMartPicker({
  data,
  onEmojiSelect,
  onClickOutside,
  theme = 'auto',
  previewPosition = 'bottom',
  skinTonePosition = 'preview',
  maxFrequentRows = 4,
  perLine = 9,
  navPosition = 'top',
  set = 'native',
  locale = 'en',
  autoFocus = false,
  searchPosition,
  dynamicWidth,
  noCountryFlags,
  className = '',
}) {
  const hostRef = useRef(null)
  const pickerRef = useRef(null)

  // Keep refs pointing at the latest callback props so stable wrappers
  // never capture a stale closure.
  const onEmojiSelectRef = useRef(onEmojiSelect)
  const onClickOutsideRef = useRef(onClickOutside)
  onEmojiSelectRef.current = onEmojiSelect
  onClickOutsideRef.current = onClickOutside

  // Stable wrappers with fixed identity — safe to pass once to the Picker
  // constructor without needing to re-initialise the element on every render.
  const stableOnEmojiSelect = useCallback((emoji) => {
    onEmojiSelectRef.current?.(emoji)
  }, [])

  const stableOnClickOutside = useCallback((e) => {
    onClickOutsideRef.current?.(e)
  }, [])

  useEffect(() => {
    let cancelled = false

    // emoji-mart's Picker stores callbacks in `this.props` during construction.
    // connectedCallback reads from `this.props`, NOT from plain element
    // properties set after construction, so we MUST use `new Picker(props)`
    // rather than `document.createElement('em-emoji-picker')` + property
    // assignment, which would leave onEmojiSelect as null internally.
    ensureEmojiMart().then(({ Picker }) => {
      if (cancelled || !hostRef.current) return

      if (!pickerRef.current) {
        const pickerProps = {
          data,
          onEmojiSelect: stableOnEmojiSelect,
          onClickOutside: stableOnClickOutside,
          theme,
          previewPosition,
          skinTonePosition,
          maxFrequentRows,
          perLine,
          navPosition,
          set,
          locale,
          autoFocus,
        }
        if (searchPosition !== undefined) pickerProps.searchPosition = searchPosition
        if (dynamicWidth !== undefined) pickerProps.dynamicWidth = dynamicWidth
        if (noCountryFlags !== undefined) pickerProps.noCountryFlags = noCountryFlags

        const el = new Picker(pickerProps)
        pickerRef.current = el
        hostRef.current.replaceChildren(el)
      }
    })

    return () => {
      cancelled = true
    }
  // Run once on mount. Callbacks stay fresh via refs; static display options
  // (theme, perLine, etc.) don't change during a single picker session.
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    return () => {
      if (hostRef.current) {
        hostRef.current.replaceChildren()
      }

      pickerRef.current = null
    }
  }, [])

  return <div ref={hostRef} className={className} />
}