import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import debounce from 'lodash.debounce';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useShallow} from 'zustand/shallow';
import {useKeyboardController} from 'react-native-keyboard-controller';
import {useNavigation} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import {Button, InputSearch, TextInputType} from '@components';
import {useMessagesSearch} from '@modules/chats/store';
import {RootStackParamList} from '@navigation/interfaces';

import {styles} from './styles';

export function ChatMessagesSearchBar({channel}: {channel: string}) {
  const {t} = useTranslation();
  const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
  const [searchText, setSearchText] = useState('');
  const {initSearch, cleanup} = useMessagesSearch(
    useShallow(state => ({
      initSearch: state.initSearch,
      cleanup: state.cleanup,
    })),
  );
  const {top} = useSafeAreaInsets();
  const inputRef = useRef<TextInputType>(null);
  const keyboardController = useKeyboardController();
  const navigaitonListenerRef = useRef<Nullable<() => void>>(null);
  const [isReadyToFocus, setIsReadyToFocus] = useState(false);

  const searchWithDebounce = useMemo(
    () =>
      debounce((text: string) => {
        initSearch(channel, text);
      }, 300),
    [initSearch, channel],
  );

  // Fixes an issue-> when closing the keyboard this is triggered with the same text
  const prevTextRef = useRef(searchText);

  const onChangeSearchText = useCallback(
    (text: string) => {
      // Skip if the text is the same
      if (text === prevTextRef.current) {
        return;
      }
      setSearchText(text);
      searchWithDebounce(text);
      prevTextRef.current = text;
    },
    [searchWithDebounce],
  );

  /**
   * Set navigation listener
   */
  useEffect(() => {
    if (navigaitonListenerRef.current === null) {
      navigaitonListenerRef.current = navigation.addListener(
        'transitionEnd',
        () => {
          setIsReadyToFocus(true);
        },
      );
    }

    return () => {
      navigaitonListenerRef.current?.();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  /**
   * Focus search input when keyboard contrller is enabled & navigation transition ends
   * This is necessary to avoid a UI glitch
   */
  useEffect(() => {
    if (keyboardController.enabled && isReadyToFocus) {
      inputRef.current?.focus();
    }
  }, [keyboardController.enabled, isReadyToFocus]);

  useEffect(() => {
    return () => {
      searchWithDebounce.cancel();
    };
  }, [searchWithDebounce]);

  return (
    <View style={[styles.container, {marginTop: top}]}>
      <InputSearch
        ref={inputRef}
        allowFontScaling={false}
        value={searchText}
        onChangeText={onChangeSearchText}
        placeholder={t('general.search')}
        autoCorrect={false}
        variant="custom"
        style={styles.input}
        blurOnClear={false}
        submitBehavior={'submit'}
      />
      <Button variant="tertiary" text={t('general.cancel')} onPress={cleanup} />
    </View>
  );
}
