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

const { query, settleArchivedForecast, refreshBucketStats } = vi.hoisted(() => ({
  query: vi.fn(),
  settleArchivedForecast: vi.fn(),
  refreshBucketStats: vi.fn(),
}));

vi.mock('../../db', () => ({ default: { query } }));
vi.mock('../archive', () => ({ settleArchivedForecast, refreshBucketStats }));
vi.mock('../../lib/team-abbreviations', () => ({
  getTeamAbbr: vi.fn(() => '???'),
}));

async function loadGradingService() {
  vi.resetModules();
  return import('../grading-service');
}

describe('grading pipeline flow', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    delete process.env.GRADE_TOTALS_ENABLED;
    vi.stubGlobal('fetch', vi.fn());
  });

  it('resolves expired forecasts and refreshes bucket stats', async () => {
    const { resolveAllPending } = await loadGradingService();

    query
      .mockResolvedValueOnce({ rows: [{
        id: 'fc1',
        event_id: 'evt1',
        league: 'nba',
        starts_at: '2026-03-27T19:00:00.000Z',
        expires_at: '2026-03-27T23:00:00.000Z',
        away_team: 'Celtics',
        home_team: 'Lakers',
        confidence_score: '0.75',
        forecast_data: { winner_pick: 'Lakers', forecast_side: 'Lakers', projected_margin: 7, projected_total_points: 221 },
        odds_data: { spread: { home: { line: -4.5, odds: -110 }, away: { line: 4.5, odds: -110 } }, total: { over: { line: 220.5, odds: -110 }, under: { line: 220.5, odds: -110 } } },
      }] })
      .mockResolvedValueOnce({ rows: [{ homeTeam: 'Lakers', awayTeam: 'Celtics', homeScore: 111, awayScore: 102, status: 'final' }] })
      .mockResolvedValueOnce({ rows: [{ event_date: '2026-03-27' }] })
      .mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 'acc-1' }] })
      .mockResolvedValueOnce({ rows: [] });

    const resolved = await resolveAllPending();

    expect(resolved).toBe(1);
    expect(refreshBucketStats).toHaveBeenCalled();
    expect(settleArchivedForecast).not.toHaveBeenCalled();
    const v2UpsertCall = query.mock.calls.find(([sql]) => String(sql).includes('INSERT INTO rm_forecast_accuracy_v2'));
    expect(v2UpsertCall).toBeTruthy();
    expect(String(v2UpsertCall?.[0])).toContain('forecast_type = $22');
  });
});
