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

describe('Driver', () => {
  it('should create a driver', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
      bio: 'A passionate racer.',
      joinedAt: new Date('2020-01-01'),
    });

    expect(driver.id).toBe('driver1');
    expect(driver.iracingId.toString()).toBe('12345');
    expect(driver.name.toString()).toBe('John Doe');
    expect(driver.country.toString()).toBe('US');
    expect(driver.bio?.toString()).toBe('A passionate racer.');
    expect(driver.joinedAt.toDate()).toEqual(new Date('2020-01-01'));
  });

  it('should create driver without bio', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
    });

    expect(driver.bio).toBeUndefined();
  });

  it('should create driver with default joinedAt', () => {
    const before = new Date();
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
    });
    const after = new Date();

    expect(driver.joinedAt.toDate().getTime()).toBeGreaterThanOrEqual(before.getTime());
    expect(driver.joinedAt.toDate().getTime()).toBeLessThanOrEqual(after.getTime());
  });

  it('should update name', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
    });

    const updated = driver.update({ name: 'Jane Doe' });
    expect(updated.name.toString()).toBe('Jane Doe');
    expect(updated.id).toBe('driver1');
  });

  it('should update country', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
    });

    const updated = driver.update({ country: 'CA' });
    expect(updated.country.toString()).toBe('CA');
  });

  it('should update bio', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
      bio: 'Old bio',
    });

    const updated = driver.update({ bio: 'New bio' });
    expect(updated.bio?.toString()).toBe('New bio');
  });

  it('should remove bio', () => {
    const driver = Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
      bio: 'Old bio',
    });

    const updated = driver.update({ bio: undefined });
    expect(updated.bio).toBeUndefined();
  });

  it('should throw on invalid id', () => {
    expect(() => Driver.create({
      id: '',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
    })).toThrow('Driver ID is required');
  });

  it('should throw on invalid iracingId', () => {
    expect(() => Driver.create({
      id: 'driver1',
      iracingId: '',
      name: 'John Doe',
      country: 'US',
    })).toThrow('iRacing ID is required');
  });

  it('should throw on invalid name', () => {
    expect(() => Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: '',
      country: 'US',
    })).toThrow('Driver name is required');
  });

  it('should throw on invalid country', () => {
    expect(() => Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: '',
    })).toThrow('Country code is required');
  });

  it('should throw on invalid country format', () => {
    expect(() => Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'U',
    })).toThrow('Country must be a valid ISO code (2-3 letters)');
  });

  it('should throw on future joinedAt', () => {
    const future = new Date();
    future.setFullYear(future.getFullYear() + 1);
    expect(() => Driver.create({
      id: 'driver1',
      iracingId: '12345',
      name: 'John Doe',
      country: 'US',
      joinedAt: future,
    })).toThrow('Joined date cannot be in the future');
  });
});