import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, expect, it } from "vitest";
import type { Namespace } 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 mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([]);

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

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

    expect(mock.selects).toHaveLength(1);
    expect(mock.selects[0]?.parameters).toContain("node-3");
    expect(mock.selects[0]?.sql).toMatch(/"parentId"/);
  });

  it("returns 2 for node with one level of children", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([baseLeafNode], []);

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

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

    expect(mock.selects).toHaveLength(2);
    expect(mock.selects[0]?.parameters).toContain("node-1");
    expect(mock.selects[1]?.parameters).toContain(baseLeafNode.id);
  });

  it("returns 3 for node with two levels of children", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([baseChildNode], [baseLeafNode], []);

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

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

    expect(mock.selects).toHaveLength(3);
    expect(mock.selects[0]?.parameters).toContain("node-1");
    expect(mock.selects[1]?.parameters).toContain(baseChildNode.id);
    expect(mock.selects[2]?.parameters).toContain(baseLeafNode.id);
  });

  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 mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([shortChild, deepChild], [], [deepGrandchild], []);

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

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

    expect(mock.selects).toHaveLength(4);
    expect(mock.selects[0]?.parameters).toContain("node-1");
    expect(mock.selects[1]?.parameters).toContain(shortChild.id);
    expect(mock.selects[2]?.parameters).toContain(deepChild.id);
    expect(mock.selects[3]?.parameters).toContain(deepGrandchild.id);
  });
});
