package com.tiedup.remake.entities;

import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.EntityDialogueManager;
import java.util.UUID;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.Nullable;

/**
 * Tracks savior and reward state for EntityDamsel.
 * Handles the emerald reward system when players rescue damsels.
 *
 * <p>Anti-abuse features:
 * <ul>
 *   <li>No reward if already rewarded (prevents infinite reward exploit)</li>
 *   <li>No reward if savior is the one who tied (prevents self-rescue exploit)</li>
 * </ul>
 *
 * <p>This system IS persisted to NBT.
 */
public class DamselRewardTracker {

    private final EntityDamsel damsel;

    /** Player who rescued this damsel (won't flee from them) */
    @Nullable
    private UUID saviorUUID;

    /** Player who tied this damsel (for anti-abuse checks) */
    @Nullable
    private UUID tiedByUUID;

    /** Whether a reward has been given (prevents re-exploitation) */
    private boolean hasGivenReward = false;

    public DamselRewardTracker(EntityDamsel damsel) {
        this.damsel = damsel;
    }

    // SAVIOR GETTERS/SETTERS

    /**
     * Set the player who rescued this damsel.
     * @param player The savior (or null to clear)
     */
    public void setSavior(@Nullable Player player) {
        this.saviorUUID = player != null ? player.getUUID() : null;
    }

    /**
     * Check if the given entity is this damsel's savior.
     * @param entity The entity to check
     * @return true if this is the savior
     */
    public boolean isSavior(Entity entity) {
        if (this.saviorUUID == null || entity == null) {
            return false;
        }
        return this.saviorUUID.equals(entity.getUUID());
    }

    /**
     * Get the savior's UUID.
     * @return The savior UUID or null if no savior
     */
    @Nullable
    public UUID getSaviorUUID() {
        return this.saviorUUID;
    }

    // ANTI-ABUSE TRACKING

    /**
     * Set the player who tied this damsel (for reward anti-abuse).
     * @param player The player who tied this damsel (or null to clear)
     */
    public void setTiedBy(@Nullable Player player) {
        this.tiedByUUID = player != null ? player.getUUID() : null;
    }

    /**
     * Get the UUID of the player who tied this damsel.
     * @return The tiedBy UUID or null
     */
    @Nullable
    public UUID getTiedByUUID() {
        return this.tiedByUUID;
    }

    /**
     * Check if this damsel has already given a reward.
     * @return true if reward already given
     */
    public boolean hasGivenReward() {
        return this.hasGivenReward;
    }

    /**
     * Reset the reward state (for respawn/new capture cycle).
     */
    public void reset() {
        this.hasGivenReward = false;
        this.tiedByUUID = null;
    }

    // REWARD LOGIC

    /**
     * Reward the player who rescued this damsel.
     * Gives emeralds and marks the player as savior (won't flee from them).
     *
     * @param savior The player who freed this damsel
     */
    public void rewardSavior(Player savior) {
        // Anti-abuse: Don't reward if already rewarded
        if (this.hasGivenReward) {
            TiedUpMod.LOGGER.debug(
                "[DamselRewardTracker] {} already gave reward, skipping",
                damsel.getName().getString()
            );
            // Still set as savior (won't flee from them)
            this.setSavior(savior);
            return;
        }

        // Anti-abuse: Don't reward if savior is the one who tied
        if (
            this.tiedByUUID != null && this.tiedByUUID.equals(savior.getUUID())
        ) {
            TiedUpMod.LOGGER.debug(
                "[DamselRewardTracker] {} was tied by {}, no reward for self-rescue",
                damsel.getName().getString(),
                savior.getName().getString()
            );
            // Still set as savior (won't flee) but no reward
            this.setSavior(savior);
            this.hasGivenReward = true; // Prevent future reward attempts too
            return;
        }

        // Mark as rewarded BEFORE giving reward (prevents race conditions)
        this.hasGivenReward = true;

        // Mark as savior (damsel won't flee from this player anymore)
        this.setSavior(savior);

        // Create reward (1-3 emeralds)
        int emeraldCount = 1 + damsel.getRandom().nextInt(3);
        ItemStack reward = new ItemStack(Items.EMERALD, emeraldCount);

        // Drop at damsel's location (player can pick it up)
        ItemEntity itemEntity = new ItemEntity(
            damsel.level(),
            damsel.getX(),
            damsel.getY() + 0.5,
            damsel.getZ(),
            reward
        );

        // Give slight velocity toward savior
        double dx = savior.getX() - damsel.getX();
        double dz = savior.getZ() - damsel.getZ();
        double dist = Math.sqrt(dx * dx + dz * dz);
        if (dist > 0.1) {
            itemEntity.setDeltaMovement(
                (dx / dist) * 0.2,
                0.2,
                (dz / dist) * 0.2
            );
        }
        damsel.level().addFreshEntity(itemEntity);

        // Thank the savior via dialogue
        damsel.talkToPlayersInRadius(
            EntityDialogueManager.DialogueCategory.DAMSEL_FREED,
            SettingsAccessor.getDialogueRadius()
        );

        TiedUpMod.LOGGER.info(
            "[DamselRewardTracker] {} rewarded {} with {} emeralds",
            damsel.getName().getString(),
            savior.getName().getString(),
            emeraldCount
        );
    }

    // NBT PERSISTENCE

    /**
     * Save reward tracker state to NBT.
     * @param tag The tag to save to
     */
    public void save(CompoundTag tag) {
        if (saviorUUID != null) {
            tag.putUUID("SaviorUUID", saviorUUID);
        }
        if (tiedByUUID != null) {
            tag.putUUID("TiedByUUID", tiedByUUID);
        }
        tag.putBoolean("HasGivenReward", hasGivenReward);
    }

    /**
     * Load reward tracker state from NBT.
     * @param tag The tag to load from
     */
    public void load(CompoundTag tag) {
        if (tag.contains("SaviorUUID")) {
            this.saviorUUID = tag.getUUID("SaviorUUID");
        }
        if (tag.contains("TiedByUUID")) {
            this.tiedByUUID = tag.getUUID("TiedByUUID");
        }
        this.hasGivenReward = tag.getBoolean("HasGivenReward");
    }
}
