package tests;

import data.GuiMysql;
import objects.SoccerMatch;
import objects.SoccerMatchAnalysis;
import tests.objects.GamePercentages;
import tests.objects.XBestGamesDTO;
import tests.objects.XBestGamesWinPercentageStatistics;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class XBestRatedGamesBettingTest extends TestClass {
    GuiMysql db = GuiMysql.getInstance();
    List<SoccerMatch> matches = new ArrayList<>();

    // Lista med spelade matches och dess värden, så att man enkelt kan få ut referens värden på alla mätvärden och
    // även beräkna procentuell vinschans (och odds)


    /**
     * For each day (with matches) calculate analysis values and compare them to previous matches with the same values
     * calculate win percentage for both teams and normalize them against each other
     */

    @Override
    public void runTest() {
        //matches.addAll(db.getPrioMatches("2019-01-01"));

        matches.addAll(db.getLeagueMatches("2015-01-01", 15290));

        while (!matches.isEmpty()) {
            LocalDateTime date = matches.get(0).getGameDate();

            List<SoccerMatch> todaysMatches = matches.stream()
                    .filter(m -> date.isEqual(m.getGameDate())).toList();

            matches.removeAll(todaysMatches);

            List<XBestGamesDTO> gamesCalculated = new ArrayList<>();

            for (SoccerMatch match : todaysMatches) {
                SoccerMatchAnalysis matchAnalysis = new SoccerMatchAnalysis(match);
                XBestGamesDTO dto = new XBestGamesDTO(5, 5);
                dto.calculateAllData(matchAnalysis);
                dto.setMatch(match);
                gamesCalculated.add(dto);
            }

            for (XBestGamesDTO dto : gamesCalculated) {
                dto.setPercentages(getPercenages(dto, 5)); // TODO: 5 is hardcoded, should be dynamic

            }

            if (todaysMatches.get(0).getGameDate().isAfter(LocalDateTime.of(2020,1,1, 0, 0))) {

                for (XBestGamesDTO dto : gamesCalculated) {

                    boolean bet = false;
                    String message = "";
                    if (dto.getMatch().getOdds1() > dto.getPercenage().getWinOdds()) {
                        message = "Bet on Home! Diff is: " + (dto.getPercenage().getWinOdds() - dto.getMatch().getOdds1());
                        bet = true;
                    }
                    if(dto.getMatch().getOddsX() > dto.getPercenage().getDrawOdds()) {
                        message = "Bet on Draw! Diff is: " + (dto.getPercenage().getDrawOdds() - dto.getMatch().getOddsX());
                        bet = true;
                    }
                    if (dto.getMatch().getOdds2() > dto.getPercenage().getLossOdds()) {
                        message = "Bet on Away! Diff is: " + (dto.getPercenage().getLossOdds() - dto.getMatch().getOdds2());
                        bet = true;
                    }

                    if (bet) {
                        System.out.println(dto.getMatch().getHomeTeamName() + " - " + dto.getMatch().getAwayTeamName() + " (" + dto.getMatch().getOdds1() + ", " + dto.getMatch().getOddsX() + ", " + dto.getMatch().getOdds2() + ") Result: " + dto.getMatch().getHomeScore() + " - " + dto.getMatch().getAwayScore());
                        System.out.println("calculated percent: " + dto.getPercenage().toString());
                        System.out.println("Calculated odds; " + dto.getPercenage().toOddsString());
                        System.out.println(message);
                    }
                }


                // TODO Pick winners from percentages.
            }
            // TODO update statistics with mathes.
            for (XBestGamesDTO dto : gamesCalculated) {
                XBestGamesWinPercentageStatistics.INSTANCE.addHomeWinLossRatio(5, dto.getValuesMap().get(5).getHomeWinLossRatio(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
                XBestGamesWinPercentageStatistics.INSTANCE.addAwayWinLossRatio(5, dto.getValuesMap().get(5).getAwayWinLossRatio(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());

                XBestGamesWinPercentageStatistics.INSTANCE.addHomeWinLossRatioHomeAndAwayMap(5, dto.getValuesMap().get(5).getHomeWinLossRatioHomeAndAway(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
                XBestGamesWinPercentageStatistics.INSTANCE.addAwayWinLossRatioHomeAndAwayMap(5, dto.getValuesMap().get(5).getAwayWinLossRatioHomeAndAway(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());

                XBestGamesWinPercentageStatistics.INSTANCE.addHomeScoringTotal(5, dto.getValuesMap().get(5).getHomeScoringTotal(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
                XBestGamesWinPercentageStatistics.INSTANCE.addAwayScoringTotal(5, dto.getValuesMap().get(5).getAwayScoringTotal(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());

                XBestGamesWinPercentageStatistics.INSTANCE.addScoringDiffLastGamesMap(5, dto.getValuesMap().get(5).getScoringDiffLastGames(),
                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
            }

            // TODO update bank.
            System.out.println("End of loop for date: " + todaysMatches.get(0).getGameDate());
        }
    }

    private GamePercentages getPercenages(XBestGamesDTO dto, int lookback) {
        XBestGamesDTO.Values valuesMap = dto.getValuesMap().getOrDefault(lookback, new XBestGamesDTO.Values());

        GamePercentages homeWinRatioPercetage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeWinRatioPercetage(lookback, valuesMap.getHomeWinLossRatio());
        GamePercentages awayWinRatioPercetage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayWinRatioPercetage(lookback, valuesMap.getAwayWinLossRatio());

        GamePercentages homeWinLossRatioHomeAndAwayPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeWinLossRatioHomeAndAwayPercentage(lookback, valuesMap.getHomeWinLossRatioHomeAndAway());
        GamePercentages awayWinLossRatioHomeAndAwayPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayWinLossRatioHomeAndAwayPercentage(lookback, valuesMap.getAwayWinLossRatioHomeAndAway());

        GamePercentages homeScoringWinPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeScoringWinPercentage(lookback, valuesMap.getHomeScoringTotal());
        GamePercentages awayScoringWinPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayScoringWinPercentage(lookback, valuesMap.getAwayScoringTotal());

        GamePercentages scoringDiffLastGamesPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getScoringDiffLastGamesPercentage(lookback, valuesMap.getScoringDiffLastGames());


        GamePercentages totalPercentages = new GamePercentages((homeWinRatioPercetage.getWinPercent() +
                homeWinLossRatioHomeAndAwayPercentage.getWinPercent() +
                homeScoringWinPercentage.getWinPercent() +
                scoringDiffLastGamesPercentage.getWinPercent()), // +
                //awayWinRatioPercetage.getLossPercent() +
                //awayWinLossRatioHomeAndAwayPercentage.getLossPercent() +
                //awayScoringWinPercentage.getLossPercent()),
                (homeWinRatioPercetage.getDrawPercent() + awayWinRatioPercetage.getDrawPercent() +
                        homeWinLossRatioHomeAndAwayPercentage.getDrawPercent() + awayWinLossRatioHomeAndAwayPercentage.getDrawPercent() +
                        homeScoringWinPercentage.getDrawPercent() + awayScoringWinPercentage.getDrawPercent() + scoringDiffLastGamesPercentage.getDrawPercent()),
                // homeWinRatioPercetage.getLossPercent() +
                        awayWinRatioPercetage.getWinPercent() +
//                        homeWinLossRatioHomeAndAwayPercentage.getLossPercent() +
                                awayWinLossRatioHomeAndAwayPercentage.getWinPercent() +
//                        homeScoringWinPercentage.getLossPercent() +
                                awayScoringWinPercentage.getWinPercent() +
                                scoringDiffLastGamesPercentage.getLossPercent());

        GamePercentages test = totalPercentages;
        normalize(totalPercentages);

        return totalPercentages;
    }

    private void normalize(GamePercentages gamePercentages) {
        float total = gamePercentages.getWinPercent() + gamePercentages.getDrawPercent() + gamePercentages.getLossPercent();
        float win = gamePercentages.getWinPercent() / total;
        float draw = gamePercentages.getDrawPercent() / total;
        float loss = gamePercentages.getLossPercent() / total;

        gamePercentages.setWinPercent(win);
        gamePercentages.setDrawPercent(draw);
        gamePercentages.setLossPercent(loss);

    }
}
