import { Extension } from "@tiptap/core";
import { PluginKey } from "@tiptap/pm/state";
import Suggestion from "@tiptap/suggestion";
import { createSuggestionRenderer } from "./suggestionRenderer";
import type { SuggestionItem } from "@/components/SuggestionDropdown.vue";

export interface TagSuggestionOptions {
  fetchTags: (query: string) => Promise<string[]>;
}

const tagSuggestionPluginKey = new PluginKey("tagSuggestion");

export const TagSuggestion = Extension.create<TagSuggestionOptions>({
  name: "tagSuggestion",

  addOptions() {
    return {
      fetchTags: async () => [],
    };
  },

  addProseMirrorPlugins() {
    return [
      Suggestion<SuggestionItem>({
        editor: this.editor,
        pluginKey: tagSuggestionPluginKey,
        char: "#",
        allowSpaces: false,
        startOfLine: false,
        allow: ({ state, range }) => {
          // Don't trigger at the start of a text block — the user is
          // likely typing a heading (# / ## / ### …), not a tag.
          const $from = state.doc.resolve(range.from);
          const textBefore = $from.parent.textContent.slice(0, $from.parentOffset);
          if (/^#*$/.test(textBefore)) return false;
          return true;
        },
        items: async ({ query }): Promise<SuggestionItem[]> => {
          try {
            const tags = await this.options.fetchTags(query);
            return tags.slice(0, 8).map((t) => ({
              label: `#${t}`,
              value: t,
            }));
          } catch {
            return [];
          }
        },
        command: ({ editor, range, props: item }) => {
          editor
            .chain()
            .focus()
            .deleteRange(range)
            .insertContent(`#${item.value} `)
            .run();
        },
        render: createSuggestionRenderer,
      }),
    ];
  },
});
