import { describe, expect, it } from 'vitest';
import { RaceIncidents, type IncidentRecord } from './RaceIncidents';

describe('RaceIncidents', () => {
  const sampleIncident: IncidentRecord = {
    type: 'contact',
    lap: 5,
    description: 'Minor contact',
    penaltyPoints: 2,
  };

  const anotherIncident: IncidentRecord = {
    type: 'track_limits',
    lap: 10,
    penaltyPoints: 0,
  };

  it('should create empty incidents', () => {
    const incidents = new RaceIncidents();
    expect(incidents.getTotalCount()).toBe(0);
    expect(incidents.isClean()).toBe(true);
    expect(incidents.hasIncidents()).toBe(false);
  });

  it('should create incidents from array', () => {
    const incidents = new RaceIncidents([sampleIncident]);
    expect(incidents.getTotalCount()).toBe(1);
    expect(incidents.isClean()).toBe(false);
    expect(incidents.hasIncidents()).toBe(true);
  });

  it('should add incident immutably', () => {
    const original = new RaceIncidents([sampleIncident]);
    const updated = original.addIncident(anotherIncident);
    expect(original.getTotalCount()).toBe(1);
    expect(updated.getTotalCount()).toBe(2);
  });

  it('should get all incidents', () => {
    const incidents = new RaceIncidents([sampleIncident, anotherIncident]);
    const all = incidents.getAllIncidents();
    expect(all).toHaveLength(2);
    expect(all).toEqual([sampleIncident, anotherIncident]);
  });

  it('should get total count', () => {
    const incidents = new RaceIncidents([sampleIncident, anotherIncident]);
    expect(incidents.getTotalCount()).toBe(2);
  });

  it('should get total penalty points', () => {
    const incidents = new RaceIncidents([sampleIncident, anotherIncident]);
    expect(incidents.getTotalPenaltyPoints()).toBe(2);
  });

  it('should get incidents by type', () => {
    const incidents = new RaceIncidents([sampleIncident, anotherIncident]);
    const contacts = incidents.getIncidentsByType('contact');
    expect(contacts).toHaveLength(1);
    expect(contacts[0]).toEqual(sampleIncident);
  });

  it('should check has incidents', () => {
    const empty = new RaceIncidents();
    const withIncidents = new RaceIncidents([sampleIncident]);
    expect(empty.hasIncidents()).toBe(false);
    expect(withIncidents.hasIncidents()).toBe(true);
  });

  it('should check is clean', () => {
    const empty = new RaceIncidents();
    const withIncidents = new RaceIncidents([sampleIncident]);
    expect(empty.isClean()).toBe(true);
    expect(withIncidents.isClean()).toBe(false);
  });

  it('should equal same incidents', () => {
    const i1 = new RaceIncidents([sampleIncident]);
    const i2 = new RaceIncidents([sampleIncident]);
    expect(i1.equals(i2)).toBe(true);
  });

  it('should not equal different incidents', () => {
    const i1 = new RaceIncidents([sampleIncident]);
    const i2 = new RaceIncidents([anotherIncident]);
    expect(i1.equals(i2)).toBe(false);
  });

  it('should not equal different length', () => {
    const i1 = new RaceIncidents([sampleIncident]);
    const i2 = new RaceIncidents([sampleIncident, anotherIncident]);
    expect(i1.equals(i2)).toBe(false);
  });

  it('should return props as copy', () => {
    const incidents = new RaceIncidents([sampleIncident]);
    const props = incidents.props;
    expect(props).toEqual([sampleIncident]);
    props.push(anotherIncident);
    expect(incidents.getTotalCount()).toBe(1);
  });
});