'use client';

import { useCallback, useMemo } from "react";
import type { Block, PartialBlock } from "@blocknote/core";
import {
  BlockColorsItem,
  SideMenu,
  TableColumnHeaderItem,
  TableRowHeaderItem,
  useBlockNoteEditor,
  useComponentsContext,
  type DragHandleMenuProps,
  type SideMenuProps,
} from "@blocknote/react";
import { useRouter } from "next/navigation";
import type { CustomBlockSchema } from "../schema";
import { deleteOnlineTable } from "@/lib/online-table";
import { emitAssetsChanged, emitDocumentsChanged } from "@/lib/events";

type InlineNode = { text?: unknown };
type TableMenuBlock = Parameters<
  typeof TableRowHeaderItem
>[0]["block"];
type DraftBlock = PartialBlock<CustomBlockSchema> & { id?: string };
type ConvertOption = {
  label: string;
  type?: Block<CustomBlockSchema>["type"];
  props?: Record<string, unknown>;
  shortcut?: string;
  action?: () => void;
};

type CustomDragProps = DragHandleMenuProps<CustomBlockSchema> & {
  currentDocumentId: string;
};

const extractText = (block: Block<CustomBlockSchema>) => {
  const inlineNodes = block.content as InlineNode[] | undefined;
  const maybeText = inlineNodes?.[0]?.text;
  if (typeof maybeText === "string" && maybeText.trim().length > 0) {
    return maybeText.trim();
  }
  return "未命名页面";
};

const CustomDragHandleMenu = ({ block, currentDocumentId }: CustomDragProps) => {
  const Components = useComponentsContext()!;
  const editor = useBlockNoteEditor<CustomBlockSchema>();
  const router = useRouter();

  const duplicateBlock = useCallback(() => {
    const blockWithoutId: DraftBlock = { ...block };
    delete blockWithoutId.id;
    editor.insertBlocks([blockWithoutId], block, "after");
  }, [block, editor]);

  const removePageReference = useCallback(async () => {
    if (block.type === "pageReference") {
      const pageId = block.props.pageId;
      if (pageId) {
        await fetch("/api/documents/delete", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ documentId: pageId }),
        });
        if (typeof window !== "undefined") {
          emitDocumentsChanged(pageId);
        }
      }
    }
    editor.removeBlocks([block.id]);
    router.refresh();
  }, [block, editor, router]);

  const handleDeleteBlock = useCallback(async () => {
    if (block.type === "pageReference") {
      void removePageReference();
      return;
    }
    if (block.type === "onlineTable") {
      const tableId = block.props.tableId as string | undefined;
      if (tableId) {
        void deleteOnlineTable(tableId)
          .catch((error) => console.error("删除在线表格失败", error));
        if (typeof window !== "undefined") {
          window.dispatchEvent(new CustomEvent("online-table-deleted", { detail: { tableId } }));
          emitAssetsChanged(currentDocumentId);
        }
      }
      editor.removeBlocks([block.id]);
      return;
    }
    if (block.type === "media") {
      const assetId = block.props.assetId as string | undefined;
      if (assetId) {
        const resp = await fetch("/api/media/batch", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ action: "delete", assetIds: [assetId] }),
        });
        if (!resp.ok) {
          const payload = await resp.json().catch(() => ({}));
          window.alert(payload?.error ?? "删除附件失败");
          return;
        }
        emitAssetsChanged(currentDocumentId);
      }
      editor.removeBlocks([block.id]);
      return;
    }
    if (block.type === "mindmap") {
      const resp = await fetch(`/api/mindmap/${currentDocumentId}/${block.id}`, { method: "DELETE" });
      if (!resp.ok) {
        const payload = await resp.json().catch(() => ({}));
        window.alert(payload?.error ?? "删除思维导图失败");
        return;
      }
      emitAssetsChanged(currentDocumentId, undefined, undefined, false, [block.id]);
      // 侧边栏/全局删除监听也会尝试移除对应块，这里做 try/catch 避免重复删除导致报错
      try {
        editor.removeBlocks([block.id]);
      } catch {
        // ignore
      }
      return;
    }
    editor.removeBlocks([block.id]);
  }, [block, currentDocumentId, editor, removePageReference]);

  const turnToPage = useCallback(async () => {
    const response = await fetch("/api/documents/create-child", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        parentId: currentDocumentId,
        title: extractText(block),
        blocks: [block],
      }),
    });

    if (!response.ok) {
      return;
    }

    const { pageId, title } = await response.json();

    editor.replaceBlocks(
      [block.id],
      [
        {
          type: "pageReference",
          props: { pageId, title },
        } as PartialBlock<CustomBlockSchema>,
      ],
    );
    router.refresh();
  }, [block, currentDocumentId, editor, router]);

  const moveOrEmbedBlock = useCallback(async () => {
    if (typeof window === "undefined") {
      return;
    }
    const targetParent = window.prompt("输入目标页面 ID（将在该页面末尾插入新子页面）", currentDocumentId);
    if (!targetParent) {
      return;
    }
    const response = await fetch("/api/documents/create-child", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        parentId: targetParent.trim(),
        title: extractText(block),
        blocks: [block],
      }),
    });
    if (!response.ok) {
      window.alert("移动失败，请确认页面 ID");
      return;
    }
    const { pageId, title } = await response.json();
    editor.replaceBlocks(
      [block.id],
      [
        {
          type: "pageReference",
          props: { pageId, title },
        } as PartialBlock<CustomBlockSchema>,
      ],
    );
    router.refresh();
  }, [block, currentDocumentId, editor, router]);

  const convertOptions = useMemo<ConvertOption[]>(
    () => [
      { label: "文本", type: "paragraph", shortcut: "Ctrl+Alt+0" },
      { label: "待办列表", type: "checkListItem", shortcut: "Ctrl+Shift+5" },
      { label: "高级待办列表", type: "advancedTodo" },
      { label: "主标题", type: "heading", props: { level: 1 }, shortcut: "Ctrl+Shift+1" },
      { label: "大标题", type: "heading", props: { level: 2 }, shortcut: "Ctrl+Shift+2" },
      { label: "中标题", type: "heading", props: { level: 3 }, shortcut: "Ctrl+Shift+3" },
      { label: "小标题", type: "heading", props: { level: 4 }, shortcut: "Ctrl+Shift+4" },
      { label: "页面", action: turnToPage },
      { label: "列表", type: "bulletListItem", shortcut: "Ctrl+Shift+6" },
      { label: "数字列表", type: "numberedListItem", shortcut: "Ctrl+Shift+7" },
      { label: "折叠列表", type: "toggleListItem", shortcut: "Ctrl+Shift+8" },
      { label: "折叠标题", type: "heading", props: { level: 2, isToggleable: true } },
      { label: "引述文字", type: "quote" },
      { label: "代码片段", type: "codeBlock" },
    ],
    [turnToPage],
  );

  const convertBlock = useCallback(
    (option: ConvertOption) => {
      if (option.action) {
        option.action();
        return;
      }
      if (!option.type) return;
      editor.updateBlock(block as any, {
        type: option.type as any,
        props: (option.props ?? {}) as any,
      } as any);
    },
    [block, editor],
  );

  const copyBlockLink = useCallback(async () => {
    if (typeof window === "undefined") {
      return;
    }
    const url = `${window.location.origin}/documents/${currentDocumentId}#block-${block.id}`;
    try {
      await navigator.clipboard.writeText(url);
      window.alert("块链接已复制");
    } catch {
      window.prompt("复制失败，请手动复制", url);
    }
  }, [block.id, currentDocumentId]);

  const openOnRight = useCallback(() => {
    if (typeof window === "undefined") {
      return;
    }
    const url = `${window.location.origin}/documents/${currentDocumentId}?preview=sidebar&focus=${block.id}`;
    window.open(url, "_blank", "noopener,noreferrer");
  }, [block.id, currentDocumentId]);

  const setAdvancedTodoStatus = useCallback(
    (status: "todo" | "doing" | "done" | "cancelled") => {
      if (block.type !== "advancedTodo") return;
      editor.updateBlock(block, {
        props: { status },
      });
    },
    [block, editor],
  );

  const toggleProgressMode = useCallback(() => {
    if (block.type !== "progressMeter") return;
    editor.updateBlock(block, {
      props: { auto: !block.props.auto },
    });
  }, [block, editor]);

  const setManualProgress = useCallback(() => {
    if (block.type !== "progressMeter") return;
    const value = Number.parseInt(window.prompt("手动设置进度（0-100）", String(block.props.percent ?? 0)) ?? "", 10);
    if (Number.isNaN(value)) return;
    const clamped = Math.min(100, Math.max(0, value));
    editor.updateBlock(block, {
      props: { percent: clamped },
    });
  }, [block, editor]);

  return (
    <Components.Generic.Menu.Dropdown className="bn-menu-dropdown bn-drag-handle-menu">
      <Components.Generic.Menu.Item className="bn-menu-item" onClick={openOnRight}>
        在右侧边栏打开
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Root sub>
        <Components.Generic.Menu.Trigger sub>
          <Components.Generic.Menu.Item className="bn-menu-item" subTrigger>
            转换为
          </Components.Generic.Menu.Item>
        </Components.Generic.Menu.Trigger>
        <Components.Generic.Menu.Dropdown sub className="bn-menu-dropdown">
          {convertOptions.map((option) => (
            <Components.Generic.Menu.Item
              key={option.label}
              className="bn-menu-item flex items-center justify-between gap-4"
              onClick={() => convertBlock(option)}
            >
              <span>{option.label}</span>
              {option.shortcut && <span className="text-[10px] text-gray-400">{option.shortcut}</span>}
            </Components.Generic.Menu.Item>
          ))}
        </Components.Generic.Menu.Dropdown>
      </Components.Generic.Menu.Root>

      <Components.Generic.Menu.Item className="bn-menu-item" onClick={duplicateBlock}>
        拷贝副本
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Item className="bn-menu-item" onClick={copyBlockLink}>
        复制链接
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Item className="bn-menu-item" onClick={moveOrEmbedBlock}>
        移动/嵌入到...
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Item
        className="bn-menu-item"
        onClick={() => window.alert("块历史功能开发中，敬请期待")}
      >
        块历史...
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Item
        className="bn-menu-item"
        onClick={() => window.alert("评论功能暂未开放")}
      >
        评论
      </Components.Generic.Menu.Item>

      <Components.Generic.Menu.Item className="bn-menu-item" onClick={handleDeleteBlock}>
        删除
      </Components.Generic.Menu.Item>

      <BlockColorsItem block={block}>颜色</BlockColorsItem>
      <TableRowHeaderItem block={block as TableMenuBlock}>表头（行）</TableRowHeaderItem>
      <TableColumnHeaderItem block={block as TableMenuBlock}>表头（列）</TableColumnHeaderItem>

      {block.type === "advancedTodo" && (
        <>
          <Components.Generic.Menu.Divider className="bn-menu-divider" />
          {[
            { label: "设为未开始", status: "todo" as const },
            { label: "设为进行中", status: "doing" as const },
            { label: "设为已完成", status: "done" as const },
            { label: "设为取消", status: "cancelled" as const },
          ].map((item) => (
            <Components.Generic.Menu.Item
              key={item.status}
              className="bn-menu-item"
              onClick={() => setAdvancedTodoStatus(item.status)}
            >
              {item.label}
            </Components.Generic.Menu.Item>
          ))}
        </>
      )}

      {block.type === "progressMeter" && (
        <>
          <Components.Generic.Menu.Divider className="bn-menu-divider" />
          <Components.Generic.Menu.Item className="bn-menu-item" onClick={toggleProgressMode}>
            {block.props.auto ? "切换为手动进度" : "切换为自动进度"}
          </Components.Generic.Menu.Item>
          {!block.props.auto && (
            <Components.Generic.Menu.Item className="bn-menu-item" onClick={setManualProgress}>
              手动设置百分比
            </Components.Generic.Menu.Item>
          )}
        </>
      )}
    </Components.Generic.Menu.Dropdown>
  );
};

type CustomSideMenuProps = SideMenuProps<CustomBlockSchema> & {
  currentDocumentId: string;
};

export const CustomSideMenu = (props: CustomSideMenuProps) => (
  <SideMenu
    {...props}
    dragHandleMenu={(dragProps) => (
      <CustomDragHandleMenu
        {...(dragProps as DragHandleMenuProps<CustomBlockSchema>)}
        currentDocumentId={props.currentDocumentId}
      />
    )}
  />
);
