// Gateway protocol types — JSON-RPC-like messages over WebSocket.

// ── Client → Server ────────────────────────────────────────────

export interface GatewayRequest {
  id: number;
  method: string;
  params?: Record<string, unknown>;
}

// ── Server → Client ────────────────────────────────────────────

export interface GatewayResponse {
  id: number;
  result: unknown;
}

export interface GatewayError {
  id: number;
  error: {
    code: ErrorCode;
    message: string;
  };
}

export interface GatewayEvent {
  id: number;
  event: EventType;
  data: unknown;
}

// ── Attachment data for gateway protocol messages ───────────────

/** Attachment data sent in agent.send params or emitted as events. */
export interface GatewayAttachment {
  /** MIME type (e.g. "image/jpeg", "audio/ogg") */
  mimeType: string;
  /** Base64-encoded data */
  data?: string;
  /** URL to the resource */
  url?: string;
  /** Filename hint */
  filename?: string;
}

// ── Event types emitted during agent.send ──────────────────────

export type EventType =
  | 'content'
  | 'tool_start'
  | 'tool_end'
  | 'attachment'
  | 'done'
  | 'error';

export interface ContentEventData {
  text: string;
}

export interface ToolStartEventData {
  tool: string;
  args: unknown;
}

export interface ToolEndEventData {
  tool: string;
  result: {
    success: boolean;
    output: string;
    error?: string;
  };
}

export interface AttachmentEventData {
  mimeType: string;
  data?: string;
  url?: string;
  filename?: string;
}

export interface DoneEventData {
  content: string;
}

export interface ErrorEventData {
  code: ErrorCode;
  message: string;
}

// ── Error codes ────────────────────────────────────────────────

export enum ErrorCode {
  ParseError = -1,
  InvalidRequest = -2,
  MethodNotFound = -3,
  AuthRequired = -4,
  AuthFailed = -5,
  SessionNotFound = 1,
  ToolNotFound = 2,
  AgentBusy = 3,
  RequestCancelled = 4,
  InternalError = 5,
}

// ── Outbound message (union of all server → client types) ──────

export type OutboundMessage = GatewayResponse | GatewayError | GatewayEvent;

// ── Validation helpers ─────────────────────────────────────────

export function isValidRequest(msg: unknown): msg is GatewayRequest {
  if (typeof msg !== 'object' || msg === null) {return false;}
  const obj = msg as Record<string, unknown>;
  return (
    typeof obj.id === 'number' &&
    typeof obj.method === 'string' &&
    (obj.params === undefined || (typeof obj.params === 'object' && obj.params !== null))
  );
}

export function parseMessage(raw: string): GatewayRequest | null {
  try {
    const parsed = JSON.parse(raw);
    if (isValidRequest(parsed)) {return parsed;}
    return null;
  } catch {
    return null;
  }
}

export function makeResponse(id: number, result: unknown): GatewayResponse {
  return { id, result };
}

export function makeError(id: number, code: ErrorCode, message: string): GatewayError {
  return { id, error: { code, message } };
}

export function makeEvent(id: number, event: EventType, data: unknown): GatewayEvent {
  return { id, event, data };
}
