import { EntityManager } from 'typeorm';
import { AiConversation, AiMessage } from './entities';
import type {
  AiChatServiceContext,
  AiSseEmitter,
  ModelContentPart,
} from './ai-chat.types';
import type { AuthenticatedUser } from '../authorization';

export async function persistExchange(
  context: AiChatServiceContext,
  manager: EntityManager,
  conversation: AiConversation,
  userId: number,
  userContent: string,
  clientRequestId: string | undefined,
  skillKey: string | null,
  metadata?: Record<string, unknown>,
  attachments?: any[],
  titleUpdate?: string,
): Promise<{ userMessage: AiMessage; assistantMessage: AiMessage }> {
  const userMessage = await manager.save(
    AiMessage,
    manager.create(AiMessage, {
      conversationId: conversation.id,
      role: 'user',
      content: userContent,
      reasoningContent: null,
      status: 'completed',
      errorCode: null,
      replyToMessageId: null,
      metadata: { clientRequestId, skillKey, ...metadata },
      attachments,
    }),
  );
  const assistantMessage = await manager.save(
    AiMessage,
    manager.create(AiMessage, {
      conversationId: conversation.id,
      role: 'assistant',
      content: '',
      reasoningContent: null,
      status: 'pending',
      errorCode: null,
      replyToMessageId: userMessage.id,
      metadata: { clientRequestId, skillKey },
    }),
  );
  await manager.update(
    AiConversation,
    { id: conversation.id, userId },
    {
      lastMessageAt: new Date(),
      ...(titleUpdate ? { title: titleUpdate } : {}),
    },
  );
  return { userMessage, assistantMessage };
}

export async function runGenerationAndRelease(
  context: AiChatServiceContext,
  input: {
    user: AuthenticatedUser;
    conversation: AiConversation;
    userMessage: AiMessage;
    assistant: AiMessage;
    clientRequestId: string;
    effectiveSkillKey: string | null;
    focusContent: string | ModelContentPart[];
    reasoningEffort?: string | null;
    signal: AbortSignal;
    emit: AiSseEmitter;
    onReady: () => void;
  },
  conversationId: number,
): Promise<void> {
  try {
    await context.executeGeneration(input);
  } finally {
    context.activeConversations.delete(conversationId);
  }
}
