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

import {
  buildPlayerPropSlateAuditReport,
  renderPlayerPropSlateAuditMarkdown,
} from '../player-prop-slate-audit';

describe('player prop slate audit', () => {
  it('summarizes direction skew, confidence gaps, stale gaps, projection clusters, and prop highlight coverage', () => {
    const report = buildPlayerPropSlateAuditReport({
      auditedAt: '2026-04-02T14:00:00.000Z',
      dateEt: '2026-04-02',
      events: [
        {
          eventId: 'evt-1',
          league: 'nba',
          matchup: 'BOS @ NYK',
          startsAt: '2026-04-02T23:00:00.000Z',
          hasForecast: true,
          propHighlightsCount: 0,
        },
        {
          eventId: 'evt-2',
          league: 'nhl',
          matchup: 'TOR @ MTL',
          startsAt: '2026-04-02T23:30:00.000Z',
          hasForecast: true,
          propHighlightsCount: 3,
        },
        {
          eventId: 'evt-5',
          league: 'nba',
          matchup: 'MIA @ ATL',
          startsAt: '2026-04-02T23:45:00.000Z',
          hasForecast: true,
          propHighlightsCount: 0,
          sourceBackedPlayerPropsCount: 8,
          sourceBackedSource: 'candidates',
        },
      ],
      assets: [
        {
          eventId: 'evt-1',
          league: 'nba',
          forecastType: 'PLAYER_PROP',
          status: 'ACTIVE',
          playerName: 'Player One',
          confidenceScore: null,
          payload: {
            recommendation: 'UNDER',
            prob: null,
            forecast_direction: '',
            agreement_score: null,
            market_quality_label: '',
            forecast: '',
            prop_type: '',
            sportsbook_display: '',
            prop: '3PT Made Under 1.5',
            projected_stat_value: 2.3,
            normalized_stat_type: '3pt made',
            market_line_value: 1.5,
          },
        },
        {
          eventId: 'evt-1',
          league: 'nba',
          forecastType: 'PLAYER_PROP',
          status: 'ACTIVE',
          playerName: 'Player Two',
          confidenceScore: null,
          payload: {
            recommendation: 'UNDER',
            prob: null,
            forecast_direction: '',
            agreement_score: null,
            market_quality_label: '',
            forecast: '',
            prop_type: '',
            sportsbook_display: '',
            prop: '3PT Made Under 1.5',
            projected_stat_value: 2.3,
            normalized_stat_type: '3pt made',
            market_line_value: 1.5,
          },
        },
        {
          eventId: 'evt-3',
          league: 'nba',
          forecastType: 'PLAYER_PROP',
          status: 'ACTIVE',
          playerName: 'Player Three',
          confidenceScore: null,
          payload: {
            recommendation: 'UNDER',
            prob: null,
            forecast_direction: '',
            agreement_score: null,
            market_quality_label: '',
            forecast: '',
            prop_type: '',
            sportsbook_display: '',
            prop: '3PT Made Under 1.5',
            projected_stat_value: 2.3,
            normalized_stat_type: '3pt made',
            market_line_value: 1.5,
          },
        },
        {
          eventId: 'evt-4',
          league: 'nba',
          forecastType: 'PLAYER_PROP',
          status: 'ACTIVE',
          playerName: 'Player Four',
          confidenceScore: null,
          payload: {
            recommendation: 'UNDER',
            prob: null,
            forecast_direction: '',
            agreement_score: null,
            market_quality_label: '',
            forecast: '',
            prop_type: '',
            sportsbook_display: '',
            prop: '3PT Made Under 1.5',
            projected_stat_value: 2.3,
            normalized_stat_type: '3pt made',
            market_line_value: 1.5,
          },
        },
        {
          eventId: 'evt-2',
          league: 'nhl',
          forecastType: 'PLAYER_PROP',
          status: 'STALE',
          playerName: 'Skater One',
          confidenceScore: 0.82,
          payload: {
            recommendation: 'UNDER',
            prob: 82,
            prop: 'Shots on Goal Under 2.5',
            projected_stat_value: 1.7,
          },
        },
        {
          eventId: 'evt-2',
          league: 'nhl',
          forecastType: 'TEAM_PROPS',
          status: 'ACTIVE',
          playerName: null,
          confidenceScore: 0.64,
          payload: {
            props: [{
              player: 'Skater Two',
              prop: 'Shots on Goal Under 1.5',
              recommendation: 'UNDER',
              prob: 64,
            }],
          },
        },
        {
          eventId: 'evt-2',
          league: 'nhl',
          forecastType: 'MLB_F5',
          status: 'ACTIVE',
          playerName: null,
          confidenceScore: 0.58,
          payload: {},
        },
      ],
    });

    expect(report.summary).toMatchObject({
      totalEvents: 3,
      eventsWithForecasts: 3,
      activePlayerProps: 4,
      sourceBackedPlayerProps: 8,
      eventsWithSourceBackedCoverage: 1,
      sourceBackedRecoverableGapCount: 1,
      sourceBackedUnrecoverableGapCount: 1,
      stalePlayerProps: 1,
      activeTeamProps: 1,
      activeGameMarketAssets: 1,
      projectionClusterCount: 1,
      staleGapCount: 1,
    });
    expect(report.directionsByLeague).toContainEqual(expect.objectContaining({
      league: 'nba',
      total: 4,
      overs: 0,
      unders: 4,
      underPct: 100,
    }));
    expect(report.confidenceGapsByLeague).toContainEqual(expect.objectContaining({
      league: 'nba',
      totalProps: 4,
      missingConfidenceScore: 4,
      missingProbability: 4,
    }));
    expect(report.payloadGapsByLeague).toContainEqual(expect.objectContaining({
      league: 'nba',
      totalProps: 4,
      missingSignalTier: 4,
      missingForecastDirection: 4,
      missingAgreementScore: 4,
      missingMarketQualityLabel: 4,
      missingForecastDisplay: 4,
      missingPropType: 4,
      missingSportsbookDisplay: 4,
    }));
    expect(report.teamBundleGapsByLeague).toContainEqual(expect.objectContaining({
      league: 'nhl',
      totalProps: 1,
      missingSignalTier: 1,
      missingForecastDirection: 1,
      missingAgreementScore: 1,
      missingMarketQualityLabel: 1,
    }));
    expect(report.marketConcentrationByLeague).toContainEqual(expect.objectContaining({
      league: 'nba',
      topPropLabel: '3pt made',
      topPropCount: 4,
      topPropSharePct: 100,
    }));
    expect(report.projectionClusters[0]).toMatchObject({
      league: 'nba',
      propKey: '3pt made @ 1.5',
      projectedValue: 2.3,
      count: 4,
    });
    expect(report.staleEventGaps[0]).toMatchObject({
      league: 'nhl',
      eventId: 'evt-2',
      activePlayerProps: 0,
      stalePlayerProps: 1,
      activeTeamProps: 1,
      activeGameMarkets: 1,
    });
    expect(report.propHighlightsCoverage).toContainEqual(expect.objectContaining({
      league: 'nba',
      eventsWithForecasts: 2,
      eventsWithPropHighlights: 0,
      emptyPropHighlights: 2,
      coveragePct: 0,
    }));
    expect(report.sourceCoverageByLeague).toContainEqual(expect.objectContaining({
      league: 'nba',
      totalEvents: 2,
      eventsWithPublishedPlayerProps: 1,
      eventsWithSourceBackedCoverage: 1,
      eventsUsingSourceBackedRecovery: 1,
      eventsWithNoPlayerPropCoverage: 0,
      publishedPlayerProps: 2,
      sourceBackedPlayerProps: 8,
      publishedCoveragePct: 50,
      sourceBackedCoveragePct: 50,
      recoveryPct: 50,
    }));
    expect(report.passed).toBe(false);
  });

  it('renders a markdown report with the main audit sections', () => {
    const markdown = renderPlayerPropSlateAuditMarkdown(buildPlayerPropSlateAuditReport({
      auditedAt: '2026-04-02T14:00:00.000Z',
      dateEt: '2026-04-02',
      events: [{
        eventId: 'evt-1',
        league: 'mlb',
        matchup: 'LAD @ SD',
        startsAt: '2026-04-02T23:00:00.000Z',
        hasForecast: true,
        propHighlightsCount: 2,
      }],
      assets: [{
        eventId: 'evt-1',
        league: 'mlb',
        forecastType: 'PLAYER_PROP',
        status: 'ACTIVE',
        playerName: 'Pitcher One',
        confidenceScore: 0.66,
        payload: {
          recommendation: 'OVER',
          prob: 66,
          prop: 'Strikeouts Over 5.5',
          projected_stat_value: 6.3,
        },
      }, {
        eventId: 'evt-1',
        league: 'mlb',
        forecastType: 'TEAM_PROPS',
        status: 'ACTIVE',
        playerName: null,
        confidenceScore: null,
        payload: {
          props: [{
            player: 'Pitcher One',
            prop: 'Strikeouts Over 5.5',
            recommendation: 'OVER',
            prob: 66,
          }],
        },
      }],
    }));

    expect(markdown).toContain('# Player Prop Slate Audit');
    expect(markdown).toContain('## Direction Skew');
    expect(markdown).toContain('## Confidence Gaps');
    expect(markdown).toContain('## Payload Gaps');
    expect(markdown).toContain('## Team Bundle Gaps');
    expect(markdown).toContain('## Market Concentration');
    expect(markdown).toContain('## Prop Highlights Coverage');
    expect(markdown).toContain('## Source Coverage By League');
  });
});
