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

import {
  PROCEED,
  foldClarifications,
  needsClarifyGate,
  toVM,
  type ClarifyAnswer,
} from "./clarify";

describe("foldClarifications", () => {
  it("原意见在前，每条澄清另起一行并保序", () => {
    const answers: ClarifyAnswer[] = [
      { question: "这段谁在说话？", answer: "主角内心独白" },
      { question: "结尾要留钩子吗？", answer: "留一个悬念" },
    ];

    const result = foldClarifications("收紧节奏", answers);

    expect(result).toBe(
      "收紧节奏\n已澄清：这段谁在说话？ → 主角内心独白\n已澄清：结尾要留钩子吗？ → 留一个悬念",
    );
  });

  it("无回答时原样返回去空白后的 instruction", () => {
    expect(foldClarifications("  收紧节奏  ", [])).toBe("收紧节奏");
  });

  it("instruction 为空时只输出澄清行", () => {
    const answers: ClarifyAnswer[] = [
      { question: "谁在说话？", answer: "配角旁白" },
    ];
    expect(foldClarifications("   ", answers)).toBe("已澄清：谁在说话？ → 配角旁白");
  });

  it("跳过空/纯空白回答的条目", () => {
    const answers: ClarifyAnswer[] = [
      { question: "Q1", answer: "  " },
      { question: "Q2", answer: "有效回答" },
    ];
    expect(foldClarifications("原意见", answers)).toBe(
      "原意见\n已澄清：Q2 → 有效回答",
    );
  });

  it("问题为空（自由输入）时省略问题只留答案", () => {
    const answers: ClarifyAnswer[] = [{ question: "  ", answer: "就按我说的改" }];
    expect(foldClarifications("原意见", answers)).toBe(
      "原意见\n已澄清：就按我说的改",
    );
  });

  it("去除问题与答案两端空白", () => {
    const answers: ClarifyAnswer[] = [
      { question: "  谁在说话？  ", answer: "  主角  " },
    ];
    expect(foldClarifications("x", answers)).toBe("x\n已澄清：谁在说话？ → 主角");
  });

  it("不可变：不修改入参数组", () => {
    const answers: ClarifyAnswer[] = [{ question: "Q", answer: "A" }];
    const snapshot = JSON.parse(JSON.stringify(answers));
    foldClarifications("原意见", answers);
    expect(answers).toEqual(snapshot);
  });

  it("全部为空回答且 instruction 为空时返回空串", () => {
    expect(foldClarifications("", [{ question: "Q", answer: "" }])).toBe("");
  });
});

describe("toVM", () => {
  it("snake_case ClarifyDecision → camelCase VM，逐字段映射", () => {
    const vm = toVM({
      need_clarification: true,
      questions: [
        {
          question: "想更冷峻还是更抒情？",
          options: [
            { label: "冷峻", value: "改得更冷峻克制" },
            { label: "抒情", value: "改得更抒情" },
          ],
          allow_free_text: true,
        },
      ],
      verification: "我这样理解对吗",
    });

    expect(vm).toEqual({
      needClarification: true,
      questions: [
        {
          question: "想更冷峻还是更抒情？",
          options: [
            { label: "冷峻", value: "改得更冷峻克制" },
            { label: "抒情", value: "改得更抒情" },
          ],
          allowFreeText: true,
        },
      ],
      verification: "我这样理解对吗",
    });
  });

  it("字段缺省时取安全默认（空/false/undefined），不信任外部数据", () => {
    const vm = toVM({});
    expect(vm).toEqual({
      needClarification: false,
      questions: [],
      verification: undefined,
    });
  });

  it("questions/options 内字段缺省时逐项补默认", () => {
    const vm = toVM({
      need_clarification: true,
      questions: [{ question: undefined, options: [{}], allow_free_text: undefined }],
      verification: null,
    });
    expect(vm).toEqual({
      needClarification: true,
      questions: [
        { question: "", options: [{ label: "", value: "" }], allowFreeText: false },
      ],
      verification: undefined,
    });
  });
});

describe("PROCEED", () => {
  it("放行常量：不反问、无问题", () => {
    expect(PROCEED).toEqual({ needClarification: false, questions: [] });
  });
});

describe("needsClarifyGate", () => {
  it("去空白后长度小于 minChars 时需要预检", () => {
    expect(needsClarifyGate("改一下", 8)).toBe(true);
  });

  it("恰好等于 minChars 时不需预检（边界）", () => {
    expect(needsClarifyGate("12345678", 8)).toBe(false);
  });

  it("超过 minChars 时不需预检", () => {
    expect(needsClarifyGate("这是一段足够清晰具体的润色意见", 8)).toBe(false);
  });

  it("纯空白按空计（长度 0 < minChars）需预检", () => {
    expect(needsClarifyGate("      ", 8)).toBe(true);
  });

  it("先去两端空白再计长度", () => {
    expect(needsClarifyGate("  改  ", 2)).toBe(true);
  });
});
