import {
  advanceDirectMessageStatus,
  createDirectConversation,
  getDirectConversationId,
  updateMessageStatusInConversation,
  upsertDirectMessage
} from '../../domain/logic/direct-message.logic';
import type { DirectMessage, DirectMessageParticipant } from '../../domain/models/direct-message.model';

const alice: DirectMessageParticipant = {
  userId: 'alice',
  username: 'alice',
  displayName: 'Alice'
};
const bob: DirectMessageParticipant = {
  userId: 'bob',
  username: 'bob',
  displayName: 'Bob'
};

describe('DirectMessageService domain flow', () => {
  it('should create conversation', () => {
    const conversation = createDirectConversation(alice, bob, 10);

    expect(conversation.id).toBe(getDirectConversationId('alice', 'bob'));
    expect(conversation.participants).toEqual(['alice', 'bob']);
    expect(conversation.unreadCount).toBe(0);
  });

  it('should send message', () => {
    const conversation = createDirectConversation(alice, bob, 10);
    const queuedMessage = createMessage('message-1', 'QUEUED');
    const withQueuedMessage = upsertDirectMessage(conversation, queuedMessage, false);
    const withSentMessage = updateMessageStatusInConversation(withQueuedMessage, queuedMessage.id, 'SENT');

    expect(withSentMessage.messages[0].status).toBe('SENT');
  });

  it('should queue message when offline', () => {
    const conversation = createDirectConversation(alice, bob, 10);
    const queuedMessage = createMessage('message-1', 'QUEUED');
    const updatedConversation = upsertDirectMessage(conversation, queuedMessage, false);

    expect(updatedConversation.messages[0].status).toBe('QUEUED');
  });

  it('should update status correctly', () => {
    expect(advanceDirectMessageStatus('QUEUED', 'SENT')).toBe('SENT');
    expect(advanceDirectMessageStatus('SENT', 'DELIVERED')).toBe('DELIVERED');
    expect(advanceDirectMessageStatus('DELIVERED', 'SENT')).toBe('DELIVERED');
    expect(advanceDirectMessageStatus('DELIVERED', 'ACKNOWLEDGED')).toBe('ACKNOWLEDGED');
  });
});

function createMessage(id: string, status: DirectMessage['status']): DirectMessage {
  return {
    id,
    conversationId: getDirectConversationId('alice', 'bob'),
    senderId: 'alice',
    recipientId: 'bob',
    content: 'Hello',
    timestamp: 20,
    status
  };
}
