import type { MessageCost, ChatEvent } from '../api/chat/types';

// ── Envelope ──

export type SidecarMessage = SidecarCommand | SidecarEvent;

// ── Commands (API server → sidecar) ──

export type SidecarCommand =
  | { type: 'ping'; id: string }
  | { type: 'state:sync'; id: string }
  // Proxy
  | { type: 'proxy:secret'; id: string }
  // Claude Code
  | { type: 'claude:spawn'; id: string; params: ClaudeSpawnParams }
  | { type: 'claude:spawn-streaming'; id: string; params: ClaudeSpawnStreamingParams }
  | { type: 'claude:kill'; id: string; sessionKey: string }
  | { type: 'claude:interrupt'; id: string; sessionKey: string }
  | { type: 'claude:clear-session'; id: string; sessionKey: string }
  // OpenCode — drive a turn via `opencode run … --format json` (tools re-anchored to cwd via --dir)
  | { type: 'opencode:run-streaming'; id: string; params: OpenCodeRunParams }
  | { type: 'opencode:kill'; id: string; sessionKey: string }
  // VNC
  | { type: 'vnc:start'; id: string; params: VncStartParams }
  // Provision the VNC password without starting a server — the UI needs it before it can connect
  | { type: 'vnc:ensure-password'; id: string; email: string }
  | { type: 'vnc:stop'; id: string; email: string }
  | { type: 'vnc:status'; id: string; email: string };

// ── Responses/Events (sidecar → API server) ──

export type SidecarEvent =
  | { type: 'pong'; id: string }
  | { type: 'state:sync'; id: string; state: ClaudeState }
  | { type: 'proxy:secret'; id: string; secret: string }
  // Claude Code
  | { type: 'claude:spawned'; id: string; sessionKey: string }
  | { type: 'claude:event'; sessionKey: string; event: ChatEvent }
  | { type: 'claude:result'; id: string; result: ClaudeCodeResult }
  | { type: 'claude:error'; id: string; error: string }
  | { type: 'claude:killed'; id: string }
  | { type: 'claude:interrupted'; id: string }
  | { type: 'claude:session-cleared'; id: string }
  // VNC
  | { type: 'vnc:started'; id: string; port: number; display: number }
  | { type: 'vnc:password'; id: string; password: string }
  | { type: 'vnc:stopped'; id: string }
  | { type: 'vnc:status'; id: string; session: VncSessionInfo | null }
  | { type: 'vnc:error'; id: string; error: string }
  // Email
  | { type: 'email:new'; userEmail: string }
  // OpenCode — the sidecar reports where its `opencode serve` is listening (random port) on connect
  | { type: 'opencode:server'; port: number }
  // OpenCode turn streaming (analog of claude:*): spawned ack, per-event stream, session id report
  | { type: 'opencode:spawned'; id: string; sessionKey: string }
  | { type: 'opencode:event'; sessionKey: string; event: ChatEvent }
  | { type: 'opencode:session'; sessionKey: string; sessionId: string }
  | { type: 'opencode:error'; id: string; error: string }
  // Music — the sidecar reports where its audio-streaming HTTP server is listening (random port) on connect
  | { type: 'music:server'; port: number }
  // Generic
  | { type: 'error'; id?: string; error: string };

// ── Claude sidecar state ──

export type ClaudeState = {
  proxySecret: string;
  claudeSessions: Record<string, string>; // sessionKey → Claude Code session_id
};

// ── Param types ──

export type ClaudeSpawnParams = {
  userId: number;
  email: string;
  username: string;
  prompt: string;
  sessionKey: string;
  model?: string;
  cwd?: string;
};

export type ClaudeSpawnStreamingParams = {
  userId: number;
  email: string;
  username: string;
  prompt: string;
  sessionKey: string;
  cwd?: string;
  model?: string;
  resumeSessionId?: string; // resume this Claude session uuid (from the /chat session list)
};

export type ClaudeCodeResult = {
  text: string;
  sessionId: string;
  model: string;
  cost: MessageCost;
};

// ── OpenCode turn params ──

export type OpenCodeRunParams = {
  sessionKey: string;
  prompt: string;
  cwd?: string; // passed to `opencode run --dir` — hard-re-anchors tools to this directory
  model?: string; // `providerID/modelID` (e.g. opencode/claude-haiku-4-5); passed to --model verbatim
  resumeSessionId?: string; // OpenCode `ses_…` id to continue (`--session`)
};

// ── VNC types ──

export type VncStartParams = {
  email: string;
  username: string;
  resolution?: string;
};

export type VncSessionInfo = {
  email: string;
  display: number;
  port: number;
  pid: number;
  alive: boolean;
};

// ── PTY types ──

export type PtyInitConfig = {
  sessionId: string;
  shell?: { command: string; args?: string[] };
  cwd?: string;
  homeDir?: string;
  userLabel?: string;
  host?: boolean;
  cols?: number;
  rows?: number;
  env?: Record<string, string>;
};

// PTY commands (API → PTY sidecar)
export type PtyCommand =
  | { type: 'pty:init'; id: string; sessionId: string; config: PtyInitConfig }
  | { type: 'pty:input'; id: string; sessionId: string; data: string }
  | { type: 'pty:resize'; id: string; sessionId: string; cols: number; rows: number }
  | { type: 'pty:close'; id: string; sessionId: string };

// PTY events (PTY sidecar → API)
export type PtyEvent =
  | { type: 'pty:ready'; id: string; sessionId: string }
  | { type: 'pty:output'; sessionId: string; data: string }
  | { type: 'pty:exit'; sessionId: string; exitCode: number; signal?: number };
