process.env.PARLAYAPI_KEY = 'test-key';
process.env.PARLAYAPI_BASE_URL = 'https://api.parlayapi.test/v1';

const mockAxiosGet = jest.fn();
jest.mock('axios', () => ({ get: (...args) => mockAxiosGet(...args) }));

const mockCache = { current: new Map() };
jest.mock('../../src/utils/redis', () => ({
  cacheGet: async (k) => mockCache.current.get(k) ?? null,
  cacheSet: async (k, v) => { mockCache.current.set(k, v); return true; },
  cacheDel: async (k) => { mockCache.current.delete(k); return true; },
  // Session 21 — gateway pulls isDegraded to decide whether to track
  // the call. Returning true here puts the gateway in degraded-mode
  // fail-open so the adapter's existing cache-and-axios assertions
  // stay accurate (no extra Redis writes for the quota counter).
  isDegraded: () => true,
}));

const adapter = require('../../src/services/adapters/parlayApiAdapter');

beforeEach(() => {
  mockAxiosGet.mockReset();
  mockCache.current.clear();
});

describe('parlayApiAdapter.configured', () => {
  test('reflects PARLAYAPI_KEY presence', () => {
    expect(adapter.configured()).toBe(true);
    delete process.env.PARLAYAPI_KEY;
    expect(adapter.configured()).toBe(false);
    process.env.PARLAYAPI_KEY = 'test-key';
  });
});

describe('parlayApiAdapter.getHistoricalProps', () => {
  test('throws on unsupported sport', async () => {
    await expect(adapter.getHistoricalProps('curling', 'X', 'points', 10)).rejects.toThrow(/Unsupported sport/);
  });

  test('normalizes API response into stable shape', async () => {
    mockAxiosGet.mockResolvedValue({
      status: 200,
      data: {
        props: [
          { player: 'Jalen Brunson', stat_type: 'points', line: 26.5, closing_line: 27.0, result: 'over', game_date: '2026-04-15' },
        ],
      },
    });
    const result = await adapter.getHistoricalProps('nba', 'Jalen Brunson', 'points', 10);
    expect(result).toHaveLength(1);
    expect(result[0]).toMatchObject({
      sport: 'nba',
      player_name: 'Jalen Brunson',
      stat_type: 'points',
      line: 26.5,
      closing_line: 27.0,
      result: 'over',
      source: 'parlayapi',
    });
  });

  test('cache hit on second call', async () => {
    mockAxiosGet.mockResolvedValue({ status: 200, data: { props: [] } });
    await adapter.getHistoricalProps('nba', 'P', 'points', 10);
    await adapter.getHistoricalProps('nba', 'P', 'points', 10);
    expect(mockAxiosGet).toHaveBeenCalledTimes(1);
  });

  test('returns [] when unconfigured', async () => {
    delete process.env.PARLAYAPI_KEY;
    expect(await adapter.getHistoricalProps('nba', 'P', 'points', 10)).toEqual([]);
    process.env.PARLAYAPI_KEY = 'test-key';
  });
});

describe('parlayApiAdapter.getClosingLines', () => {
  test('returns array from response.lines', async () => {
    mockAxiosGet.mockResolvedValue({
      status: 200,
      data: { lines: [{ player: 'A', line: 10 }, { player: 'B', line: 15 }] },
    });
    const lines = await adapter.getClosingLines('nba', '2026-04-15');
    expect(lines).toHaveLength(2);
  });
});
