import type { InfiniteData } from "@tanstack/react-query";
import type { ChatMessage } from "@/components/chat/ChatMessageCard";
import { parseMessageTime } from "./dedupeMessages";

export type ChatThreadPage = { messages: ChatMessage[]; nextPage?: number };
export type ChatThreadData = InfiniteData<ChatThreadPage, number>;

export function normalizeThreadId(id: unknown): string {
  if (!id) return "";
  return String(id);
}

export function appendMessageToThreadCache(
  oldData: ChatThreadData | undefined,
  message: ChatMessage
): ChatThreadData {
  if (!oldData?.pages?.length) {
    return {
      pages: [{ messages: [message], nextPage: undefined }],
      pageParams: [1],
    };
  }

  const exists = oldData.pages.some((p) =>
    p.messages.some((m) => m._id === message._id)
  );
  if (exists) return oldData;

  const newPages = [...oldData.pages];
  const firstPage = newPages[0];
  newPages[0] = {
    ...firstPage,
    messages: [...firstPage.messages, message],
  };

  return { ...oldData, pages: newPages };
}

/** Add or update — avoids duplicate / flicker when optimistic + socket + HTTP overlap */
export function upsertMessageInThreadCache(
  oldData: ChatThreadData | undefined,
  message: ChatMessage
): ChatThreadData {
  if (!oldData?.pages?.length) {
    return appendMessageToThreadCache(oldData, message);
  }

  const messageId = String(message._id);
  let found = false;

  const newPages = oldData.pages.map((page) => ({
    ...page,
    messages: page.messages.map((m) => {
      if (String(m._id) === messageId) {
        found = true;
        return { ...m, ...message };
      }
      return m;
    }),
  }));

  if (found) {
    return { ...oldData, pages: newPages };
  }

  return appendMessageToThreadCache(oldData, message);
}

/** هنگام refetch، پیام‌های تازهٔ cache که هنوز در پاسخ API نیستند حفظ می‌شوند */
export function mergeFetchedThreadPage(
  fetched: ChatMessage[],
  cachedFirstPage: ChatMessage[] | undefined
): ChatMessage[] {
  if (!cachedFirstPage?.length) return fetched;

  const fetchedIds = new Set(fetched.map((m) => String(m._id)));
  const preserved = cachedFirstPage.filter(
    (m) =>
      /^[a-f\d]{24}$/i.test(String(m._id)) &&
      !fetchedIds.has(String(m._id))
  );

  if (!preserved.length) return fetched;

  return [...fetched, ...preserved].sort(
    (a, b) => parseMessageTime(a) - parseMessageTime(b)
  );
}
