import {
  DEFAULT_FILE_TIMEOUT_SECONDS,
  normalizeFileTimeoutSeconds,
  parseFileTimeoutOption,
} from "../shared/file-timeout.mjs";

export const DATABASE_BINDINGS = new Set(["shared", "per-runtime"]);

export { DEFAULT_FILE_TIMEOUT_SECONDS, parseFileTimeoutOption };

export function parseWorkersOption(value) {
  return parsePositiveInteger(value, "--workers");
}

export function parseRuntimeInstancesOption(value, label = "runtime.instances") {
  return parsePositiveInteger(value, label);
}

export function normalizeRuntimeInstances(value, label = "runtime.instances") {
  return normalizePositiveInteger(value, label);
}

export function parseRuntimeMaxConcurrentTasksOption(
  value,
  label = "runtime.maxConcurrentTasks"
) {
  return parsePositiveInteger(value, label);
}

export function normalizeRuntimeMaxConcurrentTasks(
  value,
  label = "runtime.maxConcurrentTasks"
) {
  if (value === undefined || value === null) {
    return Number.POSITIVE_INFINITY;
  }
  return normalizePositiveInteger(value, label);
}

export function normalizeDatabaseBinding(value, label = "database.binding") {
  const normalized = String(value || "").trim();
  if (!DATABASE_BINDINGS.has(normalized)) {
    throw new Error(
      `Invalid ${label} value "${value}". Expected one of: shared, per-runtime.`
    );
  }
  return normalized;
}

export function resolveExecutionConfig({ cli = {}, repo = {} } = {}) {
  return normalizeExecutionConfig({
    workers: cli.workers ?? repo.workers ?? 1,
    fileTimeoutSeconds:
      cli.fileTimeoutSeconds ?? repo.fileTimeoutSeconds ?? DEFAULT_FILE_TIMEOUT_SECONDS,
  });
}

export function normalizeExecutionConfig(input = {}) {
  return {
    workers: normalizePositiveInteger(input.workers ?? 1, "execution.workers"),
    fileTimeoutSeconds: normalizeFileTimeoutSeconds(
      input.fileTimeoutSeconds ?? DEFAULT_FILE_TIMEOUT_SECONDS
    ),
  };
}

export function buildRuntimeIds(count) {
  return Array.from({ length: count }, (_unused, index) => `runtime-${index + 1}`);
}

function parsePositiveInteger(value, label) {
  const parsed = Number.parseInt(String(value), 10);
  if (!Number.isInteger(parsed) || parsed <= 0) {
    throw new Error(`Invalid ${label} value "${value}". Expected a positive integer.`);
  }
  return parsed;
}

function normalizePositiveInteger(value, label) {
  const parsed = Number(value);
  if (!Number.isInteger(parsed) || parsed <= 0) {
    throw new Error(`${label} must be a positive integer.`);
  }
  return parsed;
}
