// @vitest-environment jsdom
import { act, renderHook } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import { useRewriteClarify } from "./useRewriteClarify";
import type { ClarifyDecisionVM } from "./clarify";

const post = vi.fn();
vi.mock("@/lib/api/client", () => ({
  api: { POST: (...a: unknown[]) => post(...a) },
}));

const CLARIFY_PATH = "/projects/{project_id}/chapters/{chapter_no}/rewrite/clarify";

describe("useRewriteClarify", () => {
  beforeEach(() => post.mockReset());
  afterEach(() => vi.clearAllMocks());

  it("初始 idle、无决策", () => {
    const { result } = renderHook(() => useRewriteClarify());
    expect(result.current.status).toBe("idle");
    expect(result.current.decision).toBeNull();
  });

  it("need_clarification=true：POST rewrite/clarify 带 feedback+prior_draft，映射 VM，status=asking", async () => {
    post.mockResolvedValue({
      data: {
        need_clarification: true,
        questions: [
          {
            question: "高潮想更爽还是更虐？",
            options: [
              { label: "更爽", value: "把高潮写得更爽快" },
              { label: "更虐", value: "把高潮写得更虐" },
            ],
            allow_free_text: true,
          },
        ],
        verification: null,
      },
      error: null,
    });

    const { result } = renderHook(() => useRewriteClarify());
    let vm: ClarifyDecisionVM | undefined;
    await act(async () => {
      vm = await result.current.check("p1", 3, "改改", "整章草稿正文");
    });

    expect(post).toHaveBeenCalledWith(CLARIFY_PATH, {
      params: { path: { project_id: "p1", chapter_no: 3 } },
      body: { feedback: "改改", prior_draft: "整章草稿正文" },
    });
    expect(vm).toEqual({
      needClarification: true,
      questions: [
        {
          question: "高潮想更爽还是更虐？",
          options: [
            { label: "更爽", value: "把高潮写得更爽快" },
            { label: "更虐", value: "把高潮写得更虐" },
          ],
          allowFreeText: true,
        },
      ],
      verification: undefined,
    });
    expect(result.current.status).toBe("asking");
    expect(result.current.decision?.needClarification).toBe(true);
  });

  it("need_clarification=false：status=proceed，decision 清空", async () => {
    post.mockResolvedValue({
      data: { need_clarification: false, questions: [], verification: "我按你说的拉满高潮" },
      error: null,
    });
    const { result } = renderHook(() => useRewriteClarify());
    let vm: ClarifyDecisionVM | undefined;
    await act(async () => {
      vm = await result.current.check("p1", 1, "把第 3 段的高潮再拉满，删掉闪回", "草稿");
    });
    expect(vm?.needClarification).toBe(false);
    expect(result.current.status).toBe("proceed");
    expect(result.current.decision).toBeNull();
  });

  it("后端 error：视为放行（proceed，needClarification=false），不阻塞重写", async () => {
    post.mockResolvedValue({ data: null, error: { detail: "boom" } });
    const { result } = renderHook(() => useRewriteClarify());
    let vm: ClarifyDecisionVM | undefined;
    await act(async () => {
      vm = await result.current.check("p1", 1, "改", "草稿");
    });
    expect(vm?.needClarification).toBe(false);
    expect(result.current.status).toBe("proceed");
  });

  // 注：hook 的 try/catch 对「fetch 抛异常」的放行分支与上面「后端 error 信封」放行分支同构、
  // 行为一致（均 status=proceed、needClarification=false、返回 PROCEED）；此处不单测 throw 路径，
  // 因 mock 抛错 + React act 冲刷会触发 vitest 未处理错误误报（与被测逻辑无关，同 M1 useClarify.test.ts）。

  it("reset 清回 idle", async () => {
    post.mockResolvedValue({
      data: { need_clarification: true, questions: [{ question: "q", options: [], allow_free_text: true }] },
      error: null,
    });
    const { result } = renderHook(() => useRewriteClarify());
    await act(async () => {
      await result.current.check("p1", 1, "改", "草稿");
    });
    act(() => result.current.reset());
    expect(result.current.status).toBe("idle");
    expect(result.current.decision).toBeNull();
  });
});
