import { FileSize } from '../../../../src/domain/value-objects/file-size.vo';
import { DomainException } from '../../../../src/shared/exceptions/domain.exception';

describe('FileSize Value Object', () => {
  describe('create', () => {
    it('should create valid file size', () => {
      const fileSize = FileSize.create(1024n);
      expect(fileSize.bytes).toBe(1024n);
    });

    it('should create zero size', () => {
      const fileSize = FileSize.create(0n);
      expect(fileSize.bytes).toBe(0n);
    });

    it('should create max size (2GB)', () => {
      const maxSize = 2n * 1024n * 1024n * 1024n; // 2GB
      const fileSize = FileSize.create(maxSize);
      expect(fileSize.bytes).toBe(maxSize);
    });

    it('should throw error for negative size', () => {
      expect(() => FileSize.create(-1n)).toThrow(DomainException);
      expect(() => FileSize.create(-1n)).toThrow('FileSize cannot be negative');
    });

    it('should throw error for size exceeding 2GB', () => {
      const overSize = 3n * 1024n * 1024n * 1024n; // 3GB
      expect(() => FileSize.create(overSize)).toThrow(DomainException);
      expect(() => FileSize.create(overSize)).toThrow('FileSize cannot exceed 2GB');
    });
  });

  describe('toHumanReadable', () => {
    it('should format bytes', () => {
      const fileSize = FileSize.create(500n);
      expect(fileSize.toHumanReadable()).toBe('500.00 B');
    });

    it('should format kilobytes', () => {
      const fileSize = FileSize.create(1536n); // 1.5 KB
      expect(fileSize.toHumanReadable()).toBe('1.50 KB');
    });

    it('should format megabytes', () => {
      const fileSize = FileSize.create(1572864n); // 1.5 MB
      expect(fileSize.toHumanReadable()).toBe('1.50 MB');
    });

    it('should format gigabytes', () => {
      const fileSize = FileSize.create(1610612736n); // 1.5 GB
      expect(fileSize.toHumanReadable()).toBe('1.50 GB');
    });

    it('should handle zero', () => {
      const fileSize = FileSize.create(0n);
      expect(fileSize.toHumanReadable()).toBe('0.00 B');
    });
  });

  describe('equals', () => {
    it('should return true for same sizes', () => {
      const f1 = FileSize.create(1024n);
      const f2 = FileSize.create(1024n);

      expect(f1.equals(f2)).toBe(true);
    });

    it('should return false for different sizes', () => {
      const f1 = FileSize.create(1024n);
      const f2 = FileSize.create(2048n);

      expect(f1.equals(f2)).toBe(false);
    });
  });

  describe('toString', () => {
    it('should return string representation of bytes', () => {
      const fileSize = FileSize.create(1024n);
      expect(fileSize.toString()).toBe('1024');
    });
  });
});
