package f1.db;

import f1.entity.DriverStatistic;
import f1.entity.Team;
import f1.entity.TeamHistoryItem;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;

public class TeamDao extends BaseDao {

    public TeamDao(Database db) {
        super(db);
    }

    public ArrayList<Team> getAllTeams() {
        ArrayList<Team> teams = new ArrayList<>();
        try (var con = getConnection();
                var stmt = con.createStatement();
                var rs = stmt.executeQuery("SELECT * FROM team")) {
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String country = rs.getString("country");
                String engineSupplier = rs.getString("engine_supplier");
                int setupYear = rs.getInt("setup_time");
                java.sql.Date setupTime = java.sql.Date.valueOf(LocalDate.of(setupYear, 1, 1));
                teams.add(new Team(id, name, country, engineSupplier, setupTime));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return teams;
    }

    public Map<String, Integer> getTeamStanding(int teamId, int season) {
        Map<String, Integer> result = new HashMap<>();
        String sql = "SELECT total_score, ranking FROM season_team_standings WHERE season = ? AND team_id = ?";
        try (var con = getConnection(); var stmt = con.prepareStatement(sql)) {
            stmt.setInt(1, season);
            stmt.setInt(2, teamId);
            var rs = stmt.executeQuery();
            if (rs.next()) {
                result.put("score", rs.getInt("total_score"));
                result.put("ranking", rs.getInt("ranking"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return result;
    }

    public List<Map<String, Object>> getSeasonTop5TeamStandings(int season) {
        List<Map<String, Object>> result = new ArrayList<>();
        String sql = "SELECT t.name, s.total_score, s.ranking " +
                     "FROM season_team_standings s " +
                     "JOIN team t ON s.team_id = t.id " +
                     "WHERE s.season = ? " +
                     "ORDER BY s.ranking ASC " +
                     "LIMIT 5";
        try (var con = getConnection(); var stmt = con.prepareStatement(sql)) {
            stmt.setInt(1, season);
            var rs = stmt.executeQuery();
            while (rs.next()) {
                Map<String, Object> item = new HashMap<>();
                item.put("team_name", rs.getString("name"));
                item.put("total_score", rs.getInt("total_score"));
                item.put("ranking", rs.getInt("ranking"));
                result.add(item);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return result;
    }

    public DriverStatistic getTeamStatistic(int teamId, int season, boolean isSprint) {
        return getStatistic("rr.team_id = ?", teamId, season, isSprint);
    }

    private DriverStatistic getStatistic(String whereClause, int id, int season, boolean isSprint) {
        DriverStatistic statistic = null;
        String sql = """
                SELECT
                    COUNT(DISTINCT prix_id) AS total_cnt,
                    SUM(score) AS score_sum,
                    SUM(end_position <= 3) AS medal,
                    SUM(end_position = 1) AS gold,
                    SUM(start_position = 1) AS pole,
                    SUM(end_position <= 10) AS top_ten,
                    SUM(finish_time IN ('DNF', 'DNS', 'DSQ')) AS unfinished,
                    SUM(fastest_time = fastest.fastest) AS fastest_lap
                FROM
                    race_result rr
                NATURAL JOIN (
                    SELECT
                        rr.prix_id ,
                        MIN(rr.fastest_time) AS fastest
                    FROM
                        race_result rr
                    WHERE
                        rr.fastest_time NOT IN ('DNF', 'DNS', 'DSQ')
                        AND rr.is_sprint = ?
                        AND rr.prix_id IN (SELECT id FROM prix WHERE season = ?)
                    GROUP BY
                        rr.prix_id) fastest
                WHERE
                    %s
                    AND rr.is_sprint = ?
                    AND rr.prix_id IN (SELECT id FROM prix WHERE season = ?)
                """.formatted(whereClause);
        try (var con = getConnection(); var stmt = con.prepareStatement(sql)) {
            stmt.setBoolean(1, isSprint);
            stmt.setInt(2, season);
            stmt.setInt(3, id);
            stmt.setBoolean(4, isSprint);
            stmt.setInt(5, season);
            var rs = stmt.executeQuery();
            if (rs.next()) {
                int totalCnt = rs.getInt("total_cnt");
                int scoreSum = rs.getInt("score_sum");
                int medal = rs.getInt("medal");
                int gold = rs.getInt("gold");
                int pole = rs.getInt("pole");
                int topTen = rs.getInt("top_ten");
                int unfinished = rs.getInt("unfinished");
                int fastestLap = rs.getInt("fastest_lap");
                statistic = new DriverStatistic(totalCnt, scoreSum, medal, gold, pole, topTen, unfinished,
                        fastestLap);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return statistic;
    }

    public ArrayList<TeamHistoryItem> getTeamHistory(int teamId, int season) {
        ArrayList<TeamHistoryItem> history = new ArrayList<>();
        String sql = "SELECT prix_name, SUM(score) as total_score FROM prix_result WHERE team_id = ? AND season = ? GROUP BY prix_id, prix_name, round ORDER BY round";
        try (var con = getConnection(); var stmt = con.prepareStatement(sql)) {
            stmt.setInt(1, teamId);
            stmt.setInt(2, season);
            var rs = stmt.executeQuery();
            while (rs.next()) {
                history.add(new TeamHistoryItem(
                        rs.getString("prix_name"),
                        rs.getInt("total_score")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return history;
    }
}
