import { useCallback, useEffect, useRef, useState } from 'react';
import { Popover } from '@base-ui/react/popover';
import { Toggle } from '@base-ui/react/toggle';
import { $createLinkNode, $isLinkNode } from '@lexical/link';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $findMatchingParent, mergeRegister } from '@lexical/utils';
import * as stylex from '@stylexjs/stylex';
import {
  $createTextNode,
  $getSelection,
  $insertNodes,
  $isRangeSelection,
  $isTextNode,
  $setSelection,
  CLICK_COMMAND,
  COMMAND_PRIORITY_LOW,
  FORMAT_TEXT_COMMAND,
  SELECTION_CHANGE_COMMAND,
} from 'lexical';

import type { RangeSelection, TextFormatType } from 'lexical';
import type { ReactNode } from 'react';

import { useI18n } from '~/src/lib/i18n';
import { Layout } from '~/src/ui/layouts/layout';
import { Button } from '~/src/ui/primitives/button';
import { BoldGlyph, ItalicGlyph, LinkGlyph, UnderlineGlyph } from '../icons';
import { styles } from '../styles';
import { getSelectedNode, sanitizeUrl } from '../utils';

interface ToolbarPluginProps {
  isDisabled?: boolean;
}

export const ToolbarPlugin = ({ isDisabled }: ToolbarPluginProps) => {
  const [editor] = useLexicalComposerContext();
  const { t } = useI18n();

  const [isBold, setIsBold] = useState(false);
  const [isItalic, setIsItalic] = useState(false);
  const [isUnderline, setIsUnderline] = useState(false);
  const [isLink, setIsLink] = useState(false);
  const [linkUrl, setLinkUrl] = useState('');

  const [isLinkOpen, setIsLinkOpen] = useState(false);
  const [linkDraft, setLinkDraft] = useState('');
  const [textDraft, setTextDraft] = useState('');

  // Display text of the link/selection the toolbar currently reflects, used to
  // prefill the popover's text field.
  const [linkText, setLinkText] = useState('');

  // The link popover (and its input's autoFocus) pulls DOM focus out of the
  // editor, which collapses Lexical's selection to null. Remember the last
  // in-editor range so we can restore it before toggling the link.
  const savedSelection = useRef<RangeSelection | null>(null);

  const updateToolbar = useCallback(() => {
    const selection = $getSelection();
    if (!$isRangeSelection(selection)) return;

    savedSelection.current = selection.clone();

    setIsBold(selection.hasFormat('bold'));
    setIsItalic(selection.hasFormat('italic'));
    setIsUnderline(selection.hasFormat('underline'));

    const node = getSelectedNode(selection);
    const linkNode = $findMatchingParent(node, $isLinkNode);
    if ($isLinkNode(linkNode)) {
      setIsLink(true);
      setLinkUrl(linkNode.getURL());
      setLinkText(linkNode.getTextContent());
    } else {
      setIsLink(false);
      setLinkUrl('');
      setLinkText(selection.getTextContent());
    }
  }, []);

  useEffect(() => {
    return mergeRegister(
      editor.registerUpdateListener(({ editorState }) => {
        editorState.read(updateToolbar);
      }),
      editor.registerCommand(
        SELECTION_CHANGE_COMMAND,
        () => {
          updateToolbar();
          return false;
        },
        COMMAND_PRIORITY_LOW
      ),
      editor.registerCommand(
        CLICK_COMMAND,
        () => {
          const selection = $getSelection();
          if (!$isRangeSelection(selection)) return false;

          const linkNode = $findMatchingParent(
            getSelectedNode(selection),
            $isLinkNode
          );
          if (!$isLinkNode(linkNode)) return false;

          savedSelection.current = selection.clone();
          setLinkDraft(linkNode.getURL());
          setTextDraft(linkNode.getTextContent());
          return true;
        },
        COMMAND_PRIORITY_LOW
      )
    );
  }, [editor, updateToolbar]);

  const formatText = (format: TextFormatType) => {
    editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
  };

  const openLinkEditor = () => {
    setLinkDraft(isLink ? linkUrl : '');
    setTextDraft(linkText);
    setIsLinkOpen(true);
  };

  const applyLink = () => {
    const url = sanitizeUrl(linkDraft);
    if (url) {
      const text = textDraft.trim() || url;

      editor.update(() => {
        const saved = savedSelection.current;
        if ($isRangeSelection(saved)) {
          $setSelection(saved.clone());
        }

        const selection = $getSelection();
        const linkNode = $isRangeSelection(selection)
          ? $findMatchingParent(getSelectedNode(selection), $isLinkNode)
          : null;

        // Editing an existing link: update its URL and display text in place.
        if ($isLinkNode(linkNode)) {
          linkNode.setURL(url);
          const firstChild = linkNode.getFirstChild();
          if ($isTextNode(firstChild)) {
            firstChild.setTextContent(text);
            linkNode
              .getChildren()
              .slice(1)
              .forEach((child) => child.remove());
          }
          return;
        }

        // Inserting a new link: replace the selection with the linked text.
        const newLink = $createLinkNode(url).append($createTextNode(text));
        if ($isRangeSelection(selection)) {
          selection.insertNodes([newLink]);
        } else {
          $insertNodes([newLink]);
        }
      });
    }
    setIsLinkOpen(false);
  };

  const isDraftValid = sanitizeUrl(linkDraft) !== null;

  return (
    <div
      {...stylex.props(styles.toolbar)}
      role="toolbar"
      aria-label="Formatting"
    >
      <FormatToggle
        label="Bold"
        pressed={isBold}
        isDisabled={isDisabled}
        onPressed={() => formatText('bold')}
      >
        <BoldGlyph />
      </FormatToggle>

      <FormatToggle
        label="Italic"
        pressed={isItalic}
        isDisabled={isDisabled}
        onPressed={() => formatText('italic')}
      >
        <ItalicGlyph />
      </FormatToggle>

      <FormatToggle
        label="Underline"
        pressed={isUnderline}
        isDisabled={isDisabled}
        onPressed={() => formatText('underline')}
      >
        <UnderlineGlyph />
      </FormatToggle>

      <Popover.Root open={isLinkOpen} onOpenChange={setIsLinkOpen}>
        <Popover.Trigger
          aria-label="Add link"
          disabled={isDisabled}
          onClick={openLinkEditor}
          {...stylex.props(
            styles.toolbarButton,
            isLink && styles.toolbarButtonActive,
            isDisabled && styles.toolbarButtonDisabled
          )}
        >
          <LinkGlyph />
        </Popover.Trigger>

        <Popover.Portal>
          <Popover.Positioner sideOffset={6} side="bottom" align="start">
            <Popover.Popup {...stylex.props(styles.linkPopup)}>
              <input
                {...stylex.props(styles.linkInput)}
                type="text"
                aria-label="Link text"
                placeholder="Text to display"
                value={textDraft}
                onChange={(event) => setTextDraft(event.target.value)}
                onKeyDown={(event) => {
                  if (event.key === 'Enter' && isDraftValid) {
                    event.preventDefault();
                    applyLink();
                  }
                }}
              />
              <input
                {...stylex.props(styles.linkInput)}
                type="url"
                aria-label="Link URL"
                placeholder="https://example.com"
                value={linkDraft}
                onChange={(event) => setLinkDraft(event.target.value)}
                onKeyDown={(event) => {
                  if (event.key === 'Enter' && isDraftValid) {
                    event.preventDefault();
                    applyLink();
                  }
                }}
              />
              <Layout gap="2" justify="space-between" align="center">
                <Button
                  size="small"
                  variant="text"
                  onClick={() => setIsLinkOpen(false)}
                >
                  {t('app.actions.cancel')}
                </Button>

                <Button
                  size="small"
                  variant="primary"
                  onClick={applyLink}
                  isDisabled={!isDraftValid}
                >
                  {t('app.actions.apply')}
                </Button>
              </Layout>
            </Popover.Popup>
          </Popover.Positioner>
        </Popover.Portal>
      </Popover.Root>
    </div>
  );
};

const FormatToggle = ({
  label,
  pressed,
  isDisabled,
  onPressed,
  children,
}: {
  label: string;
  pressed: boolean;
  isDisabled?: boolean;
  onPressed: () => void;
  children: ReactNode;
}) => (
  <Toggle
    aria-label={label}
    pressed={pressed}
    disabled={isDisabled}
    onPressedChange={onPressed}
    {...stylex.props(
      styles.toolbarButton,
      pressed && styles.toolbarButtonActive,
      isDisabled && styles.toolbarButtonDisabled
    )}
  >
    {children}
  </Toggle>
);
