import { describe, expect, it } from 'vitest';

import { getPlayerPropTypeLabel } from '../player-prop-signals';
import { buildTopPropsOfDay } from '../top-props';

describe('buildTopPropsOfDay', () => {
  it('surfaces tracked MLB pitcher-under props and ranks borderline FAIR cards behind stronger edges', () => {
    const cards = buildTopPropsOfDay([
      {
        assetId: 'a1',
        eventId: 'evt-1',
        league: 'mlb',
        startsAt: '2026-03-28T19:05:00.000Z',
        playerName: 'Gerrit Cole',
        team: 'NYY',
        opponent: 'BOS',
        teamSide: 'home',
        prop: 'Strikeouts',
        statType: 'pitching_strikeouts',
        normalizedStatType: 'pitching_strikeouts',
        marketLine: 7.5,
        odds: -105,
        projectedProbability: 79,
        projectedOutcome: 6.1,
        recommendation: 'UNDER',
        playerRole: 'pitcher',
        confidenceFactor: 0.88,
        marketSource: 'fanduel',
      },
      {
        assetId: 'a2',
        eventId: 'evt-1',
        league: 'mlb',
        startsAt: '2026-03-28T19:05:00.000Z',
        playerName: 'Framber Valdez',
        team: 'HOU',
        opponent: 'SEA',
        teamSide: 'home',
        prop: 'Hits Allowed',
        statType: 'pitching_hits',
        normalizedStatType: 'pitching_hits',
        marketLine: 5.5,
        odds: -110,
        projectedProbability: 68,
        projectedOutcome: 4.8,
        recommendation: 'UNDER',
        playerRole: 'pitcher',
        confidenceFactor: 0.75,
        marketSource: 'draftkings',
      },
      {
        assetId: 'a3',
        eventId: 'evt-2',
        league: 'mlb',
        startsAt: '2026-03-28T22:40:00.000Z',
        playerName: 'Joe Boyle',
        team: 'OAK',
        opponent: 'TEX',
        teamSide: 'away',
        prop: 'Walks Allowed',
        statType: 'pitching_basesOnBalls',
        normalizedStatType: 'pitching_basesOnBalls',
        marketLine: 1.5,
        odds: -102,
        projectedProbability: 63,
        projectedOutcome: 1.1,
        recommendation: 'UNDER',
        playerRole: 'pitcher',
        confidenceFactor: 0.72,
        marketSource: 'betmgm',
      },
      {
        assetId: 'a4',
        eventId: 'evt-3',
        league: 'mlb',
        startsAt: '2026-03-28T21:10:00.000Z',
        playerName: 'Zack Wheeler',
        team: 'PHI',
        opponent: 'ATL',
        teamSide: 'home',
        prop: 'Earned Runs',
        statType: 'pitching_earnedruns',
        normalizedStatType: 'pitching_earnedruns',
        marketLine: 2.5,
        odds: -108,
        projectedProbability: 62,
        projectedOutcome: 2.0,
        recommendation: 'UNDER',
        playerRole: 'pitcher',
        confidenceFactor: 0.70,
        marketSource: 'fanduel',
      },
      {
        assetId: 'a5',
        eventId: 'evt-4',
        league: 'mlb',
        startsAt: '2026-03-28T20:10:00.000Z',
        playerName: 'Spencer Strider',
        team: 'ATL',
        opponent: 'PHI',
        teamSide: 'away',
        prop: 'Strikeouts',
        statType: 'pitching_strikeouts',
        normalizedStatType: 'pitching_strikeouts',
        marketLine: 8.5,
        odds: -101,
        projectedProbability: 66,
        projectedOutcome: 7.4,
        recommendation: 'UNDER',
        playerRole: 'pitcher',
        confidenceFactor: 0.74,
        marketSource: 'fanduel',
      },
    ], { limit: 4 });

    expect(cards).toHaveLength(4);
    expect(cards[0].playerName).toBe('Gerrit Cole');
    expect(cards[0].signal).toBe('STRONG');
    expect(cards[0].forecastDirection).toBe('UNDER');
    expect(cards[0].startsAt).toBe('2026-03-28T19:05:00.000Z');
    expect(cards[0].agreementLabel).toBe('HIGH');
    expect(cards[0].marketQualityLabel).toBe('GOOD');
    expect(cards[0].verificationLabel).toBe('Double-verified odds');
    expect(cards[0].verificationType).toBe('sportsbook');
    expect(cards.find((card) => card.assetId === 'a4')).toBeUndefined();
    expect(cards.find((card) => card.assetId === 'a3')).toMatchObject({
      playerName: 'Joe Boyle',
      signal: 'FAIR',
    });
    expect(cards[0].rankScore).toBeGreaterThanOrEqual(cards[1].rankScore);
    expect((cards.find((card) => card.assetId === 'a2')?.rankScore || 0)).toBeGreaterThan(cards.find((card) => card.assetId === 'a3')?.rankScore || 0);
  });

  it('normalizes baseball points labels to runs only for mlb context', () => {
    expect(getPlayerPropTypeLabel({
      league: 'mlb',
      prop: 'Points',
      statType: 'points',
      normalizedStatType: 'points',
    })).toBe('Runs');
    expect(getPlayerPropTypeLabel({
      league: 'nba',
      prop: 'Points',
      statType: 'points',
      normalizedStatType: 'points',
    })).toBe('Points');
  });

  it('suppresses props that cannot name a market source', () => {
    const cards = buildTopPropsOfDay([
      {
        assetId: 'a7',
        eventId: 'evt-4',
        league: 'mlb',
        startsAt: '2026-03-29T02:10:00.000Z',
        playerName: 'Source Missing',
        team: 'LAD',
        opponent: 'SF',
        teamSide: 'home',
        prop: 'Hits',
        statType: 'batting_hits',
        normalizedStatType: 'batting_hits',
        marketLine: 1.5,
        odds: -110,
        projectedProbability: 64,
        projectedOutcome: 1.8,
        recommendation: 'OVER',
        playerRole: 'batter',
        confidenceFactor: 0.7,
        sourceBacked: true,
      },
    ]);

    expect(cards).toEqual([]);
  });
});
