import { Extension } from "@tiptap/react";
import { Plugin, PluginKey } from "@tiptap/pm/state";
import type { MutableRefObject } from "react";

export function createPageLinkDeletionDetector(
  onPageLinkDeletedRef: MutableRefObject<
    ((pageId: string, redo: () => void) => void) | undefined
  >,
) {
  return Extension.create({
    name: "pageLinkDeletionDetector",
    addStorage() {
      return { skipDetection: false };
    },
    addProseMirrorPlugins() {
      const tiptapEditor = this.editor;
      return [
        new Plugin({
          key: new PluginKey("pageLinkDeletionDetector"),
          appendTransaction(_transactions, oldState, newState) {
            if (oldState.doc.eq(newState.doc)) return null;

            const oldLinks = new Set<string>();
            oldState.doc.descendants((node) => {
              if (node.type.name === "pageLink" && node.attrs.pageId) {
                oldLinks.add(node.attrs.pageId);
              }
            });

            const newLinks = new Set<string>();
            newState.doc.descendants((node) => {
              if (node.type.name === "pageLink" && node.attrs.pageId) {
                newLinks.add(node.attrs.pageId);
              }
            });

            for (const removedPageId of oldLinks) {
              if (!newLinks.has(removedPageId)) {
                // Fire async to avoid dispatching during appendTransaction
                setTimeout(() => {
                  if (
                    tiptapEditor.storage.pageLinkDeletionDetector.skipDetection
                  ) {
                    tiptapEditor.storage.pageLinkDeletionDetector.skipDetection =
                      false;
                    return;
                  }
                  // Undo the deletion immediately so the link reappears
                  tiptapEditor.commands.undo();
                  // Pass a redo function so the caller can re-delete if confirmed
                  onPageLinkDeletedRef.current?.(removedPageId, () => {
                    tiptapEditor.storage.pageLinkDeletionDetector.skipDetection =
                      true;
                    tiptapEditor.commands.redo();
                  });
                }, 0);
              }
            }

            return null;
          },
        }),
      ];
    },
  });
}
