import { describe, expect, it } from 'vitest';
import { computeWinRate, formatWLP, gradeForecast, gradeFromForecastData, sanitizeClosingSpreadForLeague, selectBenchmarkForecast } from '../benchmark-grading';

describe('benchmark-grading', () => {
  it('selects the more favorable spread number for the forecast side', () => {
    expect(selectBenchmarkForecast('spread', 'home', -7, -5)).toEqual({ value: -5, source: 'closing' });
    expect(selectBenchmarkForecast('spread', 'home', -5, -7)).toEqual({ value: -5, source: 'original' });
  });

  it('selects the more favorable total number by direction', () => {
    expect(selectBenchmarkForecast('total', 'over', 220, 218)).toEqual({ value: 218, source: 'closing' });
    expect(selectBenchmarkForecast('total', 'under', 220, 222)).toEqual({ value: 222, source: 'closing' });
  });

  it('grades spread and total outcomes with push support', () => {
    expect(gradeForecast({ forecastType: 'spread', side: 'home', originalForecast: -5.5, closingMarket: -5.5, homeScore: 110, awayScore: 105, isHome: true }).grade).toBe('L');
    expect(gradeForecast({ forecastType: 'total', side: 'over', originalForecast: 220, closingMarket: 220, homeScore: 115, awayScore: 110, isHome: true }).grade).toBe('W');
    expect(gradeForecast({ forecastType: 'total', side: 'under', originalForecast: 220, closingMarket: 220, homeScore: 110, awayScore: 110, isHome: true }).grade).toBe('P');
  });

  it('extracts benchmark data from forecast and odds payloads', () => {
    const result = gradeFromForecastData(
      {
        winner_pick: 'Lakers',
        forecast_side: 'Lakers',
        projected_margin: 7,
        total_direction: 'OVER',
        projected_total_points: 224,
      },
      {
        spread: { home: { line: -5, odds: -110 }, away: { line: 5, odds: -110 } },
        total: { over: { line: 220, odds: -110 }, under: { line: 220, odds: -110 } },
      },
      'Lakers',
      'Celtics',
      112,
      104,
    );

    expect(result?.grade).toBe('W');
    expect(result?.benchmarkForecast).toBe(-5);
    expect(result?.closingMarket).toBe(-5);
  });

  it('drops absurd MLB closing spreads before benchmark grading', () => {
    expect(sanitizeClosingSpreadForLeague('mlb', 5.5)).toBeNull();
    expect(sanitizeClosingSpreadForLeague('mlb', -14.5)).toBeNull();
    expect(sanitizeClosingSpreadForLeague('mlb', 1.5)).toBe(1.5);

    const result = gradeFromForecastData(
      {
        forecast_side: 'Kansas City Royals',
        projected_lines: { spread: { away: -2.5, home: 2.5 } },
      },
      {
        spread: { away: { line: 5.5, odds: -133 }, home: { line: -5.5, odds: 100 } },
      },
      'Cleveland Guardians',
      'Kansas City Royals',
      10,
      2,
      'mlb',
    );

    expect(result?.closingMarket).toBeNull();
    expect(result?.benchmarkForecast).toBe(-2.5);
    expect(result?.grade).toBe('L');
  });

  it('formats win rates and records cleanly', () => {
    expect(computeWinRate(10, 5)).toBe(66.7);
    expect(computeWinRate(0, 0)).toBeNull();
    expect(formatWLP(10, 5, 2)).toBe('10-5-2');
    expect(formatWLP(10, 5, 0)).toBe('10-5');
  });
});
