import { describe, expect, it } from "vitest";
import {
  buildRuntimeIds,
  DATABASE_BINDINGS,
  DEFAULT_FILE_TIMEOUT_SECONDS,
  normalizeDatabaseBinding,
  normalizeExecutionConfig,
  normalizeRuntimeMaxConcurrentTasks,
  normalizeRuntimeInstances,
  parseFileTimeoutOption,
  parseRuntimeMaxConcurrentTasksOption,
  parseRuntimeInstancesOption,
  parseWorkersOption,
  resolveExecutionConfig,
} from "./execution-config.mjs";

describe("execution-config", () => {
  it("parses worker and runtime-instance options", () => {
    expect(parseWorkersOption("8")).toBe(8);
    expect(parseRuntimeInstancesOption("2")).toBe(2);
    expect(parseRuntimeMaxConcurrentTasksOption("4")).toBe(4);
    expect(parseFileTimeoutOption("45")).toBe(45);
    expect(() => parseWorkersOption("0")).toThrow('Invalid --workers value "0"');
    expect(() => parseRuntimeInstancesOption("0")).toThrow('Invalid runtime.instances value "0"');
    expect(() => parseRuntimeMaxConcurrentTasksOption("0")).toThrow(
      'Invalid runtime.maxConcurrentTasks value "0"'
    );
    expect(() => parseFileTimeoutOption("0")).toThrow(
      'Invalid --file-timeout-seconds value "0"'
    );
  });

  it("normalizes execution defaults", () => {
    expect(normalizeExecutionConfig({ workers: 8 })).toEqual({
      workers: 8,
      fileTimeoutSeconds: DEFAULT_FILE_TIMEOUT_SECONDS,
    });
  });

  it("applies CLI values over repo execution defaults", () => {
    expect(
      resolveExecutionConfig({
        repo: { workers: 3, fileTimeoutSeconds: 30 },
        cli: { workers: 6, fileTimeoutSeconds: 90 },
      })
    ).toEqual({
      workers: 6,
      fileTimeoutSeconds: 90,
    });
  });

  it("builds runtime ids from an instance count", () => {
    expect(buildRuntimeIds(3)).toEqual(["runtime-1", "runtime-2", "runtime-3"]);
  });

  it("normalizes runtime instances and database bindings", () => {
    expect(normalizeRuntimeInstances(2)).toBe(2);
    expect(normalizeRuntimeMaxConcurrentTasks(undefined)).toBe(Number.POSITIVE_INFINITY);
    expect(normalizeRuntimeMaxConcurrentTasks(3)).toBe(3);
    for (const binding of DATABASE_BINDINGS) {
      expect(normalizeDatabaseBinding(binding)).toBe(binding);
    }
    expect(() => normalizeDatabaseBinding("legacy")).toThrow(
      'Invalid database.binding value "legacy"'
    );
  });
});
