import { describe, expect, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { DB } from "../generated/kysely-tailordb";
import { baseChildNode, baseLeafNode } from "../testing/fixtures";
import { run } from "./calculateSubtreeDepth";

describe("calculateSubtreeDepth", () => {
  it("returns 1 for leaf node (no children)", async () => {
    const { db, spies } = createMockDb<DB>();
    spies.select.mockReturnValueOnce([]);

    const result = await run(db, { nodeId: "node-3" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.depth).toBe(1);
    }
  });

  it("returns 2 for node with one level of children", async () => {
    const { db, spies } = createMockDb<DB>();
    spies.select.mockReturnValueOnce([baseLeafNode]).mockReturnValueOnce([]);

    const result = await run(db, { nodeId: "node-1" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.depth).toBe(2);
    }
  });

  it("returns 3 for node with two levels of children", async () => {
    const { db, spies } = createMockDb<DB>();
    spies.select
      .mockReturnValueOnce([baseChildNode])
      .mockReturnValueOnce([baseLeafNode])
      .mockReturnValueOnce([]);

    const result = await run(db, { nodeId: "node-1" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.depth).toBe(3);
    }
  });

  it("returns max depth for node with multiple branches", async () => {
    const shortChild = {
      id: "short-1",
      code: "S",
      name: "Short",
      parentId: "node-1",
      createdAt: new Date("2024-01-01T00:00:00.000Z"),
      updatedAt: null,
    };
    const deepChild = {
      id: "deep-1",
      code: "D",
      name: "Deep",
      parentId: "node-1",
      createdAt: new Date("2024-01-01T00:00:00.000Z"),
      updatedAt: null,
    };
    const deepGrandchild = {
      id: "deep-2",
      code: "DG",
      name: "Deep Grand",
      parentId: "deep-1",
      createdAt: new Date("2024-01-01T00:00:00.000Z"),
      updatedAt: null,
    };

    const { db, spies } = createMockDb<DB>();
    spies.select
      .mockReturnValueOnce([shortChild, deepChild])
      .mockReturnValueOnce([])
      .mockReturnValueOnce([deepGrandchild])
      .mockReturnValueOnce([]);

    const result = await run(db, { nodeId: "node-1" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.depth).toBe(3);
    }
  });
});
