import { describe, expect, it } from "vitest";
import type { CategoryNode } from "../categoryTypes";
import {
  findCategoryNode,
  flattenCategoryOptions,
  flattenCategoryTree,
  getCategoryBranchMainPlanCount,
  getCategoryParentOptions,
  retainExistingCategoryIds,
} from "../categoryTree";

const grandchild: CategoryNode = {
  id: "3", categoryCode: "C", categoryName: "C", categoryType: "SITUATION",
  parentId: "2", categoryPath: "/A/B/C", sortNo: 0, documentCount: 0,
  rowVersion: 0, children: [],
};
const child: CategoryNode = {
  id: "2", categoryCode: "B", categoryName: "B", categoryType: "STYLE",
  parentId: "1", categoryPath: "/A/B", sortNo: 0, documentCount: 0,
  rowVersion: 0, children: [grandchild],
};
const root: CategoryNode = {
  id: "1", categoryCode: "A", categoryName: "A", categoryType: "SCENE",
  parentId: null, categoryPath: "/A", sortNo: 0, documentCount: 0,
  rowVersion: 0, children: [child],
};
const other: CategoryNode = {
  ...root, id: "4", categoryCode: "D", categoryName: "D", categoryPath: "/D",
  children: [],
};

describe("category tree pure functions", () => {
  it("按服务器结构递归展平，不重建路径", () => {
    expect(flattenCategoryTree([root, other]).map(x => x.id)).toEqual(["1", "2", "3", "4"]);
    expect(findCategoryNode([root], "3")?.categoryPath).toBe("/A/B/C");
  });

  it("分类选项按任意深度缩进，父节点先于子节点且ID保持字符串", () => {
    const options = flattenCategoryOptions([other, root]);
    expect(options.map((option) => option.id)).toEqual(["1", "2", "3", "4"]);
    expect(options.map((option) => option.depth)).toEqual([0, 1, 2, 0]);
    expect(options[0].displayLabel).toBe("A");
    expect(options[1].displayLabel).toBe("\u3000\u3000B");
    expect(options[2].displayLabel).toBe("\u3000\u3000\u3000\u3000C");
    expect(typeof options[2].id).toBe("string");
    expect(options[2].categoryPath).toBe("/A/B/C");
  });

  it("同级按sortNo后按字符串ID稳定排序", () => {
    const highId = { ...other, id: "20", sortNo: 1 };
    const lowId = { ...other, id: "3", sortNo: 1 };
    const later = { ...other, id: "1", sortNo: 2 };
    expect(flattenCategoryOptions([later, highId, lowId]).map((x) => x.id))
      .toEqual(["3", "20", "1"]);
  });

  it("编辑父分类选项过滤自身和所有后代", () => {
    expect(getCategoryParentOptions([root, other], child).map(x => x.id)).toEqual(["1", "4"]);
  });

  it("刷新后只保留仍存在的展开ID", () => {
    expect([...retainExistingCategoryIds(new Set(["1", "3", "9"]), [root])]).toEqual(["1", "3"]);
  });

  it("父分类展示自身及全部后代的主案总数", () => {
    const countedGrandchild = { ...grandchild, documentCount: 3 };
    const countedChild = { ...child, documentCount: 2, children: [countedGrandchild] };
    const countedRoot = { ...root, documentCount: 1, children: [countedChild] };
    expect(getCategoryBranchMainPlanCount(countedRoot)).toBe(6);
    expect(getCategoryBranchMainPlanCount(countedChild)).toBe(5);
  });
});
