import { describe, it, expect } from 'vitest';
import { RaceTimeOfDay } from './RaceTimeOfDay';
import { RacingDomainValidationError } from '../errors/RacingDomainError';

describe('RaceTimeOfDay', () => {
  it('should create valid time', () => {
    const time = new RaceTimeOfDay(12, 30);
    expect(time.hour).toBe(12);
    expect(time.minute).toBe(30);
  });

  it('should throw on invalid hour', () => {
    expect(() => new RaceTimeOfDay(24, 0)).toThrow(RacingDomainValidationError);
    expect(() => new RaceTimeOfDay(-1, 0)).toThrow(RacingDomainValidationError);
    expect(() => new RaceTimeOfDay(12.5, 0)).toThrow(RacingDomainValidationError);
  });

  it('should throw on invalid minute', () => {
    expect(() => new RaceTimeOfDay(12, 60)).toThrow(RacingDomainValidationError);
    expect(() => new RaceTimeOfDay(12, -1)).toThrow(RacingDomainValidationError);
    expect(() => new RaceTimeOfDay(12, 30.5)).toThrow(RacingDomainValidationError);
  });

  it('should create from valid string', () => {
    const time = RaceTimeOfDay.fromString('14:45');
    expect(time.hour).toBe(14);
    expect(time.minute).toBe(45);
  });

  it('should throw on invalid string format', () => {
    expect(() => RaceTimeOfDay.fromString('14:45:00')).toThrow(RacingDomainValidationError);
    expect(() => RaceTimeOfDay.fromString('1445')).toThrow(RacingDomainValidationError);
    expect(() => RaceTimeOfDay.fromString('14-45')).toThrow(RacingDomainValidationError);
  });

  it('should throw on invalid hour in string', () => {
    expect(() => RaceTimeOfDay.fromString('25:00')).toThrow(RacingDomainValidationError);
  });

  it('should throw on invalid minute in string', () => {
    expect(() => RaceTimeOfDay.fromString('12:60')).toThrow(RacingDomainValidationError);
  });

  it('should convert to string', () => {
    const time = new RaceTimeOfDay(9, 5);
    expect(time.toString()).toBe('09:05');
  });

  it('should equal same time', () => {
    const t1 = new RaceTimeOfDay(10, 20);
    const t2 = new RaceTimeOfDay(10, 20);
    expect(t1.equals(t2)).toBe(true);
  });

  it('should not equal different time', () => {
    const t1 = new RaceTimeOfDay(10, 20);
    const t2 = new RaceTimeOfDay(10, 21);
    expect(t1.equals(t2)).toBe(false);
  });

  it('should return props', () => {
    const time = new RaceTimeOfDay(15, 30);
    expect(time.props).toEqual({ hour: 15, minute: 30 });
  });
});