'use strict';

/**
 * GET /api/live/:sport (A1 Session 11) — route wiring over the cache-aside
 * service. The service's cache behavior is unit-tested with injected deps
 * (liveTrackingService.test.js); here we lock the route contract: sport
 * gating BEFORE the service, envelope pass-through, and fail-open 200s.
 */

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

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

function mountLive() {
  delete require.cache[require.resolve('../../src/routes/live')];
  const liveRoutes = require('../../src/routes/live');
  const app = express();
  app.use('/api/live', liveRoutes);
  return app;
}

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

describe('GET /api/live/:sport', () => {
  it('returns the service envelope for a wired sport (mlb)', async () => {
    const envelope = {
      sport: 'mlb', date: '2026-07-11', hasLive: true, updated_at: 'x',
      games: [{ id: '824249', progress: { label: '▼8th', fraction: 0.83 }, players: { 'bryce harper': { name: 'Bryce Harper', values: { total_bases: 3 } } } }],
    };
    getLiveTracking.mockResolvedValue(envelope);
    const res = await request(mountLive()).get('/api/live/mlb');
    expect(res.status).toBe(200);
    expect(res.body).toEqual(envelope);
    expect(getLiveTracking).toHaveBeenCalledWith('mlb');
    expect(res.headers['cache-control']).toContain('max-age=30');
  });

  it('wnba is wired', async () => {
    getLiveTracking.mockResolvedValue({ sport: 'wnba', hasLive: false, games: [] });
    const res = await request(mountLive()).get('/api/live/wnba');
    expect(res.status).toBe(200);
    expect(getLiveTracking).toHaveBeenCalledWith('wnba');
  });

  it('an unwired sport short-circuits WITHOUT touching the service (no quota risk)', async () => {
    const res = await request(mountLive()).get('/api/live/nba');
    expect(res.status).toBe(200);
    expect(res.body).toEqual({ sport: 'nba', hasLive: false, games: [] });
    expect(getLiveTracking).not.toHaveBeenCalled();
  });

  it('a service failure fails OPEN — 200 with an honest empty envelope', async () => {
    getLiveTracking.mockRejectedValue(new Error('redis down'));
    const res = await request(mountLive()).get('/api/live/mlb');
    expect(res.status).toBe(200);
    expect(res.body).toEqual({ sport: 'mlb', hasLive: false, games: [] });
  });

  it('sport param is case-insensitive', async () => {
    getLiveTracking.mockResolvedValue({ sport: 'mlb', hasLive: false, games: [] });
    const res = await request(mountLive()).get('/api/live/MLB');
    expect(res.status).toBe(200);
    expect(getLiveTracking).toHaveBeenCalledWith('mlb');
  });
});
