import path from "node:path";

import { PostgresHarnessRLRegistry } from "./registry.ts";
import { createHarnessRLService } from "./service.ts";
import { createHarnessRLTemporalGateway } from "./temporal.ts";

export function harnessRLRuntime(env: Record<string, string | undefined> = process.env) {
  const cwd = path.resolve(String(env.HWLAB_CASERUN_REPO_ROOT ?? process.cwd()));
  const caseRepo = path.resolve(cwd, String(env.HWLAB_CASERUN_CASE_REPO ?? env.HWLAB_CASE_REPO ?? "."));
  const stateRoot = path.resolve(cwd, String(env.HARNESSRL_STATE_DIR ?? ".state/harnessrl"));
  const registry = new PostgresHarnessRLRegistry(String(env.HARNESSRL_DATABASE_URL ?? ""));
  const temporalAddress = String(env.HARNESSRL_TEMPORAL_ADDRESS ?? env.TEMPORAL_ADDRESS ?? "");
  const temporalNamespace = String(env.HARNESSRL_TEMPORAL_NAMESPACE ?? "unidesk");
  const taskQueue = String(env.HARNESSRL_TEMPORAL_TASK_QUEUE ?? "hwlab-v03-harnessrl");
  const activity = {
    startToCloseTimeoutMs: positiveInteger(env.HARNESSRL_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS, 1_800_000, "HARNESSRL_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS"),
    heartbeatTimeoutMs: positiveInteger(env.HARNESSRL_ACTIVITY_HEARTBEAT_TIMEOUT_MS, 30_000, "HARNESSRL_ACTIVITY_HEARTBEAT_TIMEOUT_MS"),
    retryInitialIntervalMs: positiveInteger(env.HARNESSRL_ACTIVITY_RETRY_INITIAL_INTERVAL_MS, 1_000, "HARNESSRL_ACTIVITY_RETRY_INITIAL_INTERVAL_MS"),
    retryMaximumIntervalMs: positiveInteger(env.HARNESSRL_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS, 30_000, "HARNESSRL_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS"),
    retryMaximumAttempts: positiveInteger(env.HARNESSRL_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS, 5, "HARNESSRL_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS")
  };
  const temporal = createHarnessRLTemporalGateway({ address: temporalAddress, namespace: temporalNamespace, taskQueue, activity });
  return {
    cwd, caseRepo, stateRoot, registry, temporalAddress, temporalNamespace, taskQueue, activity,
    service: createHarnessRLService({ registry, temporal, cwd, caseRepo, stateRoot })
  };
}

function positiveInteger(value: string | undefined, fallback: number, name: string) {
  const parsed = Number.parseInt(String(value ?? fallback), 10);
  if (!Number.isSafeInteger(parsed) || parsed <= 0) throw Object.assign(new Error(`${name} must be a positive integer`), { code: "harnessrl_temporal_config_invalid", details: { name } });
  return parsed;
}
