import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { ChevronDown, X } from 'lucide-react';
import { useDismissOnFocusOutside } from './useDismissOnFocusOutside';

interface FilterPickerFieldProps {
  value: string;
  options: string[];
  placeholder?: string;
  ariaLabel?: string;
  onChange: (value: string) => void;
  /** 输入时大小写不敏感模糊匹配 */
  caseInsensitive?: boolean;
  /** 输入框始终可编辑，聚焦即展开下拉（未输入时展示全部选项） */
  alwaysSearchable?: boolean;
}

interface PopoverPosition {
  top: number;
  left: number;
  width: number;
}

function normalizeForMatch(text: string, caseInsensitive: boolean): string {
  const trimmed = text.trim();
  return caseInsensitive ? trimmed.toUpperCase() : trimmed;
}

export function FilterPickerField({
  value,
  options,
  placeholder = '请选择',
  ariaLabel = '筛选选择',
  onChange,
  caseInsensitive = false,
  alwaysSearchable = false,
}: FilterPickerFieldProps) {
  const [open, setOpen] = useState(false);
  const [editing, setEditing] = useState(false);
  const [query, setQuery] = useState('');
  const [position, setPosition] = useState<PopoverPosition>({ top: 0, left: 0, width: 0 });
  const anchorRef = useRef<HTMLDivElement>(null);
  const popoverRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (open) return;
    if (!alwaysSearchable && editing) return;
    setQuery(value);
  }, [value, editing, open, alwaysSearchable]);

  const dismiss = useCallback(() => {
    setOpen(false);
    setEditing(false);
    setQuery(value);
  }, [value]);

  useDismissOnFocusOutside(open, [anchorRef, popoverRef], dismiss);

  const updatePosition = useCallback(() => {
    const anchor = anchorRef.current;
    if (!anchor) return;
    const rect = anchor.getBoundingClientRect();
    setPosition({
      top: rect.bottom + 6,
      left: rect.left,
      width: rect.width,
    });
  }, []);

  useEffect(() => {
    if (!open) return;
    updatePosition();
    window.addEventListener('resize', updatePosition);
    window.addEventListener('scroll', updatePosition, true);
    return () => {
      window.removeEventListener('resize', updatePosition);
      window.removeEventListener('scroll', updatePosition, true);
    };
  }, [open, updatePosition, options.length, query]);

  const filtered = useMemo(() => {
    const q = query.trim();
    if (!q) return options;
    const nq = normalizeForMatch(q, caseInsensitive);
    return options.filter((item) => normalizeForMatch(item, caseInsensitive).includes(nq));
  }, [options, query, caseInsensitive]);

  const pick = (next: string) => {
    onChange(next);
    setQuery(next);
    setOpen(false);
    setEditing(false);
    inputRef.current?.blur();
  };

  const clear = (event: React.MouseEvent) => {
    event.preventDefault();
    event.stopPropagation();
    onChange('');
    setQuery('');
    setOpen(false);
    setEditing(false);
    window.requestAnimationFrame(() => {
      updatePosition();
      inputRef.current?.focus();
    });
  };

  const openPicker = () => {
    setOpen(true);
    setQuery(value);
    if (!alwaysSearchable) {
      setEditing(true);
      window.requestAnimationFrame(() => inputRef.current?.select());
    }
    window.requestAnimationFrame(updatePosition);
  };

  const togglePicker = () => {
    if (open) {
      dismiss();
      return;
    }
    openPicker();
    inputRef.current?.focus();
  };

  const inputValue = alwaysSearchable || editing ? query : value;
  const inputReadOnly = !alwaysSearchable && !editing;

  const popover = open && typeof document !== 'undefined'
    ? createPortal(
      <div
        ref={popoverRef}
        className="vm-filter-picker-popover vm-filter-picker-popover--portal"
        role="listbox"
        aria-label={ariaLabel}
        style={{
          top: position.top,
          left: position.left,
          width: position.width,
        }}
      >
        <div className="vm-filter-picker-options">
          {filtered.length === 0 ? (
            <p className="vm-filter-picker-empty">暂无匹配项</p>
          ) : (
            filtered.map((item) => (
              <button
                key={item}
                type="button"
                role="option"
                aria-selected={value === item}
                className={`vm-filter-picker-option ${value === item ? 'checked' : ''}`}
                onMouseDown={(event) => event.preventDefault()}
                onClick={() => pick(item)}
              >
                {item}
              </button>
            ))
          )}
        </div>
      </div>,
      document.body,
    )
    : null;

  return (
    <div className="vm-filter-picker-field" ref={anchorRef}>
      <div className={`vm-filter-picker-control ${open ? 'open' : ''}`}>
        <input
          ref={inputRef}
          type="text"
          className="vm-filter-picker-input"
          value={inputValue}
          placeholder={placeholder}
          aria-label={ariaLabel}
          aria-expanded={open}
          aria-autocomplete="list"
          role="combobox"
          readOnly={inputReadOnly}
          onFocus={openPicker}
          onChange={(event) => {
            setQuery(event.target.value);
            setOpen(true);
            if (!alwaysSearchable) setEditing(true);
            window.requestAnimationFrame(updatePosition);
          }}
          onKeyDown={(event) => {
            if (event.key === 'Escape') dismiss();
            if (event.key === 'Enter' && filtered.length === 1) {
              event.preventDefault();
              pick(filtered[0]);
            }
          }}
        />
        {value ? (
          <button
            type="button"
            className="vm-filter-picker-clear"
            onClick={clear}
            aria-label={`清空${ariaLabel}`}
            tabIndex={-1}
          >
            <X size={14} aria-hidden />
          </button>
        ) : null}
        <button
          type="button"
          className="vm-filter-picker-chevron-btn"
          aria-label={`${open ? '收起' : '展开'}${ariaLabel}列表`}
          aria-expanded={open}
          tabIndex={-1}
          onMouseDown={(event) => event.preventDefault()}
          onClick={togglePicker}
        >
          <ChevronDown size={14} aria-hidden className={`vm-filter-picker-chevron ${open ? 'is-open' : ''}`} />
        </button>
      </div>
      {popover}
    </div>
  );
}
