import type { ChatMessage } from '@/types';

const INVISIBLE_CONTENT_CHARS = /[\u200B-\u200D\uFEFF]/g;
export const CHAT_WAITING_REFRESH_INTERVAL_MS = 1500;
export const CHAT_IDLE_REFRESH_INTERVAL_MS = 5000;

export function getSessionRefreshIntervalMs({
  isLoading,
  isThinking,
  documentHidden,
}: {
  isLoading: boolean;
  isThinking: boolean;
  documentHidden: boolean;
}): number | null {
  if (documentHidden) {
    return null;
  }
  if (isLoading || isThinking) {
    return CHAT_WAITING_REFRESH_INTERVAL_MS;
  }
  return CHAT_IDLE_REFRESH_INTERVAL_MS;
}

export function normalizedMessageText(content: unknown): string {
  if (typeof content === 'string') {
    return content.replace(INVISIBLE_CONTENT_CHARS, '').trim();
  }
  if (content == null) {
    return '';
  }
  return String(content).replace(INVISIBLE_CONTENT_CHARS, '').trim();
}

export function hasVisibleChatContent(msg: ChatMessage): boolean {
  if (normalizedMessageText(msg.content)) {
    return true;
  }
  return Boolean(msg.attachments?.length);
}

export function shouldDisplayChatMessage(msg: ChatMessage): boolean {
  return msg.role !== 'assistant' || hasVisibleChatContent(msg);
}

export function messageFingerprint(msg: ChatMessage): string {
  const attachmentKey = (msg.attachments ?? [])
    .map((a) => `${a.file_id ?? ''}:${a.name}:${a.content_type}:${a.size ?? ''}`)
    .join('|');
  return `${msg.role}::${String(msg.content)}::${attachmentKey}`;
}

export function mergeServerWithPendingUsers(serverMessages: ChatMessage[], localMessages: ChatMessage[]): ChatMessage[] {
  const counts = new Map<string, number>();
  for (const message of serverMessages) {
    const key = messageFingerprint(message);
    counts.set(key, (counts.get(key) ?? 0) + 1);
  }

  const pendingUsers: ChatMessage[] = [];
  for (const message of localMessages) {
    const key = messageFingerprint(message);
    const count = counts.get(key) ?? 0;
    if (count > 0) {
      counts.set(key, count - 1);
      continue;
    }
    if (message.role === 'user') {
      pendingUsers.push(message);
    }
  }

  return [...serverMessages, ...pendingUsers];
}

export function shouldMergePendingUsers(
  serverMessages: ChatMessage[],
  localMessages: ChatMessage[],
  waitingForReply: boolean
): boolean {
  if (waitingForReply) {
    return true;
  }

  const lastLocal = localMessages[localMessages.length - 1];
  if (lastLocal?.role !== 'user') {
    return false;
  }

  const counts = new Map<string, number>();
  for (const message of serverMessages) {
    const key = messageFingerprint(message);
    counts.set(key, (counts.get(key) ?? 0) + 1);
  }

  for (const message of localMessages) {
    if (message.role !== 'user') {
      continue;
    }
    const key = messageFingerprint(message);
    const count = counts.get(key) ?? 0;
    if (count > 0) {
      counts.set(key, count - 1);
      continue;
    }
    return true;
  }

  return false;
}

export function getTaskCardMessageIndexes(messages: ChatMessage[]): Set<number> {
  const latestByTask = new Map<string, number>();

  messages.forEach((message, index) => {
    if (message.role !== 'assistant' || !message.task_id) {
      return;
    }
    latestByTask.set(message.task_id, index);
  });

  return new Set(latestByTask.values());
}
