import styled from '@emotion/styled';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { useMutation } from '@tanstack/react-query';
import {
  $createRangeSelection,
  $getRoot,
  $getSelection,
  $isRangeSelection,
  $setSelection,
  BLUR_COMMAND,
  CAN_REDO_COMMAND,
  CAN_UNDO_COMMAND,
  COMMAND_PRIORITY_LOW,
  FOCUS_COMMAND,
  REDO_COMMAND,
  RangeSelection,
  TextNode,
  UNDO_COMMAND,
} from 'lexical';
import { observer } from 'mobx-react-lite';
import {
  ComponentProps,
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react';
import { useLocalStorage } from 'usehooks-ts';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import useRegenerateLyrics from '@/hooks/useRegenerateLyrics';
import { EditUndoIcon, FourStarIcon, TrashIcon } from '@/icons';
import logWebUserEvent, {
  TransactionLogger,
  createTransactionLogger,
} from '@/logging/logWebUserEvent';
import ctrlStr from '@/utils/ctrlStr';

import LyricsModelSelector, {
  cowriteLyricsModelOptions,
} from '../select/LyricsModelSelector';
import SpinnerSVG from '../svg/SpinnerSVG';
import TextareaV2 from '../textarea/TextareaV2';
import { Tooltip } from '../tooltip/Tooltip';
import $findNodeAndOffsetAtCharacterPosition from './$findNodeAndOffsetAtCharacterPosition';
import LexicalTextarea, { initialConfig } from './LexicalTextarea';
import OverscrollFade from './OverscrollFade';
import SelectionFollower, {
  updateAfterSelectionChange,
} from './SelectionFollower';

const SubtleInput = styled.input`
  padding: 3px 0 8px 0;
  border: none;
  background-color: inherit;
  color: inherit;
  width: 100%;
  border-bottom: 1px solid rgb(var(--rgb-foreground-tertiary));
  &:focus {
    outline: none;
  }
`;

const TitleInput = styled(SubtleInput)`
  font-family: PP Editorial New;
  font-size: 32px;
  flex-grow: 0;
  margin: 0;
  position: relative;
  padding-bottom: 0;
  z-index: 2;
`;

const Wrapper = styled.div`
  display: grid;
  grid-template-columns: 255px 1fr;
  height: 100%;
  min-height: 0;
`;

const Sidebar = styled.div`
  position: relative;
`;

const EditorWrapper = styled.div<{ hideSelection?: boolean }>`
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 0;
  overflow: hidden;
  p,
  span {
    ::selection {
      transition: background-color 0.2s ease;
      background-color: ${({ hideSelection }) =>
        hideSelection ? 'transparent' : 'rgb(var(--rgb-accent-pink) / 0.4)'};
    }
  }
  &:before {
    content: '';
    display: block;
    background-color: inherit;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 64px;
    z-index: 2;
  }
`;

const PromptInputWrapper = styled.div`
  display: flex;
  flex-direction: column;
  align-items: stretch;
  border: none;
  border-radius: 5px;
  background-color: rgb(var(--rgb-background-secondary));
  min-height: 80px;
  padding: 10px;
  input {
    margin-bottom: 8px;
  }
  box-shadow: -8px 0px 24px 12px rgb(var(--rgb-foreground-primary) / 0.01);
`;

const EmptyMessage = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;x
  top: 0;
  bottom: 60px;
  left: 0;
  right: 0;
  padding: 0 40px;
  opacity: 25%;
  text-align: center;
`;

const SubmitWrapper = styled.div`
  grid-row: 3 / 4;
  display: flex;
  align-items: center;
  justify-content: center;
  > * {
    height: 100%;
  }
`;

const blockMouseDown = (e: MouseEvent) => {
  e.stopPropagation();
  e.preventDefault();
};

const InfoText = styled.div`
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  padding: 10px;
  color: rgb(var(--rgb-foreground-tertiary));
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
`;

const writeHerePrompts = [
  'Write a verse about a dog',
  'Write a thoughtful chorus',
  'Add four lines about wind',
  'Gimme something catchy',
  'Get spooky',
];

const rewritePrompts = [
  'Make this wittier',
  'Make this rhyme',
  'Shorten this, 3 words max',
  'Make this more emotional',
  'Make this less literal',
];

const LyricsCowriteEditorInternal = observer(
  ({
    content,
    onSubmit,
  }: {
    content: { title: string; lyrics: string };
    onSubmit: (title: string, lyrics: string) => void;
  }) => {
    const { genForm } = useStores();
    const [editor] = useLexicalComposerContext();
    const [canUndo, setCanUndo] = useState(false);
    const [canRedo, setCanRedo] = useState(false);
    const [lastSelection, setLastSelection] = useState<RangeSelection | null>(
      null
    );
    const [selectionEmpty, setSelectionEmpty] = useState(false);
    const [isFocused, setIsFocused] = useState(false);

    useEffect(() => {
      editor.update(() => {
        $getRoot().clear();
        $getRoot().selectStart();
        const selection = $getSelection();
        selection?.insertRawText(content.lyrics);
        $getRoot().selectStart();
      });
    }, [editor, content.lyrics]);

    const selectionFollowerRef = useRef<HTMLDivElement>(null);

    const onSelectionUpdate = useCallback(
      (rect: DOMRect, scrollTop: number) => {
        updateAfterSelectionChange(rect, selectionFollowerRef, scrollTop);
        editor?.read(() => setLastSelection($getSelection() as RangeSelection));
      },
      [editor]
    );

    const regenerateLyricsMutationFunction = useRegenerateLyrics();

    const unlockEditor = useCallback(() => {
      editor?.setEditable(true);
      editor
        ?.getRootElement()
        ?.removeEventListener('mousedown', blockMouseDown);
    }, [editor]);

    const lockEditor = useCallback(() => {
      editor?.setEditable(false);
      editor?.getRootElement()?.addEventListener('mousedown', blockMouseDown);
    }, [editor]);
    const [lastLyricsContentAndInfillId, setLastLyricsContentAndInfillId] =
      useState<{ content: string; id: string; requestId: string } | null>(null);

    const abortControllerRef = useRef<AbortController | null>(null);
    const regenerateLyrics = useMutation({
      mutationFn: useCallback(
        (payload: {
          title: string;
          prompt: string;
          prefix: string;
          suffix: string;
          edit: string;
          infillTransactionLogger: TransactionLogger;
        }) => {
          abortControllerRef.current = new AbortController();
          setIsFocused(false);
          lockEditor();
          return regenerateLyricsMutationFunction(payload);
        },
        [editor, regenerateLyricsMutationFunction]
      ),
      onSuccess: async (
        { replacedText, lyricsId, lyricsRequestId },
        { prefix, edit, infillTransactionLogger }
      ) => {
        unlockEditor();

        if (abortControllerRef.current?.signal.aborted) {
          return;
        }
        if (!editor) return;

        editor.update(() => {
          let selection = $getSelection() || lastSelection;

          if (!selection) {
            $getRoot().selectEnd();
            selection = $getSelection();
          }

          if (selection) {
            $setSelection(selection.clone());
            $getSelection()!.insertRawText(replacedText);

            infillTransactionLogger.logWebUserEvent({
              actionName: 'LyricsCowriteEditorInfillInserted',
              principalObjectType: 'lyrics_request',
              principalObjectValue: lyricsRequestId,
              context: {
                generateInstanceToken: genForm.createSessionToken,
                generatedLyrics: replacedText,
                lyricsId,
              },
            });

            const replacedTextLength = replacedText.length;
            const prefixLength = prefix.length;
            const intersectionStart = $findNodeAndOffsetAtCharacterPosition(
              $getRoot(),
              edit.length ? prefixLength : prefixLength + replacedTextLength
            );
            const intersectionEnd = $findNodeAndOffsetAtCharacterPosition(
              $getRoot(),
              prefixLength + replacedTextLength
            );
            if (intersectionStart && intersectionEnd) {
              const newSelection = $createRangeSelection();
              newSelection.setTextNodeRange(
                intersectionStart.node,
                intersectionStart.offset,
                intersectionEnd.node,
                intersectionEnd.offset
              );
              $setSelection(newSelection);
            }
            setLastLyricsContentAndInfillId({
              content: $getRoot().getTextContent(),
              id: lyricsId,
              requestId: lyricsRequestId,
            });
          } else {
            infillTransactionLogger.logWebUserEvent({
              actionName: 'LyricsCowriteEditorInfillNotInserted',
              principalObjectType: 'lyrics_request',
              principalObjectValue: lyricsRequestId,
              context: {
                reason: 'Selection could not be created',
                generateInstanceToken: genForm.createSessionToken,
                generatedLyrics: replacedText,
                lyricsId,
              },
            });
          }
          setTimeout(() => editor.focus(), 100);
          setIsFocused(true);
        });
      },
      onError: (error: Error) => {
        unlockEditor();
        console.error(error);
      },
    });

    const [prompt, setPrompt] = useState('');
    const [title, setTitle] = useState(content.title);
    useEffect(() => setTitle(content.title), [content.title]);

    const handleWriteHere = useCallback(
      (infillTransactionLogger: TransactionLogger) => {
        if (!editor) return;
        editor.update(() => {
          let selection: RangeSelection = ($getSelection() ||
            lastSelection) as RangeSelection;
          if (!$isRangeSelection(selection)) {
            $getRoot().selectEnd();
            selection = $getSelection() as RangeSelection;
          }
          const startPoint = selection.anchor.isBefore(selection.focus)
            ? selection.anchor
            : selection.focus;

          const prefixSelection = $createRangeSelection();
          prefixSelection.setTextNodeRange(
            $getRoot().getFirstChild()!,
            0,
            startPoint.getNode() as TextNode,
            startPoint.offset
          );
          const suffixSelection = $createRangeSelection();
          suffixSelection.setTextNodeRange(
            startPoint.getNode() as TextNode,
            startPoint.offset,
            $getRoot().getLastChild()!,
            $getRoot().getLastChild()!.getTextContentSize()
          );
          const prefix = prefixSelection.getTextContent();
          const suffix = suffixSelection.getTextContent();

          regenerateLyrics.mutate({
            title,
            prompt,
            prefix,
            edit: '',
            suffix,
            infillTransactionLogger,
          });
        });
      },
      [editor, regenerateLyrics, title, prompt, lastSelection]
    );

    const handleRewrite = useCallback(
      (infillTransactionLogger: TransactionLogger) => {
        if (!editor) return;
        editor.update(() => {
          const selection = $getSelection();
          if ($isRangeSelection(selection)) {
            const edit = selection.getTextContent();

            const startPoint = selection.anchor.isBefore(selection.focus)
              ? selection.anchor
              : selection.focus;

            const endPoint = selection.anchor.isBefore(selection.focus)
              ? selection.focus
              : selection.anchor;

            const prefixSelection = $createRangeSelection();
            prefixSelection.setTextNodeRange(
              $getRoot().getFirstChild()!,
              0,
              startPoint.getNode() as TextNode,
              startPoint.offset
            );
            const suffixSelection = $createRangeSelection();
            suffixSelection.setTextNodeRange(
              endPoint.getNode() as TextNode,
              endPoint.offset,
              $getRoot().getLastChild()!,
              $getRoot().getLastChild()!.getTextContentSize()
            );
            const prefix = prefixSelection.getTextContent();
            const suffix = suffixSelection.getTextContent();

            regenerateLyrics.mutate({
              prompt,
              prefix,
              edit,
              suffix,
              title,
              infillTransactionLogger,
            });
          } else {
            console.error('Invalid selection');
          }
        });
      },
      [editor, regenerateLyrics, prompt, title, lastSelection]
    );

    const handleEditorMouseDown = useCallback(() => {
      const selectionFollower = selectionFollowerRef.current;
      if (!selectionFollower) return;

      selectionFollower.style.pointerEvents = 'none';
      const handleMouseUp = () => {
        selectionFollower.style.pointerEvents = '';
        window.removeEventListener('mouseup', handleMouseUp);
      };
      window.addEventListener('mouseup', handleMouseUp);
    }, []);

    const cowriteUIVisible = !!editor;
    useEffect(() => {
      const unregisterCallbacks = [
        editor.registerCommand(
          CAN_UNDO_COMMAND,
          (canUndo: boolean) => {
            setCanUndo(canUndo);
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
        editor.registerCommand(
          CAN_REDO_COMMAND,
          (canRedo: boolean) => {
            setCanRedo(canRedo);
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
        editor.registerCommand(
          BLUR_COMMAND,
          () => {
            setIsFocused(false);
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
        editor.registerCommand(
          FOCUS_COMMAND,
          () => {
            setIsFocused(true);
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
        editor.registerUpdateListener(() => {
          editor.read(() => {
            const selection = $getSelection();
            if (!$isRangeSelection(selection)) {
              setSelectionEmpty(true);
              return;
            }
            const startEndPoints = selection?.getStartEndPoints();

            if (
              startEndPoints?.[0].getNode().__key ===
                startEndPoints?.[1].getNode().__key &&
              startEndPoints?.[0].offset === startEndPoints?.[1].offset
            ) {
              setSelectionEmpty(true);
            } else {
              setSelectionEmpty(false);
            }
          });
        }),
      ];
      return () => {
        unregisterCallbacks.forEach((unregister) => unregister());
      };
    }, [editor]);

    useEffect(() => {
      const unregisterCallbacks = [
        editor.registerCommand(
          UNDO_COMMAND,
          (_, editor) => {
            editor.read(() => {
              if (
                $getRoot().getTextContent() ===
                  lastLyricsContentAndInfillId?.content &&
                lastLyricsContentAndInfillId?.id
              ) {
                genForm.apiClient.POST('/api/generate/lyrics-infill/undo', {
                  body: {
                    lyrics_id: lastLyricsContentAndInfillId?.id,
                  },
                });
                logWebUserEvent({
                  actionName: 'LyricsCowriteEditorUndo',
                  principalObjectType: 'lyrics_request',
                  principalObjectValue: lastLyricsContentAndInfillId!.requestId,
                  context: {
                    undidGeneratedInfill: true,
                    generateInstanceToken: genForm.createSessionToken,
                  },
                });
              } else {
                logWebUserEvent({
                  actionName: 'LyricsCowriteEditorUndo',
                  context: {
                    undidGeneratedInfill: false,
                    generateInstanceToken: genForm.createSessionToken,
                  },
                });
              }
            });
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
        editor.registerCommand(
          REDO_COMMAND,
          (_, editor) => {
            // this needs to run after the update is applied,
            // so, we register an update listener that nukes itself as soon as it is run
            const deregister = editor.registerUpdateListener(() => {
              setTimeout(() => {
                editor.read(() => {
                  if (
                    $getRoot().getTextContent() ===
                      lastLyricsContentAndInfillId?.content &&
                    lastLyricsContentAndInfillId?.id
                  ) {
                    genForm.apiClient.POST('/api/generate/lyrics-infill/redo', {
                      body: {
                        lyrics_id: lastLyricsContentAndInfillId?.id,
                      },
                    });
                    logWebUserEvent({
                      actionName: 'LyricsCowriteEditorRedo',
                      principalObjectType: 'lyrics_request',
                      principalObjectValue:
                        lastLyricsContentAndInfillId!.requestId,
                      context: {
                        redidGeneratedInfill: true,
                        generateInstanceToken: genForm.createSessionToken,
                      },
                    });
                  } else {
                    logWebUserEvent({
                      actionName: 'LyricsCowriteEditorRedo',
                      context: {
                        redidGeneratedInfill: false,
                        generateInstanceToken: genForm.createSessionToken,
                      },
                    });
                  }
                });
              });
              deregister();
            });
            return false;
          },
          COMMAND_PRIORITY_LOW
        ),
      ];
      return () => {
        unregisterCallbacks.forEach((unregister) => unregister());
      };
    }, [editor, lastLyricsContentAndInfillId]);

    const [hasDismissedInfo, setHasDismissedInfo] = useLocalStorage(
      'lyrics-cowrite-info-dismissed-01-27-2025-v2',
      false
    );

    const [promptInputPlaceholder, setPromptInputPlaceholder] =
      useState('Enter a prompt');

    useEffect(() => {
      if (selectionEmpty) {
        setPromptInputPlaceholder(
          writeHerePrompts[Math.floor(Math.random() * writeHerePrompts.length)]
        );
      } else {
        setPromptInputPlaceholder(
          rewritePrompts[Math.floor(Math.random() * rewritePrompts.length)]
        );
      }
    }, [selectionEmpty]);

    const handleUndo = useCallback(() => {
      editor.dispatchCommand(UNDO_COMMAND, undefined);
    }, [editor, lastLyricsContentAndInfillId]);

    const handleRedo = useCallback(() => {
      editor.dispatchCommand(REDO_COMMAND, undefined);
    }, [editor, lastLyricsContentAndInfillId]);

    return (
      <Wrapper>
        <Sidebar className='bg-background-tertiary'>
          {!hasDismissedInfo && (
            <InfoText>
              <p>Click &ldquo;Write&nbsp;Here&rdquo; to insert lyrics.</p>
              <p>
                When lyrics are selected, the button changes to
                &ldquo;Rewrite&rdquo;.
              </p>
              <Button
                size={ButtonSize.Mini}
                className='opacity-50'
                onClick={() => setHasDismissedInfo(true)}
              >
                Ok, got it
              </Button>
            </InfoText>
          )}
          <SelectionFollower
            ref={selectionFollowerRef}
            emphasizeSelection={!isFocused}
            obscureSelection={regenerateLyrics.isPending}
          >
            {cowriteUIVisible && (
              <PromptInputWrapper>
                <TextareaV2
                  className='border-0 bg-transparent px-0'
                  textAreaClassName='bg-transparent px-0 py-0 mb-3'
                  placeholder={`"${promptInputPlaceholder}"`}
                  autoFocus
                  value={prompt}
                  rows={1}
                  maxLength={256}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && !regenerateLyrics.isPending) {
                      e.preventDefault();
                      const infillTransactionLogger = createTransactionLogger();
                      if (selectionEmpty) {
                        infillTransactionLogger.logWebUserEvent({
                          actionName: 'LyricsCowriteEditorWriteHere',
                          context: {
                            prompt: prompt,
                            generateInstanceToken: genForm.createSessionToken,
                          },
                        });

                        handleWriteHere(infillTransactionLogger);
                      } else {
                        editor.read(() => {
                          infillTransactionLogger.logWebUserEvent({
                            actionName: 'LyricsCowriteEditorRewrite',
                            context: {
                              prompt: prompt,
                              selectedText:
                                $getSelection()?.getTextContent() || '',
                              generateInstanceToken: genForm.createSessionToken,
                            },
                          });
                        });
                        handleRewrite(infillTransactionLogger);
                      }
                    } else if (e.key === 'z' && (e.ctrlKey || e.metaKey)) {
                      if (e.shiftKey) {
                        handleRedo();
                      } else {
                        handleUndo();
                      }
                      e.preventDefault();
                    } else if (e.key === 'y' && (e.ctrlKey || e.metaKey)) {
                      handleRedo();
                      e.preventDefault();
                    }
                  }}
                  onChange={(e) => setPrompt(e.currentTarget.value)}
                />
                <div className='flex items-stretch justify-stretch'>
                  {prompt.length > 0 && !regenerateLyrics.isPending && (
                    <Tooltip label='Clear prompt'>
                      <Button
                        tabIndex={-1}
                        size={ButtonSize.Mini}
                        variant={ButtonVariant.Tertiary}
                        className='flex items-center bg-foreground-primary/10 px-2'
                        icon={TrashIcon}
                        onClick={() => {
                          setPrompt('');
                          logWebUserEvent({
                            actionName:
                              'LyricsCowriteEditorClearPromptButtonClicked',
                            context: {
                              generateInstanceToken: genForm.createSessionToken,
                            },
                          });
                        }}
                      />
                    </Tooltip>
                  )}
                  {regenerateLyrics.isPending && (
                    <Button
                      tabIndex={-1}
                      size={ButtonSize.Mini}
                      variant={ButtonVariant.Tertiary}
                      className='flex items-center bg-foreground-primary/10 px-2'
                      onClick={() => {
                        unlockEditor();
                        abortControllerRef.current?.abort();
                        regenerateLyrics.reset();
                        logWebUserEvent({
                          actionName:
                            'LyricsCowriteEditorCancelInfillButtonClicked',
                          context: {
                            generateInstanceToken: genForm.createSessionToken,
                          },
                        });
                      }}
                    >
                      Cancel
                    </Button>
                  )}
                  <div className='grow' />
                  <Button
                    disabled={regenerateLyrics.isPending}
                    tabIndex={-1}
                    size={ButtonSize.Mini}
                    variant={ButtonVariant.Standard}
                    className='h-8'
                    icon={
                      regenerateLyrics.isPending ? (
                        <SpinnerSVG />
                      ) : (
                        <FourStarIcon className='h-3 w-3 text-accent-pink' />
                      )
                    }
                    onClick={() => {
                      const infillTransactionLogger = createTransactionLogger();
                      if (selectionEmpty) {
                        editor.read(() => {
                          infillTransactionLogger.logWebUserEvent({
                            actionName: 'LyricsCowriteEditorWriteHere',
                            context: {
                              prompt: prompt,
                              generateInstanceToken: genForm.createSessionToken,
                            },
                          });
                        });
                        handleWriteHere(infillTransactionLogger);
                      } else {
                        editor.read(() => {
                          infillTransactionLogger.logWebUserEvent({
                            actionName: 'LyricsCowriteEditorRewrite',
                            context: {
                              prompt: prompt,
                              selectedText:
                                $getSelection()?.getTextContent() || '',
                              generateInstanceToken: genForm.createSessionToken,
                            },
                          });
                        });
                        handleRewrite(infillTransactionLogger);
                      }
                    }}
                  >
                    {regenerateLyrics.isPending
                      ? 'Writing...'
                      : selectionEmpty
                        ? 'Write Here'
                        : 'Rewrite'}
                  </Button>
                </div>
              </PromptInputWrapper>
            )}
          </SelectionFollower>
          {!cowriteUIVisible && (
            <EmptyMessage>Select some lyrics to write with Suno</EmptyMessage>
          )}
          <OverscrollFade
            above={true}
            height={10}
            fadeHeight={30}
            color='rgb(var(--rgb-background-tertiary))'
          />
          <OverscrollFade
            above={false}
            height={80}
            fadeHeight={30}
            color='rgb(var(--rgb-background-tertiary))'
          />
          <LyricsModelSelector
            className='absolute right-3 bottom-3 left-3'
            value={'classic'}
            onSetValue={() => {}}
            options={cowriteLyricsModelOptions}
          />
        </Sidebar>
        <EditorWrapper
          className='bg-background-secondary p-3'
          hideSelection={!isFocused}
          onMouseDown={handleEditorMouseDown}
        >
          <TitleInput
            value={title}
            onChange={(e) => setTitle(e.currentTarget.value)}
            placeholder='Add a song title'
          />
          <LexicalTextarea onSelectionUpdate={onSelectionUpdate} />

          <SubmitWrapper>
            <Button
              className='mr-2'
              shape={ButtonShape.Pill}
              variant={ButtonVariant.Secondary}
              onClick={() => {
                if (editor)
                  editor.read(() => {
                    const textContent = $getRoot().getTextContent();
                    onSubmit(title, textContent);
                  });
                logWebUserEvent({
                  actionName: 'LyricsCowriteEditorSaveChangesClicked',
                  context: {
                    generateInstanceToken: genForm.createSessionToken,
                  },
                });
              }}
            >
              Save Changes
            </Button>
            <Tooltip label={`Undo Change (${ctrlStr} Z)`}>
              <Button
                shape={ButtonShape.Pill}
                variant={ButtonVariant.Tertiary}
                disabled={!canUndo}
                onClick={() => {
                  handleUndo();
                }}
              >
                <EditUndoIcon />
              </Button>
            </Tooltip>
            <Tooltip label={`Redo change (${ctrlStr} Shift Z)`}>
              <Button
                shape={ButtonShape.Pill}
                variant={ButtonVariant.Tertiary}
                disabled={!canRedo}
                onClick={() => {
                  handleRedo();
                }}
              >
                <EditUndoIcon style={{ transform: 'scaleX(-1)' }} />
              </Button>
            </Tooltip>
          </SubmitWrapper>
        </EditorWrapper>
      </Wrapper>
    );
  }
);

const LyricsCowriteEditor = (
  props: ComponentProps<typeof LyricsCowriteEditorInternal>
) => {
  return (
    <LexicalComposer initialConfig={initialConfig}>
      <LyricsCowriteEditorInternal {...props} />
    </LexicalComposer>
  );
};

export default LyricsCowriteEditor;
