import { describe, expect, it } from "vitest";
import {
  addTrackerError,
  buildRunArtifact,
  buildStatusArtifact,
  buildServiceTrackers,
  finalizeServiceResult,
  formatDuration,
  formatError,
  formatServiceSummary,
  recordGraphError,
  recordTaskOutcome,
  summarizeDbBackend,
} from "./results.mjs";

describe("runner-results", () => {
  it("tracks task outcomes and graph errors", () => {
    const trackers = buildServiceTrackers(
      [
        {
          skipped: false,
          config: {
            name: "api",
            testkit: {
              database: {
                selectedBackend: "local",
              },
            },
          },
          suites: [
            {
              name: "health",
              type: "integration",
              framework: "k6",
              files: ["tests/health.js"],
              orderIndex: 0,
            },
          ],
        },
      ],
      1000
    );

    recordTaskOutcome(
      trackers,
      {
        serviceName: "api",
        suiteKey: "integration:health",
        file: "tests/health.js",
      },
      {
        failed: true,
        durationMs: 250,
        error: "boom",
      },
      1250
    );

    const tracker = trackers.get("api");
    addTrackerError(tracker, "worker failed");
    addTrackerError(tracker, "worker failed");
    recordGraphError(trackers, { assignedTargets: ["api"] }, "graph failed", 1300);

    const result = finalizeServiceResult(tracker, 1000, 1500);
    expect(result.failed).toBe(true);
    expect(result.failedSuiteCount).toBe(1);
    expect(result.totalFileCount).toBe(1);
    expect(result.failedFileCount).toBe(1);
    expect(result.passedFileCount).toBe(0);
    expect(result.errors).toEqual(["worker failed", "graph failed"]);
    expect(result.suites[0].framework).toBe("default");
    expect(result.suites[0].failedFileCount).toBe(1);
    expect(result.suites[0].files).toEqual([
      {
        path: "tests/health.js",
        failed: true,
        status: "failed",
        durationMs: 250,
        error: "boom",
      },
    ]);
  });

  it("builds run artifacts and formatting helpers", () => {
    const results = [
      {
        name: "api",
        failed: false,
        skipped: false,
        suiteCount: 1,
        completedSuiteCount: 1,
        failedSuiteCount: 0,
        totalFileCount: 3,
        completedFileCount: 3,
        passedFileCount: 3,
        failedFileCount: 0,
        notRunFileCount: 0,
        durationMs: 1200,
        dbBackend: "local",
        suites: [],
        errors: [],
      },
      {
        name: "frontend",
        failed: false,
        skipped: true,
        suiteCount: 0,
        completedSuiteCount: 0,
        failedSuiteCount: 0,
        totalFileCount: 0,
        completedFileCount: 0,
        passedFileCount: 0,
        failedFileCount: 0,
        notRunFileCount: 0,
        durationMs: 0,
        dbBackend: null,
        suites: [],
        errors: [],
      },
    ];

    const artifact = buildRunArtifact({
      productDir: "/tmp/my-product",
      results,
      startedAt: 1000,
      finishedAt: 4000,
      requestedJobs: 2,
      workerCount: 1,
      suiteType: "all",
      suiteNames: [],
      fileNames: [],
      framework: "all",
      shard: null,
      serviceFilter: null,
      metadata: {
        git: {
          branch: "main",
          commitSha: "abc",
          repoRoot: "/tmp",
        },
        host: {
          hostname: "local",
          username: "dev",
        },
        testkitVersion: "0.1.17",
      },
    });

    expect(artifact.product.name).toBe("my-product");
    expect(artifact.summary.services.total).toBe(1);
    expect(artifact.summary.files).toEqual({
      total: 3,
      passed: 3,
      failed: 0,
      notRun: 0,
    });
    expect(summarizeDbBackend(results)).toBe("local");
    expect(formatDuration(65_000)).toBe("1m 05s");
    expect(
      formatServiceSummary({
        completedSuiteCount: 2,
        failedSuiteCount: 1,
        suiteCount: 3,
        totalFileCount: 6,
        passedFileCount: 5,
        notRunFileCount: 1,
      })
    ).toBe("1/3 suites passed, 5/6 files passed, 1 suite not run");
    expect(formatError(new Error("boom"))).toBe("boom");
  });

  it("builds deterministic status artifacts", () => {
    const status = buildStatusArtifact({
      productDir: "/tmp/my-product",
      results: [
        {
          name: "api",
          failed: true,
          skipped: false,
          suites: [
            {
              name: "health",
              type: "integration",
              framework: "k6",
              files: [
                { path: "tests/api/integration/a.int.testkit.ts", status: "passed" },
                { path: "tests/api/integration/b.int.testkit.ts", status: "failed" },
              ],
            },
          ],
        },
      ],
      suiteType: "int",
      suiteNames: ["health"],
      fileNames: ["tests/api/integration/b.int.testkit.ts"],
      framework: "default",
      shard: null,
      serviceFilter: "api",
      metadata: {
        git: {
          branch: "main",
          commitSha: "abc123",
        },
        testkitVersion: "0.1.20",
      },
    });

    expect(status).toEqual({
      schemaVersion: 1,
      source: "testkit",
      notice: "Generated file. Do not edit manually.",
      product: {
        name: "my-product",
      },
      git: {
        branch: "main",
        commitSha: "abc123",
      },
      testkitVersion: "0.1.20",
      scope: {
        suiteType: "int",
        suiteNames: ["health"],
        fileNames: ["tests/api/integration/b.int.testkit.ts"],
        framework: "default",
        shard: null,
        serviceFilter: "api",
        isFullRun: false,
      },
      summary: {
        services: {
          total: 1,
          passed: 0,
          failed: 1,
        },
        tests: {
          total: 2,
          passed: 1,
          failed: 1,
          notRun: 0,
        },
      },
      tests: [
        {
          service: "api",
          type: "integration",
          path: "tests/api/integration/a.int.testkit.ts",
          status: "passed",
        },
        {
          service: "api",
          type: "integration",
          path: "tests/api/integration/b.int.testkit.ts",
          status: "failed",
        },
      ],
    });
  });

  it("marks unfiltered status artifacts as full runs", () => {
    const status = buildStatusArtifact({
      productDir: "/tmp/my-product",
      results: [],
      suiteType: "all",
      suiteNames: [],
      fileNames: [],
      framework: "all",
      shard: null,
      serviceFilter: null,
      metadata: {
        git: {
          branch: "main",
          commitSha: "abc123",
        },
        testkitVersion: "0.1.20",
      },
    });

    expect(status.scope.isFullRun).toBe(true);
  });
});
