package tests;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import objects.League;
import objects.SoccerMatch;
import objects.TeamSettings;

public class HomeTeamWinTest extends TestClass {

	ArrayList<Integer> recalcTeamsList = new ArrayList<Integer>();
	private League leagueInfo;
	private ArrayList<SoccerMatch> matches;
	private ArrayList<SoccerMatch> trainMatches;

	@Override public void runTest() {
		matches = getMatches();
		trainMatches = getTrainMatches();

		leagueInfo = getLeagueInfoById();
		for (final SoccerMatch soccerMatch : matches) {
			final int homeTeamId = soccerMatch.getHomeTeam().getTeamId();
			final int awayTeamId = soccerMatch.getAwayTeam().getTeamId();

			TeamSettings homeTeamValues = getTeamValues(homeTeamId);

			if (homeTeamValues.getLookbackHome() <= 0 || homeTeamValues.getMarginHome() <= 0) {
				homeTeamValues = calculateTeamValues(homeTeamValues, true);
			}
		}

		System.out.println("Done with Home Team TEST");
	}

	private TeamSettings calculateTeamValues(TeamSettings teamSettings, boolean isHomeTeam) {
		final ArrayList<SoccerMatch> teamMatches;
		if (isHomeTeam) {
			teamMatches = (ArrayList<SoccerMatch>) trainMatches.stream().filter(p -> p.getHomeTeam().getTeamId() == teamSettings.getTeamId())
					.collect(Collectors.toList());
		} else {
			teamMatches = (ArrayList<SoccerMatch>) trainMatches.stream().filter(p -> p.getAwayTeam().getTeamId() == teamSettings.getTeamId())
					.collect(Collectors.toList());
		}

		float bestBankResult = startingBank;
		int bestBetMargin = 0;
		int bestLookBack = 0;

		final float betLevel = bettingLevel / 100f;
		float betAmount = startingBank * betLevel;

		for (int lookback = 4; lookback < 25; lookback++) {
			for (int margin = 1; margin < 25; margin++) {
				final float betMarginDecimal = 1 + (margin / 100f);
				float bank = startingBank;
				int betOnGameCount = 0;
				int wins = 0;
				for (final SoccerMatch soccerMatch : teamMatches) {
					final List<SoccerMatch> aktuellaMatcher = trainMatches.stream().filter(p -> p.getGameDate().isBefore(soccerMatch.getGameDate()))
							.collect(Collectors.toList());
					if (soccerMatch.getHomeScore() < 0 || soccerMatch.getAwayScore() < 0) {
						continue;
					}

					// Hemma lagets resultat
					final List<SoccerMatch> hemmaMatcher = aktuellaMatcher.stream()
							.filter(p -> p.getHomeTeam().getTeamId() == teamSettings.getTeamId()).limit(lookback).collect(Collectors.toList());
					final long hemmaVinster = hemmaMatcher.stream().filter(p -> p.getHomeScore() > p.getAwayScore()).count();

					// borta lagets resultat
					final List<SoccerMatch> bortaMatcher = aktuellaMatcher.stream()
							.filter(p -> p.getAwayTeam().getTeamId() == soccerMatch.getAwayTeam().getTeamId()).limit(lookback)
							.collect(Collectors.toList());
					final long bortaForluster = bortaMatcher.stream().filter(p -> p.getHomeScore() > p.getAwayScore()).count();

					final float homeWinPercent = (hemmaVinster + bortaForluster) / Float.valueOf(hemmaMatcher.size() + bortaMatcher.size()) * 100;
					final float homeOdds = 100 / homeWinPercent;

					betAmount = bank * betLevel;

					// Spela p� hemma vins?
					if (homeOdds * betMarginDecimal <= soccerMatch.getOdds1()) {
						betOnGameCount++;
						bank = bank - betAmount;
						if (soccerMatch.getHomeScore() > soccerMatch.getAwayScore()) {
							wins++;
							bank = bank + betAmount * soccerMatch.getOdds1();
						}
					}

					if (bank != startingBank && bestBankResult < bank) {
						bestBetMargin = margin;
						bestLookBack = lookback;
						bestBankResult = bank;
					} else if (bestBankResult != startingBank && bestBankResult == bank) {
						bestBetMargin = margin;
						bestLookBack = lookback;
						bestBankResult = bank;
					}
				}
			}
		}

		if (bestLookBack > 0 && teamSettings.getLookbackHome() != bestLookBack) {
			System.out.println("Setting lookbackHome " + bestLookBack + " and margin " + bestBetMargin + " for team " + teamSettings.getTeamName()
					+ " with a bank of " + bestBankResult);
			teamSettings.setLookbackHome(bestLookBack);
			teamSettings.setMarginHome(bestBetMargin);
		}

		return teamSettings;
	}

	private TeamSettings getTeamValues(int teamId) {
		final String sql = "SELECT * FROM Team WHERE id = ?";
		final TeamSettings ts = new TeamSettings();
		try {
			final PreparedStatement stmt = getConnection().prepareStatement(sql);
			stmt.setInt(1, teamId);

			final ResultSet rs = stmt.executeQuery();

			while (rs.next()) {
				ts.setTeamId(teamId);
				ts.setTeamName(rs.getString("name"));
				ts.setLookbackHome(rs.getInt("lookbackHome"));
				ts.setLookbackDraw(rs.getInt("lookbackDraw"));
				ts.setLookbackAway(rs.getInt("lookbackAway"));
				ts.setMarginHome(rs.getInt("marginHome"));
				ts.setMarginDraw(rs.getInt("marginDraw"));
				ts.setMarginAway(rs.getInt("marginAway"));
			}

		} catch (final SQLException e) {
			e.printStackTrace();
		}

		return ts;
	}

	private ArrayList<SoccerMatch> getMatches() {
		final ArrayList<SoccerMatch> result = new ArrayList<>();

		final String sql = "SELECT res.*, " + "hTeam.name as homeTeamName, aTeam.name as awayTeamName " + "FROM SoccerResults as res "
				+ "Join Team as hTeam ON res.homeTeam = hTeam.id " + "Join Team as aTeam ON res.awayTeam = aTeam.id " + "WHERE "
				+ "DATE(gameDate) > DATE_SUB(NOW(), INTERVAL 1 YEAR) AND " + "res.leagueId = ? " + "ORDER BY gameDate ASC";

		try {
			final PreparedStatement stmt = getConnection().prepareStatement(sql);
			stmt.setInt(1, leagueId);

			result.addAll(super.getMatches(stmt));
		} catch (final SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

	private ArrayList<SoccerMatch> getTrainMatches() {
		final ArrayList<SoccerMatch> result = new ArrayList<>();

		final String sql = "SELECT res.*, " + "hTeam.name as homeTeamName, aTeam.name as awayTeamName " + "FROM SoccerResults as res "
				+ "Join Team as hTeam ON res.homeTeam = hTeam.id " + "Join Team as aTeam ON res.awayTeam = aTeam.id " + "WHERE "
				+ "DATE(gameDate) < DATE_SUB(NOW(), INTERVAL 1 YEAR) AND " + "res.leagueId = ? " + "ORDER BY gameDate DESC";

		try {
			final PreparedStatement stmt = getConnection().prepareStatement(sql);
			stmt.setInt(1, leagueId);

			result.addAll(super.getMatches(stmt));
		} catch (final SQLException e) {
			e.printStackTrace();
		}

		return result;
	}
}
