import {
  settleSelection,
  calculatePayout,
  calculateParlayPayout,
  isQuarterHandicapOrTotal,
  ScoreInput,
} from './settlement-calculator';

describe('SettlementCalculator', () => {
  const score: ScoreInput = { htHome: 1, htAway: 0, ftHome: 2, ftAway: 1 };

  describe('FT_1X2', () => {
    it('S001: home win', () => {
      expect(
        settleSelection({ marketType: 'FT_1X2', selectionCode: 'HOME', score }),
      ).toBe('WIN');
      expect(
        settleSelection({ marketType: 'FT_1X2', selectionCode: 'DRAW', score }),
      ).toBe('LOSE');
    });

    it('S002: draw', () => {
      const draw = { htHome: 0, htAway: 0, ftHome: 1, ftAway: 1 };
      expect(
        settleSelection({ marketType: 'FT_1X2', selectionCode: 'DRAW', score: draw }),
      ).toBe('WIN');
    });
  });

  describe('HT_1X2', () => {
    it('S003: half time result', () => {
      expect(
        settleSelection({ marketType: 'HT_1X2', selectionCode: 'HOME', score }),
      ).toBe('WIN');
    });
  });

  describe('FT_ODD_EVEN', () => {
    it('S004: 0-0 is even', () => {
      const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 };
      expect(
        settleSelection({ marketType: 'FT_ODD_EVEN', selectionCode: 'EVEN', score: s }),
      ).toBe('WIN');
    });
  });

  describe('Correct Score', () => {
    it('S005: exact score 2-1', () => {
      expect(
        settleSelection({
          marketType: 'FT_CORRECT_SCORE',
          selectionCode: 'SCORE_2_1',
          score,
        }),
      ).toBe('WIN');
    });

    it('S006: other home win', () => {
      const s = { htHome: 2, htAway: 0, ftHome: 5, ftAway: 0 };
      expect(
        settleSelection({
          marketType: 'FT_CORRECT_SCORE',
          selectionCode: 'OTHER_HOME',
          score: s,
          templateScores: ['SCORE_1_0', 'SCORE_2_0'],
        }),
      ).toBe('WIN');
    });

    it('S008: second half correct score', () => {
      expect(
        settleSelection({
          marketType: 'SH_CORRECT_SCORE',
          selectionCode: 'SCORE_1_1',
          score,
        }),
      ).toBe('WIN');
    });
  });

  describe('Handicap', () => {
    it('S009: full win', () => {
      const r = settleSelection({
        marketType: 'FT_HANDICAP',
        selectionCode: 'HOME',
        handicapLine: -1,
        score: { htHome: 0, htAway: 0, ftHome: 2, ftAway: 0 },
      });
      expect(r).toBe('WIN');
      expect(calculatePayout(100, 1.85, r).toNumber()).toBe(185);
    });

    it('S010: push', () => {
      const r = settleSelection({
        marketType: 'FT_HANDICAP',
        selectionCode: 'HOME',
        handicapLine: -1,
        score: { htHome: 0, htAway: 0, ftHome: 1, ftAway: 0 },
      });
      expect(r).toBe('PUSH');
      expect(calculatePayout(100, 1.85, r).toNumber()).toBe(100);
    });

    it('S011: half win -0.25', () => {
      const r = settleSelection({
        marketType: 'FT_HANDICAP',
        selectionCode: 'HOME',
        handicapLine: -0.25,
        score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 },
      });
      expect(r).toBe('HALF_LOSE');
    });

    it('0-0: home -0.5 loses', () => {
      const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 };
      expect(
        settleSelection({
          marketType: 'FT_HANDICAP',
          selectionCode: 'HOME',
          handicapLine: -0.5,
          score: s,
        }),
      ).toBe('LOSE');
    });
  });

  describe('Over/Under', () => {
    it('0-0: under 2.5 wins, over 2.5 loses', () => {
      const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 };
      const under = settleSelection({
        marketType: 'FT_OVER_UNDER',
        selectionCode: 'UNDER',
        totalLine: 2.5,
        score: s,
      });
      const over = settleSelection({
        marketType: 'FT_OVER_UNDER',
        selectionCode: 'OVER',
        totalLine: 2.5,
        score: s,
      });
      expect(under).toBe('WIN');
      expect(over).toBe('LOSE');
      expect(calculatePayout(100, 1.95, under).toNumber()).toBe(195);
    });

    it('S013: over 2.5 wins with 3 goals', () => {
      const s = { htHome: 1, htAway: 1, ftHome: 2, ftAway: 1 };
      expect(
        settleSelection({
          marketType: 'FT_OVER_UNDER',
          selectionCode: 'OVER',
          totalLine: 2.5,
          score: s,
        }),
      ).toBe('WIN');
    });

    it('S014: push on integer line', () => {
      const s = { htHome: 1, htAway: 0, ftHome: 1, ftAway: 1 };
      expect(
        settleSelection({
          marketType: 'FT_OVER_UNDER',
          selectionCode: 'OVER',
          totalLine: 2,
          score: s,
        }),
      ).toBe('PUSH');
    });
  });

  describe('Additional score-derived markets', () => {
    it('settles home and away team total goals', () => {
      const s = { htHome: 1, htAway: 0, ftHome: 2, ftAway: 1 };
      expect(
        settleSelection({
          marketType: 'FT_TEAM_TOTAL_HOME',
          selectionCode: 'OVER',
          totalLine: 1.5,
          score: s,
        }),
      ).toBe('WIN');
      expect(
        settleSelection({
          marketType: 'FT_TEAM_TOTAL_AWAY',
          selectionCode: 'UNDER',
          totalLine: 1.5,
          score: s,
        }),
      ).toBe('WIN');
    });

    it('settles half time / full time combinations', () => {
      expect(
        settleSelection({
          marketType: 'HT_FT',
          selectionCode: 'HOME_HOME',
          score,
        }),
      ).toBe('WIN');
      expect(
        settleSelection({
          marketType: 'HT_FT',
          selectionCode: 'DRAW_HOME',
          score,
        }),
      ).toBe('LOSE');
    });

    it('settles total goals ranges', () => {
      expect(
        settleSelection({
          marketType: 'FT_TOTAL_GOALS',
          selectionCode: 'TG_2_3',
          score,
        }),
      ).toBe('WIN');
      expect(
        settleSelection({
          marketType: 'FT_TOTAL_GOALS',
          selectionCode: 'TG_7_PLUS',
          score,
        }),
      ).toBe('LOSE');
    });

    it('settles corners handicap and totals from match stats', () => {
      const s = { htHome: 0, htAway: 0, ftHome: 1, ftAway: 1 };
      const stats = { homeCorners: 7, awayCorners: 4 };
      expect(
        settleSelection({
          marketType: 'FT_CORNERS_HANDICAP',
          selectionCode: 'HOME',
          handicapLine: -2.5,
          score: s,
          stats,
        }),
      ).toBe('WIN');
      expect(
        settleSelection({
          marketType: 'FT_CORNERS_OVER_UNDER',
          selectionCode: 'OVER',
          totalLine: 10.5,
          score: s,
          stats,
        }),
      ).toBe('WIN');
    });

    it('settles cards total from match stats', () => {
      expect(
        settleSelection({
          marketType: 'FT_CARDS_OVER_UNDER',
          selectionCode: 'UNDER',
          totalLine: 5.5,
          score,
          stats: { homeCards: 2, awayCards: 3 },
        }),
      ).toBe('WIN');
    });
  });

  describe('Parlay', () => {
    it('S016: all win', () => {
      const result = calculateParlayPayout(100, [
        { odds: 1.8, result: 'WIN' },
        { odds: 2.0, result: 'WIN' },
      ]);
      expect(result.betResult).toBe('WON');
      expect(result.payout.toNumber()).toBe(360);
    });

    it('S017: one lose', () => {
      const result = calculateParlayPayout(100, [
        { odds: 1.8, result: 'WIN' },
        { odds: 2.0, result: 'LOSE' },
      ]);
      expect(result.betResult).toBe('LOST');
      expect(result.payout.toNumber()).toBe(0);
    });

    it('S018: one push', () => {
      const result = calculateParlayPayout(100, [
        { odds: 1.8, result: 'WIN' },
        { odds: 2.0, result: 'PUSH' },
        { odds: 1.9, result: 'WIN' },
      ]);
      expect(result.betResult).toBe('WON');
      expect(result.payout.toNumber()).toBe(342);
    });

    it('S019: all push', () => {
      const result = calculateParlayPayout(100, [
        { odds: 1.8, result: 'PUSH' },
        { odds: 2.0, result: 'VOID' },
      ]);
      expect(result.betResult).toBe('PUSH');
      expect(result.payout.toNumber()).toBe(100);
    });
  });

  describe('OUTRIGHT_WINNER', () => {
    it('wins when selection matches winner team code', () => {
      expect(
        settleSelection({
          marketType: 'OUTRIGHT_WINNER',
          selectionCode: 'BRA',
          score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 },
          winnerTeamCode: 'BRA',
        }),
      ).toBe('WIN');
      expect(
        settleSelection({
          marketType: 'OUTRIGHT_WINNER',
          selectionCode: 'ARG',
          score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 },
          winnerTeamCode: 'BRA',
        }),
      ).toBe('LOSE');
    });
  });

  describe('Quarter line detection', () => {
    it('detects quarter lines', () => {
      expect(isQuarterHandicapOrTotal(-0.25)).toBe(true);
      expect(isQuarterHandicapOrTotal(2.5)).toBe(false);
      expect(isQuarterHandicapOrTotal(-1)).toBe(false);
    });
  });
});
