package eu.mhsl.craftattack.teamLobby;

import com.google.common.reflect.TypeToken;
import eu.mhsl.craftattack.teamLobby.data.Team;
import eu.mhsl.craftattack.teamLobby.http.ReqResp;
import eu.mhsl.craftattack.teamLobby.http.Request;
import eu.mhsl.craftattack.teamLobby.util.PluginMessageUtil;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull;

import java.net.http.HttpRequest;
import java.util.*;

public class LobbyManager {
    public LobbyManager() {
        MinecraftServer.getSchedulerManager().scheduleTask(
            this::loadTeams,
            TaskSchedule.immediate(),
            TaskSchedule.minutes(1)
        );
    }

    private final Object teamLock = new Object();
    private Set<Team> teams = Set.of();
    private final Map<Team, Lobby> instances = new HashMap<>();

    private void loadTeams() {
        HttpRequest request = Request.builder(Request.website("team"))
            .GET()
            .build();

        synchronized(this.teamLock) {
            this.teams = Request.execute(request, new TypeToken<Set<Team>>(){}.getType()).cast();
        }
    }

    public @NotNull InstanceContainer getPlayerInstance(Player player) {
        UUID playerId = player.getUuid();

        HttpRequest request = Request.builder(Request.server(
            "adminmarker/isAdmin",
            uriBuilder -> uriBuilder.addParameter("player", player.getUuid().toString())
        )).GET().build();

        record Status(String status, boolean response) {}
        ReqResp<Status> ticket = Request.execute(request, Status.class);
        if(ticket.data().response) {
            MinecraftServer.getSchedulerManager().scheduleTask(
                () -> PluginMessageUtil.connect(player, "server"),
                TaskSchedule.seconds(1),
                TaskSchedule.stop());
            return MinecraftServer.getInstanceManager().createInstanceContainer();
        }

        Team targetTeam;
        synchronized(this.teamLock) {
             targetTeam = this.teams.stream()
                .filter(team -> team.users()
                    .stream()
                    .anyMatch(user -> !user.dead() && user.uuid().equals(playerId)))
                .reduce((a, b) -> {
                    throw new IllegalStateException("Zu deinem Account wurde mehr als ein Team gefunden. Bitte melde dies bei einem Admin!");
                })
                .orElseThrow(() -> new NoSuchElementException("Zu deinem Account wurde kein zugehöriges Team gefunden, da du entweder nicht angemeldet oder bereits ausgeschieden bist!"));
        }

        synchronized(this.instances) {
            if(!this.instances.containsKey(targetTeam)) {
                Lobby instance = new Lobby(targetTeam);
                this.instances.put(targetTeam, instance);
            }
        }

        return this.instances.get(targetTeam);
    }
}
