import { describe, it, expect } from 'vitest';
import { StandingEntryViewModel } from './StandingEntryViewModel';
import type { LeagueStandingDTO } from '../types/generated/LeagueStandingDTO';

describe('StandingEntryViewModel', () => {
  const createMockStanding = (overrides?: Partial<LeagueStandingDTO>): LeagueStandingDTO => ({
    driverId: 'driver-1',
    position: 1,
    points: 100,
    wins: 3,
    podiums: 5,
    races: 8,
    ...overrides,
  });

  it('should create instance with all properties', () => {
    const dto = createMockStanding();
    const viewModel = new StandingEntryViewModel(dto, 100, 85, 'driver-1');

    expect(viewModel.driverId).toBe('driver-1');
    expect(viewModel.position).toBe(1);
    expect(viewModel.points).toBe(100);
    expect(viewModel.wins).toBe(3);
    expect(viewModel.podiums).toBe(5);
    expect(viewModel.races).toBe(8);
  });

  it('should return position as badge string', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 5 }),
      100,
      85,
      'driver-1'
    );

    expect(viewModel.positionBadge).toBe('5');
  });

  it('should calculate points gap to leader correctly', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 2, points: 85 }),
      100, // leader points
      70,  // next points
      'driver-2'
    );

    expect(viewModel.pointsGapToLeader).toBe(-15);
  });

  it('should show zero gap when driver is leader', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 1, points: 100 }),
      100, // leader points
      85,  // next points
      'driver-1'
    );

    expect(viewModel.pointsGapToLeader).toBe(0);
  });

  it('should calculate points gap to next position correctly', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 2, points: 85 }),
      100, // leader points
      70,  // next points
      'driver-2'
    );

    expect(viewModel.pointsGapToNext).toBe(15);
  });

  it('should identify current user correctly', () => {
    const viewModel1 = new StandingEntryViewModel(
      createMockStanding({ driverId: 'driver-1' }),
      100,
      85,
      'driver-1'
    );

    const viewModel2 = new StandingEntryViewModel(
      createMockStanding({ driverId: 'driver-1' }),
      100,
      85,
      'driver-2'
    );

    expect(viewModel1.isCurrentUser).toBe(true);
    expect(viewModel2.isCurrentUser).toBe(false);
  });

  it('should return "same" trend when no previous position', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 1 }),
      100,
      85,
      'driver-1'
    );

    expect(viewModel.trend).toBe('same');
  });

  it('should return "up" trend when position improved', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 1 }),
      100,
      85,
      'driver-1',
      3 // previous position was 3rd
    );

    expect(viewModel.trend).toBe('up');
  });

  it('should return "down" trend when position worsened', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 5 }),
      100,
      85,
      'driver-1',
      2 // previous position was 2nd
    );

    expect(viewModel.trend).toBe('down');
  });

  it('should return "same" trend when position unchanged', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 3 }),
      100,
      85,
      'driver-1',
      3 // same position
    );

    expect(viewModel.trend).toBe('same');
  });

  it('should return correct trend arrow for up', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 1 }),
      100,
      85,
      'driver-1',
      3
    );

    expect(viewModel.trendArrow).toBe('↑');
  });

  it('should return correct trend arrow for down', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 5 }),
      100,
      85,
      'driver-1',
      2
    );

    expect(viewModel.trendArrow).toBe('↓');
  });

  it('should return correct trend arrow for same', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 3 }),
      100,
      85,
      'driver-1'
    );

    expect(viewModel.trendArrow).toBe('-');
  });

  it('should handle edge case of last place with no one behind', () => {
    const viewModel = new StandingEntryViewModel(
      createMockStanding({ position: 10, points: 20 }),
      100, // leader points
      20,  // same points (last place)
      'driver-10'
    );

    expect(viewModel.pointsGapToNext).toBe(0);
    expect(viewModel.pointsGapToLeader).toBe(-80);
  });
});