// SPEC: PJ2026-01040409 MDTODO前端重写; PJ2026-010405 云端控制台.
// Responsibility: 验证 HWPOD 源离线时任务详情以 typed partial 投影继续呈现。

import { beforeEach, describe, expect, test, vi } from "vitest";

const { taskDetail, tasks } = vi.hoisted(() => ({
  taskDetail: vi.fn(),
  tasks: vi.fn(),
}));

vi.mock("@/api", () => ({
  projectManagementAPI: { taskDetail, tasks },
}));

import { useMdtodoTaskData } from "./useMdtodoTaskData";

describe("useMdtodoTaskData", () => {
  beforeEach(() => {
    taskDetail.mockReset();
    tasks.mockReset();
  });

  test("keeps the projected task surface usable when live HWPOD detail is unavailable", async () => {
    taskDetail.mockResolvedValueOnce({
      ok: true,
      status: 200,
      data: {
        status: "partial",
        detail: null,
        detailAuthority: {
          state: "unavailable",
          authority: "project-management-projection",
          sourceKind: "hwpod-workspace",
          code: "hwpod_node_offline",
          message: "继续展示最近一次项目投影。",
          retryable: true,
          valuesRedacted: true,
        },
      },
    });
    const state = useMdtodoTaskData();

    await state.loadTaskDetail("mdtodo:source:file:R1");

    expect(state.taskDetail.value).toBeNull();
    expect(state.taskDetailAuthority.value).toMatchObject({
      state: "unavailable",
      code: "hwpod_node_offline",
    });
    expect(state.taskDetailError.value).toBe("继续展示最近一次项目投影。");
    expect(state.taskDetailLoading.value).toBe(false);
  });

  test("clears the projection notice when source Markdown becomes readable again", async () => {
    taskDetail
      .mockResolvedValueOnce({
        ok: true,
        status: 200,
        data: {
          detail: null,
          detailAuthority: {
            state: "unavailable",
            authority: "project-management-projection",
            message: "离线",
          },
        },
      })
      .mockResolvedValueOnce({
        ok: true,
        status: 200,
        data: {
          status: "ready",
          detail: {
            taskRef: "mdtodo:source:file:R1",
            taskId: "R1",
            body: "实时正文",
          },
          detailAuthority: { state: "ready", authority: "source-markdown" },
        },
      });
    const state = useMdtodoTaskData();

    await state.loadTaskDetail("mdtodo:source:file:R1");
    await state.loadTaskDetail("mdtodo:source:file:R1");

    expect(state.taskDetail.value?.body).toBe("实时正文");
    expect(state.taskDetailAuthority.value?.state).toBe("ready");
    expect(state.taskDetailError.value).toBeNull();
  });

  test("adds an exact task outside the bounded first window", async () => {
    const target = {
      taskRef: "mdtodo:source:file:R205",
      sourceId: "source",
      fileRef: "file",
      taskId: "R205",
      title: "新建任务",
      ordinal: 205,
    };
    tasks
      .mockResolvedValueOnce({
        ok: true,
        status: 200,
        data: {
          tasks: [
            {
              ...target,
              taskRef: "mdtodo:source:file:R1",
              taskId: "R1",
              ordinal: 1,
            },
          ],
          page: { offset: 0, limit: 100, total: 205, hasMore: true },
        },
      })
      .mockResolvedValueOnce({
        ok: true,
        status: 200,
        data: { tasks: [target] },
      });
    const state = useMdtodoTaskData();

    await state.loadTaskWindow("source", "file", target.taskRef);

    expect(tasks).toHaveBeenNthCalledWith(2, {
      taskRef: target.taskRef,
      sourceId: "source",
      fileRef: "file",
      limit: 1,
    });
    expect(state.resolvePreferredTask(target.taskRef)).toMatchObject({
      taskId: "R205",
      title: "新建任务",
    });
    expect(state.tasks.value.map((task) => task.taskId)).toEqual([
      "R1",
      "R205",
    ]);
  });
});
