import type { SessionSnapshot } from './session-snapshot'

/**
 * ACP protocol shapes shared across the CLI ACP server and UI clients.
 */
export type ACPRole = 'user' | 'assistant' | 'tool' | 'system'

export type ACPContent
  = | string
    | Array<{ type: string, text?: string, [key: string]: unknown }>

export interface ACPToolCall {
  id: string
  type: 'function'
  function: {
    name: string
    arguments: string | Record<string, unknown>
    thoughtSignature?: string
  }
}

export interface ACPMessage {
  role: ACPRole
  content?: ACPContent
  reasoning_content?: string
  tool_calls?: ACPToolCall[]
  tool_call_id?: string
  name?: string
  metadata?: Record<string, unknown>
}

export interface ACPMetadata {
  session_id?: string
  stream_id?: string
  run_id?: string
  seq?: number
  replayed?: boolean
  signal?: AbortSignal
  [key: string]: unknown
}

/**
 * ACP Agent interface - describes any agent that can receive ACP messages
 */
export type GoatChainAgentSessions = Readonly<{
  list: () => Promise<SessionSnapshot[]>
  get: (id: string) => Promise<SessionSnapshot | null>
  create: () => Promise<SessionSnapshot | null>
  destroy: (id: string) => Promise<void>
  interrupt?: (id: string) => Promise<boolean>
  createWithMessages?: (
    messages: Record<string, unknown>[],
  ) => Promise<SessionSnapshot | null>
  rename?: (id: string, title: string) => Promise<SessionSnapshot | null>
  updateMetadata?: (
    id: string,
    metadata: Record<string, unknown>,
  ) => Promise<SessionSnapshot | null>
}>

export interface GoatChainAgent {
  __sessions?: GoatChainAgentSessions
  receiveMessage: (
    messages: ACPMessage[],
    metadata?: ACPMetadata,
  ) => AsyncGenerator<ACPMessage, void, void>
  steerSession?: (
    sessionId: string,
    input: string,
    metadata?: ACPMetadata,
  ) => Promise<boolean>
  setMode?: (modeId: 'agent' | 'plan') => void
  getMode?: () => 'agent' | 'plan'
  triggerManualCompression?: (sessionId?: string) => Promise<{
    success: boolean
    summary?: string
    messageCount?: number
    error?: string
    errorCode?: string
  }>
  invalidateSession?: (sessionId: string) => void
}
