package hu.jgj52.pvpcore.Listeners;

import hu.jgj52.pvpcore.Main;
import hu.jgj52.pvpcore.Utils.Database;
import hu.jgj52.pvpcore.Utils.Kits;
import hu.jgj52.pvpcore.Utils.SchematicManager;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.*;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.title.Title;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;

import static java.util.Collections.min;

public class DuelEndListener implements Listener {
    private final Main plugin;

    public DuelEndListener(Main plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onDuelEnd(PlayerDeathEvent e) throws ExecutionException, InterruptedException {
        Player player = e.getPlayer();
        boolean isEnemy = false;
        Database.QueryResult result = plugin.db.from("pvpcore_duels").eq("player", player.getUniqueId()).execute().get();
        if (result.isEmpty()) {
            result = plugin.db.from("pvpcore_duels").eq("enemy", player.getUniqueId()).execute().get();
            isEnemy = true;
        }

        Map<String, Object> row = result.data.get(0);
        if (!result.isEmpty() && (row.get("ft") == row.get("player_points") || row.get("ft") == row.get("enemy_points"))) {
            Player enemy = Bukkit.getPlayer(UUID.fromString(isEnemy ? row.get("player").toString() : row.get("enemy").toString()));
            player.getInventory().clear();
            enemy.getInventory().clear();
            e.setCancelled(true);
            player.setGameMode(GameMode.SPECTATOR);
            Location playerLoc = player.getLocation();

            Title winnerTitle = Title.title(
                    Component.text("§6🗡 §eMegnyerted a párbajt!"),
                    Component.empty(),
                    Title.Times.times(Duration.ofMillis(500), Duration.ofSeconds(3), Duration.ofMillis(1000))
            );

            Title loserTitle = Title.title(
                    Component.text("§4🗡 §cElvesztetted a párbajt!"),
                    Component.empty(),
                    Title.Times.times(Duration.ofMillis(500), Duration.ofSeconds(3), Duration.ofMillis(1000))
            );

            for (int i = 0; i < 3; i++) {
                int delay = i * 10;
                Bukkit.getScheduler().runTaskLater(plugin, () -> {
                    Firework firework = playerLoc.getWorld().spawn(playerLoc, Firework.class);
                    FireworkMeta meta = firework.getFireworkMeta();

                    FireworkEffect effect = FireworkEffect.builder()
                            .with(FireworkEffect.Type.BURST)
                            .withColor(
                                    Color.fromRGB(2437522),
                                    Color.fromRGB(14602026),
                                    Color.fromRGB(6719955)
                            )
                            .build();

                    meta.addEffect(effect);
                    meta.setPower((int) 0.5);
                    firework.setFireworkMeta(meta);
                }, delay);
            }

            player.showTitle(loserTitle);
            enemy.showTitle(winnerTitle);

            Bukkit.getScheduler().runTaskLater(plugin, () -> {
                try {
                    plugin.tpToSpawn(player);
                    plugin.tpToSpawn(enemy);
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }, 60L);

            Map<String, Object> data = new HashMap<>();
            data.put("player", row.get("player"));
            data.put("enemy", row.get("enemy"));
            data.put("ft", row.get("ft"));
            data.put("kit", row.get("kit"));
            data.put("winner", enemy.getUniqueId());
            data.put("loser", player.getUniqueId());
            data.put("player_points", row.get("player_points"));
            data.put("enemy_points", row.get("enemy_points"));
            data.put("started", row.get("started"));
            data.put("ended", System.currentTimeMillis());
            plugin.db.from("pvpcore_duel_logs").insert(data);
            plugin.db.from("pvpcore_duels").eq(isEnemy ? "enemy" : "player", player.getUniqueId()).eq(isEnemy ? "player" : "enemy", enemy.getUniqueId()).delete();
        } else if (!result.isEmpty() && row.get("ft") != row.get("player_points") && row.get("ft") != row.get("enemy_points")) {
            Player enemy = Bukkit.getPlayer(UUID.fromString(isEnemy ? row.get("player").toString() : row.get("enemy").toString()));
            Kits kitManager = new Kits(plugin);
            SchematicManager schematic = new SchematicManager(plugin);

            String gamemode = row.get("kit").toString();

            Database.QueryResult kitResult = null;
            try {
                kitResult = plugin.db.from("pvpcore_kits")
                        .eq("name", gamemode)
                        .execute()
                        .get();
            } catch (InterruptedException | ExecutionException ex) {
                throw new RuntimeException(ex);
            }

            Map<String, Object> kitRow = kitResult.data.get(0);

            player.getInventory().clear();
            enemy.getInventory().clear();
            e.setCancelled(true);
            World world = Bukkit.getWorld("arenas");
            boolean survival = Boolean.parseBoolean(kitRow.get("survival").toString());
            String arena = kitRow.get("arena").toString();
            int x = Integer.parseInt(kitRow.get("id").toString()) * 1000;
            int y = 0;
            int z;

            if (plugin.usedArenas.isEmpty()) {
                z = 0;
            } else {
                z = min(plugin.usedArenas) - 1000;
            }

            plugin.usedArenas.add(z);

            schematic.placeSchematic(world, x, y, z, arena, true);
            Location playerLoc = new Location(world, x + 20.5, y, z + 0.5, 90, 0);
            Location enemyLoc = new Location(world, x - 20.5, y, z + 0.5, -90, 0);

            for (PotionEffect potionEffect : player.getActivePotionEffects()) {
                player.removePotionEffect(potionEffect.getType());
            }
            for (PotionEffect potionEffect : enemy.getActivePotionEffects()) {
                enemy.removePotionEffect(potionEffect.getType());
            }
            player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 20, 1), true);
            enemy.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 20, 1), true);
            player.teleport(playerLoc);
            enemy.teleport(enemyLoc);
            try {
                player.getInventory().setContents(kitManager.getKit(gamemode, player, false));
                enemy.getInventory().setContents(kitManager.getKit(gamemode, enemy, false));
            } catch (ExecutionException | InterruptedException ex) {
                throw new RuntimeException(ex);
            }
            player.setHealth(20D);
            enemy.setHealth(20D);
            player.setFoodLevel(20);
            enemy.setFoodLevel(20);
            player.setSaturation(5);
            enemy.setSaturation(5);
            player.setGameMode(survival ? GameMode.SURVIVAL : GameMode.ADVENTURE);
            enemy.setGameMode(survival ? GameMode.SURVIVAL : GameMode.ADVENTURE);

            Map<String, Object> duelData = new HashMap<>();
            duelData.put("player", row.get("player"));
            duelData.put("enemy", row.get("enemy"));
            duelData.put("ft", row.get("ft"));
            duelData.put("kit", row.get("kit"));
            duelData.put(isEnemy ? "player_points" : "enemy_points", Integer.parseInt(row.get(isEnemy ? "player_points" : "enemy_points").toString()) + 1);
            duelData.put("started", row.get("started"));

            plugin.db.from("pvpcore_duels").update(duelData);

            player.setMetadata("Frozen", new FixedMetadataValue(plugin, true));
            enemy.setMetadata("Frozen", new FixedMetadataValue(plugin, true));

            new BukkitRunnable() {
                int countdown = 3;

                @Override
                public void run() {
                    if (countdown > 0) {
                        Component titleText = Component.text(String.valueOf(countdown), NamedTextColor.AQUA);
                        Title title = Title.title(
                                titleText,
                                Component.empty(),
                                Title.Times.times(Duration.ZERO, Duration.ofSeconds(1), Duration.ZERO)
                        );
                        player.showTitle(title);
                        enemy.showTitle(title);
                        countdown--;
                    } else {
                        Title startTitle = Title.title(
                                Component.text("§eA párbaj megkezdődött!"),
                                Component.empty(),
                                Title.Times.times(Duration.ZERO, Duration.ofSeconds(2), Duration.ofSeconds(1))
                        );
                        player.showTitle(startTitle);
                        enemy.showTitle(startTitle);
                        player.removeMetadata("Frozen", plugin);
                        enemy.removeMetadata("Frozen", plugin);
                        cancel();
                    }
                }
            }.runTaskTimer(plugin, 0L, 20L);
        } else {
            e.setCancelled(true);
            plugin.tpToSpawn(player);
        }
    }
}
