import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

import { SessionTranscriptStore } from "../../src/sessions/transcriptStore.js";

describe("SessionTranscriptStore", () => {
  let tempDir: string;
  let store: SessionTranscriptStore;

  beforeEach(async () => {
    tempDir = await mkdtemp(join(tmpdir(), "tjwater-transcript-"));
    store = new SessionTranscriptStore(tempDir);
    await store.initialize();
  });

  afterEach(async () => {
    await rm(tempDir, { force: true, recursive: true });
  });

  it("clones only the kept prefix when forking a thread", async () => {
    await store.appendTurn(
      {
        actorKey: "actor-2",
        clientSessionId: "thread-source",
        projectKey: "project-2",
        sessionId: "thread-source",
      },
      {
        assistantMessage: "第一轮回复",
        toolCallCount: 0,
        userMessage: "第一轮提问",
      },
    );
    await store.appendTurn(
      {
        actorKey: "actor-2",
        clientSessionId: "thread-source",
        projectKey: "project-2",
        sessionId: "thread-source",
      },
      {
        assistantMessage: "第二轮回复",
        toolCallCount: 0,
        userMessage: "第二轮提问",
      },
    );

    const cloned = await store.cloneThread(
      {
        actorKey: "actor-2",
        clientSessionId: "thread-source",
        projectKey: "project-2",
        sessionId: "thread-source",
      },
      {
        actorKey: "actor-2",
        clientSessionId: "thread-fork",
        projectKey: "project-2",
        sessionId: "thread-fork",
      },
      2,
    );

    expect(cloned.turns).toHaveLength(1);
    expect(cloned.turns[0]?.userMessage).toBe("第一轮提问");

    const forkRecentTurns = await store.getRecentTurns(
      {
        actorKey: "actor-2",
        clientSessionId: "thread-fork",
        projectKey: "project-2",
        sessionId: "thread-fork",
      },
      5,
    );
    expect(forkRecentTurns).toHaveLength(1);
    expect(forkRecentTurns[0]?.assistantMessage).toBe("第一轮回复");
  });

  it("does not duplicate the latest turn when the frontend state is saved again", async () => {
    await store.appendTurn(
      {
        actorKey: "actor-3",
        clientSessionId: "thread-3",
        projectKey: "project-3",
        sessionId: "thread-3",
      },
      {
        assistantMessage: "已完成压力波动分析。",
        toolCallCount: 1,
        userMessage: "分析压力波动。",
      },
    );

    const transcript = await store.appendTurn(
      {
        actorKey: "actor-3",
        clientSessionId: "thread-3",
        projectKey: "project-3",
        sessionId: "thread-3",
      },
      {
        assistantMessage: "已完成压力波动分析。",
        toolCallCount: 2,
        userMessage: "分析压力波动。",
      },
    );

    expect(transcript.turns).toHaveLength(1);
    expect(transcript.turns[0]?.toolCallCount).toBe(2);
  });
});
