import { deliveryStatusToMessageStatus, deliveryStatusToAck, ackStatusTransitionFrom } from './message-status.util';
import { MessageStatus } from './entities/message.entity';

describe('deliveryStatusToMessageStatus', () => {
  it("maps 'failed' to FAILED", () => {
    expect(deliveryStatusToMessageStatus('failed')).toBe(MessageStatus.FAILED);
  });

  it("maps 'delivered' to DELIVERED", () => {
    expect(deliveryStatusToMessageStatus('delivered')).toBe(MessageStatus.DELIVERED);
  });

  it("maps 'read' to READ", () => {
    expect(deliveryStatusToMessageStatus('read')).toBe(MessageStatus.READ);
  });

  it("returns null for 'pending'/'sent' — no upgrade beyond SENT", () => {
    expect(deliveryStatusToMessageStatus('pending')).toBeNull();
    expect(deliveryStatusToMessageStatus('sent')).toBeNull();
  });
});

describe('deliveryStatusToAck (deprecated legacy ack integer)', () => {
  it('derives the legacy wwebjs-style ack integer from the neutral status', () => {
    expect(deliveryStatusToAck('failed')).toBe(-1);
    expect(deliveryStatusToAck('pending')).toBe(0);
    expect(deliveryStatusToAck('sent')).toBe(1);
    expect(deliveryStatusToAck('delivered')).toBe(2);
    expect(deliveryStatusToAck('read')).toBe(3);
  });
});

describe('ackStatusTransitionFrom (monotonic delivery-state guard)', () => {
  it('DELIVERED may advance only from PENDING/SENT (never downgrades a READ row)', () => {
    expect(ackStatusTransitionFrom(MessageStatus.DELIVERED)).toEqual([MessageStatus.PENDING, MessageStatus.SENT]);
    expect(ackStatusTransitionFrom(MessageStatus.DELIVERED)).not.toContain(MessageStatus.READ);
  });

  it('READ may advance from PENDING/SENT/DELIVERED', () => {
    expect(ackStatusTransitionFrom(MessageStatus.READ)).toEqual([
      MessageStatus.PENDING,
      MessageStatus.SENT,
      MessageStatus.DELIVERED,
    ]);
  });

  it('FAILED does not clobber an already delivered/read message', () => {
    const from = ackStatusTransitionFrom(MessageStatus.FAILED);
    expect(from).toEqual([MessageStatus.PENDING, MessageStatus.SENT]);
    expect(from).not.toContain(MessageStatus.DELIVERED);
    expect(from).not.toContain(MessageStatus.READ);
  });
});
