import { Money } from './money.vo';

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

describe('Money Value Object', () => {
  describe('create', () => {
    it('should create money with valid amount', () => {
      const money = Money.create(100, 'USDT');
      expect(money.value).toBe(100);
      expect(money.currency).toBe('USDT');
    });

    it('should create zero money', () => {
      const money = Money.zero('USDT');
      expect(money.value).toBe(0);
      expect(money.isZero()).toBe(true);
    });

    it('should throw error for negative amount', () => {
      expect(() => Money.create(-100, 'USDT')).toThrow('Money amount cannot be negative');
    });
  });

  describe('static factory methods', () => {
    it('should create USDT money', () => {
      const money = Money.USDT(50);
      expect(money.currency).toBe('USDT');
      expect(money.value).toBe(50);
    });

    it('should create BNB money', () => {
      const money = Money.BNB(1.5);
      expect(money.currency).toBe('BNB');
      expect(money.value).toBe(1.5);
    });
  });

  describe('arithmetic operations', () => {
    it('should add two money values', () => {
      const money1 = Money.USDT(100);
      const money2 = Money.USDT(50);
      const result = money1.add(money2);
      expect(result.value).toBe(150);
    });

    it('should subtract money values', () => {
      const money1 = Money.USDT(100);
      const money2 = Money.USDT(30);
      const result = money1.subtract(money2);
      expect(result.value).toBe(70);
    });

    it('should throw error when subtracting more than available', () => {
      const money1 = Money.USDT(50);
      const money2 = Money.USDT(100);
      expect(() => money1.subtract(money2)).toThrow('Insufficient balance');
    });

    it('should throw error when adding different currencies', () => {
      const money1 = Money.USDT(100);
      const money2 = Money.BNB(1);
      expect(() => money1.add(money2)).toThrow('Currency mismatch');
    });
  });

  describe('comparison operations', () => {
    it('should compare less than correctly', () => {
      const money1 = Money.USDT(50);
      const money2 = Money.USDT(100);
      expect(money1.lessThan(money2)).toBe(true);
      expect(money2.lessThan(money1)).toBe(false);
    });

    it('should compare greater than correctly', () => {
      const money1 = Money.USDT(100);
      const money2 = Money.USDT(50);
      expect(money1.greaterThan(money2)).toBe(true);
    });

    it('should check equality correctly', () => {
      const money1 = Money.USDT(100);
      const money2 = Money.USDT(100);
      expect(money1.equals(money2)).toBe(true);
    });
  });
});
