import { useMemo, useState } from 'react';
import { PickerShell } from './PickerShell';

export interface SelectFieldOption {
  value: string;
  label: string;
}

export interface SelectFieldProps {
  label?: string;
  required?: boolean;
  hint?: string;
  className?: string;
  /** Either strings or {value,label} objects. */
  options?: Array<string | SelectFieldOption>;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  /** Force the search box on/off. Defaults to on when there are >7 options. */
  searchable?: boolean;
  /** Allow clearing back to ''. Defaults to true for non-required fields. */
  clearable?: boolean;
  disabled?: boolean;
}

const norm = (o: string | SelectFieldOption): SelectFieldOption =>
  typeof o === 'string' ? { value: o, label: o } : o;

/** Single-select that renders through the shared PickerShell, so it matches
 *  LookupField exactly. Static options, searched/filtered locally. An empty-
 *  value option (e.g. {value:'', label:'Choose…'}) is treated as the
 *  placeholder rather than a list row, and option values are de-duplicated. */
export function SelectField({
  label,
  required,
  hint,
  className,
  options = [],
  value,
  onChange,
  placeholder,
  searchable,
  clearable,
  disabled,
}: SelectFieldProps) {
  const [search, setSearch] = useState('');

  // Normalize, lift any empty-value option's label to the placeholder, dedupe.
  const { opts, ph } = useMemo(() => {
    const all = options.map(norm);
    const empty = all.find((o) => o.value === '');
    const seen = new Set<string>();
    const opts = all.filter((o) => {
      if (o.value === '' || seen.has(o.value)) return false;
      seen.add(o.value);
      return true;
    });
    return { opts, ph: placeholder ?? empty?.label };
  }, [options, placeholder]);

  const items = useMemo(() => {
    const q = search.trim().toLowerCase();
    return q ? opts.filter((o) => o.label.toLowerCase().includes(q)) : opts;
  }, [opts, search]);

  const display = opts.find((o) => o.value === value)?.label ?? '';
  const canSearch = searchable ?? opts.length > 7;
  const canClear = (clearable ?? !required) && value !== '';

  return (
    <PickerShell<SelectFieldOption>
      label={label}
      required={required}
      hint={hint}
      className={className}
      displayLabel={display}
      placeholder={ph}
      items={items}
      renderItem={(o) => o.label}
      itemKey={(o) => o.value}
      onPick={(o) => onChange(o.value)}
      onClear={canClear ? () => onChange('') : undefined}
      searchable={canSearch}
      search={search}
      onSearch={setSearch}
      onOpenChange={(open) => !open && setSearch('')}
      emptyText="No options."
      disabled={disabled}
    />
  );
}
