diff --git a/src/CONST.ts b/src/CONST.ts
index 6d81abc37a85..7659f5a18e9e 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1244,7 +1244,7 @@ const CONST = {
         MAX_AMOUNT_OF_SUGGESTIONS: 20,
         MAX_AMOUNT_OF_VISIBLE_SUGGESTIONS_IN_CONTAINER: 5,
         HERE_TEXT: '@here',
-        SUGGESTION_BOX_MAX_SAFE_DISTANCE: 38,
+        SUGGESTION_BOX_MAX_SAFE_DISTANCE: 10,
         BIG_SCREEN_SUGGESTION_WIDTH: 300,
     },
     COMPOSER_MAX_HEIGHT: 125,
diff --git a/src/components/AutoCompleteSuggestions/AutoCompleteSuggestionsPortal/getBottomSuggestionPadding/index.ts b/src/components/AutoCompleteSuggestions/AutoCompleteSuggestionsPortal/getBottomSuggestionPadding/index.ts
index 3ad9bbe7b152..acdc643b6b70 100644
--- a/src/components/AutoCompleteSuggestions/AutoCompleteSuggestionsPortal/getBottomSuggestionPadding/index.ts
+++ b/src/components/AutoCompleteSuggestions/AutoCompleteSuggestionsPortal/getBottomSuggestionPadding/index.ts
@@ -1,5 +1,5 @@
 function getBottomSuggestionPadding(): number {
-    return 0;
+    return 6;
 }
 
 export default getBottomSuggestionPadding;
diff --git a/src/components/AutoCompleteSuggestions/index.tsx b/src/components/AutoCompleteSuggestions/index.tsx
index 8634d6dd0ca0..1aa486eccd4d 100644
--- a/src/components/AutoCompleteSuggestions/index.tsx
+++ b/src/components/AutoCompleteSuggestions/index.tsx
@@ -22,8 +22,16 @@ const measureHeightOfSuggestionRows = (numRows: number, canBeBig: boolean): numb
     }
     return numRows * CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT;
 };
-function isSuggestionRenderedAbove(isEnoughSpaceAboveForBig: boolean, isEnoughSpaceAboveForSmall: boolean): boolean {
-    return isEnoughSpaceAboveForBig || isEnoughSpaceAboveForSmall;
+function isSuggestionMenuRenderedAbove(isEnoughSpaceAboveForBigMenu: boolean, isEnoughSpaceAboveForSmallMenu: boolean): boolean {
+    return isEnoughSpaceAboveForBigMenu || isEnoughSpaceAboveForSmallMenu;
+}
+
+type IsEnoughSpaceToRenderMenuAboveCursor = Pick<MeasureParentContainerAndCursor, 'y' | 'cursorCoordinates' | 'scrollValue'> & {
+    contentHeight: number;
+    topInset: number;
+};
+function isEnoughSpaceToRenderMenuAboveCursor({y, cursorCoordinates, scrollValue, contentHeight, topInset}: IsEnoughSpaceToRenderMenuAboveCursor): boolean {
+    return y + (cursorCoordinates.y - scrollValue) > contentHeight + topInset + CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_BOX_MAX_SAFE_DISTANCE;
 }
 
 /**
@@ -35,7 +43,7 @@ function isSuggestionRenderedAbove(isEnoughSpaceAboveForBig: boolean, isEnoughSp
 function AutoCompleteSuggestions<TSuggestion>({measureParentContainerAndReportCursor = () => {}, ...props}: AutoCompleteSuggestionsProps<TSuggestion>) {
     const containerRef = React.useRef<HTMLDivElement>(null);
     const isInitialRender = React.useRef<boolean>(true);
-    const isSuggestionAboveRef = React.useRef<boolean>(false);
+    const isSuggestionMenuAboveRef = React.useRef<boolean>(false);
     const leftValue = React.useRef<number>(0);
     const prevLeftValue = React.useRef<number>(0);
     const {windowHeight, windowWidth, isSmallScreenWidth} = useWindowDimensions();
@@ -44,11 +52,12 @@ function AutoCompleteSuggestions<TSuggestion>({measureParentContainerAndReportCu
         width: 0,
         left: 0,
         bottom: 0,
+        cursorCoordinates: {x: 0, y: 0},
     });
     const StyleUtils = useStyleUtils();
     const insets = useSafeAreaInsets();
     const {keyboardHeight} = useKeyboardState();
-    const {paddingBottom: bottomInset} = StyleUtils.getSafeAreaPadding(insets ?? undefined);
+    const {paddingBottom: bottomInset, paddingTop: topInset} = StyleUtils.getSafeAreaPadding(insets ?? undefined);
 
     useEffect(() => {
         const container = containerRef.current;
@@ -73,51 +82,51 @@ function AutoCompleteSuggestions<TSuggestion>({measureParentContainerAndReportCu
 
         measureParentContainerAndReportCursor(({x, y, width, scrollValue, cursorCoordinates}: MeasureParentContainerAndCursor) => {
             const xCoordinatesOfCursor = x + cursorCoordinates.x;
-            const leftValueForBigScreen =
+            const bigScreenLeftOffset =
                 xCoordinatesOfCursor + CONST.AUTO_COMPLETE_SUGGESTER.BIG_SCREEN_SUGGESTION_WIDTH > windowWidth
                     ? windowWidth - CONST.AUTO_COMPLETE_SUGGESTER.BIG_SCREEN_SUGGESTION_WIDTH
                     : xCoordinatesOfCursor;
-
-            let bottomValue = windowHeight - y - cursorCoordinates.y + scrollValue - (keyboardHeight || bottomInset);
-            const widthValue = isSmallScreenWidth ? width : CONST.AUTO_COMPLETE_SUGGESTER.BIG_SCREEN_SUGGESTION_WIDTH;
-
             const contentMaxHeight = measureHeightOfSuggestionRows(suggestionsLength, true);
             const contentMinHeight = measureHeightOfSuggestionRows(suggestionsLength, false);
-            const isEnoughSpaceAboveForBig = windowHeight - bottomValue - contentMaxHeight > CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_BOX_MAX_SAFE_DISTANCE;
-            const isEnoughSpaceAboveForSmall = windowHeight - bottomValue - contentMinHeight > CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_BOX_MAX_SAFE_DISTANCE;
+            let bottomValue = windowHeight - (cursorCoordinates.y - scrollValue + y) - keyboardHeight;
+            const widthValue = isSmallScreenWidth ? width : CONST.AUTO_COMPLETE_SUGGESTER.BIG_SCREEN_SUGGESTION_WIDTH;
+
+            const isEnoughSpaceToRenderMenuAboveForBig = isEnoughSpaceToRenderMenuAboveCursor({y, cursorCoordinates, scrollValue, contentHeight: contentMaxHeight, topInset});
+            const isEnoughSpaceToRenderMenuAboveForSmall = isEnoughSpaceToRenderMenuAboveCursor({y, cursorCoordinates, scrollValue, contentHeight: contentMinHeight, topInset});
 
-            const newLeftValue = isSmallScreenWidth ? x : leftValueForBigScreen;
+            const newLeftOffset = isSmallScreenWidth ? x : bigScreenLeftOffset;
             // If the suggested word is longer than 150 (approximately half the width of the suggestion popup), then adjust a new position of popup
-            const isAdjustmentNeeded = Math.abs(prevLeftValue.current - leftValueForBigScreen) > 150;
+            const isAdjustmentNeeded = Math.abs(prevLeftValue.current - bigScreenLeftOffset) > 150;
             if (isInitialRender.current || isAdjustmentNeeded) {
-                isSuggestionAboveRef.current = isSuggestionRenderedAbove(isEnoughSpaceAboveForBig, isEnoughSpaceAboveForSmall);
-                leftValue.current = newLeftValue;
+                isSuggestionMenuAboveRef.current = isSuggestionMenuRenderedAbove(isEnoughSpaceToRenderMenuAboveForBig, isEnoughSpaceToRenderMenuAboveForSmall);
+                leftValue.current = newLeftOffset;
                 isInitialRender.current = false;
-                prevLeftValue.current = newLeftValue;
+                prevLeftValue.current = newLeftOffset;
             }
 
             let measuredHeight = 0;
-            if (isSuggestionAboveRef.current && isEnoughSpaceAboveForBig) {
+            if (isSuggestionMenuAboveRef.current && isEnoughSpaceToRenderMenuAboveForBig) {
                 // calculation for big suggestion box above the cursor
                 measuredHeight = measureHeightOfSuggestionRows(suggestionsLength, true);
-            } else if (isSuggestionAboveRef.current && isEnoughSpaceAboveForSmall) {
+            } else if (isSuggestionMenuAboveRef.current && isEnoughSpaceToRenderMenuAboveForSmall) {
                 // calculation for small suggestion box above the cursor
                 measuredHeight = measureHeightOfSuggestionRows(suggestionsLength, false);
             } else {
                 // calculation for big suggestion box below the cursor
                 measuredHeight = measureHeightOfSuggestionRows(suggestionsLength, true);
-                bottomValue = windowHeight - y - cursorCoordinates.y + scrollValue - measuredHeight - CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT;
+                bottomValue = windowHeight - y - cursorCoordinates.y + scrollValue - measuredHeight - CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT - keyboardHeight;
             }
             setSuggestionHeight(measuredHeight);
             setContainerState({
                 left: leftValue.current,
                 bottom: bottomValue,
                 width: widthValue,
+                cursorCoordinates,
             });
         });
-    }, [measureParentContainerAndReportCursor, windowHeight, windowWidth, keyboardHeight, isSmallScreenWidth, suggestionsLength, bottomInset]);
+    }, [measureParentContainerAndReportCursor, windowHeight, windowWidth, keyboardHeight, isSmallScreenWidth, suggestionsLength, bottomInset, topInset]);
 
-    if (containerState.width === 0 && containerState.left === 0 && containerState.bottom === 0) {
+    if ((containerState.width === 0 && containerState.left === 0 && containerState.bottom === 0) || (containerState.cursorCoordinates.x === 0 && containerState.cursorCoordinates.y === 0)) {
         return null;
     }
     return (
diff --git a/src/libs/focusComposerWithDelay/types.ts b/src/libs/focusComposerWithDelay/types.ts
index 4cd2f785f2bc..97a1298e8c7a 100644
--- a/src/libs/focusComposerWithDelay/types.ts
+++ b/src/libs/focusComposerWithDelay/types.ts
@@ -3,6 +3,8 @@ import type {TextInput} from 'react-native';
 type Selection = {
     start: number;
     end: number;
+    positionX?: number;
+    positionY?: number;
 };
 
 type FocusComposerWithDelay = (shouldDelay?: boolean, forcedSelectionRange?: Selection) => void;
diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
index 6cc55c825983..46abfba93bf5 100644
--- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
+++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx
@@ -748,6 +748,8 @@ function ComposerWithSuggestions(
     }, []);
 
     useEffect(() => {
+        // We use the tag to store the native ID of the text input. Later, we use it in onSelectionChange to pick up the proper text input data.
+
         tag.value = findNodeHandle(textInputRef.current) ?? -1;
         // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
     }, []);
diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx
index bf82a28dd48a..9fede8068e64 100644
--- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx
+++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx
@@ -60,6 +60,7 @@ type SuggestionsRef = {
     updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu?: boolean) => void;
     setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void;
     getSuggestions: () => Mention[] | Emoji[];
+    getIsSuggestionsMenuVisible: () => boolean;
 };
 
 type ReportActionComposeOnyxProps = {
diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx
index 9b04fd7df4dc..8d5a544afd42 100644
--- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx
+++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx
@@ -150,7 +150,7 @@ function SuggestionEmoji(
      */
     const calculateEmojiSuggestion = useCallback(
         (selectionStart?: number, selectionEnd?: number) => {
-            if (selectionStart !== selectionEnd || !selectionEnd || shouldBlockCalc.current || !value) {
+            if (selectionStart !== selectionEnd || !selectionEnd || shouldBlockCalc.current || !value || (selectionStart === 0 && selectionEnd === 0)) {
                 shouldBlockCalc.current = false;
                 resetSuggestions();
                 return;
@@ -181,6 +181,7 @@ function SuggestionEmoji(
         if (!isComposerFocused) {
             return;
         }
+
         calculateEmojiSuggestion(selection.start, selection.end);
     }, [selection, calculateEmojiSuggestion, isComposerFocused]);
 
@@ -193,6 +194,8 @@ function SuggestionEmoji(
 
     const getSuggestions = useCallback(() => suggestionValues.suggestedEmojis, [suggestionValues]);
 
+    const getIsSuggestionsMenuVisible = useCallback(() => isEmojiSuggestionsMenuVisible, [isEmojiSuggestionsMenuVisible]);
+
     useImperativeHandle(
         ref,
         () => ({
@@ -201,8 +204,9 @@ function SuggestionEmoji(
             setShouldBlockSuggestionCalc,
             updateShouldShowSuggestionMenuToFalse,
             getSuggestions,
+            getIsSuggestionsMenuVisible,
         }),
-        [resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions],
+        [resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions, getIsSuggestionsMenuVisible],
     );
 
     if (!isEmojiSuggestionsMenuVisible) {
diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx
index 129c8c822d74..86a05bad1994 100644
--- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx
+++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx
@@ -408,6 +408,7 @@ function SuggestionMention(
     );
 
     const getSuggestions = useCallback(() => suggestionValues.suggestedMentions, [suggestionValues]);
+    const getIsSuggestionsMenuVisible = useCallback(() => isMentionSuggestionsMenuVisible, [isMentionSuggestionsMenuVisible]);
 
     useImperativeHandle(
         ref,
@@ -417,8 +418,9 @@ function SuggestionMention(
             setShouldBlockSuggestionCalc,
             updateShouldShowSuggestionMenuToFalse,
             getSuggestions,
+            getIsSuggestionsMenuVisible,
         }),
-        [resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions],
+        [resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions, getIsSuggestionsMenuVisible],
     );
 
     if (!isMentionSuggestionsMenuVisible) {
diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.tsx b/src/pages/home/report/ReportActionCompose/Suggestions.tsx
index f82b38c3e154..158c60b0e89a 100644
--- a/src/pages/home/report/ReportActionCompose/Suggestions.tsx
+++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx
@@ -124,6 +124,11 @@ function Suggestions(
         suggestionEmojiRef.current?.setShouldBlockSuggestionCalc(shouldBlock);
         suggestionMentionRef.current?.setShouldBlockSuggestionCalc(shouldBlock);
     }, []);
+    const getIsSuggestionsMenuVisible = useCallback((): boolean => {
+        const isEmojiVisible = suggestionEmojiRef.current?.getIsSuggestionsMenuVisible() ?? false;
+        const isSuggestionVisible = suggestionMentionRef.current?.getIsSuggestionsMenuVisible() ?? false;
+        return isEmojiVisible || isSuggestionVisible;
+    }, []);
 
     useImperativeHandle(
         ref,
@@ -134,8 +139,9 @@ function Suggestions(
             updateShouldShowSuggestionMenuToFalse,
             setShouldBlockSuggestionCalc,
             getSuggestions,
+            getIsSuggestionsMenuVisible,
         }),
-        [onSelectionChange, resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions],
+        [onSelectionChange, resetSuggestions, setShouldBlockSuggestionCalc, triggerHotkeyActions, updateShouldShowSuggestionMenuToFalse, getSuggestions, getIsSuggestionsMenuVisible],
     );
 
     useEffect(() => {
diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx
index 6618b20a5a6a..40e9a4c6bf41 100644
--- a/src/pages/home/report/ReportActionItemMessageEdit.tsx
+++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx
@@ -1,11 +1,15 @@
 import lodashDebounce from 'lodash/debounce';
 import type {ForwardedRef} from 'react';
 import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react';
-import type {NativeSyntheticEvent, TextInput, TextInputFocusEventData, TextInputKeyPressEventData} from 'react-native';
-import {InteractionManager, Keyboard, View} from 'react-native';
+import {findNodeHandle, InteractionManager, Keyboard, View} from 'react-native';
+import type {MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInput, TextInputFocusEventData, TextInputKeyPressEventData, TextInputScrollEventData} from 'react-native';
+import {useFocusedInputHandler} from 'react-native-keyboard-controller';
 import {useOnyx} from 'react-native-onyx';
+import {useSharedValue} from 'react-native-reanimated';
 import type {Emoji} from '@assets/emojis/types';
+import type {MeasureParentContainerAndCursorCallback} from '@components/AutoCompleteSuggestions/types';
 import Composer from '@components/Composer';
+import type {TextSelection} from '@components/Composer/types';
 import EmojiPickerButton from '@components/EmojiPicker/EmojiPickerButton';
 import ExceededCommentLength from '@components/ExceededCommentLength';
 import Icon from '@components/Icon';
@@ -42,6 +46,10 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type * as OnyxTypes from '@src/types/onyx';
 import * as ReportActionContextMenu from './ContextMenu/ReportActionContextMenu';
+import getCursorPosition from './ReportActionCompose/getCursorPosition';
+import getScrollPosition from './ReportActionCompose/getScrollPosition';
+import type {SuggestionsRef} from './ReportActionCompose/ReportActionCompose';
+import Suggestions from './ReportActionCompose/Suggestions';
 import shouldUseEmojiPickerSelection from './shouldUseEmojiPickerSelection';
 
 type ReportActionItemMessageEditProps = {
@@ -81,12 +89,17 @@ function ReportActionItemMessageEdit(
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
+    const containerRef = useRef<View>(null);
     const reportScrollManager = useReportScrollManager();
     const {translate, preferredLocale} = useLocalize();
     const {isKeyboardShown} = useKeyboardState();
     const {isSmallScreenWidth} = useWindowDimensions();
     const prevDraftMessage = usePrevious(draftMessage);
-
+    const suggestionsRef = useRef<SuggestionsRef>(null);
+    const mobileInputScrollPosition = useRef(0);
+    const cursorPositionValue = useSharedValue({x: 0, y: 0});
+    const tag = useSharedValue(-1);
+    const isInitialMount = useRef(true);
     const emojisPresentBefore = useRef<Emoji[]>([]);
     const [draft, setDraft] = useState(() => {
         if (draftMessage) {
@@ -94,7 +107,7 @@ function ReportActionItemMessageEdit(
         }
         return draftMessage;
     });
-    const [selection, setSelection] = useState<Selection>({start: draft.length, end: draft.length});
+    const [selection, setSelection] = useState<TextSelection>({start: draft.length, end: draft.length, positionX: 0, positionY: 0});
     const [isFocused, setIsFocused] = useState<boolean>(false);
     const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength();
     const [modal, setModal] = useState<OnyxTypes.Modal>({
@@ -123,11 +136,6 @@ function ReportActionItemMessageEdit(
         setDraft(draftMessage);
     }, [draftMessage, action, prevDraftMessage]);
 
-    useEffect(() => {
-        // required for keeping last state of isFocused variable
-        isFocusedRef.current = isFocused;
-    }, [isFocused]);
-
     useEffect(() => {
         InputFocus.composerFocusKeepFocusOn(textInputRef.current as HTMLElement, isFocused, modal, onyxFocused);
     }, [isFocused, modal, onyxFocused]);
@@ -165,25 +173,32 @@ function ReportActionItemMessageEdit(
     );
 
     useEffect(
-        () => () => {
-            InputFocus.callback(() => setIsFocused(false));
-            InputFocus.inputFocusChange(false);
-
-            // Skip if the current report action is not active
-            if (!isActive()) {
+        () => {
+            if (isInitialMount.current) {
+                isInitialMount.current = false;
                 return;
             }
 
-            if (EmojiPickerAction.isActive(action.reportActionID)) {
-                EmojiPickerAction.clearActive();
-            }
-            if (ReportActionContextMenu.isActiveReportAction(action.reportActionID)) {
-                ReportActionContextMenu.clearActiveReportAction();
-            }
+            return () => {
+                InputFocus.callback(() => setIsFocused(false));
+                InputFocus.inputFocusChange(false);
 
-            // Show the main composer when the focused message is deleted from another client
-            // to prevent the main composer stays hidden until we swtich to another chat.
-            setShouldShowComposeInputKeyboardAware(true);
+                // Skip if the current report action is not active
+                if (!isActive()) {
+                    return;
+                }
+
+                if (EmojiPickerAction.isActive(action.reportActionID)) {
+                    EmojiPickerAction.clearActive();
+                }
+                if (ReportActionContextMenu.isActiveReportAction(action.reportActionID)) {
+                    ReportActionContextMenu.clearActiveReportAction();
+                }
+
+                // Show the main composer when the focused message is deleted from another client
+                // to prevent the main composer stays hidden until we swtich to another chat.
+                setShouldShowComposeInputKeyboardAware(true);
+            };
         },
         // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- this cleanup needs to be called only on unmount
         [action.reportActionID],
@@ -248,10 +263,12 @@ function ReportActionItemMessageEdit(
             setDraft(newDraft);
 
             if (newDraftInput !== newDraft) {
-                const position = Math.max(selection.end + (newDraft.length - draftRef.current.length), cursorPosition ?? 0);
+                const position = Math.max((selection?.end ?? 0) + (newDraft.length - draftRef.current.length), cursorPosition ?? 0);
                 setSelection({
                     start: position,
                     end: position,
+                    positionX: 0,
+                    positionY: 0,
                 });
             }
 
@@ -318,6 +335,8 @@ function ReportActionItemMessageEdit(
         const newSelection = {
             start: selection.start + emoji.length + CONST.SPACE_LENGTH,
             end: selection.start + emoji.length + CONST.SPACE_LENGTH,
+            positionX: 0,
+            positionY: 0,
         };
         setSelection(newSelection);
 
@@ -329,6 +348,21 @@ function ReportActionItemMessageEdit(
         updateDraft(ComposerUtils.insertText(draft, selection, `${emoji} `));
     };
 
+    const hideSuggestionMenu = useCallback(() => {
+        if (!suggestionsRef.current) {
+            return;
+        }
+        suggestionsRef.current.updateShouldShowSuggestionMenuToFalse(false);
+    }, [suggestionsRef]);
+    const onSaveScrollAndHideSuggestionMenu = useCallback(
+        (e: NativeSyntheticEvent<TextInputScrollEventData>) => {
+            mobileInputScrollPosition.current = e?.nativeEvent?.contentOffset?.y ?? 0;
+
+            hideSuggestionMenu();
+        },
+        [hideSuggestionMenu],
+    );
+
     /**
      * Key event handlers that short cut to saving/canceling.
      *
@@ -340,6 +374,17 @@ function ReportActionItemMessageEdit(
                 return;
             }
             const keyEvent = e as KeyboardEvent;
+            const isSuggestionsMenuVisible = suggestionsRef.current?.getIsSuggestionsMenuVisible();
+
+            if (isSuggestionsMenuVisible && keyEvent.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) {
+                suggestionsRef.current?.triggerHotkeyActions(keyEvent);
+                return;
+            }
+            if (keyEvent.key === CONST.KEYBOARD_SHORTCUTS.ESCAPE.shortcutKey && isSuggestionsMenuVisible) {
+                e.preventDefault();
+                hideSuggestionMenu();
+                return;
+            }
             if (keyEvent.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey && !keyEvent.shiftKey) {
                 e.preventDefault();
                 publishDraft();
@@ -348,7 +393,59 @@ function ReportActionItemMessageEdit(
                 deleteDraft();
             }
         },
-        [deleteDraft, isKeyboardShown, isSmallScreenWidth, publishDraft],
+        [deleteDraft, hideSuggestionMenu, isKeyboardShown, isSmallScreenWidth, publishDraft],
+    );
+
+    const measureContainer = useCallback(
+        (callback: MeasureInWindowOnSuccessCallback) => {
+            if (!containerRef.current) {
+                return;
+            }
+            containerRef.current.measureInWindow(callback);
+        },
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
+        [isFocused],
+    );
+
+    const measureParentContainerAndReportCursor = useCallback(
+        (callback: MeasureParentContainerAndCursorCallback) => {
+            const {scrollValue} = getScrollPosition({mobileInputScrollPosition, textInputRef});
+            const {x: xPosition, y: yPosition} = getCursorPosition({positionOnMobile: cursorPositionValue.value, positionOnWeb: selection});
+            measureContainer((x, y, width, height) => {
+                callback({
+                    x,
+                    y,
+                    width,
+                    height,
+                    scrollValue,
+                    cursorCoordinates: {x: xPosition, y: yPosition},
+                });
+            });
+        },
+        [cursorPositionValue.value, measureContainer, selection],
+    );
+
+    useEffect(() => {
+        // We use the tag to store the native ID of the text input. Later, we use it in onSelectionChange to pick up the proper text input data.
+
+        // eslint-disable-next-line react-compiler/react-compiler
+        tag.value = findNodeHandle(textInputRef.current) ?? -1;
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
+    }, []);
+    useFocusedInputHandler(
+        {
+            onSelectionChange: (event) => {
+                'worklet';
+
+                if (event.target === tag.value) {
+                    cursorPositionValue.value = {
+                        x: event.selection.end.x,
+                        y: event.selection.end.y,
+                    };
+                }
+            },
+        },
+        [],
     );
 
     /**
@@ -360,9 +457,21 @@ function ReportActionItemMessageEdit(
         validateCommentMaxLength(draft, {reportID});
     }, [draft, reportID, validateCommentMaxLength]);
 
+    useEffect(() => {
+        // required for keeping last state of isFocused variable
+        isFocusedRef.current = isFocused;
+
+        if (!isFocused) {
+            hideSuggestionMenu();
+        }
+    }, [isFocused, hideSuggestionMenu]);
+
     return (
         <>
-            <View style={[styles.chatItemMessage, styles.flexRow]}>
+            <View
+                style={[styles.chatItemMessage, styles.flexRow]}
+                ref={containerRef}
+            >
                 <View
                     style={[
                         isFocused ? styles.chatItemComposeBoxFocusedColor : styles.chatItemComposeBoxColor,
@@ -440,8 +549,23 @@ function ReportActionItemMessageEdit(
                             selection={selection}
                             onSelectionChange={(e) => setSelection(e.nativeEvent.selection)}
                             isGroupPolicyReport={isGroupPolicyReport}
+                            shouldCalculateCaretPosition
+                            onScroll={onSaveScrollAndHideSuggestionMenu}
                         />
                     </View>
+
+                    <Suggestions
+                        ref={suggestionsRef}
+                        isComposerFocused={textInputRef.current?.isFocused()}
+                        updateComment={updateDraft}
+                        measureParentContainerAndReportCursor={measureParentContainerAndReportCursor}
+                        isGroupPolicyReport={false}
+                        value={draft}
+                        setValue={setDraft}
+                        selection={selection}
+                        setSelection={setSelection}
+                    />
+
                     <View style={styles.editChatItemEmojiWrapper}>
                         <EmojiPickerButton
                             isDisabled={shouldDisableEmojiPicker}
