import { describe, expect, it } from "vitest";
import {
  buildRunSummaryLines,
  formatDuration,
  formatError,
  formatFrameworkLabel,
  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 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("Summary: 2 passed, 0 failed, 0 skipped, 0 not run across 3 files");
    expect(lines.join("\n")).toContain("Runtime Errors:");
    expect(lines.join("\n")).toContain("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("Summary: 0 passed, 0 failed, 1 skipped, 0 not run across 1 file");
    expect(lines.at(-1)).toBe("Result: PASSED");
  });

  it("appends known-failure issue validation summary lines", () => {
    const lines = buildRunSummaryLines(
      [
        {
          name: "api",
          skipped: false,
          failed: false,
          suiteCount: 1,
          completedSuiteCount: 1,
          skippedSuiteCount: 0,
          failedSuiteCount: 0,
          totalFileCount: 1,
          passedFileCount: 1,
          skippedFileCount: 0,
          notRunFileCount: 0,
          durationMs: 1_000,
          suites: [],
          errors: [],
        },
      ],
      1_000,
      {
        summary: {
          byCode: {
            closed_but_failing: 2,
            title_mismatch: 1,
          },
        },
      }
    );

    expect(lines.join("\n")).toContain("Known-failure issues:");
    expect(lines.join("\n")).toContain("2 closed issues still failing");
    expect(lines.join("\n")).toContain("1 title mismatch");
  });

  it("prefers structured HTTP assertion details over threshold wrapper text", () => {
    const lines = buildRunSummaryLines(
      [
        {
          name: "api",
          skipped: false,
          failed: true,
          suiteCount: 1,
          completedSuiteCount: 1,
          skippedSuiteCount: 0,
          failedSuiteCount: 1,
          totalFileCount: 1,
          passedFileCount: 0,
          failedFileCount: 1,
          skippedFileCount: 0,
          notRunFileCount: 0,
          durationMs: 500,
          suites: [
            {
              failed: true,
              type: "int",
              name: "default",
              framework: "k6",
              failedFiles: ["__testkit__/health/health.int.testkit.ts"],
              durationMs: 500,
              files: [
                {
                  path: "__testkit__/health/health.int.testkit.ts",
                  status: "failed",
                  error: "Default runtime thresholds failed: checks(rate==1.0)",
                  failureDetails: [
                    {
                      kind: "http-assertion",
                      key: "GET /health > status is 200",
                      title: "status is 200",
                      message: "GET /health expected 200, got 404",
                      request: {
                        method: "GET",
                        path: "/health",
                        requestId: "req-1",
                      },
                      response: {
                        status: 404,
                        bodyPreview: '{"error":"nope"}',
                      },
                    },
                  ],
                  triage: {
                    status: "known_failure",
                    entries: [
                      {
                        id: "health-is-bad",
                        state: "open",
                        issue: {
                          repo: "acme/example",
                          number: 42,
                        },
                      },
                    ],
                  },
                },
              ],
              error: null,
            },
          ],
          errors: [],
        },
      ],
      500
    );

    expect(lines.join("\n")).toContain("GET /health expected 200, got 404");
    expect(lines.join("\n")).toContain('response: {"error":"nope"}');
    expect(lines.join("\n")).toContain("triage: known issue #42 open");
    expect(lines.join("\n")).not.toContain("Default runtime thresholds failed: checks(rate==1.0)\n    response:");
  });
});
