import { describe, expect, it } from "vitest";

import initialView from "../../fixtures/player-view/initial.json";
import type { ForkBranchRequest, PlayerView, TurnRequest } from "@contracts";

import { forkDemoBranch, submitDemoTurn } from "./turnAdapter";

function request(intent: TurnRequest["intent"], input: string): TurnRequest {
  return {
    storyId: initialView.storyId,
    branchId: initialView.branchId,
    expectedNodeId: initialView.nodeId,
    actionId: `test_${intent}`,
    intent,
    input
  };
}

describe("local turn adapter", () => {
  it("preserves literal player input without inventing additional player speech", async () => {
    const literalInput = "我把手电筒放在长椅上。";
    const result = await submitDemoTurn(
      request("speak_or_act", literalInput),
      initialView as PlayerView
    );
    const playerBeats = result.playerView.beats.filter((beat) => beat.speaker === "你");

    expect(playerBeats).toHaveLength(1);
    expect(playerBeats[0]?.text).toBe(literalInput);
  });

  it("accepts an empty Continue intent without creating a player beat", async () => {
    const result = await submitDemoTurn(request("continue", ""), initialView as PlayerView);

    expect(result.committedNodeId).toBe("node_002");
    expect(result.playerView.beats.some((beat) => beat.speaker === "你")).toBe(false);
    expect(result.playerView.beats.at(-1)?.speaker).toBe("娜娜");
  });

  it("mirrors a fork without moving or deleting the source history", async () => {
    const advanced = await submitDemoTurn(
      request("speak_or_act", "我先去看看站台。"),
      initialView as PlayerView
    );
    const forkRequest: ForkBranchRequest = {
      storyId: advanced.playerView.storyId,
      currentBranchId: advanced.playerView.branchId,
      expectedCurrentNodeId: advanced.playerView.nodeId,
      sourceNodeId: initialView.nodeId,
      actionId: "fork_adapter_test"
    };

    const forked = await forkDemoBranch(forkRequest, advanced.playerView);

    expect(forked.branchId).toBe("branch_fork_adapter_test");
    expect(forked.playerView.nodeId).toBe(initialView.nodeId);
    expect(forked.playerView.branchId).toBe(forked.branchId);
    expect(forked.playerView.history).toHaveLength(1);
    expect(forked.playerView.history[0]?.isCurrent).toBe(true);
    expect(advanced.playerView.branchId).toBe(initialView.branchId);
    expect(advanced.playerView.nodeId).toBe("node_002");
  });
});
