import * as fs from 'node:fs';
import { pathToFileURL } from 'node:url';

import type { MatrixActor } from '@open-matrix/core/core/MatrixActor.js';
import { buildMountedInstanceBootstrapProps } from '@open-matrix/core/runtime/InstanceBootstrapContext.js';
import {
  buildMatrixHttpAssetMount,
  MatrixHttpAssetEndpointActor,
} from '@open-matrix/system-gateway-http';
import { HostAuthStateStore, HostCredentialStore } from '@open-matrix/system-auth';
import {
  loadBootstrapJsonObject,
  resolveBootstrapRefPath,
  loadBootstrapJsonValue,
} from '@open-matrix/core/runtime/InstanceBootstrapRefs.js';
import { MatrixRuntime } from '@open-matrix/core/runtime/MatrixRuntime.js';
import { loadMatrixServiceManifest } from '../utils/service-manifest.js';
import {
  loadPackageEnvironment,
  loadPackageEnvironmentFromPath,
  type IMatrixPackageEnvironment,
} from '../utils/package-environment.js';
import {
  deregisterRunnerBindings,
  deregisterRunnerRuntime,
  heartbeatRunnerRuntime,
  type IRunnerWebappRouteMetadata,
  registerRunnerBindings,
  type IRunnerBindingDeregistration,
  type IRunnerBindingRegistration,
  registerRunnerRuntime,
  renewRunnerBindings,
  resolveRunnerRuntimeId,
  type IRunnerRuntimeDeregistration,
  type IRunnerRuntimeRegistration,
} from '../utils/runner-control-plane.js';
import {
  defaultRunnerRuntimeMount,
  mountRunnerRuntimeControl,
  type RunnerRuntimeLifecycleState,
} from '../utils/runner-runtime-control.js';
import { resolveRunnerTransportPlan, type IResolvedRunnerTransportPlan } from '../utils/runner-transport.js';
import {
  createRunnerRuntimeHandle,
  formatRunnerRuntimeClosed,
  type IRunnerRuntimeClosed,
  type IRunnerRuntimeHandle,
} from '../utils/runner-runtime.js';
import {
  loadMatrixWebappManifest,
  type ILoadedMatrixWebappManifest,
} from '../utils/webapp-manifest.js';
import { installRunnerPlacementPolicy } from '../utils/runner-placement-policy.js';

export interface IServiceCommandOptions {
  readonly check?: boolean;
  readonly json?: boolean;
  readonly env?: string;
  readonly envFile?: string;
  readonly overrides?: string;
  readonly entry?: string;
  readonly export?: string;
  readonly root?: string;
  readonly mount?: string;
  readonly config?: string;
  readonly secrets?: string;
}

export interface IServiceCommandResult {
  readonly packageName: string;
  readonly packageDir: string;
  readonly manifestPath: string;
  readonly entryPath: string;
  readonly exportName: string;
  readonly checked: boolean;
  readonly environmentName?: string;
  readonly environmentPath?: string;
  readonly runnerTransport?: IResolvedRunnerTransportPlan;
  readonly overrides: Record<string, unknown>;
  readonly root?: string;
  readonly mount?: string;
  readonly configRef?: string;
  readonly secretsRef?: string;
  readonly instance: Record<string, unknown>;
  readonly serviceInstance: Record<string, unknown>;
  readonly deploymentInstance: Record<string, unknown>;
  readonly runtimeRegistration?: IRunnerRuntimeRegistration;
  readonly bindingRegistration?: IRunnerBindingRegistration;
  readonly runtimeDeregistration?: IRunnerRuntimeDeregistration;
  readonly bindingDeregistration?: IRunnerBindingDeregistration;
  readonly result?: unknown;
}

export interface IStartedServiceCommand {
  readonly result: IServiceCommandResult;
  readonly shutdownRequested: Promise<string>;
  readonly transportClosed?: Promise<IRunnerRuntimeClosed>;
  shutdown(): Promise<IServiceCommandResult>;
}

type BootstrapResult = {
  runtime?: {
    shutdown?: () => Promise<void> | void;
  };
} & Record<string, unknown>;

interface IStandaloneRunnerServices {
  readonly runtime: MatrixRuntime;
  readonly environment?: IMatrixPackageEnvironment;
  readonly runnerTransport?: IResolvedRunnerTransportPlan;
}

export async function serviceCommand(
  packageDir: string,
  options: IServiceCommandOptions = {},
): Promise<IServiceCommandResult> {
  const started = await startServiceCommand(packageDir, options);
  if (options.check) {
    return await started.shutdown();
  }

  if (options.json) {
    console.log(JSON.stringify(started.result, null, 2));
  } else {
    console.log(`[mx service] started ${started.result.packageName} via ${started.result.exportName}`);
    console.log(`[mx service] manifest: ${started.result.manifestPath}`);
    console.log(`[mx service] entry: ${started.result.entryPath}`);
  }

  let finalResult = started.result;
  const shutdownRequested = started.transportClosed
    ? Promise.race([
      started.shutdownRequested,
      started.transportClosed.then((closed) => {
        throw new Error(formatRunnerRuntimeClosed(closed));
      }),
    ])
    : started.shutdownRequested;

  await waitForShutdownSignal(async () => {
    finalResult = await started.shutdown();
  }, shutdownRequested);

  return finalResult;
}

export async function startServiceCommand(
  packageDir: string,
  options: IServiceCommandOptions = {},
): Promise<IStartedServiceCommand> {
  const loaded = loadMatrixServiceManifest(packageDir);
  const webapp = loadMatrixWebappManifest(loaded.packageDir);
  const envFile = options.envFile?.trim();
  const selectedEnvironment = envFile
    ? loadPackageEnvironmentFromPath(packageDir, envFile, options.env)
    : options.env?.trim()
    ? loadPackageEnvironment(packageDir, options.env)
    : undefined;
  const entryPath = options.entry
    ? loadBootstrapEntryPath(loaded.packageDir, options.entry, 'service entry override')
    : loaded.entryPath;
  const exportName = options.export?.trim() || loaded.exportName;
  const root = options.root?.trim()
    || selectedEnvironment?.environment.runtime.root
    || loaded.root;
  const runnerTransport = selectedEnvironment
    ? resolveRunnerTransportPlan(loaded.packageDir, selectedEnvironment, root)
    : undefined;
  const mount = options.mount?.trim() || loaded.mount;
  const configRef = options.config?.trim() || loaded.configRef;
  const config = configRef ? loadBootstrapJsonObject(loaded.packageDir, configRef, 'service config') : {};
  const manifestOverrides = deepMerge(config, loaded.overrides);
  const cliOverrides = parseOverrides(options.overrides);
  const effectiveOverrides = deepMerge(manifestOverrides, cliOverrides);
  const secretsRef = options.secrets?.trim() || undefined;
  const secrets = secretsRef ? loadBootstrapJsonValue(loaded.packageDir, secretsRef, 'service secrets') : undefined;
  const mountedInstanceBootstrap = buildMountedInstanceBootstrapProps({
    ...loaded.serviceInstance,
    ...(mount ? { mount } : {}),
    ...(configRef ? { configRef } : {}),
    ...(Array.isArray(secrets)
      ? { secretRefs: structuredClone(secrets) }
      : loaded.serviceInstance.secretRefs
        ? { secretRefs: structuredClone(loaded.serviceInstance.secretRefs) }
        : {}),
  }, effectiveOverrides);
  const { instance, serviceInstance, deploymentInstance } = mountedInstanceBootstrap;
  const bootstrapContext = {
    packageName: loaded.packageName,
    packageDir: loaded.packageDir,
    manifestPath: loaded.manifestPath,
    entryPath,
    exportName,
    ...(root ? { root } : {}),
    ...(mount ? { mount } : {}),
    ...(configRef ? { configRef } : {}),
    ...(secretsRef ? { secretsRef } : {}),
    ...(secrets !== undefined ? { secrets } : {}),
    ...(loaded.transport ? { transport: loaded.transport } : {}),
    ...(loaded.auth ? { auth: loaded.auth } : {}),
    ...(loaded.http ? { http: loaded.http } : {}),
    ...(selectedEnvironment ? {
      environmentName: selectedEnvironment.envName,
      environmentPath: selectedEnvironment.environmentPath,
      environment: selectedEnvironment.environment,
    } : {}),
    ...(runnerTransport ? { runnerTransport } : {}),
    ...mountedInstanceBootstrap,
  };
  const runnerRuntimeHandle = await createRunnerRuntimeHandle(root, runnerTransport);
  const runnerRuntime = runnerRuntimeHandle.runtime;
  registerHostHomeService(runnerRuntime, selectedEnvironment?.environment.host?.matrixDir);
  const runtimeId = resolveRunnerRuntimeId(loaded, selectedEnvironment);
  const runtimeMount = selectedEnvironment?.environment.runtime.runtimeMount
    ?? process.env.MATRIX_RUNTIME_MOUNT
    ?? defaultRunnerRuntimeMount(runtimeId);
  // Slice 1b (control-actor-nav): control authority is the canonical
  // per-runtime mount, not the legacy `.control` sibling.
  const controlMount = selectedEnvironment?.environment.runtime.controlMount
    ?? process.env.MATRIX_RUNTIME_CONTROL_MOUNT
    ?? runtimeMount;
  let lifecycleState: RunnerRuntimeLifecycleState = 'starting';
  let requestRuntimeShutdown: (reason: string) => void = () => undefined;
  const shutdownRequested = new Promise<string>((resolve) => {
    requestRuntimeShutdown = resolve;
  });
  const runnerServices: IStandaloneRunnerServices = {
    runtime: runnerRuntime,
    ...(selectedEnvironment ? { environment: selectedEnvironment.environment } : {}),
    ...(runnerTransport ? { runnerTransport } : {}),
  };
  installRunnerPlacementPolicy({
    runtime: runnerRuntime,
    manifest: loaded,
    environment: selectedEnvironment,
    runtimeId,
    authorityRoot: root,
  });

  const moduleUrl = `${pathToFileURL(entryPath).href}?mx_service=${Date.now()}-${Math.random().toString(16).slice(2)}`;
  const mod = await import(moduleUrl) as Record<string, unknown>;
  const bootstrap = mod[exportName];
  if (typeof bootstrap !== 'function') {
    throw new Error(`Package runtime factory export "${exportName}" was not found in ${entryPath}`);
  }

  const bootstrapResult = await (bootstrap as (...args: unknown[]) => Promise<unknown> | unknown)(
    effectiveOverrides,
    runnerServices,
    undefined,
    bootstrapContext,
  );
  const activeRuntime = resolveBootstrapRuntime(bootstrapResult) ?? runnerRuntime;
  const webappAssetMount = webapp
    ? await mountMatrixHttpAssetEndpoint(activeRuntime, webapp, runtimeId)
    : undefined;
  const mounted = await mountRunnerRuntimeControl({
    runtime: activeRuntime,
    runtimeId,
    runtimeMount,
    controlMount,
    startedAt: new Date().toISOString(),
    getState: () => lifecycleState,
    requestShutdown: (reason) => requestRuntimeShutdown(reason),
    loadedPackage: {
      packageRef: loaded.packageName,
      manifest: {
        packageRef: loaded.packageName,
        ...(loaded.mount ? { mount: loaded.mount } : {}),
        packageDir: loaded.packageDir,
      },
    },
  });
  const mountedControlMount = mounted.controlMount;
  lifecycleState = 'ready';
  const runtimeRegistration = await registerRunnerRuntime(
    activeRuntime,
    loaded,
    selectedEnvironment,
    runnerTransport,
    mountedInstanceBootstrap.serviceInstance.mount,
    runtimeMount,
    mountedControlMount,
    webapp && webappAssetMount ? buildRunnerWebappRouteMetadata(webapp, webappAssetMount) : undefined,
  );
  const bindingRegistration = await registerRunnerBindings(
    activeRuntime,
    loaded,
    selectedEnvironment,
    runtimeRegistration.runtimeId,
    mountedInstanceBootstrap.serviceInstance.mount,
  );
  lifecycleState = 'live';
  const serializedInstance = sanitizeForJson(instance) as Record<string, unknown>;
  let runtimeDeregistration: IRunnerRuntimeDeregistration | undefined;
  let bindingDeregistration: IRunnerBindingDeregistration | undefined;
  // Heartbeat tick + self-healing reclaim.
  //
  // registry.claim.renew (inside heartbeatRunnerRuntime / renewRunnerBindings)
  // returns the count of claims the server-side registry actually refreshed.
  // 0 means "the registry has no record of your claim" — typically because
  // the registry actor's in-memory _claims map was wiped when the SYSTEM
  // runtime restarted. Without reclaim the original claim's TTL (45s)
  // expires, the runtime vanishes from registry.query, the gateway can't
  // route to it, and apps appear "not registered" until manual intervention.
  //
  // We re-issue exactly what we issued at registration time. Server-side ops
  // are idempotent (onRegistryClaim preserves registeredAt/claimedAt for
  // existing entries; bindings.register is keyed by provider+match), so
  // reclaiming against a healthy registry is harmless.
  //
  // Log discipline: log STATE TRANSITIONS, not every tick. First failure
  // logs; subsequent consecutive failures at the same attempt count stay
  // silent; every 10th attempt logs that we're still trying; recovery from
  // a degraded state logs the duration. Healthy ticks log nothing.
  let runtimeReclaimAttempts = 0;
  let bindingReclaimAttempts = 0;

  const logIfTransitionOrMilestone = (
    attempts: number,
    onFirst: () => void,
    onMilestone: () => void,
  ): void => {
    if (attempts === 1) {
      onFirst();
    } else if (attempts % 10 === 0) {
      onMilestone();
    }
  };

  const runtimePresenceTimer = options.check === true
    ? undefined
    : setInterval(() => {
      void (async () => {
        try {
          const [heartbeat, renewal] = await Promise.all([
            heartbeatRunnerRuntime(activeRuntime, runtimeRegistration),
            renewRunnerBindings(activeRuntime, bindingRegistration),
          ]);

          if (heartbeat && !heartbeat.known) {
            runtimeReclaimAttempts += 1;
            logIfTransitionOrMilestone(
              runtimeReclaimAttempts,
              () => console.error(
                `[mx service] registry forgot runtime claim for ${heartbeat.runtimeId} (renewed=0); reclaiming`,
              ),
              () => console.error(
                `[mx service] still reclaiming runtime ${heartbeat.runtimeId} after ${runtimeReclaimAttempts} attempts`,
              ),
            );
            try {
              const reclaimed = await runtimeRegistration.reclaim();
              if (runtimeReclaimAttempts > 0) {
                console.error(
                  `[mx service] runtime reclaim recovered for ${heartbeat.runtimeId} after ${runtimeReclaimAttempts} attempt(s): ${reclaimed.inventoryClaimCount} inventory claims re-issued`,
                );
              }
              runtimeReclaimAttempts = 0;
            } catch (reclaimErr) {
              logIfTransitionOrMilestone(
                runtimeReclaimAttempts,
                () => console.error(
                  `[mx service] runtime reclaim failed for ${heartbeat.runtimeId}: ${reclaimErr instanceof Error ? reclaimErr.message : String(reclaimErr)} (will retry next tick)`,
                ),
                () => console.error(
                  `[mx service] runtime reclaim still failing for ${heartbeat.runtimeId} after ${runtimeReclaimAttempts} attempts: ${reclaimErr instanceof Error ? reclaimErr.message : String(reclaimErr)}`,
                ),
              );
            }
          } else if (heartbeat && runtimeReclaimAttempts > 0) {
            // Registry started answering renew=N>0 without us reclaiming
            // first — extremely rare (the registry would need to repopulate
            // claims from somewhere) but log the recovery so operators see
            // it. Reset the counter.
            console.error(
              `[mx service] runtime registry recovered without explicit reclaim for ${heartbeat.runtimeId} after ${runtimeReclaimAttempts} attempt(s)`,
            );
            runtimeReclaimAttempts = 0;
          }

          if (renewal && renewal.refreshed === 0 && (bindingRegistration?.bindings.length ?? 0) > 0) {
            bindingReclaimAttempts += 1;
            logIfTransitionOrMilestone(
              bindingReclaimAttempts,
              () => console.error(
                `[mx service] registry forgot binding claims for ${renewal.runtimeId} (refreshed=0); reclaiming`,
              ),
              () => console.error(
                `[mx service] still reclaiming bindings for ${renewal.runtimeId} after ${bindingReclaimAttempts} attempts`,
              ),
            );
            try {
              const reclaimed = await bindingRegistration?.reclaim();
              if (reclaimed && bindingReclaimAttempts > 0) {
                console.error(
                  `[mx service] binding reclaim recovered for ${renewal.runtimeId} after ${bindingReclaimAttempts} attempt(s): ${reclaimed.registryClaimCount} registry claims + ${reclaimed.bindingsRegisteredCount} binding forwards re-issued`,
                );
              }
              bindingReclaimAttempts = 0;
            } catch (reclaimErr) {
              logIfTransitionOrMilestone(
                bindingReclaimAttempts,
                () => console.error(
                  `[mx service] binding reclaim failed for ${renewal.runtimeId}: ${reclaimErr instanceof Error ? reclaimErr.message : String(reclaimErr)} (will retry next tick)`,
                ),
                () => console.error(
                  `[mx service] binding reclaim still failing for ${renewal.runtimeId} after ${bindingReclaimAttempts} attempts: ${reclaimErr instanceof Error ? reclaimErr.message : String(reclaimErr)}`,
                ),
              );
            }
          } else if (renewal && bindingReclaimAttempts > 0) {
            console.error(
              `[mx service] binding registry recovered without explicit reclaim for ${renewal.runtimeId} after ${bindingReclaimAttempts} attempt(s)`,
            );
            bindingReclaimAttempts = 0;
          }
        } catch (err) {
          console.error(
            `[mx service] runtime presence tick failed: ${err instanceof Error ? err.message : String(err)}`,
          );
        }
      })();
    }, 10_000);
  const buildResult = (): IServiceCommandResult => ({
    packageName: loaded.packageName,
    packageDir: loaded.packageDir,
    manifestPath: loaded.manifestPath,
    entryPath,
    exportName,
    checked: options.check === true,
    ...(selectedEnvironment ? {
      environmentName: selectedEnvironment.envName,
      environmentPath: selectedEnvironment.environmentPath,
    } : {}),
    ...(runnerTransport ? { runnerTransport } : {}),
    overrides: effectiveOverrides,
    ...(root ? { root } : {}),
    ...(mount ? { mount } : {}),
    ...(configRef ? { configRef } : {}),
    ...(secretsRef ? { secretsRef } : {}),
    instance: serializedInstance,
    serviceInstance: structuredClone(serializedInstance),
    deploymentInstance: structuredClone(serializedInstance),
    runtimeRegistration,
    bindingRegistration,
    ...(runtimeDeregistration ? { runtimeDeregistration } : {}),
    ...(bindingDeregistration ? { bindingDeregistration } : {}),
    result: sanitizeForJson(bootstrapResult),
  });
  let shutdownPromise: Promise<IServiceCommandResult> | null = null;

  return {
    result: buildResult(),
    ...(runnerRuntimeHandle.closed ? { transportClosed: runnerRuntimeHandle.closed } : {}),
    async shutdown(): Promise<IServiceCommandResult> {
      if (!shutdownPromise) {
        shutdownPromise = (async () => {
          lifecycleState = 'stopping';
          if (runtimePresenceTimer) {
            clearInterval(runtimePresenceTimer);
          }
          ({ runtimeDeregistration, bindingDeregistration } = await shutdownBootstrapRuntime(
            bootstrapResult,
            activeRuntime,
            runtimeRegistration,
            bindingRegistration,
            runnerRuntimeHandle,
          ));
          lifecycleState = 'stopped';
          return buildResult();
        })();
      }
      return await shutdownPromise;
    },
    shutdownRequested,
  };
}

function registerHostHomeService(
  runtime: MatrixRuntime,
  matrixDir: string | undefined,
): void {
  const hostHome = matrixDir?.trim();
  if (hostHome) {
    runtime.registerService('matrix-host-home', hostHome);
    runtime.registerService('credential-store', new HostCredentialStore(new HostAuthStateStore(hostHome)));
  }
}

async function mountMatrixHttpAssetEndpoint(
  runtime: MatrixRuntime,
  webapp: ILoadedMatrixWebappManifest,
  runtimeId?: string,
): Promise<string> {
  const assetMount = buildMatrixHttpAssetMount(webapp.appName, runtimeId);
  if (!runtime.hasComponent(assetMount)) {
    await runtime.createSupervised(MatrixHttpAssetEndpointActor as unknown as new () => MatrixActor, assetMount, {
      assetEndpoint: {
        packageName: webapp.packageName,
        appName: webapp.appName,
        distDir: webapp.distDir,
        entryFile: webapp.entryFile,
      },
    });
  }
  return assetMount;
}

function buildRunnerWebappRouteMetadata(
  webapp: ILoadedMatrixWebappManifest,
  assetMount: string,
): IRunnerWebappRouteMetadata {
  return {
    appName: webapp.appName,
    routePrefix: `/apps/${webapp.appName}/`,
    ...(webapp.displayName ? { displayName: webapp.displayName } : {}),
    ...(webapp.icon ? { icon: webapp.icon } : {}),
    ...(typeof webapp.navOrder === 'number' ? { navOrder: webapp.navOrder } : {}),
    ...(webapp.description ? { description: webapp.description } : {}),
    ...(webapp.shells && webapp.shells.length > 0 ? { shells: webapp.shells } : {}),
    assetMount,
  };
}

function parseOverrides(raw: string | undefined): Record<string, unknown> {
  if (!raw) return {};
  try {
    const parsed = JSON.parse(raw) as unknown;
    if (!isRecord(parsed)) {
      throw new Error('overrides must be a JSON object');
    }
    return parsed;
  } catch (err) {
    throw new Error(`Failed to parse service overrides: ${err instanceof Error ? err.message : String(err)}`);
  }
}

function deepMerge(
  base: Record<string, unknown>,
  patch: Record<string, unknown>,
): Record<string, unknown> {
  const output = structuredClone(base);
  for (const [key, value] of Object.entries(patch)) {
    const current = output[key];
    if (isRecord(current) && isRecord(value)) {
      output[key] = deepMerge(current, value);
      continue;
    }
    output[key] = value;
  }
  return output;
}

function loadBootstrapEntryPath(packageDir: string, ref: string, label: string): string {
  const entryPath = ref.trim();
  if (entryPath.length === 0) {
    throw new Error(`${label} must be a non-empty path`);
  }
  const filePath = resolveBootstrapRefPath(packageDir, entryPath);
  if (!fs.existsSync(filePath)) {
    throw new Error(`${label} not found at ${filePath}`);
  }
  return filePath;
}

async function shutdownBootstrapRuntime(
  result: unknown,
  activeRuntime?: MatrixRuntime,
  registration?: IRunnerRuntimeRegistration,
  bindingRegistration?: IRunnerBindingRegistration,
  runnerRuntimeHandle?: IRunnerRuntimeHandle,
): Promise<{
  readonly runtimeDeregistration?: IRunnerRuntimeDeregistration;
  readonly bindingDeregistration?: IRunnerBindingDeregistration;
}> {
  let shutdownHandled = false;
  let runtimeDeregistration: IRunnerRuntimeDeregistration | undefined;
  let bindingDeregistration: IRunnerBindingDeregistration | undefined;
  if (isRecord(result)) {
    const runtime: unknown = result.runtime;
    if (isRecord(runtime)) {
      const shutdown = runtime.shutdown;
      if (typeof shutdown === 'function') {
        if (activeRuntime) {
          bindingDeregistration = await deregisterRunnerBindings(activeRuntime, bindingRegistration);
          runtimeDeregistration = await deregisterRunnerRuntime(activeRuntime, registration);
        }
        await shutdown.call(runtime);
        shutdownHandled = Object.is(runtime, runnerRuntimeHandle?.runtime);
      }
    }
  }
  if (runnerRuntimeHandle && !shutdownHandled) {
    if (!runtimeDeregistration && activeRuntime) {
      bindingDeregistration = await deregisterRunnerBindings(activeRuntime, bindingRegistration);
      runtimeDeregistration = await deregisterRunnerRuntime(activeRuntime, registration);
    }
    await runnerRuntimeHandle.shutdown();
  }
  return {
    ...(runtimeDeregistration ? { runtimeDeregistration } : {}),
    ...(bindingDeregistration ? { bindingDeregistration } : {}),
  };
}

function resolveBootstrapRuntime(result: unknown): MatrixRuntime | undefined {
  if (!isRecord(result)) {
    return undefined;
  }
  const runtime = result.runtime;
  return runtime instanceof MatrixRuntime ? runtime : undefined;
}

function sanitizeForJson(value: unknown, depth = 8, seen = new WeakSet<object>()): unknown {
  if (value == null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
    return value;
  }
  if (typeof value === 'bigint') {
    return value.toString();
  }
  if (typeof value === 'function' || typeof value === 'symbol') {
    return undefined;
  }
  if (Array.isArray(value)) {
    if (depth <= 0) return `[array:${value.length}]`;
    return value
      .map((entry) => sanitizeForJson(entry, depth - 1, seen))
      .filter((entry) => entry !== undefined);
  }
  if (!isRecord(value)) {
    return String(value);
  }
  if (seen.has(value)) {
    return '[circular]';
  }
  seen.add(value);
  if (depth <= 0) {
    return '[object]';
  }
  const output: Record<string, unknown> = {};
  for (const [key, entry] of Object.entries(value)) {
    const sanitized = sanitizeForJson(entry, depth - 1, seen);
    if (sanitized !== undefined) {
      output[key] = sanitized;
    }
  }
  return output;
}

async function waitForShutdownSignal(
  onShutdown: () => Promise<void>,
  shutdownRequested?: Promise<string>,
): Promise<void> {
  await new Promise<void>((resolve, reject) => {
    let settled = false;
    const complete = (err?: unknown) => {
      if (settled) return;
      settled = true;
      process.off('SIGINT', handleSignal);
      process.off('SIGTERM', handleSignal);
      if (err) {
        reject(err);
        return;
      }
      resolve();
    };

    const handleSignal = () => {
      void onShutdown()
        .then(() => complete())
        .catch((err) => complete(err));
    };

    process.on('SIGINT', handleSignal);
    process.on('SIGTERM', handleSignal);
    shutdownRequested
      ?.then(() => handleSignal())
      .catch((err) => complete(err));
  });
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}
