import unittest

from leeger.enum.MatchupType import MatchupType
from leeger.exception.InvalidWeekFormatException import InvalidWeekFormatException
from leeger.model.league.Matchup import Matchup
from leeger.model.league.Week import Week
from leeger.validate import weekValidation


class TestWeekValidation(unittest.TestCase):
    def test_checkWeekHasAtLeastOneMatchup_weekDoesntHaveAtLeastOneMatchup_raisesException(self):
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkWeekHasAtLeastOneMatchup(Week(weekNumber=1, matchups=list()))
        self.assertEqual("Week 1 must have at least 1 matchup.", str(context.exception))

    def test_checkForDuplicateMatchups_duplicateMatchupInstances_raisesException(self):
        matchup = Matchup(teamAId="a", teamBId="b", teamAScore=1, teamBScore=2)
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkForDuplicateMatchups(
                Week(weekNumber=1, matchups=[matchup, matchup])
            )
        self.assertEqual("Matchups must all be unique instances.", str(context.exception))

    def test_checkWeekDoesNotHaveMoreThanOneChampionshipMatchup_multipleChampionshipMatchups_raisesException(
        self,
    ):
        matchup1 = Matchup(
            teamAId="a",
            teamBId="b",
            teamAScore=1,
            teamBScore=2,
            matchupType=MatchupType.CHAMPIONSHIP,
        )
        matchup2 = Matchup(
            teamAId="a",
            teamBId="b",
            teamAScore=1,
            teamBScore=2,
            matchupType=MatchupType.CHAMPIONSHIP,
        )
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkWeekDoesNotHaveMoreThanOneChampionshipMatchup(
                Week(weekNumber=1, matchups=[matchup1, matchup2])
            )
        self.assertEqual(
            "Week 1 has 2 championship matchups. Maximum is 1.", str(context.exception)
        )

    def test_checkWeekHasMatchupsWithNoDuplicateTeamIds_teamHasMultipleMatchupsInWeek_raisesException(
        self,
    ):
        matchup1 = Matchup(teamAId="a", teamBId="b", teamAScore=1, teamBScore=2)
        matchup2 = Matchup(teamAId="c", teamBId="b", teamAScore=1, teamBScore=2)
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkWeekHasMatchupsWithNoDuplicateTeamIds(
                Week(weekNumber=1, matchups=[matchup1, matchup2])
            )
        self.assertEqual("Week 1 has matchups with duplicate team IDs.", str(context.exception))

    def test_checkWeekWithPlayoffOrChampionshipMatchupDoesNotHaveRegularSeasonMatchup_weekHasPlayoffMatchupAndRegularSeasonMatchup_raisesException(
        self,
    ):
        matchup1 = Matchup(
            teamAId="a", teamBId="b", teamAScore=1, teamBScore=2, matchupType=MatchupType.PLAYOFF
        )
        matchup2 = Matchup(
            teamAId="c",
            teamBId="b",
            teamAScore=1,
            teamBScore=2,
            matchupType=MatchupType.REGULAR_SEASON,
        )
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkWeekWithPlayoffOrChampionshipMatchupDoesNotHaveRegularSeasonMatchup(
                Week(weekNumber=1, matchups=[matchup1, matchup2])
            )
        self.assertEqual(
            "Week 1 has regular season matchups and playoff/championship matchups in the same week.",
            str(context.exception),
        )

    def test_checkWeekWithPlayoffOrChampionshipMatchupDoesNotHaveRegularSeasonMatchup_weekHasChampionshipMatchupAndRegularSeasonMatchup_raisesException(
        self,
    ):
        matchup1 = Matchup(
            teamAId="a",
            teamBId="b",
            teamAScore=1,
            teamBScore=2,
            matchupType=MatchupType.CHAMPIONSHIP,
        )
        matchup2 = Matchup(
            teamAId="c",
            teamBId="b",
            teamAScore=1,
            teamBScore=2,
            matchupType=MatchupType.REGULAR_SEASON,
        )
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkWeekWithPlayoffOrChampionshipMatchupDoesNotHaveRegularSeasonMatchup(
                Week(weekNumber=1, matchups=[matchup1, matchup2])
            )
        self.assertEqual(
            "Week 1 has regular season matchups and playoff/championship matchups in the same week.",
            str(context.exception),
        )

    def test_checkMultiWeekMatchupsWithSameIdAreOnlyInOneMatchupPerWeek_weekHasSameMultiMatchupIdInMultipleMatchups_raisesException(
        self,
    ):
        matchup1 = Matchup(
            teamAId="a", teamBId="b", teamAScore=1, teamBScore=2, multiWeekMatchupId="1"
        )
        matchup2 = Matchup(
            teamAId="c", teamBId="b", teamAScore=1, teamBScore=2, multiWeekMatchupId="1"
        )
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkMultiWeekMatchupsWithSameIdAreOnlyInOneMatchupPerWeek(
                Week(weekNumber=1, matchups=[matchup1, matchup2])
            )
        self.assertEqual(
            "Week 1 has the multi-week matchup ID '1' in multiple matchups.", str(context.exception)
        )

    """
    TYPE CHECK TESTS
    """

    def test_checkAllTypes_weekNumberIsntTypeInt_raisesException(self):
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkAllTypes(Week(weekNumber=None, matchups=list()))
        self.assertEqual("weekNumber must be type 'int'.", str(context.exception))

    def test_checkAllTypes_weekMatchupsIsntTypeList_raisesException(self):
        # not given a list
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkAllTypes(Week(weekNumber=1, matchups=None))
        self.assertEqual("matchups must be type 'list[Matchup]'.", str(context.exception))

        # given a list of non Matchup
        with self.assertRaises(InvalidWeekFormatException) as context:
            weekValidation.checkAllTypes(Week(weekNumber=1, matchups=["foo"]))
        self.assertEqual("matchups must be type 'list[Matchup]'.", str(context.exception))
