package data;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import objects.SoccerMatch;
import objects.Team;
import tests.objects.LeagueDTO;

public class TestDatabase extends GuiMysql {

    private static TestDatabase instance;
    private Connection conn;

    private TestDatabase() {
        conn = getConnection();
    }

    public static TestDatabase getInstance() {
        if (instance == null) {
            instance = new TestDatabase();
        }

        return instance;
    }

    public int getLeagueId(int countryId, String leagueName) {
        String sql = "SELECT id FROM League WHERE name = ? AND countryId = ?";
        int result = -1;

        try (PreparedStatement stat = conn.prepareStatement(sql)) {
            stat.setString(1, leagueName);
            stat.setInt(2, countryId);

            ResultSet rs = stat.executeQuery();

            while (rs.next()) {
                result = rs.getInt("id");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    public int getCountryId(String countryName) {
        String sql = "SELECT id FROM country WHERE name = ?";
        int result = -1;
        try (PreparedStatement stat = conn.prepareStatement(sql)) {
            stat.setString(1, countryName);

            ResultSet rs = stat.executeQuery();

            while (rs.next()) {
                result = rs.getInt("id");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }

    public List<LeagueDTO> getPrioLeagues() {
        String sql = "SELECT l.id as id, l.name as name, l.countryId as countryId, c.name as countryName FROM `League` l inner join Country c ON c.id = l.countryId where l.prio = ?";
        List<LeagueDTO> result = new ArrayList<>();

        try (PreparedStatement stat = conn.prepareStatement(sql)) {
            stat.setBoolean(1, true);

            ResultSet rs = stat.executeQuery();

            while (rs.next()) {
                result.add(new LeagueDTO(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"),
                        rs.getString("countryName")));
            }

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

        return result;
    }

    public LeagueDTO getLeagueDTO(int leagueId) {
        String sql = "SELECT l.id as id, l.name as name, l.countryId as countryId, c.name as countryName FROM `League` l inner join Country c ON c.id = l.countryId where l.id = ?";
        LeagueDTO result = null;

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

            ResultSet rs = stat.executeQuery();

            while (rs.next()) {
                result = new LeagueDTO(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"),
                        rs.getString("countryName"));
            }

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

        return result;
    }

    public List<SoccerMatch> getMatches(LeagueDTO league) {
        String sql = "SELECT sr.*, ht.name as homeTeam, awt.name as awayTeam, c.name AS countryName, c.id AS countryId FROM SoccerResults sr INNER JOIN Country c ON c.id = sr.countryId INNER JOIN Team ht ON ht.id = sr.homeTeamId AND ht.leagueId = sr.leagueId INNER JOIN Team awt ON awt.id = sr.awayTeamId AND awt.leagueId = sr.leagueId  WHERE sr.leagueId = ? ORDER BY gameDate ASC";
        List<SoccerMatch> result = new ArrayList<>();

        try (PreparedStatement stat = conn.prepareStatement(sql)) {

            stat.setInt(1, league.getId());
            ResultSet rs = stat.executeQuery();
            while (rs.next()) {
                SoccerMatch sm = new SoccerMatch(rs.getInt("id"),
                        new Team(rs.getInt("homeTeamId"), rs.getString("homeTeam"), rs.getInt("countryId"),
                                rs.getString("countryName"),
                                league.getId(), league.getName()),
                        new Team(rs.getInt("awayTeamId"), rs.getString("awayTeam"), rs.getInt("countryId"),
                                rs.getString("countryName"),
                                league.getId(), league.getName()),
                        rs.getFloat("odds1"), rs.getFloat("oddsX"), rs.getFloat("odds2"), rs.getInt("homeScore"),
                        rs.getInt("awayScore"),
                        LocalDateTime.parse(rs.getString("gameDate")), rs.getString("season"));
                sm.setHomeTeamName(rs.getString("homeTeam"));
                sm.setAwayTeamName(rs.getString("awayTeam"));
                result.add(sm);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }

    public float getRoundedDiff(SoccerMatch soccerMatch) {
        float result = -1f;
        String sql = "SELECT ROUND((sHome.avgScored * sAway.avgConceded) + (sAway.avgScored * sHome.avgConceded),1) roundedDiff "
                + "FROM SoccerResults "
                + "INNER JOIN (SELECT homeTeamId, AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded "
                + "FROM SoccerResults "
                + "WHERE homeScore != -1 AND homeTeamId = ? AND DATE(gameDate) < ? AND leagueId = ? "
                + "GROUP BY homeTeamId) as sHome "
                + "ON SoccerResults.homeTeamId = sHome.homeTeamId "
                + "INNER JOIN (SELECT awayTeamId, AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored "
                + "FROM SoccerResults "
                + "WHERE awayScore != -1 AND awayTeamId = ? AND DATE(gameDate) < ? AND leagueId = ? "
                + "GROUP BY awayTeamId) as sAway "
                + "ON SoccerResults.awayTeamId = sAway.awayTeamId "
                + "WHERE homeScore != -1 "
                + "AND awayScore != -1 "
                + "AND leagueId = ? "
                + "AND DATE(gameDate) < ? "
                + "GROUP BY roundedDiff;";

        try (PreparedStatement stat = conn.prepareStatement(sql)) {
            stat.setInt(1, soccerMatch.getHomeTeam().getTeamId());
            stat.setString(2, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
            stat.setInt(3, soccerMatch.getHomeTeam().getTeamLeagueId());

            stat.setInt(4, soccerMatch.getAwayTeam().getTeamId());
            stat.setString(5, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
            stat.setInt(6, soccerMatch.getAwayTeam().getTeamLeagueId());

            stat.setInt(7, soccerMatch.getHomeTeam().getTeamLeagueId());
            stat.setString(8, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));

            ResultSet rs = stat.executeQuery();

            while (rs.next()) {
                result = rs.getFloat("roundedDiff");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }

}
