"use client";

import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";
import TaskList from "@tiptap/extension-task-list";
import TaskItem from "@tiptap/extension-task-item";
import { TableKit } from "@tiptap/extension-table";
import { SlashCommand } from "./slash-command-extension";
import { ChartBlock } from "./blocks/chart-node";
import { ActionChecklist } from "./blocks/action-checklist-node";
import { NoteLinkBlock } from "./blocks/note-link-node";
import { ReminderBlock } from "./blocks/reminder-node";
import { ImageBlock } from "./blocks/image-node";
import { StickerBlock } from "./blocks/sticker-node";
import { StickerPickerButton } from "./sticker-picker";
import type { NoteEditorContext } from "./blocks/note-editor-context";
import {
  Bold,
  Italic,
  List,
  ListOrdered,
  ListChecks,
  Heading2,
  Code,
  Undo,
  Redo,
  Minus,
  Table as TableIcon,
  Image as ImageIcon,
  Sticker as StickerIcon,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { useEffect, useRef } from "react";

interface NoteEditorProps {
  content: Record<string, unknown>;
  onChange: (content: Record<string, unknown>) => void;
  editable?: boolean;
  // Identifies the note this editor is currently showing. Needed by the
  // sub-note and reminder blocks. Changing noteContext.id recreates the
  // editor (see the useEditor deps below) so those blocks never read a
  // stale parent note when navigating between notes.
  noteContext?: NoteEditorContext;
  // "glass" renders the editor as a translucent card so a note cover/theme
  // shows through around it, instead of the normal opaque app background.
  surface?: "solid" | "glass";
}

function ToolbarButton({
  onClick,
  active,
  children,
  title,
}: {
  onClick: () => void;
  active?: boolean;
  children: React.ReactNode;
  title: string;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      title={title}
      className={cn(
        "p-1.5 rounded-md transition-colors cursor-pointer",
        active
          ? "bg-accent text-accent-foreground"
          : "text-muted-foreground hover:bg-accent hover:text-accent-foreground"
      )}
    >
      {children}
    </button>
  );
}

export function NoteEditor({ content, onChange, editable = true, noteContext, surface = "solid" }: NoteEditorProps) {
  const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const initialContent =
    content && Object.keys(content).length > 0
      ? content
      : {
          type: "doc",
          content: [{ type: "paragraph" }],
        };

  const editor = useEditor({
    immediatelyRender: false,
    extensions: [
      StarterKit.configure({
        heading: { levels: [1, 2, 3] },
        codeBlock: {
          HTMLAttributes: {
            class: "rounded-md bg-muted p-4 font-mono text-sm",
          },
        },
        horizontalRule: {},
      }),
      Placeholder.configure({
        placeholder: "Start writing... (tip: type \"/\" for commands)",
      }),
      TaskList,
      TaskItem.configure({ nested: true }),
      TableKit.configure({ table: { resizable: true } }),
      ChartBlock,
      ActionChecklist,
      NoteLinkBlock.configure({
        parentNoteId: noteContext?.id ?? null,
        parentTeamId: noteContext?.teamId ?? null,
        parentFolderId: noteContext?.folderId ?? null,
        parentProjectId: noteContext?.projectId ?? null,
      }),
      ReminderBlock.configure({
        parentNoteId: noteContext?.id ?? "",
        parentNoteTitle: noteContext?.title ?? "",
      }),
      ImageBlock.configure({
        parentNoteId: noteContext?.id ?? "",
      }),
      StickerBlock,
      SlashCommand,
    ],
    content: initialContent,
    editable,
    editorProps: {
      attributes: {
        class:
          "prose prose-sm max-w-none focus:outline-none min-h-[300px] px-0 py-2",
      },
    },
    onUpdate: ({ editor }) => {
      if (debounceTimer.current) clearTimeout(debounceTimer.current);
      debounceTimer.current = setTimeout(() => {
        onChange(editor.getJSON() as Record<string, unknown>);
      }, 500);
    },
  }, [noteContext?.id]);

  // Update content if it changes externally
  useEffect(() => {
    if (!editor) return;
    const currentJson = JSON.stringify(editor.getJSON());
    const newJson = JSON.stringify(content);
    if (currentJson !== newJson && content && Object.keys(content).length > 0) {
      // emitUpdate defaults to true in Tiptap v3 — without this, an
      // external content update (e.g. an AI action) fires onUpdate as if
      // the user had typed, scheduling a spurious autosave.
      editor.commands.setContent(content, { emitUpdate: false });
    }
  }, [content, editor]);

  useEffect(() => {
    if (!editor) return;
    editor.setEditable(editable);
  }, [editable, editor]);

  if (!editor) return null;

  return (
    <div
      className={cn(
        "flex flex-col h-full rounded-2xl p-4",
        surface === "glass"
          ? "border border-white/15 bg-black/25 backdrop-blur-xl shadow-xl"
          : "border border-border/60 bg-background/60",
      )}
    >
      {/* Toolbar */}
      {editable && (
        <div className="flex items-center gap-0.5 border-b border-border pb-2 mb-2 flex-wrap">
          <ToolbarButton
            onClick={() =>
              editor.chain().focus().toggleHeading({ level: 1 }).run()
            }
            active={editor.isActive("heading", { level: 1 })}
            title="Heading 1"
          >
            <span className="text-xs font-bold w-4 text-center">H1</span>
          </ToolbarButton>
          <ToolbarButton
            onClick={() =>
              editor.chain().focus().toggleHeading({ level: 2 }).run()
            }
            active={editor.isActive("heading", { level: 2 })}
            title="Heading 2"
          >
            <Heading2 className="h-4 w-4" />
          </ToolbarButton>

          <div className="w-px h-5 bg-border mx-1" />

          <ToolbarButton
            onClick={() => editor.chain().focus().toggleBold().run()}
            active={editor.isActive("bold")}
            title="Bold"
          >
            <Bold className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().toggleItalic().run()}
            active={editor.isActive("italic")}
            title="Italic"
          >
            <Italic className="h-4 w-4" />
          </ToolbarButton>

          <div className="w-px h-5 bg-border mx-1" />

          <ToolbarButton
            onClick={() => editor.chain().focus().toggleBulletList().run()}
            active={editor.isActive("bulletList")}
            title="Bullet list"
          >
            <List className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().toggleOrderedList().run()}
            active={editor.isActive("orderedList")}
            title="Numbered list"
          >
            <ListOrdered className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().toggleTaskList().run()}
            active={editor.isActive("taskList")}
            title="Checklist"
          >
            <ListChecks className="h-4 w-4" />
          </ToolbarButton>

          <div className="w-px h-5 bg-border mx-1" />

          <ToolbarButton
            onClick={() => editor.chain().focus().toggleCodeBlock().run()}
            active={editor.isActive("codeBlock")}
            title="Code block"
          >
            <Code className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().setHorizontalRule().run()}
            title="Divider"
          >
            <Minus className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() =>
              editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
            }
            title="Insert table"
          >
            <TableIcon className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().insertContent({ type: "noteImage" }).run()}
            title="Insert image"
          >
            <ImageIcon className="h-4 w-4" />
          </ToolbarButton>
          <StickerPickerButton
            onSelect={(sticker) =>
              editor.chain().focus().insertContent({ type: "stickerBlock", attrs: { stickerId: sticker.id } }).run()
            }
            trigger={(open) => (
              <ToolbarButton onClick={open} title="Add sticker">
                <StickerIcon className="h-4 w-4" />
              </ToolbarButton>
            )}
          />

          <div className="flex-1" />

          <ToolbarButton
            onClick={() => editor.chain().focus().undo().run()}
            title="Undo"
          >
            <Undo className="h-4 w-4" />
          </ToolbarButton>
          <ToolbarButton
            onClick={() => editor.chain().focus().redo().run()}
            title="Redo"
          >
            <Redo className="h-4 w-4" />
          </ToolbarButton>
        </div>
      )}

      {/* Editor — relative so sticker decorations can anchor to it by % position */}
      <EditorContent
        editor={editor}
        className="tiptap relative flex-1 rounded-xl px-1 py-1 text-base"
      />
    </div>
  );
}
