import { ReactRenderer } from '@tiptap/react';
import type { SuggestionOptions } from '@tiptap/suggestion';
import { MentionList, type MentionListRef } from './MentionList';
import type { MentionItem, MentionConfig } from './types';

export function createMentionSuggestion(
  config: MentionConfig,
): Omit<SuggestionOptions<MentionItem>, 'editor'> {
  const { maxItems = 5, trigger = '@' } = config;

  return {
    char: trigger,

    items: ({ query }) => {
      const q = query.toLowerCase();
      return config.items
        .filter((item) => item.label.toLowerCase().includes(q))
        .slice(0, maxItems);
    },

    render: () => {
      let component: ReactRenderer<MentionListRef> | null = null;
      let popup: HTMLDivElement | null = null;

      return {
        onStart: (props) => {
          component = new ReactRenderer(MentionList, {
            props: {
              items: props.items,
              command: (item: MentionItem) => {
                props.command({ id: item.id, label: item.label });
              },
            },
            editor: props.editor,
          });

          popup = document.createElement('div');
          popup.style.cssText = 'position: absolute; z-index: 99999;';
          popup.appendChild(component.element);

          const rect = props.clientRect?.();
          if (rect) {
            popup.style.top = `${rect.bottom + window.scrollY + 4}px`;
            popup.style.left = `${rect.left + window.scrollX}px`;
          }

          document.body.appendChild(popup);
        },

        onUpdate: (props) => {
          component?.updateProps({
            items: props.items,
            command: (item: MentionItem) => {
              props.command({ id: item.id, label: item.label });
            },
          });

          const rect = props.clientRect?.();
          if (rect && popup) {
            popup.style.top = `${rect.bottom + window.scrollY + 4}px`;
            popup.style.left = `${rect.left + window.scrollX}px`;
          }
        },

        onKeyDown: (props) => {
          if (props.event.key === 'Escape') {
            popup?.remove();
            component?.destroy();
            return true;
          }
          return component?.ref?.onKeyDown(props.event as unknown as React.KeyboardEvent) ?? false;
        },

        onExit: () => {
          popup?.remove();
          component?.destroy();
        },
      };
    },
  };
}
