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

import { normalizeGroupedMlbMarkets } from '../mlb-market-gapfill';
import { groupRawMlbMarketSources, mapPlayerPropLineRowToRawMarketSource } from '../mlb-market-normalizer';

function makeRow(overrides: Record<string, any> = {}): any {
  return {
    playerExternalId: 'SHOHEI_OHTANI_1_MLB',
    propType: 'batting_hits',
    lineValue: null,
    fdLine: null,
    dkLine: null,
    oddsAmerican: -110,
    fdOverOdds: null,
    dkOverOdds: null,
    vendor: 'sportsgameodds',
    oddId: 'odd-1',
    marketName: 'Shohei Ohtani Hits Over/Under',
    snapshotAt: '2026-03-28T18:58:00.000Z',
    updatedAt: '2026-03-28T18:58:00.000Z',
    createdAt: '2026-03-28T18:58:00.000Z',
    homeTeam: 'LAD',
    awayTeam: 'SEA',
    gameStart: '2026-03-28T19:00:00.000Z',
    raw: {
      bookmaker: 'FanDuel',
      sportsgameodds: {
        playerID: 'SHOHEI_OHTANI_1_MLB',
        sideID: 'over',
        marketName: 'Shohei Ohtani Hits Over/Under',
      },
    },
    ...overrides,
  };
}

function mapRow(row: any) {
  return mapPlayerPropLineRowToRawMarketSource(row, {
    eventId: 'evt-1',
    startsAt: '2026-03-28T19:00:00.000Z',
    homeTeam: 'LAD',
    awayTeam: 'SEA',
  });
}

describe('MLB market normalizer integration', () => {
  it('pairs exact source-specific lines across books into a complete market', () => {
    const over = mapRow(makeRow({
      fdLine: 1.5,
      fdOverOdds: -110,
      raw: {
        bookmaker: 'FanDuel',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'over',
          marketName: 'Shohei Ohtani Hits Over/Under',
        },
      },
    }));
    const under = mapRow(makeRow({
      dkLine: 1.5,
      dkOverOdds: -105,
      oddId: 'odd-2',
      raw: {
        bookmaker: 'DraftKings',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'under',
          marketName: 'Shohei Ohtani Hits Over/Under',
        },
      },
    }));

    const [market] = normalizeGroupedMlbMarkets(groupRawMlbMarketSources([over!, under!]));

    expect(market.completenessStatus).toBe('multi_source_complete');
    expect(market.completionMethod).toBe('multi_source');
    expect(market.line).toBe(1.5);
    expect(market.over?.source).toBe('fanduel');
    expect(market.under?.source).toBe('draftkings');
  });

  it('keeps different lines in separate incomplete buckets', () => {
    const over = mapRow(makeRow({
      fdLine: 1.5,
      raw: {
        bookmaker: 'FanDuel',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'over',
          marketName: 'Shohei Ohtani Hits Over/Under',
        },
      },
    }));
    const under = mapRow(makeRow({
      dkLine: 2.5,
      dkOverOdds: -105,
      oddId: 'odd-2',
      raw: {
        bookmaker: 'DraftKings',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'under',
          marketName: 'Shohei Ohtani Hits Over/Under',
        },
      },
    }));

    const markets = normalizeGroupedMlbMarkets(groupRawMlbMarketSources([over!, under!]));

    expect(markets).toHaveLength(2);
    expect(markets.every((market) => market.completenessStatus === 'incomplete')).toBe(true);
    expect(markets.map((market) => market.line)).toEqual([1.5, 2.5]);
  });

  it('drops malformed rows when no usable line can be resolved', () => {
    const mapped = mapRow(makeRow({
      lineValue: null,
      fdLine: null,
      dkLine: null,
      raw: {
        bookmaker: 'FanDuel',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'over',
          marketName: 'Shohei Ohtani Hits Over/Under',
          bookOverUnder: 'not-a-number',
        },
      },
    }));

    expect(mapped).toBeNull();
  });

  it('prefers sportsbook-specific bookOverUnder when present', () => {
    const mapped = mapRow(makeRow({
      lineValue: 3.5,
      fdLine: 1.5,
      raw: {
        bookmaker: 'FanDuel',
        sportsgameodds: {
          playerID: 'SHOHEI_OHTANI_1_MLB',
          sideID: 'over',
          marketName: 'Shohei Ohtani Hits Over/Under',
          bookOverUnder: '0.5',
        },
      },
    }));

    expect(mapped?.line).toBe(0.5);
  });
});
