// Integration: /api/streaks/:sport and /api/hotlist/:sport (Session 23).
// rosterLogs is mocked so we exercise route → engine without Redis.

const express = require('express');
const request = require('supertest');

jest.mock('../../src/services/rosterLogs', () => ({
  loadRosterLogs: jest.fn(),
}));
const { loadRosterLogs } = require('../../src/services/rosterLogs');

function mountStreaks() {
  delete require.cache[require.resolve('../../src/routes/streaks')];
  const app = express();
  app.use('/api/streaks', require('../../src/routes/streaks'));
  return app;
}
function mountHotlist() {
  delete require.cache[require.resolve('../../src/routes/hotlist')];
  const app = express();
  app.use('/api/hotlist', require('../../src/routes/hotlist'));
  return app;
}

beforeEach(() => jest.clearAllMocks());

describe('GET /api/streaks/:sport', () => {
  test('returns computed streaks from cached logs', async () => {
    loadRosterLogs.mockResolvedValue([
      { name: 'Wemby', team: 'SA', games: [{ points: 30 }, { points: 28 }, { points: 26 }] },
    ]);
    const res = await request(mountStreaks()).get('/api/streaks/nba');
    expect(res.status).toBe(200);
    expect(res.body.source).toBe('computed');
    expect(res.body.streaks[0].player).toBe('Wemby');
    expect(res.body.streaks[0].currentStreak).toBe(3);
  });

  test('stat filter narrows the response', async () => {
    loadRosterLogs.mockResolvedValue([
      { name: 'A', games: [{ points: 30 }, { points: 30 }] },
      { name: 'B', games: [{ assists: 9 }, { assists: 8 }] },
    ]);
    const res = await request(mountStreaks()).get('/api/streaks/nba?stat=points');
    expect(res.body.stat).toBe('points');
    expect(res.body.streaks.every((s) => s.category === 'points')).toBe(true);
  });

  test('empty roster → empty streaks, not an error', async () => {
    loadRosterLogs.mockResolvedValue([]);
    const res = await request(mountStreaks()).get('/api/streaks/mlb');
    expect(res.status).toBe(200);
    expect(res.body.streaks).toEqual([]);
  });

  test('loader throwing → 200 with empty streaks (platform never down)', async () => {
    loadRosterLogs.mockRejectedValue(new Error('redis exploded'));
    const res = await request(mountStreaks()).get('/api/streaks/nba');
    expect(res.status).toBe(200);
    expect(res.body.streaks).toEqual([]);
  });

  test('unsupported sport → 404', async () => {
    const res = await request(mountStreaks()).get('/api/streaks/cricket');
    expect(res.status).toBe(404);
  });
});

describe('GET /api/hotlist/:sport', () => {
  test('returns ranked hot players', async () => {
    loadRosterLogs.mockResolvedValue([
      { name: 'Riser', seasonAvg: { points: 18 }, games: [{ points: 28 }, { points: 30 }] },
    ]);
    const res = await request(mountHotlist()).get('/api/hotlist/nba?stat=points');
    expect(res.status).toBe(200);
    expect(res.body.players[0].name).toBe('Riser');
    expect(res.body.players[0].rank).toBe(1);
  });

  test('empty roster → empty players', async () => {
    loadRosterLogs.mockResolvedValue([]);
    const res = await request(mountHotlist()).get('/api/hotlist/mlb');
    expect(res.body.players).toEqual([]);
  });

  test('unsupported sport → 404', async () => {
    const res = await request(mountHotlist()).get('/api/hotlist/nfl');
    expect(res.status).toBe(404);
  });
});
