import React, {useMemo, useState} from 'react';
import {ListRenderItem, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {Menu} from '@components/_HuGo/Menu';
import {Title} from '@components/_HuGo/Title';
import {Pressable} from '@components/_core/Pressable';
import {Typography} from '@components/_core/Typography';
import {StateCard} from '@components/_HuGo/StateCard';
import {useTheme} from '@shared/theme';
import {commonStyles} from '@shared/styles';
import {DEFAULT_THRESHOLD} from '@shared/constants';

import {styles} from './styles';
import {useInputController} from '../../hooks/useInputController';
import {InputCore} from '../InputCore';
import {InputBox} from '../InputBox';
import {
  SingleSelectProps,
  InputSelectOption,
  OnChangeCallback,
  InputSelectControllerProps,
} from '../InputSelect/interfaces';
import {INPUT_ICONS} from '../../constants';

const keyExtractor = <T,>(item: InputSelectOption<T>) => `${item.id}`;

const filterRule = <T,>(item: InputSelectOption<T>, filterText: string) =>
  item.label.toLowerCase().includes(filterText.toLowerCase());

export function InputDropdown<T = number>({
  label,
  helper,
  isError,
  isSuccess,
  disabled,
  filterable,
  searchPlaceholder,
  options,
  onClose,
  onChange,
  placeholder,
  value,
  onEndReached,
  onFilterText,
  ListEmptyComponent,
  formatSelectedItem,
  size,
}: SingleSelectProps<T>) {
  const {t} = useTranslation();
  const {theme, iconSizes} = useTheme();
  const [focused, setFocused] = useState(false);
  const [selectedId, setSelectedId] = useState<Nullable<T>>(
    value !== undefined ? value : null,
  );
  const color = disabled
    ? theme.text.neutral.disabled
    : theme.text.neutral.default;
  const itemSelected = useMemo(
    () => options.find(option => value === option.id),
    [options, value],
  );
  const isSelectedValueNull = selectedId === null;

  const onInputPress = () => {
    setFocused(true);
  };

  const onModalClose = () => {
    setFocused(false);
    itemSelected?.id !== undefined && setSelectedId(itemSelected?.id);
    onClose?.();
  };

  const onItemPress = (id: T) => () => {
    setSelectedId(id);
  };

  const onPressApply = () => {
    onModalClose();
    !isSelectedValueNull && (onChange as OnChangeCallback<T>)?.(selectedId);
  };

  const renderItem: ListRenderItem<InputSelectOption<T>> = ({item}) => (
    <Pressable
      backgroundColor="transparent"
      onPress={onItemPress(item.id)}
      style={styles.item}
      disabled={item.disabled}>
      <View
        style={[
          styles.itemContainer,
          selectedId === item.id && {
            backgroundColor: theme.action.background.neutral.focus.default,
          },
        ]}>
        <Title
          title={item.label}
          description={item.description}
          descriptionNumberOfLines={2}
          size="s"
          style={commonStyles.flex}
        />
      </View>
    </Pressable>
  );

  const Placeholder = (
    <Typography color={theme.text.neutral.lighter}>{placeholder}</Typography>
  );

  const EmptyComponent = ListEmptyComponent || (
    <View style={styles.emptyContainer}>
      <StateCard
        title={t('general.no_results_found.title')}
        description={t('general.no_results_found.description')}
        variant="empty"
      />
    </View>
  );

  return (
    <>
      <InputCore
        label={label}
        helper={helper}
        isSuccess={isSuccess}
        isError={isError}
        focused={focused}
        disabled={disabled}>
        <InputBox
          isSuccess={isSuccess}
          isError={isError}
          disabled={disabled}
          focused={focused}
          size={size}
          onPress={onInputPress}
          RightComponent={
            <INPUT_ICONS.down size={iconSizes.x6} color={color} />
          }>
          <View style={styles.valueContainer}>
            {itemSelected ? (
              <Typography color={color} numberOfLines={1}>
                {formatSelectedItem
                  ? formatSelectedItem(itemSelected)
                  : itemSelected.label}
              </Typography>
            ) : placeholder ? (
              Placeholder
            ) : null}
          </View>
        </InputBox>
      </InputCore>
      <Menu
        data={options}
        isVisible={focused}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
        filterRule={filterRule}
        onFilterText={onFilterText}
        onClose={onModalClose}
        withCloseButton={false}
        useBottomSheetTextInput={false}
        title={placeholder || label}
        filterable={filterable}
        searchPlaceholder={searchPlaceholder}
        onEndReachedThreshold={DEFAULT_THRESHOLD}
        onEndReached={onEndReached}
        ListEmptyComponent={EmptyComponent}
        footer={{
          primaryButton: {
            text: t('general.apply'),
            onPress: onPressApply,
            disabled: isSelectedValueNull,
          },
          secondaryButton: {
            text: t('general.close'),
            onPress: onModalClose,
          },
        }}
      />
    </>
  );
}

export function InputDropdownController<T = number>({
  name,
  showSuccess,
  helper,
  ...props
}: InputSelectControllerProps<T>) {
  const inputController = useInputController({
    name,
    showSuccess,
    helperText: helper,
  });

  const onChange = (value: T) => {
    inputController.onChange(value);
    (props.onChange as OnChangeCallback<T>)?.(value);
  };

  return (
    <InputDropdown<T> {...props} {...inputController} onChange={onChange} />
  );
}
