const { detectCorrelations } = require('../../src/services/correlationEngine');

function makeLeg(overrides = {}) {
  return {
    player: 'Nikola Jokic',
    stat_type: 'points',
    direction: 'over',
    line: 26.5,
    grade: 'B',
    confidence: 70,
    _team: 'DEN',
    _gameTime: '2026-03-21T19:00:00Z',
    reasoning: { steps: { season_avg: { value: 26.3 } } },
    ...overrides,
  };
}

describe('correlationEngine', () => {
  test('returns empty array when no correlations exist', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', _team: 'DEN', _gameTime: '2026-03-21T19:00:00Z' }),
      makeLeg({ player: 'Jayson Tatum', _team: 'BOS', _gameTime: '2026-03-21T20:00:00Z' }),
    ];
    const flags = detectCorrelations(legs, []);
    expect(flags).toEqual([]);
  });

  test('detects same_game_opposing_players', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', stat_type: 'points', direction: 'over', _team: 'DEN', _gameTime: 'game1' }),
      makeLeg({ player: 'LeBron James', stat_type: 'points', direction: 'over', _team: 'LAL', _gameTime: 'game1' }),
    ];
    const flags = detectCorrelations(legs, []);
    expect(flags).toHaveLength(1);
    expect(flags[0].type).toBe('same_game_opposing_players');
    expect(flags[0].impact).toBe('minor_negative');
  });

  test('detects same_game_same_team', () => {
    const legs = [
      makeLeg({ player: 'LeBron James', _team: 'LAL', _gameTime: 'game1' }),
      makeLeg({ player: 'Anthony Davis', _team: 'LAL', _gameTime: 'game1' }),
    ];
    const flags = detectCorrelations(legs, []);
    expect(flags).toHaveLength(1);
    expect(flags[0].type).toBe('same_game_same_team');
    expect(flags[0].impact).toBe('minor_negative');
  });

  test('detects same_player_conflicting (opposite directions)', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', stat_type: 'points', direction: 'over' }),
      makeLeg({ player: 'Nikola Jokic', stat_type: 'points', direction: 'under' }),
    ];
    const flags = detectCorrelations(legs, []);
    expect(flags).toHaveLength(1);
    expect(flags[0].type).toBe('same_player_conflicting');
    expect(flags[0].impact).toBe('major_negative');
  });

  test('detects positive_correlation (same player, complementary same direction)', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', stat_type: 'points', direction: 'over' }),
      makeLeg({ player: 'Nikola Jokic', stat_type: 'rebounds', direction: 'over' }),
    ];
    const flags = detectCorrelations(legs, []);
    expect(flags).toHaveLength(1);
    expect(flags[0].type).toBe('positive_correlation');
    expect(flags[0].impact).toBe('positive');
  });

  test('detects blowout_cascade (2+ legs, high spread)', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', _team: 'DEN', _gameTime: 'game1' }),
      makeLeg({ player: 'LeBron James', _team: 'LAL', _gameTime: 'game1', stat_type: 'rebounds' }),
    ];
    const spreads = [
      { home_team: 'DEN', away_team: 'LAL', game_time: 'game1', home_spread: -12, book: 'draftkings' },
    ];
    const flags = detectCorrelations(legs, spreads);
    const cascade = flags.find((f) => f.type === 'blowout_cascade');
    expect(cascade).toBeDefined();
    expect(cascade.impact).toBe('major_negative');
  });

  test('handles single leg (no correlations possible)', () => {
    const legs = [makeLeg()];
    const flags = detectCorrelations(legs, []);
    expect(flags).toEqual([]);
  });

  test('multiple correlations can fire simultaneously', () => {
    const legs = [
      makeLeg({ player: 'Nikola Jokic', stat_type: 'points', direction: 'over', _team: 'DEN', _gameTime: 'game1' }),
      makeLeg({ player: 'LeBron James', stat_type: 'points', direction: 'over', _team: 'LAL', _gameTime: 'game1' }),
      makeLeg({ player: 'Anthony Davis', stat_type: 'rebounds', direction: 'over', _team: 'LAL', _gameTime: 'game1' }),
    ];
    const flags = detectCorrelations(legs, []);
    // Jokic vs LeBron = same_game_opposing_players, LeBron vs AD = same_game_same_team
    expect(flags.length).toBeGreaterThanOrEqual(2);
  });
});
