import React, { useMemo } from 'react';
import { FaTimes } from 'react-icons/fa';

import { LANGUAGE_OPTIONS } from '../../data/locales';
import SearchableSelect from '../widgets/SearchableSelect';

/** Props for {@link LanguageMultiSelect}. */
interface LanguageMultiSelectProps {
  /** Currently-selected language codes (lowercased ISO 639-1). */
  value: string[];
  /** Fired with the next selection whenever the merchant adds or removes one. */
  onChange: (next: string[]) => void;
  /** Disable the whole control while a generation is in flight. */
  disabled?: boolean;
  /** Hard cap on how many languages can be selected. Hides the picker once hit. */
  max?: number;
  /** Language codes to keep out of the dropdown (e.g. the fixed primary). */
  exclude?: string[];
}

/**
 * Pick one or more languages for article generation. Selected languages
 * render as removable chips; the searchable dropdown below adds another.
 * Picking two or more languages tells the backend to generate the topic in
 * each language at once and link them as a switchable "language version" set.
 *
 * Built on the same {@link SearchableSelect} and {@link LANGUAGE_OPTIONS} the
 * settings drawer uses, so the option list stays in lockstep with the brand
 * language picker.
 *
 * @param props {LanguageMultiSelectProps} Controlled multi-select props.
 * @returns {JSX.Element} The language multi-select.
 */
const LanguageMultiSelect = ({
  value,
  onChange,
  disabled = false,
  max,
  exclude = [],
}: LanguageMultiSelectProps): JSX.Element => {
  // Map code -> human label so chips show "Hungarian" not "hu". Falls back to
  // the raw code for any language not in the canonical list.
  const labelByCode = useMemo(() => {
    const map = new Map<string, string>();
    for (const option of LANGUAGE_OPTIONS) map.set(option.value, option.label);

    return map;
  }, []);

  // Hide already-selected and excluded languages from the dropdown so the
  // merchant can't add a duplicate or the fixed primary; the empty "value"
  // keeps the trigger in placeholder mode.
  const remainingOptions = useMemo(
    () =>
      LANGUAGE_OPTIONS.filter(
        option =>
          !value.includes(option.value) && !exclude.includes(option.value)
      ),
    [value, exclude]
  );

  const atMax = typeof max === 'number' && value.length >= max;

  const handleAdd = (next: string): void => {
    const code = (next || '').trim().toLowerCase();
    if (!code || value.includes(code) || atMax) return;
    onChange([...value, code]);
  };

  const handleRemove = (code: string): void => {
    onChange(value.filter(entry => entry !== code));
  };

  return (
    <div className="flex flex-col gap-2">
      {value.length > 0 && (
        <div className="flex flex-wrap gap-1.5">
          {value.map(code => (
            <span
              key={code}
              className={`inline-flex items-center gap-1 rounded-full border border-gray-300 bg-gray-50 px-2.5 py-1 text-xs text-gray-900 ${
                disabled ? 'opacity-60' : ''
              }`}
            >
              {labelByCode.get(code) ?? code.toUpperCase()}
              {!disabled && (
                <button
                  type="button"
                  aria-label={`Remove ${labelByCode.get(code) ?? code}`}
                  onClick={() => handleRemove(code)}
                  className="text-gray-500 hover:text-gray-900"
                >
                  <FaTimes aria-hidden="true" size={10} />
                </button>
              )}
            </span>
          ))}
        </div>
      )}
      {!disabled && !atMax && (
        <SearchableSelect
          value=""
          onChange={handleAdd}
          options={remainingOptions}
          placeholder={
            value.length ? 'Add another language…' : 'Select language…'
          }
          searchPlaceholder="Search languages…"
        />
      )}
    </div>
  );
};

export default LanguageMultiSelect;
