/**
 * Consumer-facing tmux port interfaces
 *
 * DESIGN DECISION (Phase 3): Port interfaces needed by core-layer consumers
 * (EventDrivenWorkerPool, RecoveryManager) are defined here so that core-layer
 * modules have a stable contract without importing from the implementations layer.
 *
 * src/implementations/tmux/types.ts imports these types from here and re-exports
 * them so that existing callers that import from tmux/types.ts continue to work.
 *
 * Internal types (WrapperConfig, WrapperManifest, StalenessConfig, ExecFn, WatchFn,
 * TmuxSessionConfig, TmuxAgentType, etc.) remain in src/implementations/tmux/types.ts
 * because they are implementation concerns. TmuxSpawnConfig extends TmuxSpawnCoreConfig
 * defined here — that extension is the only coupling point.
 */

import type { TaskId } from './domain.js';
import type { AutobeatError } from './errors.js';
import type { Result } from './result.js';

// ─── Handle ───────────────────────────────────────────────────────────────────

/**
 * Handle to a live tmux session.
 * Returned from TmuxConnectorPort.spawn(); passed back to destroy/sendKeys/isAlive.
 */
export interface TmuxHandle {
  /** Full session name (e.g. "beat-task-abc123") */
  readonly sessionName: string;
  /** Task ID that owns this session */
  readonly taskId: TaskId;
  /** Base directory where session data (sentinel, messages) lives */
  readonly sessionsDir: string;
}

// ─── Output message ───────────────────────────────────────────────────────────

/**
 * A single output message written by the wrapper script.
 */
export interface OutputMessage {
  readonly sequence: number;
  readonly timestamp: string;
  readonly type: 'stdout' | 'stderr' | 'result';
  readonly content: string;
}

// ─── Callbacks ────────────────────────────────────────────────────────────────

/**
 * Callbacks passed to TmuxConnectorPort.spawn() for push-based event delivery.
 */
export interface SpawnCallbacks {
  onOutput: (msg: OutputMessage) => void;
  onExit: (code: number | null, signal?: string) => void;
}

// ─── Spawn config ─────────────────────────────────────────────────────────────

/**
 * Minimal spawn configuration for the TmuxConnectorPort interface.
 *
 * DESIGN DECISION: Defined here (core layer) to break the circular dependency
 * between core/agents.ts (AgentAdapter.buildTmuxCommand return type) and
 * src/implementations/tmux/types.ts (TmuxSpawnConfig). Only the fields needed
 * at the port boundary are declared here. Implementation-layer TmuxSpawnConfig
 * extends this interface and adds agent-specific fields (TmuxAgentType, staleness,
 * etc.) that are not implementation concerns of the core layer.
 *
 * Core-layer consumers (EventDrivenWorkerPool) treat this type opaquely — they
 * receive it from AgentAdapter.buildTmuxCommand() and pass it directly to
 * TmuxConnectorPort.spawn() without accessing individual fields.
 */
export interface TmuxSpawnCoreConfig {
  /** Task identifier — used to name the session directory and tmux session */
  readonly taskId: TaskId;
  /** Base directory where all session data lives */
  readonly sessionsDir: string;
  /** Session name — must match SESSION_NAME_REGEX (beat-* prefix) */
  readonly name: string;
  /** Command to run inside the session */
  readonly command: string;
  /** CLI arguments to pass to the agent */
  readonly agentArgs: readonly string[];
}

// ─── Port interfaces ──────────────────────────────────────────────────────────

/**
 * Minimal session manager port for RecoveryManager (Phase 3).
 * Only the methods needed by core-layer consumers are exposed here.
 * The full TmuxSessionManagerPort (with createSession, destroySession, etc.)
 * remains in src/implementations/tmux/types.ts for the tmux package internals.
 */
export interface TmuxSessionManagerCorePort {
  isAlive(name: string): Result<boolean, AutobeatError>;
  /**
   * Send control key sequence (e.g. C-c) to a session WITHOUT -l (literal) mode.
   * Implementation: tmux send-keys -t '<name>' <keys>  (no -l flag)
   */
  sendControlKeys(name: string, keys: string): Result<void, AutobeatError>;
  /**
   * List all active tmux sessions. Used by RecoveryManager to batch liveness
   * checks at startup — one exec call instead of N sequential has-session calls.
   * Returns an array of objects with at least a `name` field; on error (e.g.
   * no tmux server running) returns an empty array rather than propagating the error
   * so callers can treat the empty result as "no live sessions".
   */
  listSessions(): Result<ReadonlyArray<{ readonly name: string }>, AutobeatError>;
}

/**
 * Port interface for the high-level managed session lifecycle.
 * TmuxConnector is the canonical implementation.
 *
 * DESIGN DECISION: Defined in core/tmux-types.ts in Phase 3 so that core-layer
 * consumers (EventDrivenWorkerPool) can depend on this interface without
 * importing from the implementations layer.
 *
 * spawn() accepts TmuxSpawnCoreConfig — the minimal core-layer type. The concrete
 * TmuxConnector casts it to the richer TmuxSpawnConfig (which extends TmuxSpawnCoreConfig)
 * at the implementation boundary, where the full field set is needed to configure
 * the tmux session and wrapper script.
 */
export interface TmuxConnectorPort {
  spawn(config: TmuxSpawnCoreConfig, callbacks: SpawnCallbacks): Result<TmuxHandle, AutobeatError>;
  destroy(handle: TmuxHandle): Result<void, AutobeatError>;
  sendKeys(handle: TmuxHandle, keys: string): Result<void, AutobeatError>;
  /**
   * Send control key sequence (e.g. C-c) to a session WITHOUT -l (literal) mode.
   * Delegates to TmuxSessionManagerPort.sendControlKeys(handle.sessionName, keys).
   */
  sendControlKeys(handle: TmuxHandle, keys: string): Result<void, AutobeatError>;
  isAlive(handle: TmuxHandle): Result<boolean, AutobeatError>;
  getActiveHandles(): TmuxHandle[];
  dispose(): void;
}
