import { type ChatSendResponse, type UiMessage } from "@/data/dto/chat";
import { todayString } from "@/utils";

/**
 * ChatMessage[] -> UiMessage[].
 * Business fact: `role === "assistant"` means the message is from AI.
 */
export function localMessagesToUi(
  records: ReadonlyArray<{
    id?: string;
    type?: string;
    content: string;
    role: string;
    createdAt: string;
    audioUrl?: string | null;
    image?: { type: string | null; url: string | null };
    lockDetail?: {
      locked: boolean;
      showContent: boolean;
      showUpgrade: boolean;
      reason: string | null;
      hint: string | null;
      detail: Record<string, unknown> | null;
    };
  }>,
): UiMessage[] {
  return records.map((m) => ({
    ...(m.id ? { id: m.id } : {}),
    content: getAiMessageDisplayContent({
      content: m.content,
      isFromAI: m.role === "assistant",
      hasImage: Boolean(m.image?.url),
    }),
    isFromAI: m.role === "assistant",
    date: messageDateFromCreatedAt(m.createdAt),
    ...(m.audioUrl ? { audioUrl: m.audioUrl } : {}),
    ...deriveUiLockFields(m.lockDetail, m.image?.url),
  }));
}

/**
 * ChatSendResponse -> UiMessage.
 * Business fact: the backend response is the AI reply.
 */
export function sendResponseToUiMessage(response: ChatSendResponse): UiMessage {
  return {
    ...(response.messageId ? { id: response.messageId } : {}),
    content: getAiMessageDisplayContent({
      content: response.reply,
      isFromAI: true,
      hasImage: Boolean(response.image.url),
    }),
    isFromAI: true,
    date: todayString(new Date(response.timestamp)),
    ...(response.audioUrl ? { audioUrl: response.audioUrl } : {}),
    ...deriveUiLockFields(response.lockDetail, response.image.url),
  };
}

function messageDateFromCreatedAt(createdAt: string): string {
  const parsed = new Date(createdAt);
  if (Number.isNaN(parsed.getTime())) return todayString();
  return todayString(parsed);
}

function getAiMessageDisplayContent(input: {
  content: string;
  isFromAI: boolean;
  hasImage?: boolean;
}): string {
  return input.isFromAI && input.hasImage ? "" : input.content;
}

function deriveUiLockFields(
  lockDetail:
    | {
        locked: boolean;
        showContent: boolean;
        showUpgrade: boolean;
        reason: string | null;
        hint: string | null;
      }
    | undefined,
  imageUrl?: string | null,
): Partial<UiMessage> {
  const lockReason = lockDetail?.reason ?? null;
  const isPrivateMessage = lockReason === "private_message";
  const isVoiceMessage = lockReason === "voice_message";
  return {
    ...(imageUrl ? { imageUrl } : {}),
    ...(imageUrl && lockDetail?.showUpgrade ? { imagePaywalled: true } : {}),
    ...(lockDetail ? { locked: lockDetail.locked, lockReason } : {}),
    ...(isPrivateMessage ? { isPrivate: true } : {}),
    ...(isPrivateMessage && lockDetail?.locked
      ? { lockedPrivate: true }
      : {}),
    ...((isPrivateMessage || isVoiceMessage) && lockDetail?.hint
      ? { privateMessageHint: lockDetail.hint }
      : {}),
  };
}
