import type {
  DirectMessage,
  DirectMessageConversation,
  DirectMessageParticipant,
  DirectMessageStatus
} from '../models/direct-message.model';

const STATUS_ORDER: Record<DirectMessageStatus, number> = {
  QUEUED: 0,
  SENT: 1,
  DELIVERED: 2,
  ACKNOWLEDGED: 3
};

export function getDirectConversationId(firstUserId: string, secondUserId: string): string {
  return `dm-${[firstUserId, secondUserId]
    .map((userId) => encodeURIComponent(userId.trim()))
    .sort()
    .join('--')}`;
}

export function advanceDirectMessageStatus(
  currentStatus: DirectMessageStatus,
  incomingStatus: DirectMessageStatus
): DirectMessageStatus {
  return STATUS_ORDER[incomingStatus] > STATUS_ORDER[currentStatus]
    ? incomingStatus
    : currentStatus;
}

export function createDirectConversation(
  currentUser: DirectMessageParticipant,
  peer: DirectMessageParticipant,
  now: number
): DirectMessageConversation {
  const participants = [currentUser.userId, peer.userId].sort();

  return {
    id: getDirectConversationId(currentUser.userId, peer.userId),
    participants,
    participantProfiles: {
      [currentUser.userId]: currentUser,
      [peer.userId]: peer
    },
    messages: [],
    lastMessageAt: now,
    unreadCount: 0
  };
}

export function upsertDirectMessage(
  conversation: DirectMessageConversation,
  message: DirectMessage,
  incrementUnread: boolean
): DirectMessageConversation {
  const existingIndex = conversation.messages.findIndex((entry) => entry.id === message.id);
  const messages = [...conversation.messages];

  if (existingIndex >= 0) {
    const existing = messages[existingIndex];

    messages[existingIndex] = {
      ...existing,
      ...message,
      status: advanceDirectMessageStatus(existing.status, message.status)
    };
  } else {
    messages.push(message);
  }

  messages.sort((firstMessage, secondMessage) => firstMessage.timestamp - secondMessage.timestamp);

  return {
    ...conversation,
    messages,
    lastMessageAt: Math.max(conversation.lastMessageAt, message.timestamp),
    unreadCount: incrementUnread ? conversation.unreadCount + 1 : conversation.unreadCount
  };
}

export function updateMessageStatusInConversation(
  conversation: DirectMessageConversation,
  messageId: string,
  status: DirectMessageStatus
): DirectMessageConversation {
  const messages = conversation.messages.map((message) => message.id === messageId
    ? { ...message, status: advanceDirectMessageStatus(message.status, status) }
    : message);

  return { ...conversation, messages };
}
