"use client";

import { Node, mergeAttributes } from "@tiptap/react";
import { ReactNodeViewRenderer } from "@tiptap/react";
import type { NodeViewProps } from "@tiptap/react";
import { Star } from "lucide-react";
import * as React from "react";

import { cn } from "@/lib/utils";

import { NodeViewWrapper } from "@tiptap/react";

export type DividerStyle = "solid" | "dashed" | "dotted" | "dots" | "star";

function lineClass(style: DividerStyle) {
  switch (style) {
    case "solid":
      return "h-px bg-border";
    case "dashed":
      return "h-0 w-full border-t-2 border-dashed border-border";
    case "dotted":
      return "h-0 w-full border-t-2 border-dotted border-border";
    case "dots":
      return "hidden";
    case "star":
      return "h-px w-full bg-border/70";
    default:
      return "h-px bg-border";
  }
}

function DividerView(props: NodeViewProps) {
  const { node, updateAttributes, selected } = props;
  const style = (node.attrs.style as DividerStyle) ?? "solid";

  return (
    <NodeViewWrapper
      className={cn(
        "divider-block group relative my-6 flex min-h-[28px] items-center justify-center py-1",
        selected &&
          "rounded ring-2 ring-primary/40 ring-offset-2 ring-offset-background",
      )}
      data-type="divider"
      data-divider-style={style}
      contentEditable={false}
    >
      <div
        className={cn(
          "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2",
          lineClass(style),
        )}
        aria-hidden
      />
      {style === "dots" ? (
        <div className="relative flex items-center justify-center gap-2 px-8">
          <span className="h-1.5 w-1.5 rounded-full bg-muted-foreground/45" />
          <span className="h-1.5 w-1.5 rounded-full bg-muted-foreground/45" />
          <span className="h-1.5 w-1.5 rounded-full bg-muted-foreground/45" />
        </div>
      ) : null}
      {style === "star" ? (
        <span
          className="relative z-[1] inline-flex size-8 items-center justify-center rounded-full border border-border bg-background text-primary shadow-sm dark:bg-card"
          contentEditable={false}
        >
          <Star className="size-4 fill-primary/15 text-primary" aria-hidden />
        </span>
      ) : style !== "dots" ? (
        <span className="sr-only">Divider</span>
      ) : null}
      <select
        aria-label="Divider style"
        className={cn(
          "absolute right-0 top-1/2 z-10 -translate-y-1/2 cursor-pointer rounded border border-border bg-background px-1 py-0.5 text-[10px] text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
          "focus:opacity-100",
        )}
        value={style}
        onChange={(e) =>
          updateAttributes({ style: e.target.value as DividerStyle })
        }
        onClick={(e) => e.stopPropagation()}
      >
        <option value="solid">Solid</option>
        <option value="dashed">Dashed</option>
        <option value="dotted">Dotted</option>
        <option value="dots">Dots</option>
        <option value="star">Star</option>
      </select>
    </NodeViewWrapper>
  );
}

export const Divider = Node.create({
  name: "divider",
  group: "block",
  atom: true,
  draggable: true,
  selectable: true,

  addAttributes() {
    return {
      style: {
        default: "solid" as DividerStyle,
        parseHTML: (el) =>
          (el.getAttribute("data-divider-style") as DividerStyle | null) ??
          "solid",
        renderHTML: (attrs) => ({
          "data-divider-style": attrs.style ?? "solid",
        }),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'div[data-type="divider"]',
      },
    ];
  },

  renderHTML({ HTMLAttributes }) {
    return [
      "div",
      mergeAttributes(HTMLAttributes, {
        "data-type": "divider",
        role: "separator",
      }),
    ];
  },

  addNodeView() {
    return ReactNodeViewRenderer(DividerView);
  },

  addKeyboardShortcuts() {
    return {
      "Mod-Shift-Alt-d": () =>
        this.editor.commands.insertContent({
          type: this.name,
          attrs: { style: "solid" },
        }),
    };
  },
});
