import React, {useEffect, useRef, useState} from 'react';
import {
  Keyboard,
  StyleSheet,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';
import {shallowEqual, useDispatch} from 'react-redux';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from '@components/Icon';
import {clearEditMessage} from '@modules/chat/redux';
import {useSendMessage, useTypingIndicator} from '@modules/chat/hooks';
import {CHAT_INPUT_HEIGHT} from '@modules/chat/constants';
import {useAppSelector} from '@redux/utils';
import {commonStyles} from '@shared/styles';
import {isIos} from '@shared/utils';
import {COLORS} from '@shared/colors';
import {BORDER_RADIUS, SPACING} from '@shared/theme';

import GifDisplayer from './components/GifDisplayer';

interface Props {
  onAddAttachmentPress: () => void;
  initialMessage?: string;
}

export function ChatTextInput({onAddAttachmentPress, initialMessage}: Props) {
  const {bottom} = useSafeAreaInsets();
  const dispatch = useDispatch();
  const inputRef = useRef<TextInput>(null);
  const [message, setMessage] = useState(initialMessage || '');
  const {sendTextMessage, sendGifMessage} = useSendMessage();
  const {allowAttachments, editMessage, replyMessageIdSelected, currentChatId} =
    useAppSelector(
      ({instance, chats}) => ({
        allowAttachments: instance.allowAttachmentsInChats,
        editMessage: chats.currentChat.editMessage,
        replyMessageIdSelected: chats.currentChat.replyMessage?.id,
        currentChatId: chats.currentChat.chatId,
      }),
      shallowEqual,
    );
  const {startTyping, stopTyping} = useTypingIndicator({chatId: currentChatId});
  const showSendButton = message.trim().length;

  const onSendPress = () => {
    stopTyping();
    sendTextMessage(message.trim());
    inputRef.current?.clear();
    setMessage('');
  };

  const onAddPress = () => {
    Keyboard.dismiss();
    onAddAttachmentPress();
  };

  const onEditCancel = () => {
    setMessage('');
    Keyboard.dismiss();
    dispatch(clearEditMessage());
  };

  const onChangeText = (newValue: string) => {
    setMessage(newValue);

    if (newValue.trim()) {
      startTyping();
    } else {
      stopTyping();
    }
  };

  const onBlur = () => stopTyping();

  /**
   * Effect to handle edit message
   */
  useEffect(() => {
    if (editMessage) {
      editMessage.text && setMessage(editMessage.text);
      inputRef.current?.focus();
    }
  }, [editMessage]);

  /**
   * Effect to focus input when a reply box exists
   */
  useEffect(() => {
    if (replyMessageIdSelected) {
      inputRef.current?.focus();
    }
  }, [replyMessageIdSelected]);

  /**
   * Effect to handle initial message from route params
   */
  useEffect(() => {
    if (initialMessage) {
      inputRef.current?.focus();
    }
  }, [initialMessage]);

  return (
    <View style={[styles.container, !!bottom && {paddingBottom: bottom}]}>
      {editMessage ? (
        <TouchableOpacity onPress={onEditCancel} hitSlop={SPACING.x1}>
          <Icon name="cancel" />
        </TouchableOpacity>
      ) : allowAttachments ? (
        <TouchableOpacity onPress={onAddPress} hitSlop={SPACING.x1}>
          <Icon name="add" color={COLORS.PRIMARY} />
        </TouchableOpacity>
      ) : (
        <View style={styles.emptyBox} />
      )}
      <View style={styles.middleContainer}>
        <View style={styles.inputContainer}>
          <TextInput
            ref={inputRef}
            value={message}
            onChangeText={onChangeText}
            onBlur={onBlur}
            scrollEnabled
            returnKeyType="default"
            multiline
            style={styles.input}
          />
          {!message.length && allowAttachments && (
            <GifDisplayer onSelect={sendGifMessage} color={COLORS.PRIMARY} />
          )}
        </View>
        {showSendButton ? (
          <TouchableOpacity onPress={onSendPress} hitSlop={SPACING.x1}>
            <Icon name="send" color={COLORS.PRIMARY} />
          </TouchableOpacity>
        ) : (
          <Icon name="send" color={COLORS.GRAY_FOUR} />
        )}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: COLORS.WHITE,
    minHeight: CHAT_INPUT_HEIGHT,
    paddingHorizontal: SPACING.x2,
    paddingVertical: SPACING.x1,
    flexDirection: 'row',
    alignItems: 'center',
    gap: SPACING.x1,
  },
  middleContainer: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    gap: SPACING.x1,
  },
  inputContainer: {
    alignItems: 'center',
    backgroundColor: COLORS.WHITE,
    borderColor: COLORS.GRAY_FOUR,
    borderRadius: BORDER_RADIUS.l,
    borderWidth: 0.5,
    flexDirection: 'row',
    flexGrow: 1,
    flexShrink: 1,
    paddingHorizontal: SPACING['x1.5'],
    paddingVertical: SPACING.x1,
  },
  input: {
    ...commonStyles.mainFontFamily,
    alignSelf: 'center',
    flex: 1,
    maxHeight: 100,
    paddingBottom: isIos ? SPACING['x0.5'] : 0,
    textAlignVertical: 'top',
  },
  emptyBox: {width: SPACING.x3, height: '100%'},
  sendButton: {
    width: SPACING.x4,
    height: SPACING.x4,
    borderRadius: SPACING.x2,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: COLORS.PRIMARY,
  },
});
