import { sendCommand } from "./client";
import { pickCase } from "./normalize";

// ── Public types ────────────────────────────────────────────────

export type ConversationDto = {
  id: string;
  title: string;
  createdAt: string;
  updatedAt: string;
};

export type ConversationMessageDto = {
  id: string;
  role: string;
  text: string;
  createdAt: string;
};

export type ConversationDetailDto = {
  id: string;
  title: string;
  messages: ConversationMessageDto[];
  createdAt: string;
  updatedAt: string;
};

export type ConversationChatResult = {
  userMessage: ConversationMessageDto;
  assistantMessage: ConversationMessageDto;
};

// ── Raw (PascalCase) variants ───────────────────────────────────

type ConversationDtoRaw = {
  id?: string;
  title?: string;
  createdAt?: string;
  updatedAt?: string;
  Id?: string;
  Title?: string;
  CreatedAt?: string;
  UpdatedAt?: string;
};

type ConversationMessageDtoRaw = {
  id?: string;
  role?: string;
  text?: string;
  createdAt?: string;
  Id?: string;
  Role?: string;
  Text?: string;
  CreatedAt?: string;
};

type ConversationDetailDtoRaw = {
  id?: string;
  title?: string;
  messages?: ConversationMessageDtoRaw[];
  createdAt?: string;
  updatedAt?: string;
  Id?: string;
  Title?: string;
  Messages?: ConversationMessageDtoRaw[];
  CreatedAt?: string;
  UpdatedAt?: string;
};

type ConversationChatResultRaw = {
  userMessage?: ConversationMessageDtoRaw;
  assistantMessage?: ConversationMessageDtoRaw;
  UserMessage?: ConversationMessageDtoRaw;
  AssistantMessage?: ConversationMessageDtoRaw;
};

// ── Normalizers ─────────────────────────────────────────────────

function normalizeMessage(
  raw: ConversationMessageDtoRaw,
): ConversationMessageDto {
  return {
    id: pickCase(raw, "id", "Id", ""),
    role: pickCase(raw, "role", "Role", ""),
    text: pickCase(raw, "text", "Text", ""),
    createdAt: pickCase(raw, "createdAt", "CreatedAt", ""),
  };
}

function normalizeConversation(raw: ConversationDtoRaw): ConversationDto {
  return {
    id: pickCase(raw, "id", "Id", ""),
    title: pickCase(raw, "title", "Title", ""),
    createdAt: pickCase(raw, "createdAt", "CreatedAt", ""),
    updatedAt: pickCase(raw, "updatedAt", "UpdatedAt", ""),
  };
}

function normalizeDetail(raw: ConversationDetailDtoRaw): ConversationDetailDto {
  const msgs = pickCase(
    raw,
    "messages",
    "Messages",
    [] as ConversationMessageDtoRaw[],
  );
  return {
    id: pickCase(raw, "id", "Id", ""),
    title: pickCase(raw, "title", "Title", ""),
    messages: msgs.map(normalizeMessage),
    createdAt: pickCase(raw, "createdAt", "CreatedAt", ""),
    updatedAt: pickCase(raw, "updatedAt", "UpdatedAt", ""),
  };
}

function normalizeChatResult(
  raw: ConversationChatResultRaw,
): ConversationChatResult {
  const userRaw = pickCase(
    raw,
    "userMessage",
    "UserMessage",
    {} as ConversationMessageDtoRaw,
  );
  const assistantRaw = pickCase(
    raw,
    "assistantMessage",
    "AssistantMessage",
    {} as ConversationMessageDtoRaw,
  );
  return {
    userMessage: normalizeMessage(userRaw),
    assistantMessage: normalizeMessage(assistantRaw),
  };
}

// ── API functions ───────────────────────────────────────────────

export async function listConversations(): Promise<ConversationDto[]> {
  const data = await sendCommand<ConversationDtoRaw[]>({
    action: "conversations.list",
    payload: {},
  });
  return (data ?? []).map(normalizeConversation);
}

export async function getConversation(
  id: string,
): Promise<ConversationDetailDto> {
  const data = await sendCommand<ConversationDetailDtoRaw>({
    action: "conversations.get",
    id,
    payload: {},
  });
  return normalizeDetail(data);
}

export async function createConversation(
  title: string,
): Promise<ConversationDto> {
  const data = await sendCommand<ConversationDtoRaw>({
    action: "conversations.create",
    payload: { title },
  });
  return normalizeConversation(data);
}

export async function updateConversation(
  id: string,
  title: string,
): Promise<boolean> {
  return sendCommand<boolean>({
    action: "conversations.update",
    id,
    payload: { title },
  });
}

export async function deleteConversation(id: string): Promise<boolean> {
  return sendCommand<boolean>({
    action: "conversations.delete",
    id,
    payload: {},
  });
}

export async function conversationChat(
  conversationId: string,
  prompt: string,
): Promise<ConversationChatResult> {
  const data = await sendCommand<ConversationChatResultRaw>({
    action: "conversations.chat",
    payload: { conversationId, prompt },
  });
  return normalizeChatResult(data);
}
