import type {
  ChatLockDetailData,
  ChatSendResponse,
} from "@/data/schemas/chat";
import {
  createClientUiMessageIdentity,
  createLegacyUiMessageIdentity,
  createRemoteUiMessageIdentity,
  type UiMessage,
} from "@/stores/chat/ui-message";
import { todayString } from "@/utils/date";

/**
 * ChatMessage[] -> UiMessage[].
 * Business fact: `role === "assistant"` means the message is from AI.
 */
export function localMessagesToUi(
  records: readonly {
    id?: string;
    type?: string;
    content: string;
    role: string;
    createdAt: string;
    audioUrl?: string | null;
    image?: { type: string | null; url: string | null };
    lockDetail?: ChatLockDetailData;
  }[],
): UiMessage[] {
  const occurrences = new Map<string, number>();
  return records.map((m) => {
    const isFromAI = m.role === "assistant";
    const identityBase = m.id
      ? `remote:${m.id}:${m.role}`
      : `legacy:${createLegacyFingerprint(m)}`;
    const occurrence = occurrences.get(identityBase) ?? 0;
    occurrences.set(identityBase, occurrence + 1);
    const identity = m.id
      ? createRemoteUiMessageIdentity(m.id, isFromAI, occurrence)
      : createLegacyUiMessageIdentity(identityBase, occurrence);

    return {
      ...identity,
      content: getAiMessageDisplayContent({
        content: m.content,
        isFromAI,
        hasImage: Boolean(m.image?.url),
      }),
      isFromAI,
      date: messageDateFromCreatedAt(m.createdAt),
      ...(m.audioUrl && m.lockDetail?.locked !== true
        ? { 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
      ? createRemoteUiMessageIdentity(response.messageId, true)
      : createClientUiMessageIdentity("reply")),
    content: getAiMessageDisplayContent({
      content: response.reply,
      isFromAI: true,
      hasImage: Boolean(response.image.url),
    }),
    isFromAI: true,
    date: todayString(new Date(response.timestamp)),
    ...(response.audioUrl && !response.lockDetail.locked
      ? { audioUrl: response.audioUrl }
      : {}),
    ...(response.paymentGuidance
      ? { paymentGuidance: response.paymentGuidance }
      : response.chatAction
        ? { chatAction: response.chatAction }
        : response.commercialAction
          ? { commercialAction: response.commercialAction }
          : {}),
    ...deriveUiLockFields(response.lockDetail, response.image.url),
  };
}

function createLegacyFingerprint(record: {
  type?: string;
  content: string;
  role: string;
  createdAt: string;
  audioUrl?: string | null;
  image?: { type: string | null; url: string | null };
  lockDetail?: ChatLockDetailData;
}): string {
  return JSON.stringify([
    record.role,
    record.type ?? "text",
    record.content,
    record.createdAt,
    record.audioUrl ?? null,
    record.image?.type ?? null,
    record.image?.url ?? null,
    record.lockDetail?.locked ?? null,
    record.lockDetail?.reason ?? null,
  ]);
}

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: ChatLockDetailData | undefined,
  imageUrl?: string | null,
): Partial<UiMessage> {
  const lockReason = lockDetail?.reason ?? null;
  const isLocked = lockDetail?.locked === true;
  const isPrivateMessage = isLocked && lockReason === "private_message";
  const isLockedImage =
    isLocked && (lockReason === "image_paywall" || lockReason === "image");
  return {
    ...(imageUrl ? { imageUrl } : {}),
    ...(imageUrl && isLockedImage ? { imagePaywalled: true } : {}),
    ...(lockDetail ? { locked: lockDetail.locked, lockReason } : {}),
    ...(isPrivateMessage ? { isPrivate: true } : {}),
    ...(isPrivateMessage ? { lockedPrivate: true } : {}),
  };
}
