import React, { useState, useRef, useEffect, useId } from 'react';

/**
 * Searchable multi-select for custom order meta fields.
 * Keyboard: type to filter, ↑/↓ to move, Enter to add, Esc to close, Backspace on an empty search removes the last tag.
 *
 * Props:
 *  allFields: object  { "field_key": "field_key", ... }
 *  selected:  array   ["field_key", ...]
 *  onChange:  fn(newArray)
 *  disabled:  bool
 */
const CustomFieldSelect = ({ allFields = {}, selected = [], onChange, disabled = false }) => {
  const listId = useId();
  const [search, setSearch] = useState('');
  const [open, setOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(0);
  const [above, setAbove] = useState(false);
  const containerRef = useRef(null);
  const inputRef = useRef(null);

  const selectedArr = Array.isArray(selected) ? selected : [];

  useEffect(() => {
    const handler = (e) => {
      if (containerRef.current && !containerRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  // Open the list upward when there isn't room below it (the sticky save bar covers the page bottom).
  useEffect(() => {
    if (!open) return undefined;
    const place = () => {
      if (!containerRef.current) return;
      const rect = containerRef.current.getBoundingClientRect();
      const bar = document.querySelector('.ssgsw_button_container');
      const bottomLimit = bar ? bar.getBoundingClientRect().top : window.innerHeight;
      const spaceBelow = bottomLimit - rect.bottom;
      const spaceAbove = rect.top - 40;
      setAbove(spaceBelow < 240 && spaceAbove > spaceBelow);
    };
    place();
    window.addEventListener('scroll', place, true);
    window.addEventListener('resize', place);
    return () => {
      window.removeEventListener('scroll', place, true);
      window.removeEventListener('resize', place);
    };
  }, [open]);

  const allKeys = Object.keys(allFields);
  const filtered = allKeys.filter(
    (k) => k.toLowerCase().includes(search.toLowerCase()) && !selectedArr.includes(k)
  );

  const add = (key) => {
    if (!key) return;
    if (!selectedArr.includes(key)) onChange([...selectedArr, key]);
    setSearch('');
    setActiveIndex(0);
    if (inputRef.current) inputRef.current.focus();
  };

  const remove = (key) => onChange(selectedArr.filter((k) => k !== key));

  const onKeyDown = (e) => {
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      setOpen(true);
      setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setActiveIndex((i) => Math.max(i - 1, 0));
    } else if (e.key === 'Enter') {
      e.preventDefault();
      if (open) add(filtered[activeIndex]);
    } else if (e.key === 'Escape') {
      setOpen(false);
    } else if (e.key === 'Backspace' && search === '' && selectedArr.length) {
      remove(selectedArr[selectedArr.length - 1]);
    }
  };

  return (
    <div
      ref={containerRef}
      className={`osgsw-cf-select${disabled ? ' osgsw-cf-select--disabled' : ''}${open && above ? ' is-above' : ''}`}
    >
      {/* Tag input area */}
      <div
        className="osgsw-cf-select__input-area"
        onClick={() => {
          if (disabled) return;
          setOpen(true);
          if (inputRef.current) inputRef.current.focus();
        }}
      >
        {selectedArr.map((key) => (
          <span key={key} className="osgsw-cf-select__tag">
            {key}
            {!disabled && (
              <button
                type="button"
                className="osgsw-cf-select__tag-remove"
                aria-label={`Remove ${key}`}
                onClick={(e) => { e.stopPropagation(); remove(key); }}
              >
                ×
              </button>
            )}
          </span>
        ))}
        {!disabled && (
          <input
            ref={inputRef}
            type="text"
            role="combobox"
            aria-expanded={open}
            aria-controls={listId}
            aria-autocomplete="list"
            aria-activedescendant={open && filtered[activeIndex] ? `${listId}-${activeIndex}` : undefined}
            aria-label="Custom fields"
            className="osgsw-cf-select__search"
            placeholder={selectedArr.length === 0 ? 'Search custom fields...' : ''}
            value={search}
            onChange={(e) => { setSearch(e.target.value); setOpen(true); setActiveIndex(0); }}
            onFocus={() => setOpen(true)}
            onKeyDown={onKeyDown}
          />
        )}
      </div>

      {/* Dropdown list */}
      {open && !disabled && (
        <ul className="osgsw-cf-select__dropdown" role="listbox" id={listId} aria-label="Custom fields">
          {filtered.length === 0 ? (
            <li className="osgsw-cf-select__empty">
              {search ? 'No matching fields found.' : 'All available fields are already selected.'}
            </li>
          ) : (
            filtered.map((key, index) => (
              <li
                key={key}
                id={`${listId}-${index}`}
                role="option"
                aria-selected={index === activeIndex}
                className={`osgsw-cf-select__option${index === activeIndex ? ' is-active' : ''}`}
                onMouseEnter={() => setActiveIndex(index)}
                onMouseDown={(e) => { e.preventDefault(); add(key); }}
              >
                {key}
              </li>
            ))
          )}
        </ul>
      )}
    </div>
  );
};

export default CustomFieldSelect;
