import { describe, expect, it } from 'vitest';
import { Money } from './Money';

describe('Money', () => {
  it('should create valid money', () => {
    const money = Money.create(1000, 'USD');
    expect(money.amount).toBe(1000);
    expect(money.currency).toBe('USD');
  });

  it('should default to USD', () => {
    const money = Money.create(500);
    expect(money.currency).toBe('USD');
  });

  it('should validate amount not negative', () => {
    expect(() => Money.create(-100, 'USD')).toThrow('Money amount cannot be negative');
  });

  it('should validate amount finite', () => {
    expect(() => Money.create(Infinity, 'USD')).toThrow('Money amount must be a finite number');
    expect(() => Money.create(NaN, 'USD')).toThrow('Money amount must be a finite number');
  });

  it('should calculate platform fee', () => {
    const money = Money.create(1000, 'USD'); // $10.00
    const fee = money.calculatePlatformFee();
    expect(fee.amount).toBe(100); // $1.00
    expect(fee.currency).toBe('USD');
  });

  it('should calculate net amount', () => {
    const money = Money.create(1000, 'USD'); // $10.00
    const net = money.calculateNetAmount();
    expect(net.amount).toBe(900); // $9.00
    expect(net.currency).toBe('USD');
  });

  it('should add money', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'USD');
    const sum = money1.add(money2);
    expect(sum.amount).toBe(800);
    expect(sum.currency).toBe('USD');
  });

  it('should not add different currencies', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'EUR');
    expect(() => money1.add(money2)).toThrow('Cannot add money with different currencies');
  });

  it('should subtract money', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'USD');
    const diff = money1.subtract(money2);
    expect(diff.amount).toBe(200);
    expect(diff.currency).toBe('USD');
  });

  it('should not subtract different currencies', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'EUR');
    expect(() => money1.subtract(money2)).toThrow('Cannot subtract money with different currencies');
  });

  it('should not subtract to negative', () => {
    const money1 = Money.create(300, 'USD');
    const money2 = Money.create(500, 'USD');
    expect(() => money1.subtract(money2)).toThrow('Subtraction would result in negative amount');
  });

  it('should check greater than', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'USD');
    expect(money1.isGreaterThan(money2)).toBe(true);
    expect(money2.isGreaterThan(money1)).toBe(false);
  });

  it('should not compare different currencies', () => {
    const money1 = Money.create(500, 'USD');
    const money2 = Money.create(300, 'EUR');
    expect(() => money1.isGreaterThan(money2)).toThrow('Cannot compare money with different currencies');
  });

  it('should have props', () => {
    const money = Money.create(1000, 'USD');
    expect(money.props).toEqual({
      amount: 1000,
      currency: 'USD',
    });
  });

  it('equals', () => {
    const money1 = Money.create(1000, 'USD');
    const money2 = Money.create(1000, 'USD');
    const money3 = Money.create(500, 'USD');
    const money4 = Money.create(1000, 'EUR');
    expect(money1.equals(money2)).toBe(true);
    expect(money1.equals(money3)).toBe(false);
    expect(money1.equals(money4)).toBe(false);
  });
});