package de.viper.survivalplus.listeners;

import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class NewbieProtectionListener implements Listener {

    private final SurvivalPlus plugin;
    private final boolean enabled;
    private final int durationMinutes;
    private final int COOLDOWN_SECONDS = 60; // Abklingzeit für Nachrichten in Sekunden (1 Minute)

    // Maps für Zeiten, BossBars und Nachrichten-Abklingzeit
    private final Map<UUID, Integer> remainingSeconds = new HashMap<>();
    private final Map<UUID, BossBar> bossBars = new HashMap<>();
    private final Map<UUID, Long> messageCooldowns = new HashMap<>();
    
    // NEU: Set um zu speichern, wer schon mal gejoint ist
    private final Set<UUID> hasJoined = new HashSet<>();

    // YAML Datei
    private File dataFile;
    private FileConfiguration dataConfig;

    public NewbieProtectionListener(SurvivalPlus plugin) {
        this.plugin = plugin;
        this.enabled = plugin.getConfig().getBoolean("newbie-protection.enabled", true);
        this.durationMinutes = plugin.getConfig().getInt("newbie-protection.duration-minutes", 30);

        if (!plugin.getDataFolder().exists()) {
            plugin.getDataFolder().mkdirs();
        }
        loadData();

        if (enabled) {
            startTimer();
        }
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        if (!enabled) return;

        Player player = event.getPlayer();
        UUID uuid = player.getUniqueId();

        boolean isFirstJoin = !hasJoined.contains(uuid);

        if (isFirstJoin) {
            // Erster Join EVER -> Schutz geben und als "gejoint" markieren
            remainingSeconds.put(uuid, durationMinutes * 60);
            hasJoined.add(uuid);
            
            createBossBar(player, remainingSeconds.get(uuid));
        } else {
            // Spieler war schonmal da -> Prüfen ob noch Schutz übrig ist
            Integer timeLeft = remainingSeconds.get(uuid);
            if (timeLeft != null && timeLeft > 0) {
                // Schutz läuft noch -> Bossbar wiederherstellen
                createBossBar(player, timeLeft);
            }
            // Wenn timeLeft null ist oder 0, passiert nichts -> Kein Schutz für den "alten Hasen"
        }
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        if (!enabled) return;
        Player player = event.getPlayer();
        UUID uuid = player.getUniqueId();
        
        // Bossbar entfernen, aber Status (Zeit & Joined) in Map/Datei behalten
        BossBar bar = bossBars.remove(uuid);
        if (bar != null) {
            bar.removeAll();
        }
        saveData();
    }

    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (!enabled) return;
        if (!(event.getEntity() instanceof Player)) return;

        Player victim = (Player) event.getEntity();
        UUID victimId = victim.getUniqueId();
        Integer timeLeft = remainingSeconds.get(victimId);

        // Nur schützen, wenn Zeit > 0
        if (timeLeft == null || timeLeft <= 0) return;

        event.setCancelled(true);

        // Prüfe Cooldown für Nachrichten
        long currentTime = System.currentTimeMillis() / 1000;
        if (currentTime >= messageCooldowns.getOrDefault(victimId, 0L) + COOLDOWN_SECONDS) {
            victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
            messageCooldowns.put(victimId, currentTime);
        }

        if (event.getDamager() instanceof Player) {
            Player damager = (Player) event.getDamager();
            UUID damagerId = damager.getUniqueId();
            if (currentTime >= messageCooldowns.getOrDefault(damagerId, 0L) + COOLDOWN_SECONDS) {
                damager.sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
                messageCooldowns.put(damagerId, currentTime);
            }
        }
    }

    private void startTimer() {
        new BukkitRunnable() {
            @Override
            public void run() {
                for (UUID uuid : new HashSet<>(remainingSeconds.keySet())) {
                    Player p = Bukkit.getPlayer(uuid);

                    if (p == null || !p.isOnline()) {
                        // Spieler offline -> Zeit pausiert
                        continue;
                    }

                    int timeLeft = remainingSeconds.getOrDefault(uuid, 0);

                    if (timeLeft <= 0) {
                        // Zeit abgelaufen -> Bossbar weg, aber aus hasJoined NICHT löschen
                        removeProtection(uuid);
                        continue;
                    }

                    // Zeit runterzählen
                    timeLeft--;
                    remainingSeconds.put(uuid, timeLeft);

                    // Bossbar updaten
                    updateBossBar(p, timeLeft);
                }
                // Jedes Mal zyklisch speichern
                saveData();
            }
        }.runTaskTimer(plugin, 20L, 20L);
    }
    
    private void removeProtection(UUID uuid) {
        remainingSeconds.remove(uuid);
        BossBar bar = bossBars.remove(uuid);
        if (bar != null) {
            bar.removeAll();
        }
    }
    
    private void createBossBar(Player player, int seconds) {
        BossBar bar = Bukkit.createBossBar(
                ChatColor.GREEN + "Neulingsschutz: " + formatTime(seconds),
                BarColor.GREEN,
                BarStyle.SOLID
        );
        bar.addPlayer(player);
        bar.setProgress(Math.max(0, seconds / (float) (durationMinutes * 60)));
        bossBars.put(player.getUniqueId(), bar);
    }

    private void updateBossBar(Player player, int seconds) {
        BossBar bar = bossBars.get(player.getUniqueId());
        if (bar != null) {
            bar.setTitle(ChatColor.GREEN + "Neulingsschutz: " + formatTime(seconds));
            bar.setProgress(Math.max(0, seconds / (float) (durationMinutes * 60)));
        }
    }

    // ---------- Datei Handling ----------
    private void loadData() {
        dataFile = new File(plugin.getDataFolder(), "newbieprotection.yml");
        if (!dataFile.exists()) {
            try {
                dataFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        dataConfig = YamlConfiguration.loadConfiguration(dataFile);
        
        hasJoined.clear();
        remainingSeconds.clear();
        
        for (String key : dataConfig.getKeys(false)) {
            try {
                UUID uuid = UUID.fromString(key);
                
                // Gelesen: 'joined' Status und 'seconds'
                boolean joined = dataConfig.getBoolean(key + ".joined", false);
                int sec = dataConfig.getInt(key + ".seconds", 0);
                
                if (joined) {
                    hasJoined.add(uuid);
                }
                
                if (sec > 0) {
                    remainingSeconds.put(uuid, sec);
                }
            } catch (IllegalArgumentException ignored) {}
        }
    }

    public void saveData() {
        dataConfig = YamlConfiguration.loadConfiguration(dataFile);
        
        // Wir speichern ALLE Spieler, die schon mal gejoint sind (hasJoined)
        // damit wir beim Rejoin wissen, dass sie keinen Neulingsschutz mehr bekommen.
        for (UUID uuid : hasJoined) {
            dataConfig.set(uuid + ".joined", true);
            
            Integer sec = remainingSeconds.get(uuid);
            if (sec != null && sec > 0) {
                dataConfig.set(uuid + ".seconds", sec);
            } else {
                // Wenn Schutz abgelaufen (0 oder nicht in Map), speichern wir 0 oder löschen wir den Key?
                // Besser: löschen wir den Key "seconds", aber "joined" bleibt true.
                dataConfig.set(uuid + ".seconds", null);
            }
        }
        
        try {
            dataConfig.save(dataFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String formatTime(int totalSec) {
        int min = totalSec / 60;
        int sec = totalSec % 60;
        return String.format("%02d:%02d", min, sec);
    }
}