import type { LanguageTag } from '@logto/language-kit';
import { languages as uiLanguageNameMapping } from '@logto/language-kit';
import classNames from 'classnames';
import type { ChangeEvent } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import Plus from '@/assets/images/plus.svg';
import SearchIcon from '@/assets/images/search.svg';
import Button from '@/components/Button';
import TextInput from '@/components/TextInput';
import { onKeyDownHandler } from '@/utilities/a11y';

import * as style from './AddLanguageSelector.module.scss';

type Props = {
  options: LanguageTag[];
  onSelect: (languageTag: LanguageTag) => void;
};

const AddLanguageSelector = ({ options, onSelect }: Props) => {
  const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
  const selectorRef = useRef<HTMLDivElement>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);
  const [isDropDownOpen, setIsDropDownOpen] = useState(false);
  const [searchInputValue, setSearchInputValue] = useState('');

  const filteredOptions = searchInputValue
    ? options.filter(
        (languageTag) =>
          languageTag.toLocaleLowerCase().includes(searchInputValue.toLocaleLowerCase()) ||
          uiLanguageNameMapping[languageTag]
            .toLocaleLowerCase()
            .includes(searchInputValue.toLocaleLowerCase())
      )
    : options;

  const clickOutsideHandler = ({ target }: MouseEvent) => {
    if (target instanceof HTMLElement && !selectorRef.current?.contains(target)) {
      setIsDropDownOpen(false);
      setSearchInputValue('');
    }
  };

  useEffect(() => {
    if (isDropDownOpen) {
      searchInputRef.current?.focus();
      document.addEventListener('mousedown', clickOutsideHandler);
    } else {
      document.removeEventListener('mousedown', clickOutsideHandler);
    }

    return () => {
      if (isDropDownOpen) {
        document.removeEventListener('mousedown', clickOutsideHandler);
      }
    };
  }, [isDropDownOpen, searchInputRef]);

  const handleSelect = (languageTag: LanguageTag) => {
    onSelect(languageTag);
    setIsDropDownOpen(false);
    setSearchInputValue('');
  };

  return (
    <div ref={selectorRef} className={style.languageSelector}>
      <div className={style.input}>
        <Button
          className={classNames(style.addLanguageButton, isDropDownOpen && style.hidden)}
          icon={<Plus className={style.buttonIcon} />}
          title="sign_in_exp.others.manage_language.add_language"
          type="default"
          size="medium"
          onClick={() => {
            setIsDropDownOpen(true);
          }}
        />
        <TextInput
          ref={searchInputRef}
          icon={<SearchIcon className={style.buttonIcon} />}
          className={classNames(!isDropDownOpen && style.hidden)}
          placeholder={t('general.type_to_search')}
          value={searchInputValue}
          onChange={(event: ChangeEvent<HTMLInputElement>) => {
            setSearchInputValue(event.target.value);
          }}
        />
      </div>
      {isDropDownOpen && filteredOptions.length > 0 && (
        <ul className={style.dropDown}>
          {filteredOptions.map((languageTag) => (
            <li
              key={languageTag}
              role="tab"
              tabIndex={0}
              className={style.dropDownItem}
              onKeyDown={onKeyDownHandler(() => {
                handleSelect(languageTag);
              })}
              onClick={() => {
                handleSelect(languageTag);
              }}
            >
              <div className={style.languageName}>{uiLanguageNameMapping[languageTag]}</div>
              <div className={style.languageTag}>{languageTag}</div>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default AddLanguageSelector;
