package tests;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import objects.League;
import objects.SoccerMatch;

public class DrawTests2 extends TestClass {

	private League leagueInfo;

	ArrayList<results> possitiveResults = new ArrayList<>();

	@Override public void setup(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId, Integer countryId,
			Integer leagueId) {
		super.setup(date, startingBank, bettingLevel, betMargin, lookBack, sportId, countryId, leagueId);

		leagueInfo = getLeagueInfoById();
	}

	@Override public void runTest() {
		final ArrayList<SoccerMatch> matches = getMatches();

		final LocalDateTime startDate = matches.get(0).getGameDate();
		final LocalDateTime endDate = matches.get(0).getGameDate().plusYears(1);

		List<SoccerMatch> matchesFiltered = matches.stream()
				.filter(p -> (p.getGameDate().isAfter(matches.get(0).getGameDate()) || p.getGameDate().equals(matches.get(0).getGameDate()))
						&& p.getGameDate().isBefore(matches.get(0).getGameDate().plusYears(1)))
				.collect(Collectors.toList());

		final float betLevel = bettingLevel / 100f;

		final LocalDateTime currentDate = matches.get(0).getGameDate();
		LocalDate localDate = currentDate.toLocalDate();
		float betAmount = startingBank * betLevel;

		int betOnGameCount = 0;
		int wins = 0;

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

		System.out.println("Draw Test 2");
		int i = 0;
		while (matchesFiltered.size() > 0) {
			i++;
			for (int lookBack = 4; lookBack < 25; lookBack++) {
				for (int betMargin = 1; betMargin < 35; betMargin++) {
					final float betMarginDecimal = 1 + (betMargin / (float) 100);
					float bank = startingBank;
					betOnGameCount = 0;
					wins = 0;
					for (final SoccerMatch match : matchesFiltered) {
						if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
							continue;
						}

						final List<SoccerMatch> homeMatches = matchesFiltered.stream().filter(
								p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
								.limit(lookBack).collect(Collectors.toList());
						final List<SoccerMatch> awayMatches = matchesFiltered.stream().filter(
								p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
								.limit(lookBack).collect(Collectors.toList());

						final long hemmaLika = homeMatches.stream().filter(p -> p.getHomeScore() == p.getAwayScore()).count();
						final long bortaLika = awayMatches.stream().filter(p -> p.getAwayScore() == p.getHomeScore()).count();

						final float drawWinPercent = (hemmaLika + bortaLika) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
						final float drawOdds = 100 / drawWinPercent;

						if (localDate.isBefore(match.getGameDate().toLocalDate())) {
							betAmount = bank * betLevel;
							localDate = match.getGameDate().toLocalDate();
						}

						if (drawOdds * betMarginDecimal <= match.getOddsX()) {
							betOnGameCount++;
							bank = bank - betAmount;
							if (match.getAwayScore() == match.getHomeScore()) {
								wins++;
								bank = bank + betAmount * match.getOddsX();
							}
						}

					}
					if (bank > startingBank) {
						final int lookBack2 = lookBack;
						final int betMargin2 = betMargin;
						final java.util.Optional<results> found = possitiveResults.stream()
								.filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
						if (found.isPresent()) {
							final results results = found.get();
							results.addCount();
							results.addBank(bank);
						} else {
							possitiveResults.add(new results(lookBack, betMargin, bank));
						}
					}
				}
			}
			final LocalDateTime startDate2 = matchesFiltered.get(0).getGameDate().plusYears(1);
			final LocalDateTime endDate2 = startDate2.plusYears(1);
			matchesFiltered.clear();
			matchesFiltered = matches.stream()
					.filter(p -> (p.getGameDate().isAfter(startDate2) || p.getGameDate().equals(startDate2)) && p.getGameDate().isBefore(endDate2))
					.collect(Collectors.toList());
		}

		Collections.sort(possitiveResults);
		for (final results res : possitiveResults) {
			System.out.println("Lookback " + res.getLookback() + " and margin " + res.getMargin() + " At count " + res.getCount() + " of " + i
					+ " with bank: " + res.getBank());
		}
	}

	public 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 " + "res.leagueId = ? "
				+ "ORDER BY gameDate ASC";

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

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

		return result;
	}

	public class results implements Comparable<results> {
		int lookback;
		int margin;
		int count;
		float bank;

		public results(int lookback, int margin, float bank) {
			this.lookback = lookback;
			this.margin = margin;
			this.bank = bank;
			count = 1;
		}

		public float getBank() {
			return bank;
		}

		public void addBank(float bank) {
			this.bank = (this.bank + bank) / 2;
		}

		public void addCount() {
			count++;
		}

		public int getCount() {
			return count;
		}

		public int getLookback() {
			return lookback;
		}

		public int getMargin() {
			return margin;
		}

		public void setLookback(int lookback) {
			this.lookback = lookback;
		}

		public void setMargin(int margin) {
			this.margin = margin;
		}

		@Override public int compareTo(results res) {
			int returnValue = 0;
			if (this.count > res.getCount()) {
				returnValue = -1;
			} else if (this.count == res.getCount()) {
				if (this.bank > res.getBank()) {
					returnValue = -1;
				} else if (this.bank < res.getBank()) {
					returnValue = 1;
				} else {
					returnValue = 0;
				}
			} else if (this.count < res.getCount()) {
				returnValue = 1;
			}
			return returnValue;
		}
	}
}
