import { useMemo } from 'react';

import type { SelectProps } from '~/src/components/Select2';
import type { FC } from 'react';

import { getTimezoneOffset } from '~/lib/utils/date';
import locales from '~/locales/fragments/timezonePicker';
import { useI18nStatic } from '~/src/lib/i18n';
import { useSelector } from '~/src/store/redux';
import { selectUserLanguage } from '~/src/store/session/selectors';
import { FastSelectOption, Select } from '../Select2';

export interface TimezonePickerProps
  extends Omit<
    SelectProps,
    | 'testId'
    | 'width'
    | 'placeholder'
    | 'value'
    | 'renderOption'
    | 'options'
    | 'searchFeature'
  > {
  testId?: string;
  date?: string;
}

export const TimezonePicker: FC<TimezonePickerProps> = ({
  testId = 'timezonePicker',
  date,
  ...selectProps
}) => {
  const { t } = useI18nStatic<'timezonePicker'>(locales);
  const language = useSelector(selectUserLanguage);

  const options = useMemo(() => {
    const timezoneOptions = getTimezones(
      date ? new Date(date) : new Date(),
      language
    ).map(({ timezone, timezoneName }) => {
      const formattedTimezone = timezone.replaceAll(/_/g, ' ');

      return {
        id: timezone,
        text: `(${timezoneName}) ${formattedTimezone}`,
      };
    });

    return timezoneOptions;
  }, [language, date]);

  return (
    <Select
      {...selectProps}
      testId={testId}
      width="100%"
      placeholder={t('placeholder')}
      options={options}
      renderOption={(props) => <FastSelectOption {...props} />}
      searchFeature={{ type: 'search' }}
    />
  );
};

const getTimezoneName = (
  dateOffset: Date,
  timezone: string,
  locale: string = 'en-US'
): string | undefined => {
  const formatter = new Intl.DateTimeFormat(locale, {
    timeZone: timezone,
    timeZoneName: 'shortOffset',
  });

  const timeZonePart = formatter
    .formatToParts(dateOffset)
    .find(({ type }) => type === 'timeZoneName');

  return timeZonePart?.value;
};

const getTimezones = (dateOffset: Date, locale: string = 'en-US') => {
  const timeZones = Intl.supportedValuesOf('timeZone');

  const formattedTimezones = timeZones
    .flatMap((timezone) => {
      const timezoneName = getTimezoneName(dateOffset, timezone, locale);
      const offset = getTimezoneOffset(dateOffset, timezone);

      return timezoneName ? [{ timezoneName, timezone, offset }] : [];
    })
    .sort((a, b) => a.offset - b.offset);

  return formattedTimezones;
};
