/**
 * Container orchestrator abstraction. Implementations can back onto Docker, Podman, or Kubernetes.
 */

export interface ContainerSpec {
  /** Docker/OCI image reference */
  image: string;
  /** Human-readable name (used as container name prefix) */
  name: string;
  /** Custom command to run (overrides image CMD) */
  command?: string[];
  /** Environment variables */
  env?: Record<string, string>;
  /** Host port to bind (null = auto-assign) */
  hostPort?: number | null;
  /** Container port to expose */
  containerPort?: number;
  /** Memory limit in bytes (default: 512 MB) */
  memoryLimit?: number;
  /** CPU period quota (nanoCPUs, default: 0.5 CPU) */
  nanoCpus?: number;
  /** Labels for identification / filtering */
  labels?: Record<string, string>;
  /** Network name to attach to */
  network?: string;
}

export interface ContainerInfo {
  containerId: string;
  name: string;
  state: 'running' | 'stopped' | 'starting' | 'error' | 'unknown';
  port?: number;
  /** Container IP on the first non-default network (for internal communication) */
  ip?: string;
  createdAt: Date;
}

export interface ContainerLogs {
  stdout: string;
  stderr: string;
}

export interface ExecResult {
  exitCode: number;
  stdout: string;
  stderr: string;
}

export interface McpOrchestrator {
  /** Pull an image if not present locally */
  pullImage(image: string): Promise<void>;

  /** Create and start a container */
  createContainer(spec: ContainerSpec): Promise<ContainerInfo>;

  /** Stop a running container */
  stopContainer(containerId: string, timeoutSeconds?: number): Promise<void>;

  /** Remove a stopped container */
  removeContainer(containerId: string, force?: boolean): Promise<void>;

  /** Get container info */
  inspectContainer(containerId: string): Promise<ContainerInfo>;

  /** Get container logs */
  getContainerLogs(containerId: string, opts?: { tail?: number; since?: number }): Promise<ContainerLogs>;

  /** Execute a command inside a running container with optional stdin */
  execInContainer(containerId: string, cmd: string[], opts?: { stdin?: string; timeoutMs?: number }): Promise<ExecResult>;

  /** Start a long-running interactive exec session (bidirectional stdio stream). */
  execInteractive?(containerId: string, cmd: string[]): Promise<InteractiveExec>;

  /** Check if the orchestrator runtime is available */
  ping(): Promise<boolean>;
}

/** A bidirectional stream to an interactive exec session. */
export interface InteractiveExec {
  /** Demuxed stdout stream (JSON-RPC responses come here). */
  stdout: NodeJS.ReadableStream;
  /** Write raw bytes to the process stdin. */
  write(data: string): void;
  /** Kill the exec process. */
  close(): void;
}

/** Default resource limits */
export const DEFAULT_MEMORY_LIMIT = 512 * 1024 * 1024; // 512 MB
export const DEFAULT_NANO_CPUS = 500_000_000;           // 0.5 CPU
