/**
 * Orchestrator chat connectors (F4).
 *
 * A connector mediates the chat channel between the fleet **orchestrator** and
 * its human operator. Connectors are PEERS — tmux (default), Discord, Matrix,
 * and future first-party plugins — selected per fleet, never hardwired. Fleet
 * core depends only on the small uniform interface below, so a new connector
 * drops in without touching the fleet.
 *
 * The interface is deliberately minimal: send (orchestrator → human),
 * subscribe (human → orchestrator), health (reachable/authed liveness). Thread
 * support is optional metadata (`threadId`) so thread-capable connectors
 * (Matrix rooms/threads, the future Mosaic Discord plugin) fit without an
 * interface change.
 */

/** The connector kinds shipped/known to the framework. */
export type ConnectorKind = 'tmux' | 'discord' | 'matrix';

/** A message the orchestrator sends out to the human operator. */
export interface OutboundMessage {
  /** Message body (markdown where the connector supports it). */
  text: string;
  /** Optional thread/topic id for thread-capable connectors. */
  threadId?: string;
  /** Optional attachment references (paths or URLs); connector-dependent. */
  attachments?: string[];
}

/** A message received from the human operator. */
export interface InboundMessage {
  /** Message body. */
  text: string;
  /** Thread/topic id if the connector carries one. */
  threadId?: string;
  /** Opaque sender identifier (connector-scoped). */
  sender: string;
  /** ISO-8601 timestamp the connector assigns/observes. */
  ts: string;
}

/** Result of a send — the "ack" half of ack/health. */
export interface SendResult {
  /** True when the connector accepted/delivered the message. */
  delivered: boolean;
  /** Connector-assigned message id when available. */
  messageId?: string;
  /** Reason when `delivered` is false. */
  error?: string;
}

/** Liveness of a connector — the "health" half of ack/health. */
export interface ConnectorHealth {
  /** The transport endpoint is reachable. */
  reachable: boolean;
  /** Credentials are valid / the connector is authenticated. */
  authenticated: boolean;
  /** ISO-8601 of the last successful interaction, if any. */
  lastSeen?: string;
  /** Human-readable detail (e.g. failure reason). */
  detail?: string;
}

/** Unsubscribe handle returned by `subscribe`. */
export type Unsubscribe = () => void;

/**
 * The uniform contract every orchestrator chat connector implements. Small by
 * design — send / subscribe / health — so connectors are interchangeable and
 * fleet core never branches on connector kind.
 */
export interface OrchestratorConnector {
  /** Which kind of connector this is. */
  readonly kind: ConnectorKind;
  /** Send a message from the orchestrator to the operator. */
  send(message: OutboundMessage): Promise<SendResult>;
  /** Subscribe to inbound operator messages; returns an unsubscribe handle. */
  subscribe(handler: (message: InboundMessage) => void): Unsubscribe;
  /** Report connector liveness (reachable + authenticated). */
  health(): Promise<ConnectorHealth>;
}

/**
 * Connector configuration carried by the roster (the `connector` block).
 * Secrets (access tokens, bot tokens) are NEVER stored here — they come from
 * the environment (the gateway env-config pattern). Absent config ⇒ tmux.
 */
export interface ConnectorConfig {
  kind: ConnectorKind;
  /** Matrix connector settings (homeserver + room); token via env. */
  matrix?: MatrixConnectorConfig;
  /** Discord connector settings (channel); token via env. */
  discord?: DiscordConnectorConfig;
}

export interface MatrixConnectorConfig {
  /** Local homeserver base URL, e.g. https://matrix.example.internal */
  homeserverUrl: string;
  /** Full Matrix user id of the orchestrator, e.g. @mos:example.internal */
  userId: string;
  /** Room id/alias the orchestrator converses in. */
  roomId: string;
}

export interface DiscordConnectorConfig {
  /** Channel id the orchestrator converses in. */
  channelId: string;
}

/** The default connector when a roster declares none (back-compat). */
export const DEFAULT_CONNECTOR_KIND: ConnectorKind = 'tmux';
