import React, { useCallback, useEffect, useState } from 'react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import {
  $getSelection,
  $isRangeSelection,
  $isTextNode,
  FORMAT_TEXT_COMMAND,
  UNDO_COMMAND,
  REDO_COMMAND,
  $createParagraphNode,
} from 'lexical';
import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
import {
  INSERT_ORDERED_LIST_COMMAND,
  INSERT_UNORDERED_LIST_COMMAND,
  REMOVE_LIST_COMMAND,
  ListNode,
} from '@lexical/list';
import {
  $createHeadingNode,
  $isHeadingNode,
  type HeadingTagType,
  $createQuoteNode,
  $isQuoteNode,
} from '@lexical/rich-text';
import { $setBlocksType } from '@lexical/selection';
import { $getNearestNodeOfType } from '@lexical/utils';
import BoldIcon from '../../assets/icons/bold.svg?react';
import ItalicIcon from '../../assets/icons/italic.svg?react';
import LinkIcon from '../../assets/icons/link.svg?react';
import BulletedListIcon from '../../assets/icons/bulletedlist.svg?react';
import NumberedListIcon from '../../assets/icons/numberedlist.svg?react';
import UndoIcon from '../../assets/icons/undo.svg?react';
import RedoIcon from '../../assets/icons/redo.svg?react';
import QuoteIcon from '../../assets/icons/blockquote.svg?react';
import RemoveFormatIcon from '../../assets/icons/remove-format.svg?react';
import './TextEditorToolbar.css';

type BlockType = 'paragraph' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'quote';

function TextEditorToolbar() {
  const [editor] = useLexicalComposerContext();
  const [isBold, setIsBold] = useState<boolean>(false);
  const [isItalic, setIsItalic] = useState<boolean>(false);
  const [isLink, setIsLink] = useState<boolean>(false);
  const [isBulletList, setIsBulletList] = useState<boolean>(false);
  const [isNumberedList, setIsNumberedList] = useState<boolean>(false);
  const [blockType, setBlockType] = useState<BlockType>('paragraph');

  const updateToolbar = useCallback(() => {
    const selection = $getSelection();
    if ($isRangeSelection(selection)) {
      setIsBold(selection.hasFormat('bold'));
      setIsItalic(selection.hasFormat('italic'));

      // Check if selection is inside a link
      const node = selection.anchor.getNode();
      const parent = node.getParent();
      setIsLink($isLinkNode(parent) || $isLinkNode(node));

      // Check for list types
      const anchorNode = selection.anchor.getNode();
      const element =
        anchorNode.getKey() === 'root' ? anchorNode : anchorNode.getTopLevelElementOrThrow();
      const elementDOM = editor.getElementByKey(element.getKey());

      if (elementDOM !== null) {
        const listNode = $getNearestNodeOfType(anchorNode, ListNode);
        const type = listNode ? listNode.getListType() : null;
        setIsBulletList(type === 'bullet');
        setIsNumberedList(type === 'number');
      }

      // Check block type.
      if ($isHeadingNode(element)) {
        const tag = element.getTag();
        setBlockType(tag as BlockType);
      } else if ($isQuoteNode(element)) {
        setBlockType('quote');
      } else {
        setBlockType('paragraph');
      }
    }
  }, [editor]);

  useEffect(() => {
    return editor.registerUpdateListener(({ editorState }) => {
      editorState.read(() => {
        updateToolbar();
      });
    });
  }, [editor, updateToolbar]);

  const insertLink = useCallback(() => {
    if (!isLink) {
      const url = prompt('Enter URL:');
      if (url) {
        editor.dispatchCommand(TOGGLE_LINK_COMMAND, url);
      }
    } else {
      editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
    }
  }, [editor, isLink]);

  const formatBulletList = () => {
    if (isBulletList) {
      editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
    } else {
      editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
    }
  };

  const formatNumberedList = () => {
    if (isNumberedList) {
      editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
    } else {
      editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
    }
  };

  const formatBlock = (type: BlockType) => {
    editor.update(() => {
      const selection = $getSelection();
      if ($isRangeSelection(selection)) {
        if (type === 'paragraph') {
          $setBlocksType(selection, () => $createParagraphNode());
        } else if (type === 'quote') {
          $setBlocksType(selection, () => $createQuoteNode());
        } else {
          $setBlocksType(selection, () => $createHeadingNode(type as HeadingTagType));
        }
      }
    });
  };

  const clearFormatting = useCallback(() => {
    editor.update(() => {
      const selection = $getSelection();
      if ($isRangeSelection(selection)) {
        // Remove all text formatting from all selected nodes
        const nodes = selection.getNodes();
        nodes.forEach((node) => {
          if ($isTextNode(node)) {
            node.setFormat(0);
          }
        });

        // Remove links
        nodes.forEach((node) => {
          const parent = node.getParent();
          if ($isLinkNode(parent)) {
            const children = parent.getChildren();
            children.forEach((child) => {
              parent.insertBefore(child);
            });
            parent.remove();
          } else if ($isLinkNode(node)) {
            const children = node.getChildren();
            children.forEach((child) => {
              node.insertBefore(child);
            });
            node.remove();
          }
        });

        // Convert headings and quotes to paragraphs for all selected blocks
        $setBlocksType(selection, () => $createParagraphNode());

        // Remove list formatting for all selected nodes
        const processedLists = new Set<string>();
        nodes.forEach((node) => {
          const listNode = $getNearestNodeOfType(node, ListNode);
          if (listNode && !processedLists.has(listNode.getKey())) {
            processedLists.add(listNode.getKey());
            editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
          }
        });
      }
    });
  }, [editor]);

  return (
    <div className="text-editor-toolbar">
      <button
        onClick={() => editor.dispatchCommand(UNDO_COMMAND, undefined)}
        className="text-editor-toolbar__button"
        type="button"
        title="Undo"
      >
        <UndoIcon />
      </button>
      <button
        onClick={() => editor.dispatchCommand(REDO_COMMAND, undefined)}
        className="text-editor-toolbar__button"
        type="button"
        title="Redo"
      >
        <RedoIcon />
      </button>
      <div className="text-editor-toolbar__divider"></div>
      <select
        value={blockType}
        onChange={(e) => formatBlock(e.target.value as BlockType)}
        className="text-editor-toolbar__select"
        aria-label="Select block formatting"
      >
        <option value="paragraph">Paragraph</option>
        <option value="h1">Heading 1</option>
        <option value="h2">Heading 2</option>
        <option value="h3">Heading 3</option>
        <option value="h4">Heading 4</option>
        <option value="h5">Heading 5</option>
        <option value="h6">Heading 6</option>
        <option value="quote">Quote</option>
      </select>
      <div className="text-editor-toolbar__divider"></div>
      <button
        onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold')}
        className={`text-editor-toolbar__button ${isBold ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Bold"
      >
        <BoldIcon />
      </button>
      <button
        onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic')}
        className={`text-editor-toolbar__button ${isItalic ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Italic"
      >
        <ItalicIcon />
      </button>
      <button
        onClick={insertLink}
        className={`text-editor-toolbar__button ${isLink ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Link"
      >
        <LinkIcon />
      </button>
      <button
        onClick={formatBulletList}
        className={`text-editor-toolbar__button ${isBulletList ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Bulleted List"
      >
        <BulletedListIcon />
      </button>
      <button
        onClick={formatNumberedList}
        className={`text-editor-toolbar__button ${isNumberedList ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Numbered List"
      >
        <NumberedListIcon />
      </button>
      <button
        onClick={() => formatBlock(blockType === 'quote' ? 'paragraph' : 'quote')}
        className={`text-editor-toolbar__button ${blockType === 'quote' ? 'text-editor-toolbar__button--active' : ''}`}
        type="button"
        title="Quote"
      >
        <QuoteIcon />
      </button>
      <button
        onClick={clearFormatting}
        className="text-editor-toolbar__button"
        type="button"
        title="Remove Formatting"
      >
        <RemoveFormatIcon />
      </button>
    </div>
  );
}

export default TextEditorToolbar;
