import { resolve } from "node:path";

import { resolveCliChildJsonCommandResult } from "./cli-child-json-recovery";
import { runCommand, type CommandResult } from "./command";
import { resolveConfigRef } from "./ops/config-refs";
import { readEnvSourceFile, requiredEnvValue } from "./secrets";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneSpecForNode, isHwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeNativeDevelopmentSpec } from "./hwlab-node-lanes";

type Application = "workbench" | "hwpod" | "caserun";
type Service = "api" | "worker" | "web";
type Action = "start" | "stop" | "restart" | "status" | "logs";

export function hwlabNativeDevelopmentHelp(): Record<string, unknown> {
  return {
    ok: true,
    command: "hwlab nodes native-development workbench",
    usage: [
      "bun scripts/cli.ts hwlab nodes native-development workbench status --node <node> --lane <lane>",
      "bun scripts/cli.ts hwlab nodes native-development workbench api|worker|web start|stop|restart|status|logs --node <node> --lane <lane>",
      "bun scripts/cli.ts hwlab nodes native-development workbench cli <health|session|turn|events ...> --node <node> --lane <lane>",
      "bun scripts/cli.ts hwlab nodes native-development hwpod status --node <node> --lane <lane>",
      "bun scripts/cli.ts hwlab nodes native-development hwpod api|worker|web start|stop|restart|status|logs --node <node> --lane <lane>",
      "bun scripts/cli.ts hwlab nodes native-development caserun api|web start|stop|restart|status|logs --node <node> --lane <lane>",
    ],
    contract: "L1 API/Web 用户入口只输出 owning YAML 解析出的固定 HTTPS 域名；IP、port 和 bind/probe 地址不作为用户入口。",
    configPath: hwlabRuntimeLaneConfigPath(),
  };
}

export function runHwlabNativeDevelopmentCommand(args: string[]): Record<string, unknown> {
  if (args.length === 0 || args.includes("--help") || args.includes("-h")) return hwlabNativeDevelopmentHelp();
  const [applicationRaw, serviceRaw, actionRaw] = args;
  const application = parseApplication(applicationRaw);
  const node = requiredOption(args, "--node");
  const lane = requiredOption(args, "--lane");
  if (!isHwlabRuntimeLane(lane)) throw new Error(`--lane must be declared in ${hwlabRuntimeLaneConfigPath()}`);
  const spec = hwlabRuntimeLaneSpecForNode(lane, node);
  const native = spec.nativeDevelopment?.[application];
  if (native === undefined) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.${application} is required`);
  const env = application === "workbench"
    ? workbenchEnvironment(spec, native as HwlabRuntimeNativeDevelopmentSpec["workbench"])
    : application === "hwpod"
      ? hwlabHwpodNativeDevelopmentEnvironment(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>)
      : hwlabCaseRunNativeDevelopmentEnvironment(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["caserun"]>);
  if (application === "workbench" && serviceRaw === "cli") {
    const commandArgs = withoutOptions(args.slice(2), ["--node", "--lane"]);
    if (commandArgs.length === 0) throw new Error("native-development workbench cli requires a Workbench command");
    const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "workbench", ...commandArgs];
    const result = runCommand(command, spec.workspace, {
      timeoutMs: cliTimeoutMs(commandArgs),
      env: { ...process.env, ...env, WORKBENCH_API_URL: env.WORKBENCH_NATIVE_API_URL },
    });
    const payload = parsePayload(result, "hwlab-workbench-cli-json");
    const failed = result.exitCode !== 0 || payload.ok === false;
    return {
      ok: !failed,
      command: "hwlab nodes native-development workbench cli",
      node,
      lane,
      transport: commandArgs.includes("--over-api") ? "native-api" : "local-dispatcher",
      configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.workbench`,
      workbenchResult: payload,
      ...(failed ? { error: nativeCliFailure(result, payload) } : {}),
    };
  }
  if (application === "hwpod" && serviceRaw === "cli") {
    const commandArgs = withoutOptions(args.slice(2), ["--node", "--lane"]);
    if (commandArgs.length === 0) throw new Error("native-development hwpod cli requires a HWPOD command");
    const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "hwpod", ...commandArgs];
    const result = runCommand(command, spec.workspace, {
      timeoutMs: cliTimeoutMs(commandArgs),
      env: { ...process.env, ...env, HWLAB_RUNTIME_API_URL: env.HWPOD_NATIVE_API_URL },
    });
    const payload = parsePayload(result, "hwlab-hwpod-cli-json");
    const failed = result.exitCode !== 0 || payload.ok === false;
    return {
      ok: !failed,
      command: "hwlab nodes native-development hwpod cli",
      node,
      lane,
      transport: commandArgs.includes("--over-api") ? "native-api" : "local-function",
      configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.hwpod`,
      hwpodResult: payload,
      ...(failed ? { error: nativeCliFailure(result, payload) } : {}),
    };
  }
  if (application === "workbench" && serviceRaw === "status") {
    const remaining = withoutOptions(args.slice(2), ["--node", "--lane"]);
    if (remaining.length > 0) throw new Error(`native-development workbench status does not accept positional arguments: ${remaining.join(" ")}`);
    const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "workbench", "service", "status"];
    const result = runCommand(command, spec.workspace, { timeoutMs: 15_000, env: { ...process.env, ...env } });
    const payload = parsePayload(result, "hwlab-workbench-service-status-json");
    return {
      ok: result.exitCode === 0 && payload.ok !== false,
      command: "hwlab nodes native-development workbench status",
      node,
      lane,
      action: "status",
      configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.workbench`,
      userEndpoint: { url: `${native.publicExposure.publicBaseUrl}/workbench` },
      serviceResult: payload,
      ...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_cli_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
    };
  }
  if (application === "hwpod" && serviceRaw === "status") {
    const remaining = withoutOptions(args.slice(2), ["--node", "--lane"]);
    if (remaining.length > 0) throw new Error(`native-development hwpod status does not accept positional arguments: ${remaining.join(" ")}`);
    const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "hwpod", "service", "status"];
    const result = runCommand(command, spec.workspace, { timeoutMs: 30_000, env: { ...process.env, ...env } });
    const payload = parsePayload(result, "hwlab-hwpod-service-status-json");
    return {
      ok: result.exitCode === 0 && payload.ok !== false,
      command: "hwlab nodes native-development hwpod status",
      node,
      lane,
      action: "status",
      configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.hwpod`,
      userEndpoint: { url: `${native.publicExposure.publicBaseUrl}${(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>).web.accessProfile.startPath}` },
      serviceResult: payload,
      ...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_cli_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
    };
  }
  const service = parseService(serviceRaw, application);
  const action = parseAction(actionRaw);
  const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", application, "service", service, action];
  const result = runCommand(command, spec.workspace, { timeoutMs: 15_000, env: { ...process.env, ...env } });
  const payload = parsePayload(result, `hwlab-${application}-${service}-${action}-json`);
  const publicEndpoint = service === "api"
    ? { url: native.publicExposure.publicBaseUrl }
    : service === "web"
      ? { url: application === "hwpod" ? `${native.publicExposure.publicBaseUrl}${(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>).web.accessProfile.startPath}` : `${native.publicExposure.publicBaseUrl}/${application === "workbench" ? "workbench" : "caserun"}` }
      : null;
  return {
    ok: result.exitCode === 0 && payload.ok !== false,
    command: `hwlab nodes native-development ${application} ${service} ${action}`,
    node,
    lane,
    service,
    action,
    configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.${application}`,
    publicExposureSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.${application}.publicExposure`,
    userEndpoint: publicEndpoint,
    serviceResult: payload,
    ...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_service_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
  };
}

function workbenchEnvironment(spec: HwlabRuntimeLaneSpec, native: HwlabRuntimeNativeDevelopmentSpec["workbench"]): NodeJS.ProcessEnv {
  const sourceRef = hwlabNativeDevelopmentSourceCommitRef(spec);
  const sourceCommitResult = runCommand(["git", "rev-parse", "--verify", `${sourceRef}^{commit}`], spec.workspace, { timeoutMs: 5_000 });
  if (sourceCommitResult.exitCode !== 0 || !/^[0-9a-f]{40}$/iu.test(sourceCommitResult.stdout.trim())) throw new Error(`cannot resolve HWLAB L1 runner source commit from ${sourceRef} in ${spec.workspace}`);
  return hwlabNativeDevelopmentEnvironment(native, spec, sourceCommitResult.stdout.trim());
}

export function hwlabNativeDevelopmentSourceCommitRef(spec: HwlabRuntimeLaneSpec): string {
  const remoteName = spec.sourceWorkspace?.git?.remoteName;
  if (!remoteName) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${spec.lane}.targets.${spec.nodeId}.sourceWorkspace.git.remoteName is required for L1 runner source authority`);
  return `refs/remotes/${remoteName}/${spec.sourceBranch}`;
}

export function hwlabNativeDevelopmentEnvironment(native: HwlabRuntimeNativeDevelopmentSpec["workbench"], spec: HwlabRuntimeLaneSpec, sourceCommit: string): NodeJS.ProcessEnv {
  const codeAgent = spec.codeAgentRuntime;
  if (codeAgent === undefined) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${spec.lane}.targets.${spec.nodeId}.codeAgentRuntime is required`);
  const kafkaBridge = codeAgent.kafkaEventBridge;
  if (kafkaBridge === undefined) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${spec.lane}.targets.${spec.nodeId}.${native.kafka.configRef} is required`);
  if (native.kafka.hwlabEventConsumerGroupId === kafkaBridge.hwlabEventConsumerGroupId) throw new Error("native Workbench Kafka consumer group must be distinct from the Cloud API live SSE consumer group");
  if (!/^[0-9a-f]{40}$/iu.test(sourceCommit)) throw new Error("sourceCommit must be the HWLAB L1 runner source authority 40-hex git SHA");
  const providerSecretNames = codeAgent.providerSecretNames;
  if (providerSecretNames === undefined) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${spec.lane}.targets.${spec.nodeId}.codeAgentRuntime.providerSecretNames is required`);
  const defaultProviderKey = codeAgent.defaultProviderProfile.toLowerCase().replace(/[^a-z0-9]+/gu, "-");
  if (!providerSecretNames[defaultProviderKey]) throw new Error(`codeAgentRuntime.providerSecretNames.${defaultProviderKey} is required for defaultProviderProfile=${codeAgent.defaultProviderProfile}`);
  const authorizationSource = readEnvSourceFile({
    root: "/root/.unidesk/.state/secrets",
    sourceRef: codeAgent.apiKeySourceRef,
  });
  const agentRunApiKey = requiredEnvValue(authorizationSource.values, codeAgent.apiKeySourceKey, codeAgent.apiKeySourceRef);
  const sessionIndex = native.kafka.refreshReplay.sessionIndex;
  return {
    WORKBENCH_MODE: native.mode,
    WORKBENCH_TEMPORAL_ADDRESS: native.temporal.address,
    WORKBENCH_TEMPORAL_NAMESPACE: native.temporal.namespace,
    WORKBENCH_TEMPORAL_TASK_QUEUE: native.temporal.taskQueue,
    WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS: String(native.temporal.activity.startToCloseTimeoutMs),
    WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS: String(native.temporal.activity.retryInitialIntervalMs),
    WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS: String(native.temporal.activity.retryMaximumIntervalMs),
    WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS: String(native.temporal.activity.retryMaximumAttempts),
    AGENTRUN_MGR_URL: native.agentRun.managerUrl,
    AGENTRUN_API_KEY: agentRunApiKey,
    HWLAB_CODE_AGENT_ADAPTER: codeAgent.adapter,
    HWLAB_CODE_AGENT_AGENTRUN_ALLOW_PRIVATE_URL: "1",
    HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: spec.nodeId,
    HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: codeAgent.defaultProviderProfile,
    HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE: codeAgent.runnerNamespace,
    HWLAB_CODE_AGENT_AGENTRUN_SECRET_NAMESPACE: codeAgent.secretNamespace,
    ...providerSecretNameEnvironment(providerSecretNames),
    HWLAB_CODE_AGENT_AGENTRUN_GITHUB_TOOL_SECRET_NAME: codeAgent.toolSecretNames.githubPr,
    HWLAB_CODE_AGENT_AGENTRUN_UNIDESK_SSH_TOOL_SECRET_NAME: codeAgent.toolSecretNames.unideskSsh,
    HWLAB_CODE_AGENT_AGENTRUN_REPO_URL: spec.gitReadUrl,
    HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: sourceCommit,
    HWLAB_RUNTIME_API_URL: native.agentRun.runtimeApiUrl,
    HWLAB_RUNTIME_WEB_URL: native.agentRun.runtimeWebUrl,
    HWLAB_RUNTIME_NAMESPACE: spec.runtimeNamespace,
    HWLAB_RUNTIME_LANE: spec.lane,
    HWLAB_RUNTIME_ENDPOINT_LOCKED: "1",
    HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME: "1",
    HWLAB_KAFKA_DIRECT_PUBLISH_ENABLED: "false",
    HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_ENABLED: "true",
    HWLAB_KAFKA_TRANSACTIONAL_PROJECTOR_ENABLED: "false",
    HWLAB_KAFKA_PROJECTION_OUTBOX_RELAY_ENABLED: "false",
    HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false",
    HWLAB_KAFKA_BOOTSTRAP_SERVERS: native.kafka.bootstrapServers,
    HWLAB_KAFKA_DNS_SERVERS: native.kafka.dnsServers.join(","),
    HWLAB_KAFKA_DNS_SEARCH_DOMAINS: native.kafka.dnsSearchDomains.join(","),
    HWLAB_KAFKA_AGENTRUN_EVENT_TOPIC: kafkaBridge.agentRunEventTopic,
    HWLAB_KAFKA_EVENT_TOPIC: kafkaBridge.hwlabEventTopic,
    HWLAB_KAFKA_CLIENT_ID: native.kafka.clientId,
    HWLAB_KAFKA_HWLAB_EVENT_GROUP_ID: native.kafka.hwlabEventConsumerGroupId,
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_GROUP_PREFIX: native.kafka.refreshReplay.groupIdPrefix,
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_TIMEOUT_MS: String(native.kafka.refreshReplay.timeoutMs),
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_SCAN_LIMIT: String(native.kafka.refreshReplay.scanLimit),
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_MATCHED_EVENT_LIMIT: String(native.kafka.refreshReplay.matchedEventLimit),
    HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_LIVE_BUFFER_LIMIT: String(native.kafka.refreshReplay.liveBufferLimit),
    ...(sessionIndex === undefined ? {} : {
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_ENABLED: String(sessionIndex.enabled),
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_MAX_EVENTS: String(sessionIndex.maxEvents),
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_MAX_EVENTS_PER_SESSION: String(sessionIndex.maxEventsPerSession),
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_BOOTSTRAP_TIMEOUT_MS: String(sessionIndex.bootstrapTimeoutMs),
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_REBUILD_INTERVAL_MS: String(sessionIndex.rebuildIntervalMs),
      HWLAB_WORKBENCH_KAFKA_REFRESH_INDEX_REBUILD_COOLDOWN_MS: String(sessionIndex.rebuildCooldownMs),
    }),
    WORKBENCH_NATIVE_SERVICE_STATE_DIR: native.stateDir,
    WORKBENCH_NATIVE_STATE_FILE: resolve(spec.workspace, native.stateFile),
    WORKBENCH_API_BIND_HOST: native.api.bindHost,
    WORKBENCH_API_PROBE_HOST: native.api.probeHost,
    WORKBENCH_PUBLIC_BASE_URL: native.publicExposure.publicBaseUrl,
    WORKBENCH_API_PORT: String(native.api.port),
    WORKBENCH_API_IDLE_TIMEOUT_SECONDS: String(native.api.idleTimeoutSeconds),
    WORKBENCH_WORKER_BIND_HOST: native.worker.bindHost,
    WORKBENCH_WORKER_PROBE_HOST: native.worker.probeHost,
    WORKBENCH_WORKER_HEALTH_PORT: String(native.worker.healthPort),
    WORKBENCH_WEB_BIND_HOST: native.web.bindHost,
    WORKBENCH_WEB_PROBE_HOST: native.web.probeHost,
    WORKBENCH_WEB_PORT: String(native.web.port),
    WORKBENCH_NATIVE_API_URL: `http://${native.api.probeHost}:${native.api.port}`,
    WORKBENCH_WEB_RUNTIME_CONFIG: JSON.stringify(native.web.runtimeConfig),
  };
}

function providerSecretNameEnvironment(providerSecretNames: Readonly<Record<string, string>>): NodeJS.ProcessEnv {
  return Object.fromEntries(Object.entries(providerSecretNames).map(([profile, secretName]) => {
    const profileKey = profile.toUpperCase().replace(/[^A-Z0-9]+/gu, "_");
    return [`HWLAB_CODE_AGENT_AGENTRUN_${profileKey}_SECRET_NAME`, secretName];
  }));
}

export function parseHwlabNativeCliPayload(
  result: Pick<CommandResult, "stdout" | "stderr" | "exitCode" | "signal" | "timedOut">,
  requestedStdoutType = "hwlab-native-cli-json",
): Record<string, unknown> {
  const resolution = resolveCliChildJsonCommandResult({ result, requestedStdoutType });
  if (resolution.parsed !== null) return resolution.parsed;
  const diagnostics = resolution.diagnostics;
  const stdoutKind = String(diagnostics.stdoutKind ?? "non-json");
  const code = result.timedOut
    ? "hwlab_native_cli_timeout"
    : stdoutKind === "empty"
      ? "hwlab_native_cli_output_empty"
      : "hwlab_native_cli_output_invalid";
  return {
    ok: false,
    status: "failed",
    error: {
      code,
      message: result.timedOut
        ? "HWLAB native CLI timed out before returning a complete JSON result"
        : stdoutKind === "empty"
          ? "HWLAB native CLI returned no JSON result"
          : "HWLAB native CLI returned an incomplete or invalid JSON result",
      exitCode: result.exitCode,
      signal: result.signal,
      timedOut: result.timedOut,
      stdoutKind,
      stdoutBytes: Buffer.byteLength(result.stdout),
      stderrBytes: Buffer.byteLength(result.stderr),
      stderrTail: result.stderr.trim().slice(-2000),
      parser: diagnostics,
      valuesRedacted: true,
    },
    valuesRedacted: true,
  };
}

function parsePayload(result: CommandResult, requestedStdoutType: string): Record<string, unknown> {
  return parseHwlabNativeCliPayload(result, requestedStdoutType);
}

function nativeCliFailure(result: CommandResult, payload: Record<string, unknown>): Record<string, unknown> {
  const payloadError = payload.error;
  if (payloadError !== null && typeof payloadError === "object" && !Array.isArray(payloadError)) return payloadError as Record<string, unknown>;
  return {
    code: result.timedOut ? "hwlab_native_cli_timeout" : "hwlab_native_cli_failed",
    exitCode: result.exitCode,
    signal: result.signal,
    timedOut: result.timedOut,
    stderrTail: result.stderr.trim().slice(-2000),
    valuesRedacted: true,
  };
}

function parseApplication(value: string | undefined): Application {
  if (value === "workbench" || value === "hwpod" || value === "caserun") return value;
  throw new Error("native-development application must be workbench, hwpod, or caserun");
}

function parseService(value: string | undefined, application: Application): Service {
  if (value === "api" || value === "web" || (application !== "caserun" && value === "worker")) return value;
  throw new Error(`native-development ${application} service must be ${application === "caserun" ? "api or web" : "api, worker, or web"}`);
}

function parseAction(value: string | undefined): Action {
  if (value === "start" || value === "stop" || value === "restart" || value === "status" || value === "logs") return value;
  throw new Error("native-development workbench action must be start, stop, restart, status, or logs");
}

function requiredOption(args: string[], option: string): string {
  const index = args.indexOf(option);
  const value = index < 0 ? undefined : args[index + 1];
  if (!value || value.startsWith("--")) throw new Error(`${option} requires a value`);
  return value;
}

function withoutOptions(args: string[], options: string[]): string[] {
  const result: string[] = [];
  for (let index = 0; index < args.length; index += 1) {
    if (options.includes(args[index])) {
      index += 1;
      continue;
    }
    result.push(args[index]);
  }
  return result;
}

function cliTimeoutMs(args: string[]): number {
  const index = args.indexOf("--timeout-ms");
  const requested = index >= 0 ? Number.parseInt(args[index + 1] ?? "", 10) : 0;
  return Number.isSafeInteger(requested) && requested > 0 ? requested + 5_000 : 30_000;
}

function hwlabCaseRunNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntimeNativeDevelopmentSpec["caserun"]>): NodeJS.ProcessEnv {
  return {
    CASERUN_NATIVE_SERVICE_STATE_DIR: native.stateDir,
    CASERUN_PUBLIC_BASE_URL: native.publicExposure.publicBaseUrl,
    CASERUN_PROBE_HOST: native.api.probeHost,
    CASERUN_API_BIND_HOST: native.api.bindHost,
    CASERUN_API_PORT: String(native.api.port),
    CASERUN_WEB_BIND_HOST: native.web.bindHost,
    CASERUN_WEB_PORT: String(native.web.port),
  };
}

export function hwlabHwpodNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>): NodeJS.ProcessEnv {
  const nodeAuthSource = readEnvSourceFile({
    root: "/root/.unidesk/.state/secrets",
    sourceRef: native.nodeAuth.sourceRef,
  });
  const nodeToken = requiredEnvValue(nodeAuthSource.values, native.nodeAuth.sourceKey, native.nodeAuth.sourceRef);
  const databaseSource = readEnvSourceFile({
    root: "/root/.unidesk/.state/secrets",
    sourceRef: native.specRegistry.database.sourceRef,
  });
  const databaseUrl = requiredEnvValue(databaseSource.values, native.specRegistry.database.sourceKey, native.specRegistry.database.sourceRef);
  const builtInSpecs = native.specRegistry.builtInConfigRefs.map((configRef) => {
    const resolved = resolveConfigRef(configRef, "nativeDevelopment.hwpod.specRegistry.builtInConfigRefs");
    return { configRef, sha256: resolved.sha256, document: resolved.value };
  });
  return {
    HWPOD_NATIVE_SERVICE_STATE_DIR: native.stateDir,
    HWPOD_HEALTH_TIMEOUT_MS: String(native.healthTimeoutMs),
    HWPOD_PUBLIC_BASE_URL: native.publicExposure.publicBaseUrl,
    HWPOD_TEMPORAL_ADDRESS: native.temporal.address,
    HWPOD_TEMPORAL_NAMESPACE: native.temporal.namespace,
    HWPOD_TEMPORAL_TASK_QUEUE: native.temporal.taskQueue,
    HWPOD_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS: String(native.temporal.activity.startToCloseTimeoutMs),
    HWPOD_ACTIVITY_RETRY_INITIAL_INTERVAL_MS: String(native.temporal.activity.retryInitialIntervalMs),
    HWPOD_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS: String(native.temporal.activity.retryMaximumIntervalMs),
    HWPOD_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS: String(native.temporal.activity.retryMaximumAttempts),
    HWPOD_NODE_WS_TOKEN: nodeToken,
    HWPOD_SPEC_DATABASE_URL: databaseUrl,
    HWPOD_SPEC_DATABASE_SCHEMA: native.specRegistry.database.schema,
    HWPOD_SPEC_DATABASE_TABLE: native.specRegistry.database.table,
    HWPOD_SPEC_DATABASE_CONNECTION_TIMEOUT_MS: String(native.specRegistry.database.connectionTimeoutMs),
    HWPOD_BUILTIN_SPEC_DOCUMENTS_JSON: JSON.stringify(builtInSpecs),
    HWPOD_API_BIND_HOST: native.api.bindHost,
    HWPOD_API_PROBE_HOST: native.api.probeHost,
    HWPOD_API_PORT: String(native.api.port),
    HWPOD_WORKER_BIND_HOST: native.worker.bindHost,
    HWPOD_WORKER_PROBE_HOST: native.worker.probeHost,
    HWPOD_WORKER_HEALTH_PORT: String(native.worker.healthPort),
    HWPOD_WEB_BIND_HOST: native.web.bindHost,
    HWPOD_WEB_PROBE_HOST: native.web.probeHost,
    HWPOD_WEB_PORT: String(native.web.port),
    HWPOD_WEB_RUNTIME_CONFIG: JSON.stringify(native.web.runtimeConfig),
    HWPOD_WEB_ACCESS_PROFILE_JSON: JSON.stringify(native.web.accessProfile),
    HWPOD_NATIVE_API_URL: `http://${native.api.probeHost}:${native.api.port}`,
    HWPOD_NODE_OPS_API_URL: `http://${native.api.probeHost}:${native.api.port}`,
  };
}
