import { describe, expect, it } from 'vitest';
import { SessionType, type SessionTypeValue } from './SessionType';

describe('SessionType', () => {
  it('should create session type', () => {
    const session = new SessionType('practice');
    expect(session.value).toBe('practice');
    expect(session.props).toBe('practice');
  });

  it('should throw for invalid session type', () => {
    expect(() => new SessionType('invalid' as unknown as SessionTypeValue)).toThrow();
    expect(() => new SessionType('' as unknown as SessionTypeValue)).toThrow();
  });

  it('should have static factory methods', () => {
    expect(SessionType.practice().value).toBe('practice');
    expect(SessionType.qualifying().value).toBe('qualifying');
    expect(SessionType.sprint().value).toBe('sprint');
    expect(SessionType.main().value).toBe('main');
    expect(SessionType.timeTrial().value).toBe('timeTrial');
  });

  it('should equal same session types', () => {
    const s1 = new SessionType('main');
    const s2 = new SessionType('main');
    expect(s1.equals(s2)).toBe(true);
  });

  it('should not equal different session types', () => {
    const s1 = new SessionType('practice');
    const s2 = new SessionType('qualifying');
    expect(s1.equals(s2)).toBe(false);
  });

  describe('countsForPoints', () => {
    it('should return true for main and sprint', () => {
      expect(SessionType.main().countsForPoints()).toBe(true);
      expect(SessionType.sprint().countsForPoints()).toBe(true);
    });

    it('should return false for others', () => {
      expect(SessionType.practice().countsForPoints()).toBe(false);
      expect(SessionType.qualifying().countsForPoints()).toBe(false);
      expect(SessionType.timeTrial().countsForPoints()).toBe(false);
    });
  });

  describe('determinesGrid', () => {
    it('should return true for qualifying and q sessions', () => {
      expect(SessionType.qualifying().determinesGrid()).toBe(true);
      expect(new SessionType('q1').determinesGrid()).toBe(true);
      expect(new SessionType('q2').determinesGrid()).toBe(true);
      expect(new SessionType('q3').determinesGrid()).toBe(true);
    });

    it('should return false for others', () => {
      expect(SessionType.practice().determinesGrid()).toBe(false);
      expect(SessionType.sprint().determinesGrid()).toBe(false);
      expect(SessionType.main().determinesGrid()).toBe(false);
      expect(SessionType.timeTrial().determinesGrid()).toBe(false);
    });
  });

  describe('getDisplayName', () => {
    it('should return correct display names', () => {
      expect(SessionType.practice().getDisplayName()).toBe('Practice');
      expect(SessionType.qualifying().getDisplayName()).toBe('Qualifying');
      expect(new SessionType('q1').getDisplayName()).toBe('Q1');
      expect(SessionType.sprint().getDisplayName()).toBe('Sprint Race');
      expect(SessionType.main().getDisplayName()).toBe('Main Race');
      expect(SessionType.timeTrial().getDisplayName()).toBe('Time Trial');
    });
  });

  describe('getShortName', () => {
    it('should return correct short names', () => {
      expect(SessionType.practice().getShortName()).toBe('P');
      expect(SessionType.qualifying().getShortName()).toBe('Q');
      expect(new SessionType('q1').getShortName()).toBe('Q1');
      expect(SessionType.sprint().getShortName()).toBe('SPR');
      expect(SessionType.main().getShortName()).toBe('RACE');
      expect(SessionType.timeTrial().getShortName()).toBe('TT');
    });
  });
});