import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { TextAutoTooltip } from '../../../../components/Text/TextAutoTooltip';
import { COUNTRIES_NAMES } from '../../../../constans/contryNames';
import { COUNTRIES_PHONE_CODES } from '../../../../constans/countriesPhoneCodes';
import { ALL_COUNTRIES, Country } from '../../../../constans/country';
import { useTranslation } from '../../../../core/hooks/useTranslation';
import { TestIdProps } from '../../../../types';
import { assertEmptyObject } from '../../../../utils/assertEmptyObject';
import { makeTestId } from '../../../../utils/makeTestId';
import { SelectFieldProps } from '../../../SelectField/SelectField';
import { CountryOption } from '../../types';

import { FlagTrigger } from './FlagTrigger/FlagTrigger';
import {
  StyledCountryChoseSelectContainer,
  StyledOptionCode,
  TunedCountrySelect,
  TunedOptionFlag,
} from './styled';

const optionComponent: SelectFieldProps<CountryOption>['optionComponent'] = {
  renderer: (props) => {
    return (
      <>
        <TunedOptionFlag country={props.option.value} />
        <TextAutoTooltip>{props.option.label}</TextAutoTooltip>
        <StyledOptionCode>{COUNTRIES_PHONE_CODES[props.option.value]}</StyledOptionCode>
      </>
    );
  },
  height: 32,
};

export interface CountryChoseSelectProps extends TestIdProps {
  /** Selected country */
  country?: Country;
  /** If `true` then component should be disabled */
  disabled: boolean;
  /** Function that will be invoked when user selects some country option */
  countryClick: (country: Country) => void;
}

/**
 * Special selector that allow to select phone country.
 *
 * This is internal component of {@link PhoneField} component.
 */
export function CountryChoseSelect(props: CountryChoseSelectProps) {
  const { country, disabled, countryClick, testId, ...rest } = props;
  assertEmptyObject(rest);

  const { t } = useTranslation();
  const refCountrySelector = useRef<HTMLDivElement>(null);
  const [countrySelectWidth, setcountrySelectWidth] = useState(0);

  const translatedCountries = useMemo(() => {
    return ALL_COUNTRIES.map((value) => ({ value, label: t(COUNTRIES_NAMES[value]) }));
  }, [t]);

  const handleChange = useCallback(
    (selected: Country | null) => {
      /* istanbul ignore next */
      if (selected === null) {
        throw new Error("The country can't be null");
      }

      countryClick(selected);
    },
    [countryClick],
  );

  useEffect(() => {
    const countrySelectorObserver = new ResizeObserver((entries) => {
      if (refCountrySelector.current) {
        for (const entry of entries) {
          setcountrySelectWidth(entry.contentRect.width);
        }
      }
    });

    if (refCountrySelector.current) {
      countrySelectorObserver.observe(refCountrySelector.current);
    }

    return () => countrySelectorObserver.disconnect();
  }, []);

  return (
    <StyledCountryChoseSelectContainer ref={refCountrySelector}>
      <TunedCountrySelect
        disabled={disabled}
        noOptionsMessage={t('ui.phoneField.noCountries')}
        onChange={handleChange}
        optionComponent={optionComponent}
        optionComponentWidth={countrySelectWidth}
        options={translatedCountries}
        testId={testId}
        trigger={<FlagTrigger country={country} testId={makeTestId(testId, 'trigger')} />}
        value={country}
        optionToSearchString={(option) =>
          `${option.value} ${option.label} ${COUNTRIES_PHONE_CODES[option.value]}`
        }
      />
    </StyledCountryChoseSelectContainer>
  );
}
