"use client";

/**
 * 富文本试卷编辑页
 *
 * 数据来源（P7 扩展，MSW mock）：
 * - GraphQL ExamRichEditorQuery：按 examId 拉取富文本试卷内容（Tiptap examNodes 结构）
 * - GraphQL SaveExamRichContentMutation：保存富文本内容
 *
 * 布局：
 * - 顶部：试卷标题 + 总分 + 题数
 * - 中间：富文本编辑器（contenteditable div + 工具栏：加粗/斜体/标题/列表/插入题目/分页符）
 * - "保存" 调用 SaveExamRichContentMutation
 * - "预览" 在新 tab 打开 /exams/[id]
 * - "导出 PDF" 调用 window.print()
 *
 * 维护者：ai13（teacher-portal）
 */

import { useState, useRef, useEffect } from "react";
import { useQuery, useMutation } from "urql";
import { useParams } from "next/navigation";
import Link from "next/link";
import { Loading, Empty } from "@edu/ui-components";
import {
  ExamRichEditorQuery,
  SaveExamRichContentMutation,
} from "@/lib/graphql-p7-advanced";

/** 工具栏按钮定义 */
interface ToolButton {
  command: string;
  label: string;
  value?: string;
}

const TOOLBAR_GROUPS: ToolButton[][] = [
  [
    { command: "bold", label: "加粗" },
    { command: "italic", label: "斜体" },
  ],
  [
    { command: "formatBlock", label: "H1", value: "h1" },
    { command: "formatBlock", label: "H2", value: "h2" },
    { command: "formatBlock", label: "H3", value: "h3" },
    { command: "formatBlock", label: "正文", value: "p" },
  ],
  [
    { command: "insertUnorderedList", label: "无序列表" },
    { command: "insertOrderedList", label: "有序列表" },
  ],
  [
    { command: "insertQuestion", label: "插入题目" },
    { command: "insertPageBreak", label: "插入分页符" },
  ],
];

/** 执行工具栏命令（contenteditable + document.execCommand，mock 实现） */
function execToolbar(
  cmd: string,
  value: string | undefined,
  editorRef: React.RefObject<HTMLDivElement>,
): void {
  if (cmd === "insertQuestion") {
    // 插入题目占位块
    document.execCommand("insertHTML", false, questionBlockHtml());
    return;
  }
  if (cmd === "insertPageBreak") {
    document.execCommand(
      "insertHTML",
      false,
      '<div class="page-break" style="page-break-after:always;border-top:2px dashed var(--color-rule);margin:1rem 0;padding-top:0.5rem;color:var(--color-ink-muted);font-size:0.75rem;text-align:center;">— 分页 —</div>',
    );
    return;
  }
  // 标准命令
  document.execCommand(cmd, false, value);
  // 确保编辑器保持焦点
  editorRef.current?.focus();
}

/** 生成题目占位 HTML */
function questionBlockHtml(): string {
  return '<div class="question-block" style="border:1px solid var(--color-rule);border-radius:0.5rem;padding:1rem;margin:1rem 0;background:var(--color-surface);"><p style="font-weight:600;margin-bottom:0.5rem;">题目（请在下方编写题干）</p><p>选项 / 作答区...</p></div>';
}

export default function ExamRichEditorPage(): React.ReactNode {
  const params = useParams<{ id: string }>();
  const examId = params?.id ?? "";

  const [result] = useQuery({
    query: ExamRichEditorQuery,
    variables: { examId },
    pause: !examId,
  });

  const [, saveContent] = useMutation(SaveExamRichContentMutation);

  const editorRef = useRef<HTMLDivElement>(null);
  const [saving, setSaving] = useState(false);
  const [saveMsg, setSaveMsg] = useState<string | null>(null);
  const [saveError, setSaveError] = useState<string | null>(null);
  const [initialized, setInitialized] = useState(false);

  const editor = result.data?.examRichEditor;

  // 初始化编辑器内容（mock：将 JSON content 渲染为可编辑 HTML）
  useEffect(() => {
    if (!editor || initialized || !editorRef.current) return;
    // mock：将 content 的文本内容直接渲染
    const content = editor.content as {
      type?: string;
      content?: Array<{ type?: string; text?: string; attrs?: { level?: number } }>;
    } | null;
    if (content && Array.isArray(content.content)) {
      const html = content.content
        .map((node) => {
          if (node.type === "heading") {
            const level = node.attrs?.level ?? 1;
            return `<h${level}>${node.text ?? ""}</h${level}>`;
          }
          if (node.type === "paragraph") {
            return `<p>${node.text ?? ""}</p>`;
          }
          return "";
        })
        .join("");
      editorRef.current.innerHTML = html || "<p></p>";
    } else {
      editorRef.current.innerHTML = "<p></p>";
    }
    setInitialized(true);
  }, [editor, initialized]);

  /** 保存富文本内容 */
  const handleSave = async () => {
    if (!editorRef.current) return;
    setSaving(true);
    setSaveError(null);
    setSaveMsg(null);
    // 将编辑器 HTML 序列化为 JSON（mock：保存为简化结构）
    const content = {
      type: "doc",
      content: serializeEditorToNodes(editorRef.current),
    };
    const res = await saveContent({
      input: { examId, content },
    });
    setSaving(false);
    if (res.error) {
      setSaveError(res.error.message);
      return;
    }
    setSaveMsg("已保存");
  };

  /** 预览：在新 tab 打开考试详情 */
  const handlePreview = () => {
    window.open(`/exams/${examId}`, "_blank");
  };

  /** 导出 PDF：调用浏览器打印 */
  const handleExportPdf = () => {
    window.print();
  };

  return (
    <div className="px-10 py-10">
      <header className="mb-8">
        <p className="mb-2">
          <Link
            href={`/exams/${examId}`}
            className="text-tiny uppercase tracking-wide text-ink-muted hover:opacity-70"
          >
            ← 返回考试详情
          </Link>
        </p>
        <h1 className="text-3xl font-serif text-ink">富文本试卷编辑</h1>
        <p className="mt-1 text-sm text-ink-muted">
          GraphQL ExamRichEditorQuery + SaveExamRichContentMutation · core-edu 域（P7 扩展，MSW mock）
        </p>
      </header>

      <div className="rule-thin mb-8" />

      {result.fetching ? (
        <Loading lines={6} />
      ) : result.error ? (
        <div className="mark-left mb-4 py-2 border-l-2 border-danger pl-md">
          <p className="text-sm px-3 text-danger">
            加载失败：{result.error.message}
          </p>
        </div>
      ) : !editor ? (
        <Empty title="未找到试卷" description="该考试不存在或无富文本内容" />
      ) : (
        <section className="max-w-4xl">
          {/* 顶部信息卡片 */}
          <div className="mb-6 flex items-baseline justify-between">
            <div>
              <h2 className="text-xl font-serif text-ink">{editor.title}</h2>
              <p className="mt-1 text-sm text-ink-muted">
                最后更新：
                {new Date(editor.updatedAt).toLocaleString("zh-CN")}
              </p>
            </div>
            <div className="flex items-baseline gap-6 text-sm">
              <div>
                <span className="text-tiny uppercase tracking-wide text-ink-muted">
                  总分
                </span>
                <span className="ml-2 font-serif text-ink">
                  {editor.totalScore}
                </span>
              </div>
              <div>
                <span className="text-tiny uppercase tracking-wide text-ink-muted">
                  题数
                </span>
                <span className="ml-2 font-serif text-ink">
                  {editor.questionCount}
                </span>
              </div>
            </div>
          </div>

          {/* 工具栏 */}
          <div className="mb-4 p-2 border border-rule rounded-card bg-surface flex items-center gap-2 flex-wrap">
            {TOOLBAR_GROUPS.map((group, gi) => (
              <div key={gi} className="flex items-center gap-1">
                {gi > 0 && (
                  <span
                    className="mx-1 inline-block w-px h-5 bg-rule"
                    aria-hidden="true"
                  />
                )}
                {group.map((btn) => (
                  <button
                    key={`${btn.command}-${btn.label}`}
                    type="button"
                    onClick={() => execToolbar(btn.command, btn.value, editorRef)}
                    className="px-2 py-1 text-tiny text-ink bg-transparent border border-transparent rounded-button hover:bg-subtle hover:border-rule"
                    title={btn.label}
                  >
                    {btn.label}
                  </button>
                ))}
              </div>
            ))}
          </div>

          {/* 编辑器 */}
          <div
            ref={editorRef}
            contentEditable
            suppressContentEditableWarning
            className="min-h-[400px] p-6 border border-rule rounded-card bg-paper text-ink focus:outline-none focus:border-accent font-serif"
            style={{ lineHeight: 1.8 }}
            aria-label="富文本试卷编辑器"
          />

          {/* 错误 / 消息 */}
          {saveError && (
            <div className="mark-left mt-4 py-2 border-l-2 border-danger pl-md">
              <p className="text-sm px-3 text-danger">保存失败：{saveError}</p>
            </div>
          )}
          {saveMsg && (
            <p className="mt-4 text-tiny text-success">{saveMsg}</p>
          )}

          {/* 操作按钮 */}
          <div className="mt-6 flex items-center gap-4">
            <button
              type="button"
              onClick={handleSave}
              disabled={saving}
              className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover disabled:opacity-50"
            >
              {saving ? "保存中..." : "保存"}
            </button>
            <button
              type="button"
              onClick={handlePreview}
              className="px-4 py-2 text-sm text-ink bg-transparent border border-rule rounded-button hover:bg-subtle"
            >
              预览
            </button>
            <button
              type="button"
              onClick={handleExportPdf}
              className="px-4 py-2 text-sm text-ink bg-transparent border border-rule rounded-button hover:bg-subtle"
            >
              导出 PDF
            </button>
          </div>
        </section>
      )}
    </div>
  );
}

/** 将编辑器 DOM 序列化为简化节点结构（mock Tiptap examNodes） */
function serializeEditorToNodes(
  el: HTMLDivElement,
): Array<{ type: string; text?: string; attrs?: { level?: number } }> {
  const nodes: Array<{ type: string; text?: string; attrs?: { level?: number } }> = [];
  const children = Array.from(el.children);
  for (const child of children) {
    const tag = child.tagName.toLowerCase();
    const text = child.textContent ?? "";
    if (tag === "h1") {
      nodes.push({ type: "heading", text, attrs: { level: 1 } });
    } else if (tag === "h2") {
      nodes.push({ type: "heading", text, attrs: { level: 2 } });
    } else if (tag === "h3") {
      nodes.push({ type: "heading", text, attrs: { level: 3 } });
    } else if (tag === "ul" || tag === "ol") {
      nodes.push({ type: tag === "ul" ? "bulletList" : "orderedList", text });
    } else if (tag === "div") {
      nodes.push({ type: "questionBlock", text });
    } else {
      nodes.push({ type: "paragraph", text });
    }
  }
  return nodes;
}
