import { logger } from '@@/api/chat/logger';
import type { MessageCost, ChatEvent } from '@@/api/chat/types';
import * as sidecar from '@@/sidecar-registry';

type ClaudeCodeParams = {
  userId: number;
  email: string;
  username: string;
  prompt: string;
  sessionKey: string;
  model?: string;
};

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

export function clearClaudeCodeSession(sessionKey: string, email?: string): void {
  sidecar.clearClaudeSession(sessionKey, email);
}

export async function sendClaudeCode(params: ClaudeCodeParams): Promise<ClaudeCodeResult> {
  logger.info('Claude Code exec (via sidecar)', { sessionKey: params.sessionKey });
  return sidecar.spawnClaude(params);
}

// ── Streaming variant for Chat Panel WebSocket ──

type ClaudeCodeStreamingParams = {
  userId: number;
  email: string;
  username: string;
  prompt: string;
  sessionKey: string;
  cwd?: string;
  model?: string;
  resumeSessionId?: string;
  onEvent: (event: ChatEvent) => void;
};

type ClaudeCodeStreamingHandle = {
  kill: () => void;
};

export async function sendClaudeCodeStreaming(params: ClaudeCodeStreamingParams): Promise<ClaudeCodeStreamingHandle> {
  const { onEvent, ...spawnParams } = params;

  logger.info('Claude Code streaming exec (via sidecar)', { sessionKey: params.sessionKey });

  // Session-scoped subscription. The persistent session outlives the turn, so background task events
  // (task:notification) arrive AFTER 'result' — do NOT unsubscribe on a terminal turn event; only on
  // an explicit kill/teardown (the returned handle, called from deleteSession/disconnect).
  const unsub = sidecar.onClaudeEvent((sessionKey, event) => {
    if (sessionKey === params.sessionKey) onEvent(event);
  });

  await sidecar.spawnClaudeStreaming(spawnParams);

  return {
    kill: () => {
      sidecar.killClaude(params.sessionKey, params.email);
      unsub();
    },
  };
}
