import { DepositOrder } from './deposit-order.aggregate';
import { UserId, ChainType, DepositStatus, Money } from '@/domain/value-objects';
import Decimal from 'decimal.js';

jest.mock('@/shared/exceptions/domain.exception', () => ({
  DomainError: class DomainError extends Error {
    constructor(message: string) {
      super(message);
      this.name = 'DomainError';
    }
  },
}));

describe('DepositOrder Aggregate', () => {
  describe('create', () => {
    it('should create a new deposit order', () => {
      const order = DepositOrder.create({
        accountSequence: 'D2512110001',
        userId: UserId.create(1),
        chainType: ChainType.KAVA,
        amount: Money.USDT(100),
        txHash: 'tx_hash_123',
      });

      expect(order.userId.value).toBe(BigInt(1));
      expect(order.chainType).toBe(ChainType.KAVA);
      expect(order.amount.value).toBe(100);
      expect(order.txHash).toBe('tx_hash_123');
      expect(order.status).toBe(DepositStatus.PENDING);
      expect(order.isPending).toBe(true);
      expect(order.isConfirmed).toBe(false);
      expect(order.confirmedAt).toBeNull();
    });
  });

  describe('confirm', () => {
    it('should confirm a pending deposit', () => {
      const order = DepositOrder.create({
        accountSequence: 'D2512110001',
        userId: UserId.create(1),
        chainType: ChainType.BSC,
        amount: Money.USDT(50),
        txHash: 'tx_hash_456',
      });

      order.confirm();

      expect(order.status).toBe(DepositStatus.CONFIRMED);
      expect(order.isConfirmed).toBe(true);
      expect(order.isPending).toBe(false);
      expect(order.confirmedAt).not.toBeNull();
    });

    it('should throw error when confirming non-pending deposit', () => {
      const order = DepositOrder.create({
        accountSequence: 'D2512110001',
        userId: UserId.create(1),
        chainType: ChainType.KAVA,
        amount: Money.USDT(100),
        txHash: 'tx_hash_789',
      });

      order.confirm();
      expect(() => order.confirm()).toThrow('Only pending');
    });
  });

  describe('fail', () => {
    it('should mark pending deposit as failed', () => {
      const order = DepositOrder.create({
        accountSequence: 'D2512110001',
        userId: UserId.create(1),
        chainType: ChainType.KAVA,
        amount: Money.USDT(100),
        txHash: 'tx_hash_fail',
      });

      order.fail();

      expect(order.status).toBe(DepositStatus.FAILED);
    });

    it('should throw error when failing non-pending deposit', () => {
      const order = DepositOrder.create({
        accountSequence: 'D2512110001',
        userId: UserId.create(1),
        chainType: ChainType.KAVA,
        amount: Money.USDT(100),
        txHash: 'tx_hash_test',
      });

      order.confirm();
      expect(() => order.fail()).toThrow('Only pending');
    });
  });

  describe('reconstruct', () => {
    it('should reconstruct from database record', () => {
      const order = DepositOrder.reconstruct({
        id: BigInt(1),
        accountSequence: 'D2512110100',
        userId: BigInt(100),
        chainType: 'KAVA',
        amount: new Decimal(200),
        txHash: 'tx_reconstructed',
        status: 'CONFIRMED',
        confirmedAt: new Date(),
        createdAt: new Date(),
      });

      expect(order.id).toBe(BigInt(1));
      expect(order.status).toBe(DepositStatus.CONFIRMED);
      expect(order.isConfirmed).toBe(true);
    });
  });
});
