import { mergeAttributes, Node } from "@tiptap/core";
import { ReactNodeViewRenderer } from "@tiptap/react";
import { LinkPreviewComponent } from "./link-preview-component";

export interface LinkPreviewOptions {
  HTMLAttributes: {
    [key: string]: any;
  };
  fetchMetadata?: (
    url: string,
  ) => Promise<{ title?: string; description?: string; cover?: string }>;
}

declare module "@tiptap/core" {
  interface Commands<ReturnType> {
    linkPreview: {
      /**
       * Add an linkPreview
       */

      createLinkPreview: () => ReturnType;
    };
  }
}

export default Node.create<LinkPreviewOptions>({
  name: "linkPreview",

  group: "block",

  atom: true,

  // content: "block+",

  addOptions() {
    return {
      HTMLAttributes: {
        class: "link-preview-wrapper",
      },
      fetchMetadata: async (url) => {
        // Default: Simple metadata fetch (Override this via `configure()`)
        return {
          title: "Placeholder Title",
          description:
            "You need to provide a custom `fetchMetadata` function You need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` functionYou need to provide a custom `fetchMetadata` function",
          cover: "",
        };
      },
    };
  },

  addAttributes() {
    return {
      href: {
        default: null,
        parseHTML(element) {
          return element.getAttribute("href");
        },
      },
      title: {
        default: null,
        parseHTML(element) {
          return element?.firstChild?.childNodes?.[0]?.childNodes?.[0]
            ?.nodeValue;
        },
        renderHTML() {
          return;
        },
      },
      description: {
        default: null,
        parseHTML(element) {
          return element?.firstChild?.childNodes?.[1]?.childNodes?.[0]
            ?.nodeValue;
        },
        renderHTML() {
          return;
        },
      },
      image: {
        default: null,
        parseHTML(element) {
          // @ts-ignore
          return element.childNodes[1].src;
        },
        renderHTML() {
          return;
        },
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: `div[data-type="${this.name}"]`,
        priority: 1000,
      },
    ];
  },

  renderHTML({ HTMLAttributes }) {
    return ["div", mergeAttributes({ "data-type": this.name }, HTMLAttributes)];
  },
  addNodeView() {
    return ReactNodeViewRenderer(LinkPreviewComponent);
  },
  addPasteRules() {
    return [
      {
        find: /(https?:\/\/[^\s]+)/g,
        handler: ({ match, state, range }) => {
          const url = match[0];

          // Replace the pasted URL with the link preview node
          state.tr.replaceWith(
            range.from,
            range.to,
            this.type.create({ href: url }),
          );
        },
      },
    ];
  },
  addCommands() {
    return {
      createLinkPreview:
        () =>
        ({ chain }) => {
          return chain()
            .insertContent({
              type: "linkPreview",
              attrs: {},
            })
            .focus()
            .run();
        },
    };
  },
});
