import React, {
  createContext,
  useContext,
  useMemo,
  useState,
  ReactNode,
  useEffect,
  useRef,
} from 'react';
import debounce from 'lodash.debounce';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {TaggedUser} from '@interfaces/taggedUsers';

import {useInputValue} from './InputValueContext';
import {CHAT_FOOTER_HEIGHT} from '../constants';

// Context state interface
interface MentionsState {
  isDialogVisible: boolean;
  searchText: string;
  tags: TaggedUser[];
  tagUserStartPosition: number;
  messageBodyWithoutLastTag: string;
  chatFooterHeight: number;
}

// Context actions interface
interface MentionsActions {
  setIsDialogVisible: (visible: boolean) => void;
  setSearchText: (text: string) => void;
  addTag: (tag: TaggedUser) => void;
  setInitialTags: (params: {
    tags: TaggedUser[];
    tagUserStartPosition: number;
    messageBodyWithoutLastTag: string;
  }) => void;
  changeTagPosition: (
    userId: number,
    newStartPosition: number,
    currentStartPosition?: number,
  ) => void;
  removeTag: (userId: number, taggedUser?: TaggedUser) => void;
  setTagUserStartPosition: (position: number) => void;
  setMessageBodyWithoutLastTag: (message: string) => void;
  resetMentions: () => void;
  setChatFooterHeight: (height: number) => void;
}

// Combined context value
interface MentionsContextValue extends MentionsState, MentionsActions {}

// Initial state
const INITIAL_STATE: MentionsState = {
  isDialogVisible: false,
  searchText: '',
  tags: [],
  tagUserStartPosition: 0,
  messageBodyWithoutLastTag: '',
  chatFooterHeight: CHAT_FOOTER_HEIGHT,
};

// Create context
const MentionsContext = createContext<MentionsContextValue | undefined>(
  undefined,
);

// Provider props interface
interface MentionsProviderProps {
  children: ReactNode;
}

// Provider component
export const MentionsProvider: React.FC<MentionsProviderProps> = ({
  children,
}) => {
  const {bottom} = useSafeAreaInsets();
  const [state, setState] = useState<MentionsState>({
    ...INITIAL_STATE,
    chatFooterHeight: CHAT_FOOTER_HEIGHT + bottom,
  });
  const [inputValue] = useInputValue();
  const shouldClear = inputValue?.length === 0;

  // Memoized actions to prevent unnecessary re-renders
  const actions = useMemo<MentionsActions>(
    () => ({
      setIsDialogVisible: (visible: boolean) => {
        setState(prev => ({...prev, isDialogVisible: visible}));
      },

      setSearchText: (text: string) => {
        setState(prev => ({...prev, searchText: text}));
      },

      addTag: (tag: TaggedUser) => {
        setState(prev => ({...prev, tags: [...prev.tags, tag]}));
      },

      setInitialTags: ({
        tags,
        tagUserStartPosition,
        messageBodyWithoutLastTag,
      }) => {
        setState(prev => ({
          ...prev,
          tags,
          tagUserStartPosition,
          messageBodyWithoutLastTag,
        }));
      },

      removeTag: (userId: number, taggedUser?: TaggedUser) => {
        setState(prev => ({
          ...prev,
          tags: prev.tags.filter(user => {
            return taggedUser
              ? user.start !== taggedUser.start
              : user.type.user.id !== userId;
          }),
        }));
      },

      changeTagPosition: (
        userId: number,
        newStartPosition: number,
        currentStartPosition?: number,
      ) => {
        setState(prev => ({
          ...prev,
          tags: prev.tags.map(tag =>
            tag.type.user.id === userId &&
            (currentStartPosition === undefined ||
              tag.start === currentStartPosition)
              ? {...tag, start: newStartPosition}
              : tag,
          ),
        }));
      },

      setTagUserStartPosition: (position: number) => {
        setState(prev => ({...prev, tagUserStartPosition: position}));
      },

      setMessageBodyWithoutLastTag: (message: string) => {
        setState(prev => ({...prev, messageBodyWithoutLastTag: message}));
      },
      resetMentions: () => {
        setState(s => ({
          ...INITIAL_STATE,
          // Use current chatFooter height set up by (onLayout)
          chatFooterHeight: s.chatFooterHeight,
        }));
      },

      setChatFooterHeight: (height: number) => {
        setState(prev =>
          prev.chatFooterHeight === height
            ? prev
            : {...prev, chatFooterHeight: height},
        );
      },
    }),
    [],
  );

  const setChatFooterHeight = useRef(
    debounce(actions.setChatFooterHeight, 100),
  );

  // Memoized context value to prevent unnecessary re-renders
  const contextValue = useMemo<MentionsContextValue>(
    () => ({
      ...state,
      ...actions,
      setChatFooterHeight: setChatFooterHeight.current,
    }),
    [state, actions],
  );

  const isMounted = useRef(false);

  /**
   * Clear mentions state when input value is empty.
   * Skip on first mount — shouldClear is already true for empty input,
   * which would immediately overwrite the correct initial state.
   */
  useEffect(() => {
    if (!isMounted.current) {
      isMounted.current = true;
      return;
    }
    if (shouldClear) {
      actions.resetMentions();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [shouldClear]);

  return (
    <MentionsContext.Provider value={contextValue}>
      {children}
    </MentionsContext.Provider>
  );
};

// Custom hook to use the context
export const useMentions = (): MentionsContextValue => {
  const context = useContext(MentionsContext);

  if (context === undefined) {
    throw new Error('useMentions must be used within a MentionsProvider');
  }

  return context;
};

// Export context for advanced usage
export {MentionsContext};
