import { describe, expect, it, vi } from "vitest";
import type { Json } from "@/types/supabase";
import {
  applyDocWriteToolResultToPageBody,
  buildAiAgentSessionsStoragePayload,
  extractCurrentPageTitleFromSlashToolResult,
  shouldSyncActiveSessionSnapshot,
} from "./DocumentAiAgentPanel.runtime";

type TestSession = {
  id: string;
  title: string;
  createdAt: number;
  updatedAt: number;
  messages: Array<{ role: "user" | "assistant"; content: string }>;
  toolLogs: Array<{ type: string; id?: string; tool?: string; ok?: boolean; ms?: number; result?: unknown }>;
  codexSessionId?: string | null;
  codexMode?: "chat" | "test" | "dev" | null;
};

function buildSession(overrides: Partial<TestSession> = {}): TestSession {
  return {
    id: "session-1",
    title: "新会话",
    createdAt: 1,
    updatedAt: 2,
    messages: [{ role: "assistant", content: "欢迎语" }],
    toolLogs: [],
    codexSessionId: null,
    codexMode: null,
    ...overrides,
  };
}

describe("DocumentAiAgentPanel.runtime 会话回写保护", () => {
  it("当前会话快照与本地消息和日志一致时，不应触发回写", () => {
    const session = buildSession();
    expect(shouldSyncActiveSessionSnapshot(session, session.messages, session.toolLogs)).toBe(false);
  });

  it("当前会话快照与本地消息或日志不同时时，才应触发回写", () => {
    const session = buildSession({
      messages: [{ role: "assistant", content: "旧内容" }],
      toolLogs: [{ type: "info", message: "old" }],
    });
    expect(
      shouldSyncActiveSessionSnapshot(
        session,
        [{ role: "assistant", content: "新内容" }],
        [{ type: "info", message: "new" }],
      ),
    ).toBe(true);
  });

  it("持久化 payload 应稳定包含标准化后的会话列表", () => {
    const payload = buildAiAgentSessionsStoragePayload("session-1", [
      buildSession({
        updatedAt: 999,
        messages: [{ role: "assistant", content: "欢迎语" }],
      }),
    ]);

    const parsed = JSON.parse(payload) as {
      activeSessionId: string;
      sessions: Array<{ id: string; title: string; createdAt: number; updatedAt: number; messages: Json; toolLogs: Json }>;
    };
    expect(parsed.activeSessionId).toBe("session-1");
    expect(parsed.sessions).toHaveLength(1);
    expect(parsed.sessions[0]?.id).toBe("session-1");
    expect(parsed.sessions[0]?.messages).toEqual([{ role: "assistant", content: "欢迎语" }]);
  });
});

describe("applyDocWriteToolResultToPageBody", () => {
  it("doc 写工具成功时应按最新持久化元信息执行 page body save", async () => {
    const applyPageBodyCommandImpl = vi.fn(async () => ({
      revision: 6,
      conflictDetectionKey: "doc-1:6",
    }));
    const applyEditorSnapshot = vi.fn();
    const onPersistedMetaChange = vi.fn();

    const applied = await applyDocWriteToolResultToPageBody({
      tool: "doc_insert_blocks",
      ok: true,
      result: {
        data: [{ id: "block_1", type: "paragraph", content: "AI 正文" }],
      },
      documentId: "doc-1",
      getLatestPageAggregateSnapshot: () => ({
        blocks: [{ id: "block_0", type: "paragraph", content: "旧正文" }] as Json,
        pageSubtree: null,
        persistedMeta: {
          workspaceId: "ws-1",
          revision: 5,
          conflictDetectionKey: "doc-1:5",
        },
        pageOptions: {
          wideLayout: false,
          smallText: false,
          showHeadingNumbers: true,
          showToc: false,
          showStructure: false,
          protectEditing: false,
          showWordCount: true,
          collapseBacklinks: false,
          pageFont: "default",
          layoutDensity: "normal",
          hideChildPages: false,
          showBlockRefCount: false,
          embedDefaultBlockId: null,
        },
      }),
      applyEditorSnapshot,
      onPersistedMetaChange,
      applyPageBodyCommandImpl,
    });

    expect(applied).toBe(true);
    expect(applyPageBodyCommandImpl).toHaveBeenCalledWith({
      documentId: "doc-1",
      workspaceId: "ws-1",
      revision: 5,
      conflictDetectionKey: "doc-1:5",
      blocks: [{ id: "block_1", type: "paragraph", content: "AI 正文" }],
      applyEditorSnapshot,
    });
    expect(onPersistedMetaChange).toHaveBeenCalledWith({
      revision: 6,
      conflictDetectionKey: "doc-1:6",
    });
  });

  it("非 doc 写工具或无 data 时应直接忽略", async () => {
    const applyPageBodyCommandImpl = vi.fn();

    await expect(
      applyDocWriteToolResultToPageBody({
        tool: "docs_read",
        ok: true,
        result: { data: [] },
        documentId: "doc-1",
        getLatestPageAggregateSnapshot: () => ({
          blocks: null,
          pageSubtree: null,
          persistedMeta: {
            workspaceId: "ws-1",
            revision: 5,
            conflictDetectionKey: "doc-1:5",
          },
          pageOptions: {
            wideLayout: false,
            smallText: false,
            showHeadingNumbers: true,
            showToc: false,
            showStructure: false,
            protectEditing: false,
            showWordCount: true,
            collapseBacklinks: false,
            pageFont: "default",
            layoutDensity: "normal",
            hideChildPages: false,
            showBlockRefCount: false,
            embedDefaultBlockId: null,
          },
        }),
        applyEditorSnapshot: vi.fn(),
        onPersistedMetaChange: vi.fn(),
        applyPageBodyCommandImpl,
      }),
    ).resolves.toBe(false);

    expect(applyPageBodyCommandImpl).not.toHaveBeenCalled();
  });

  it("doc 写工具返回非 legacy blocks 数组时应直接忽略", async () => {
    const applyPageBodyCommandImpl = vi.fn();

    await expect(
      applyDocWriteToolResultToPageBody({
        tool: "doc_replace_range",
        ok: true,
        result: {
          data: {
            documentId: "doc-1",
            blocks: [],
          },
        },
        documentId: "doc-1",
        getLatestPageAggregateSnapshot: () => ({
          blocks: null,
          pageSubtree: null,
          persistedMeta: {
            workspaceId: "ws-1",
            revision: 5,
            conflictDetectionKey: "doc-1:5",
          },
          pageOptions: {
            wideLayout: false,
            smallText: false,
            showHeadingNumbers: true,
            showToc: false,
            showStructure: false,
            protectEditing: false,
            showWordCount: true,
            collapseBacklinks: false,
            pageFont: "default",
            layoutDensity: "normal",
            hideChildPages: false,
            showBlockRefCount: false,
            embedDefaultBlockId: null,
          },
        }),
        applyEditorSnapshot: vi.fn(),
        onPersistedMetaChange: vi.fn(),
        applyPageBodyCommandImpl,
      }),
    ).resolves.toBe(false);

    expect(applyPageBodyCommandImpl).not.toHaveBeenCalled();
  });
});

describe("extractCurrentPageTitleFromSlashToolResult", () => {
  it("slash_run 成功重命名当前页时应返回新标题", () => {
    expect(
      extractCurrentPageTitleFromSlashToolResult({
        tool: "slash_run",
        ok: true,
        documentId: "doc-1",
        result: {
          parsed: {
            command: "rename_doc",
            params: {
              documentId: "doc-1",
              title: "AI 新标题",
            },
          },
        },
      }),
    ).toBe("AI 新标题");
  });

  it("非当前页或非 rename 结果时应忽略", () => {
    expect(
      extractCurrentPageTitleFromSlashToolResult({
        tool: "slash_run",
        ok: true,
        documentId: "doc-1",
        result: {
          parsed: {
            command: "rename_doc",
            params: {
              documentId: "doc-2",
              title: "别的页面",
            },
          },
        },
      }),
    ).toBeNull();
  });
});
