import { describe, it, expect, vi, beforeEach } from "vitest";
import { getModuleOverviews, formatModuleOverviews, runDocModules } from "./modules";

describe("getModuleOverviews", () => {
  it("returns modules with overview and counts", () => {
    const modules = getModuleOverviews();
    expect(modules.length).toBeGreaterThan(0);

    const org = modules.find((m) => m.name === "organization");
    expect(org).toBeDefined();
    expect(org!.commandCount).toBeGreaterThan(0);
    expect(org!.queryCount).toBeGreaterThan(0);
    expect(org!.modelCount).toBeGreaterThan(0);
    expect(org!.overview).toContain("Organization module");
    expect(org!.dependencies).toContain("primitives");
  });

  it("returns empty dependencies for modules with none", () => {
    const modules = getModuleOverviews();
    const primitives = modules.find((m) => m.name === "primitives");
    expect(primitives).toBeDefined();
    expect(primitives!.dependencies).toEqual([]);
  });

  it("returns modules in alphabetical order", () => {
    const modules = getModuleOverviews();
    const names = modules.map((m) => m.name);
    const sorted = [...names].sort();
    expect(names).toEqual(sorted);
  });
});

describe("formatModuleOverviews", () => {
  it("formats modules with overview and counts", () => {
    const output = formatModuleOverviews([
      {
        name: "test-module",
        commandCount: 5,
        queryCount: 3,
        modelCount: 2,
        overview: "Test module overview.",
        dependencies: ["primitives"],
      },
    ]);
    expect(output).toContain("# test-module (5 commands, 3 queries, 2 models)");
    expect(output).toContain("Test module overview.");
    expect(output).toContain("Dependencies: primitives");
    expect(output).toContain("1 modules");
  });

  it("shows 'none' for modules with no dependencies", () => {
    const output = formatModuleOverviews([
      {
        name: "standalone",
        commandCount: 0,
        queryCount: 0,
        modelCount: 0,
        overview: "",
        dependencies: [],
      },
    ]);
    expect(output).toContain("Dependencies: none");
  });

  it("handles empty list", () => {
    expect(formatModuleOverviews([])).toBe("No modules found.");
  });
});

describe("runDocModules", () => {
  beforeEach(() => {
    vi.restoreAllMocks();
  });

  it("outputs valid JSON with --format json", () => {
    const logs: string[] = [];
    vi.spyOn(console, "log").mockImplementation((...args: unknown[]) => {
      logs.push(args.map(String).join(" "));
    });

    const exitCode = runDocModules("json");
    expect(exitCode).toBe(0);

    const parsed = JSON.parse(logs.join("\n")) as unknown[];
    expect(Array.isArray(parsed)).toBe(true);
    expect(parsed.length).toBeGreaterThan(0);

    const first = parsed[0] as Record<string, unknown>;
    expect(first).toHaveProperty("name");
    expect(first).toHaveProperty("commandCount");
    expect(first).toHaveProperty("queryCount");
    expect(first).toHaveProperty("modelCount");
    expect(first).toHaveProperty("overview");
    expect(first).toHaveProperty("dependencies");
  });
});
