import { describe, expect, it } from "vitest";
import {
  parseFileTimeoutOption,
  parseShardOption,
  parseSuiteOption,
  parseTypeOption,
  parseWorkersOption,
  resolveRequestedFiles,
  resolveCliSelection,
} from "./args.mjs";

describe("cli-args", () => {
  it("resolves a positional suite type", () => {
    expect(
      resolveCliSelection({
        first: "int",
        second: null,
        third: null,
      })
    ).toEqual({
      dbAction: null,
      knownFailuresAction: null,
      lifecycle: null,
      positionalType: "int",
    });
  });

  it("resolves lifecycle commands", () => {
    expect(
      resolveCliSelection({
        first: "status",
        second: null,
        third: null,
      })
    ).toEqual({
      dbAction: null,
      knownFailuresAction: null,
      lifecycle: "status",
      positionalType: null,
    });
  });

  it("resolves known-failures and db subcommands", () => {
    expect(
      resolveCliSelection({
        first: "known-failures",
        second: "render",
        third: null,
      })
    ).toEqual({
      dbAction: null,
      knownFailuresAction: "render",
      lifecycle: null,
      positionalType: null,
    });

    expect(
      resolveCliSelection({
        first: "db",
        second: "snapshot",
        third: "capture",
      })
    ).toEqual({
      dbAction: "snapshot-capture",
      knownFailuresAction: null,
      lifecycle: null,
      positionalType: null,
    });
  });

  it("rejects unknown positional arguments", () => {
    expect(() =>
      resolveCliSelection({
        first: "mystery",
        second: null,
        third: null,
      })
    ).toThrow('Unknown argument "mystery"');
  });

  it("parses types and suite selectors", () => {
    expect(parseTypeOption(["e2e,scenario,dal"], "int")).toEqual([
      "int",
      "e2e",
      "scenario",
      "dal",
    ]);
    expect(() => parseTypeOption(["all", "int"])).toThrow("cannot be combined");

    expect(parseSuiteOption(["auth,scenario:journeys,dal:queries"])).toEqual([
      { kind: "plain", name: "auth", raw: "auth" },
      { kind: "typed", type: "scenario", name: "journeys", raw: "scenario:journeys" },
      { kind: "typed", type: "dal", name: "queries", raw: "dal:queries" },
    ]);
  });

  it("parses and validates execution options", () => {
    expect(parseWorkersOption("3")).toBe(3);
    expect(parseFileTimeoutOption("45")).toBe(45);
    expect(() => parseWorkersOption("0")).toThrow("Invalid --workers value");
    expect(() => parseFileTimeoutOption("0")).toThrow(
      "Invalid --file-timeout-seconds value"
    );
  });

  it("parses and validates shards", () => {
    expect(parseShardOption("2/5")).toEqual({ index: 2, total: 5 });
    expect(parseShardOption(null)).toBeNull();
    expect(() => parseShardOption("2-of-5")).toThrow("Invalid --shard value");
    expect(() => parseShardOption("3/2")).toThrow("Expected 1 <= i <= n");
  });

  it("normalizes requested file paths against the product directory", () => {
    expect(
      resolveRequestedFiles(
        [
          "/tmp/product/tests/api/integration/health.int.testkit.ts",
          "./tests/api/integration/health.int.testkit.ts",
          "product/tests/api/integration/health.int.testkit.ts",
        ],
        "/tmp/product",
        "/tmp"
      )
    ).toEqual(["tests/api/integration/health.int.testkit.ts"]);
  });
});
