import { describe, expect, it } from "vitest";
import {
  buildRunSummaryLines,
  formatBatchDescriptor,
  formatDuration,
  formatError,
  formatFrameworkLabel,
  formatPlaywrightBatchFiles,
  formatServiceSummary,
  formatSuiteFramework,
  longestServiceName,
} from "./formatting.mjs";

describe("runner formatting", () => {
  it("formats durations compactly", () => {
    expect(formatDuration(900)).toBe("1s");
    expect(formatDuration(61_000)).toBe("1m 01s");
  });

  it("sanitizes default-runtime error messages", () => {
    expect(
      formatError(new Error("Command failed with exit code 99: /tmp/vendor/k6 run test.js"))
    ).toBe("Default runtime failed with exit code 99: test.js");
  });

  it("formats service summaries with not-run files", () => {
    expect(
      formatServiceSummary({
        completedSuiteCount: 2,
        failedSuiteCount: 1,
        skippedSuiteCount: 0,
        suiteCount: 3,
        totalFileCount: 5,
        passedFileCount: 3,
        skippedFileCount: 0,
        notRunFileCount: 1,
      })
    ).toBe("1/3 suites passed, 3/5 files passed, 1 suite not run");
  });

  it("formats skipped suites distinctly from passed suites", () => {
    expect(
      formatServiceSummary({
        completedSuiteCount: 2,
        failedSuiteCount: 0,
        skippedSuiteCount: 1,
        suiteCount: 2,
        totalFileCount: 3,
        passedFileCount: 1,
        skippedFileCount: 2,
        notRunFileCount: 0,
      })
    ).toBe("1/2 suites passed, 1/3 files passed, 1 suite skipped");
  });

  it("formats batch descriptors", () => {
    expect(formatBatchDescriptor({ framework: "k6", tasks: [{}, {}] })).toBe(" (2 files)");
    expect(formatBatchDescriptor({ framework: "playwright", tasks: [{}] })).toBe(
      " (playwright, 1 file)"
    );
  });

  it("formats Playwright file previews", () => {
    expect(formatPlaywrightBatchFiles({ tasks: [{ file: "a" }] })).toBe(" · a");
    expect(
      formatPlaywrightBatchFiles({
        tasks: [{ file: "a" }, { file: "b" }, { file: "c" }, { file: "d" }],
      })
    ).toBe(" · a, b, c, +1 more");
  });

  it("formats framework labels", () => {
    expect(formatFrameworkLabel("k6")).toBe("");
    expect(formatFrameworkLabel("playwright")).toBe("playwright");
    expect(formatSuiteFramework("playwright")).toBe(" [playwright]");
  });

  it("computes longest service name", () => {
    expect(longestServiceName([{ name: "api" }, { name: "frontend" }])).toBe(8);
  });

  it("builds printable summary lines", () => {
    const lines = buildRunSummaryLines(
      [
        {
          name: "frontend",
          skipped: false,
          failed: true,
          suiteCount: 2,
          completedSuiteCount: 2,
          skippedSuiteCount: 0,
          failedSuiteCount: 1,
          totalFileCount: 3,
          passedFileCount: 2,
          skippedFileCount: 0,
          notRunFileCount: 0,
          durationMs: 20_000,
          suites: [
            {
              failed: true,
              type: "e2e",
              name: "auth",
              framework: "playwright",
              failedFiles: ["a.pw.testkit.ts"],
              durationMs: 12_000,
              error: "boom",
            },
          ],
          errors: ["worker broke"],
        },
      ],
      20_000
    );

    expect(lines.join("\n")).toContain("services 0/1 passed");
    expect(lines.join("\n")).toContain("FAIL frontend");
    expect(lines.join("\n")).toContain("worker error: worker broke");
    expect(lines.at(-1)).toBe("Result: FAILED (1/1 services failed)");
  });

  it("marks services with only skipped suites as SKIP", () => {
    const lines = buildRunSummaryLines(
      [
        {
          name: "api",
          skipped: false,
          failed: false,
          suiteCount: 1,
          completedSuiteCount: 1,
          skippedSuiteCount: 1,
          failedSuiteCount: 0,
          totalFileCount: 1,
          passedFileCount: 0,
          skippedFileCount: 1,
          notRunFileCount: 0,
          durationMs: 0,
          suites: [],
          errors: [],
        },
      ],
      0
    );

    expect(lines.join("\n")).toContain("suites 1 skipped");
    expect(lines.join("\n")).toContain("files 1 skipped");
    expect(lines.join("\n")).toContain("SKIP api");
    expect(lines.at(-1)).toBe("Result: PASSED");
  });
});
