package eu.mhsl.minenet.minigames.score.tournament;

import eu.mhsl.minenet.minigames.score.Score;
import net.minestom.server.entity.Player;

import java.util.*;
import java.util.stream.Collectors;

public class Tournament {
    private final List<Score> gameScores = new ArrayList<>();
    private RewardConfiguration rewardConfiguration;
    private MemorialConfiguration memorialConfiguration;

    public void addScore(Score score) {
        this.gameScores.add(score);
    }

    public Map<Player, Integer> getGameScores() {
        Map<Player, Integer> data = new HashMap<>();
        this.gameScores.forEach(game -> {
            int count = 0;
            for(Set<Player> players : game.getScores()) {
                count++;
                for(Player player : players) {
                    int points = (game.getScores().size() - count) + this.boost(count, game.getScores().size());

                    data.computeIfPresent(player, (existingPlayer, existingPoints) -> existingPoints + points);
                    data.computeIfAbsent(player, newPlayer -> points);
                }
            }
        });
        return data;
    }

    public Rewards getRewards() {
        Map<UUID, Integer> itemCount = new HashMap<>();
        int count = 0;
        for(Set<Player> players : this.getPlaces()) {
            if(count >= this.rewardConfiguration.rewardCount().size()) break;
            for(Player player : players) {
                itemCount.put(player.getUuid(), this.rewardConfiguration.rewardCount().get(count));
            }
            count++;
        }

        return new Rewards(
            this.memorialConfiguration.memorialMaterial().namespace().value(),
            this.memorialConfiguration.memorialTitle(),
            this.memorialConfiguration.memorialLore(),
            this.getGameScores().keySet().stream().map(Player::getUuid).toList(),
            this.rewardConfiguration.item().namespace().value(),
            itemCount
        );
    }

    public List<Set<Player>> getPlaces() {
        Map<Integer, Set<Player>> players = this.getGameScores().entrySet().stream()
            .collect(
                Collectors.groupingBy(
                    Map.Entry::getValue,
                    Collectors.mapping(Map.Entry::getKey, Collectors.toSet())
                )
            );

        return players.entrySet().stream()
            .sorted(Map.Entry.<Integer, Set<Player>>comparingByKey().reversed())
            .map(Map.Entry::getValue)
            .toList();
    }

    private int boost(int selfPlace, int placeCount) {
        return switch(selfPlace) {
            case 0 -> placeCount / 3;
            case 1 -> placeCount / 4;
            case 2 -> placeCount / 5;
            default -> 0;
        };
    }

    public void setRewardConfiguration(RewardConfiguration rewardConfiguration) {
        this.rewardConfiguration = rewardConfiguration;
    }

    public void setMemorialConfiguration(MemorialConfiguration memorialConfiguration) {
        this.memorialConfiguration = memorialConfiguration;
    }
}
