import type { ChatMessage } from "@/components/chat/ChatMessageCard";

export function parseMessageTime(message: ChatMessage): number {
  const withIso = message as ChatMessage & { createdAtIso?: string };
  if (withIso.createdAtIso) {
    const t = new Date(withIso.createdAtIso).getTime();
    if (!Number.isNaN(t)) return t;
  }
  if (message.createdAt?.includes("T")) {
    const t = new Date(message.createdAt).getTime();
    if (!Number.isNaN(t)) return t;
  }
  return 0;
}

const PENDING_MATCH_WINDOW_MS = 120_000;

function matchesPendingServer(server: ChatMessage, pending: ChatMessage): boolean {
  if (String(server.senderId) !== String(pending.senderId)) return false;
  if (String(pending.fileType || "") !== String(server.fileType || "")) return false;

  const pendingTime = parseMessageTime(pending);
  const serverTime = parseMessageTime(server);
  if (pendingTime && serverTime) {
    if (Math.abs(serverTime - pendingTime) > PENDING_MATCH_WINDOW_MS) return false;
  }

  if (pending.fileType === "location" || (!pending.fileType && !pending.file)) {
    return server.content === pending.content;
  }

  return Boolean(pending.fileType && server.fileType === pending.fileType);
}

export function findPendingMatchForServer(
  server: ChatMessage,
  pending: ChatMessage[]
): ChatMessage | undefined {
  return pending.find((p) => matchesPendingServer(server, p));
}

export function filterResolvedPendingMessages(
  server: ChatMessage[],
  pending: ChatMessage[]
): ChatMessage[] {
  return pending.filter((p) => {
    if (server.some((s) => String(s._id) === String(p._id))) return false;
    return !server.some((s) => matchesPendingServer(s, p));
  });
}

export function dedupeChatMessages(messages: ChatMessage[]): ChatMessage[] {
  const seen = new Set<string>();
  const result: ChatMessage[] = [];

  for (const m of messages) {
    if (!m) continue;
    const idKey =
      m._id && /^[a-f\d]{24}$/i.test(m._id)
        ? m._id
        : `${m.senderId}|${m.content}|${m.file}|${m.createdAt}`;
    if (seen.has(idKey)) continue;
    seen.add(idKey);
    result.push(m);
  }

  return result;
}
