package fr.luc.gamingcore.model;

import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;

import java.util.Objects;
import java.util.UUID;

/**
 * Représente un territoire (chunk de 16x16 blocs) revendiqué par une guilde.
 */
public class GuildClaim {

    private int id;
    private final UUID guildId;
    private final String worldName;
    private final int chunkX;
    private final int chunkZ;
    private final long claimedAt;

    /**
     * Constructeur d'un claim de territoire de guilde.
     *
     * @param id        Identifiant unique du claim en base de données (0 si nouveau).
     * @param guildId   Identifiant UUID de la guilde propriétaire.
     * @param worldName Nom du monde Minecraft.
     * @param chunkX    Coordonnée X du chunk.
     * @param chunkZ    Coordonnée Z du chunk.
     * @param claimedAt Horodatage en millisecondes du moment de l'achat du claim.
     */
    public GuildClaim(int id, UUID guildId, String worldName, int chunkX, int chunkZ, long claimedAt) {
        this.id = id;
        this.guildId = Objects.requireNonNull(guildId, "Le UUID de la guilde ne peut pas être nul.");
        this.worldName = Objects.requireNonNull(worldName, "Le nom du monde ne peut pas être nul.");
        this.chunkX = chunkX;
        this.chunkZ = chunkZ;
        this.claimedAt = claimedAt > 0 ? claimedAt : System.currentTimeMillis();
    }

    /**
     * Obtient l'identifiant de base de données du claim.
     *
     * @return L'ID numérique.
     */
    public int getId() {
        return id;
    }

    /**
     * Modifie l'identifiant généré après insertion en base de données.
     *
     * @param id Le nouvel ID.
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * Obtient le UUID de la guilde propriétaire de ce territoire.
     *
     * @return L'UUID de la guilde.
     */
    public UUID getGuildId() {
        return guildId;
    }

    /**
     * Obtient le nom du monde où se situe ce chunk.
     *
     * @return Le nom du monde Minecraft.
     */
    public String getWorldName() {
        return worldName;
    }

    /**
     * Obtient la coordonnée X du chunk.
     *
     * @return L'abscisse de chunk.
     */
    public int getChunkX() {
        return chunkX;
    }

    /**
     * Obtient la coordonnée Z du chunk.
     *
     * @return L'ordonnée de chunk.
     */
    public int getChunkZ() {
        return chunkZ;
    }

    /**
     * Obtient la date et heure de revendication du chunk en millisecondes.
     * Utilisé pour calculer la surchauffe temporelle glissante sur 24h.
     *
     * @return Timestamp d'achat.
     */
    public long getClaimedAt() {
        return claimedAt;
    }

    /**
     * Vérifie si ce claim correspond aux coordonnées et monde spécifiés.
     *
     * @param world  Nom du monde.
     * @param chunkX Coordonnée X du chunk.
     * @param chunkZ Coordonnée Z du chunk.
     * @return true si les coordonnées correspondent exactement, false sinon.
     */
    public boolean matches(String world, int chunkX, int chunkZ) {
        return this.worldName.equalsIgnoreCase(world) && this.chunkX == chunkX && this.chunkZ == chunkZ;
    }

    /**
     * Récupère l'instance Bukkit Chunk correspondante si le monde est chargé.
     *
     * @return Le Chunk Bukkit ou null si le monde n'est pas chargé.
     */
    public Chunk toBukkitChunk() {
        World world = Bukkit.getWorld(worldName);
        if (world == null) return null;
        return world.getChunkAt(chunkX, chunkZ);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GuildClaim that = (GuildClaim) o;
        return chunkX == that.chunkX && chunkZ == that.chunkZ && Objects.equals(worldName, that.worldName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(worldName, chunkX, chunkZ);
    }

    @Override
    public String toString() {
        return worldName + ":" + chunkX + "," + chunkZ;
    }
}
