package de.simolzimol.mclogger.paper.listeners;

import de.simolzimol.mclogger.paper.PaperLoggerPlugin;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Handles login, logout and basic player session data.
 *
 * @author SimolZimol
 */
public class PlayerSessionListener implements Listener {

    private final PaperLoggerPlugin plugin;
    /** Stores login timestamp per UUID for session duration calculation. */
    private final Map<UUID, Long> loginTimes = new ConcurrentHashMap<>();

    public PlayerSessionListener(PaperLoggerPlugin plugin) {
        this.plugin = plugin;
    }

    /**
     * Login event: player has authenticated and is connecting.
     */
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onLogin(PlayerLoginEvent event) {
        Player p = event.getPlayer();
        String ip = event.getAddress() != null ? event.getAddress().getHostAddress() : "unknown";

        plugin.getDb().upsertPlayer(
                p.getUniqueId().toString(),
                p.getName(),
                p.getDisplayName().length() > 64 ? p.getDisplayName().substring(0, 64) : p.getDisplayName(),
                ip,
                p.locale().toLanguageTag(),
                p.isOp()
        );
    }

    /**
     * Join event: player appears in-game.
     */
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onJoin(PlayerJoinEvent event) {
        Player p = event.getPlayer();
        loginTimes.put(p.getUniqueId(), System.currentTimeMillis());

        String ip = p.getAddress() != null
                ? p.getAddress().getAddress().getHostAddress() : "unknown";

        // Session is opened by the Velocity proxy on PostLoginEvent

        Map<String, Object> details = new HashMap<>();
        details.put("join_message", event.joinMessage() != null ? event.joinMessage().toString() : "");
        details.put("first_join", !p.hasPlayedBefore());
        details.put("gamemode", p.getGameMode().name());
        plugin.getDb().insertServerEvent("player_join",
                p.getName() + " joined the server", details);
    }

    /**
     * Quit event: player leaves the server.
     */
    @EventHandler(priority = EventPriority.MONITOR)
    public void onQuit(PlayerQuitEvent event) {
        Player p = event.getPlayer();
        UUID uuid = p.getUniqueId();
        Long storedLogin = loginTimes.remove(uuid);
        long durationSec = storedLogin != null ? (System.currentTimeMillis() - storedLogin) / 1000 : 0;

        // Session is closed by the Velocity proxy on DisconnectEvent

        Map<String, Object> details = new HashMap<>();
        details.put("reason", event.getReason().name());
        details.put("playtime_sec", durationSec);
        plugin.getDb().insertServerEvent("player_quit",
                p.getName() + " left the server", details);
    }

    /**
     * Kick event: player was kicked.
     */
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onKick(PlayerKickEvent event) {
        Player p = event.getPlayer();
        Map<String, Object> details = new HashMap<>();
        details.put("reason", event.getReason());
        details.put("cause", event.getCause().name());
        plugin.getDb().insertServerEvent("player_kick",
                p.getName() + " was kicked: " + event.getReason(), details);
    }
}
