import { RatingReference } from './RatingReference';
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';

describe('RatingReference', () => {
  describe('create', () => {
    it('should create valid reference for race', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.type).toBe('race');
      expect(ref.id).toBe('race-123');
    });

    it('should create valid reference for penalty', () => {
      const ref = RatingReference.create('penalty', 'penalty-456');
      expect(ref.type).toBe('penalty');
      expect(ref.id).toBe('penalty-456');
    });

    it('should create valid reference for vote', () => {
      const ref = RatingReference.create('vote', 'vote-789');
      expect(ref.type).toBe('vote');
      expect(ref.id).toBe('vote-789');
    });

    it('should create valid reference for adminAction', () => {
      const ref = RatingReference.create('adminAction', 'admin-101');
      expect(ref.type).toBe('adminAction');
      expect(ref.id).toBe('admin-101');
    });

    it('should throw for invalid type', () => {
      expect(() => RatingReference.create('invalid' as 'race', 'id-123')).toThrow(IdentityDomainValidationError);
    });

    it('should throw for empty type', () => {
      expect(() => RatingReference.create('' as 'race', 'id-123')).toThrow(IdentityDomainValidationError);
    });

    it('should throw for empty id', () => {
      expect(() => RatingReference.create('race', '')).toThrow(IdentityDomainValidationError);
    });

    it('should throw for whitespace id', () => {
      expect(() => RatingReference.create('race', '  ')).toThrow(IdentityDomainValidationError);
    });

    it('should trim whitespace from id', () => {
      const ref = RatingReference.create('race', '  race-123  ');
      expect(ref.id).toBe('race-123');
    });
  });

  describe('equals', () => {
    it('should return true for same type and id', () => {
      const ref1 = RatingReference.create('race', 'race-123');
      const ref2 = RatingReference.create('race', 'race-123');
      expect(ref1.equals(ref2)).toBe(true);
    });

    it('should return false for different types', () => {
      const ref1 = RatingReference.create('race', 'race-123');
      const ref2 = RatingReference.create('penalty', 'race-123');
      expect(ref1.equals(ref2)).toBe(false);
    });

    it('should return false for different ids', () => {
      const ref1 = RatingReference.create('race', 'race-123');
      const ref2 = RatingReference.create('race', 'race-456');
      expect(ref1.equals(ref2)).toBe(false);
    });
  });

  describe('props', () => {
    it('should expose props correctly', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.props.type).toBe('race');
      expect(ref.props.id).toBe('race-123');
    });
  });

  describe('toString', () => {
    it('should return string representation', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.toString()).toBe('race:race-123');
    });
  });

  describe('isRace', () => {
    it('should return true for race type', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.isRace()).toBe(true);
    });

    it('should return false for other types', () => {
      const ref = RatingReference.create('penalty', 'penalty-123');
      expect(ref.isRace()).toBe(false);
    });
  });

  describe('isPenalty', () => {
    it('should return true for penalty type', () => {
      const ref = RatingReference.create('penalty', 'penalty-123');
      expect(ref.isPenalty()).toBe(true);
    });

    it('should return false for other types', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.isPenalty()).toBe(false);
    });
  });

  describe('isVote', () => {
    it('should return true for vote type', () => {
      const ref = RatingReference.create('vote', 'vote-123');
      expect(ref.isVote()).toBe(true);
    });

    it('should return false for other types', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.isVote()).toBe(false);
    });
  });

  describe('isAdminAction', () => {
    it('should return true for adminAction type', () => {
      const ref = RatingReference.create('adminAction', 'admin-123');
      expect(ref.isAdminAction()).toBe(true);
    });

    it('should return false for other types', () => {
      const ref = RatingReference.create('race', 'race-123');
      expect(ref.isAdminAction()).toBe(false);
    });
  });
});