// Terminal types (spec §4.5)

import type { Terminal, TerminalKind } from "@coder-studio/core";

/**
 * Specification for creating a new terminal
 */
export interface TerminalSpec {
  workspaceId: string;
  kind: TerminalKind;
  argv: string[];
  cwd: string;
  env?: Record<string, string>;
  cols?: number;
  rows?: number;
  title?: string;
  /**
   * Hex color (e.g. "#fcfffd") of the frontend xterm.js theme background that
   * will render this terminal. The TerminalManager uses it to derive
   * COLORFGBG so child TUIs (Claude Code, Codex, …) can pick a matching
   * light/dark color scheme. This is the only signal that survives the
   * Windows ConPTY layer, which otherwise intercepts OSC 11 background
   * queries. On Windows the server also injects OSC 11 responses directly
   * for TUIs such as Gemini CLI that rely on that escape sequence.
   */
  themeBackground?: string;
}

/**
 * Options for spawning a PTY process
 */
export interface PtySpawnOptions {
  cwd: string;
  env: Record<string, string>;
  cols: number;
  rows: number;
}

/**
 * Result of replay operation
 */
export type ReplayResult =
  | { status: "ok"; data: Buffer; seq: number }
  | { status: "too_old" }
  | { status: "unknown" };

export type TerminalReplayAvailability =
  | { kind: "available"; fromSeq: number }
  | { kind: "too_old" };

export type TerminalSnapshotAvailability = { kind: "available" } | { kind: "unavailable" };

export type TerminalRecoveryInspection =
  | {
      status: "ok";
      headSeq: number;
      replay: TerminalReplayAvailability;
      snapshot: TerminalSnapshotAvailability;
      alive: boolean;
      exitCode?: number;
    }
  | { status: "unknown" };

/**
 * Error thrown when terminal is not alive
 */
export class TerminalNotAliveError extends Error {
  constructor(message = "Terminal is not alive") {
    super(message);
    this.name = "TerminalNotAliveError";
  }
}

/**
 * Error thrown when terminal spawn fails synchronously
 */
export class TerminalSpawnError extends Error {
  readonly code = "terminal_spawn_failed";

  constructor(
    public readonly kind: "spawn_failed_sync",
    public readonly cause: Error,
    public readonly details?: {
      command?: string;
      cwd?: string;
      terminalKind?: TerminalKind;
    }
  ) {
    super(`Terminal spawn failed: ${cause.message}`);
    this.name = "TerminalSpawnError";
  }
}

/**
 * PTY process interface (abstraction over node-pty)
 */
export interface PtyProcess {
  readonly pid: number;
  onData(callback: (data: string) => void): void;
  onExit(
    callback: (event: {
      exitCode: number;
      signal?: number;
      reason?: "exit" | "pty_disconnected";
    }) => void
  ): void;
  write(data: Buffer | string): void;
  resize(cols: number, rows: number): void;
  kill(signal?: NodeJS.Signals): Promise<void>;
}

/**
 * PTY host interface (abstraction for testing)
 */
export interface PtyHost {
  spawn(argv: string[], options: PtySpawnOptions): PtyProcess;
}

/**
 * Broadcaster interface (for WebSocket broadcast)
 */
export interface Broadcaster {
  broadcast(topic: string, payload: unknown): void;
}

/**
 * Database interface for terminal persistence
 */
export interface TerminalDatabase {
  insert(terminal: Terminal): void;
  markEnded(id: string, endedAt: number, exitCode: number): void;
}

/**
 * Terminal ID type
 */
export type TerminalId = string;
