import path from "node:path";

import { createCloudWorkbenchApplication } from "./cloud-application.ts";
import { createWorkbenchDispatcher } from "./dispatcher.ts";
import { createNativeTestWorkbenchApplication } from "./native-application.ts";
import { createNativeAgentRunWorkbenchApplication } from "./native-agentrun-application.ts";
import { createNativeTestTemporalGateway } from "./native-temporal.ts";
import { createWorkbenchTemporalGateway } from "./temporal.ts";
import { createWorkbenchKafkaEventPublisher } from "./kafka-event-publisher.ts";
import type { WorkbenchEventPublisher } from "./contracts.ts";

export function workbenchRuntime(env: Record<string, string | undefined> = process.env, options: { eventPublisher?: WorkbenchEventPublisher | null } = {}) {
  const mode = String(env.WORKBENCH_MODE ?? "").trim();
  if (mode !== "native-test" && mode !== "agentrun-native" && mode !== "temporal") throw codedError("workbench_mode_required", "WORKBENCH_MODE must be native-test, agentrun-native, or temporal");
  const stateFile = path.resolve(String(env.WORKBENCH_NATIVE_STATE_FILE ?? ".state/workbench-native/state.json"));
  const eventPublisher = mode === "native-test"
    ? null
    : Object.hasOwn(options, "eventPublisher")
      ? options.eventPublisher ?? null
      : createWorkbenchKafkaEventPublisher({ env });
  const application = mode === "native-test"
    ? createNativeTestWorkbenchApplication({ stateFile })
    : mode === "agentrun-native"
      ? createNativeAgentRunWorkbenchApplication({ stateFile, env, eventPublisher })
      : createCloudWorkbenchApplication({ baseUrl: String(env.WORKBENCH_CLOUD_API_URL ?? ""), authorization: String(env.WORKBENCH_CLOUD_API_AUTHORIZATION ?? ""), eventPublisher });
  const temporalAddress = String(env.WORKBENCH_TEMPORAL_ADDRESS ?? env.TEMPORAL_ADDRESS ?? "");
  const temporalNamespace = String(env.WORKBENCH_TEMPORAL_NAMESPACE ?? "unidesk");
  const taskQueue = String(env.WORKBENCH_TEMPORAL_TASK_QUEUE ?? "hwlab-v03-workbench");
  const activity = mode === "native-test" ? null : {
    startToCloseTimeoutMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS, "WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS"),
    retryInitialIntervalMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS, "WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS"),
    retryMaximumIntervalMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS, "WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS"),
    retryMaximumAttempts: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS, "WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS")
  };
  const temporal = mode === "native-test" ? createNativeTestTemporalGateway(application) : createWorkbenchTemporalGateway({ address: temporalAddress, namespace: temporalNamespace, taskQueue, activity: activity! });
  return {
    mode,
    stateFile,
    temporalAddress,
    temporalNamespace,
    taskQueue, activity,
    eventPublisher,
    application,
    temporal,
    dispatch: createWorkbenchDispatcher({ application, temporal, mode }),
    async close() { await temporal.close(); await application.close?.(); }
  };
}

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