package com.tiedup.remake.entities.master.components;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterRandomEventGoal;
import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.minigame.StruggleSessionManager;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 * MasterPetManager - Manages pet player lifecycle for a Master entity.
 *
 * Responsibilities:
 * - Pet player resolution (UUID to ServerPlayer)
 * - Pet collar equip/removal
 * - Leash attach/detach
 * - Collar data sync for disconnect persistence
 * - Collar resistance reset (on struggle detection)
 * - Pet freedom (on master death/escape)
 *
 * The pet UUID itself is stored in {@link MasterStateManager} -- this component
 * does NOT duplicate that field. It accesses it via the stateManager reference.
 */
public class MasterPetManager {

    /** Pet collar resistance (very high) */
    public static final int PET_COLLAR_RESISTANCE = 250;

    /** Back-reference to the owning Master entity */
    private final EntityMaster master;

    /** State manager holding the pet UUID */
    private final MasterStateManager stateManager;

    // CONSTRUCTOR

    public MasterPetManager(
        EntityMaster master,
        MasterStateManager stateManager
    ) {
        this.master = master;
        this.stateManager = stateManager;
    }

    // PET PLAYER RESOLUTION

    /**
     * Get the pet player entity from the server.
     *
     * @return The pet ServerPlayer, or null if offline/not set
     */
    @Nullable
    public ServerPlayer getPetPlayer() {
        UUID petUUID = stateManager.getPetPlayerUUID();
        if (petUUID == null) return null;

        if (master.level() instanceof ServerLevel serverLevel) {
            return serverLevel.getServer().getPlayerList().getPlayer(petUUID);
        }
        return null;
    }

    /**
     * Set the pet player. Initializes state to FOLLOWING and starts distraction timer.
     *
     * @param player The player to become the pet
     */
    public void setPetPlayer(ServerPlayer player) {
        stateManager.setPetPlayerUUID(player.getUUID());
        stateManager.setCurrentState(MasterState.FOLLOWING);
        stateManager.initializeDistractionTimer();
    }

    /**
     * Check if this master has a pet.
     *
     * @return true if a pet UUID is set
     */
    public boolean hasPet() {
        return stateManager.hasPet();
    }

    /**
     * Check if a player is the pet of this master.
     *
     * @param player The player to check
     * @return true if the player's UUID matches the pet UUID
     */
    public boolean isPetPlayer(Player player) {
        if (player == null) return false;
        UUID petUUID = stateManager.getPetPlayerUUID();
        return petUUID != null && petUUID.equals(player.getUUID());
    }

    // PET COLLAR

    /**
     * Put a pet collar on the player.
     * Replaces any existing collar (e.g., shock collar from Kidnapper) with a choke collar.
     * Configures it for pet play mode.
     *
     * @param player The player to collar
     */
    public void putPetCollar(ServerPlayer player) {
        IBondageState state = KidnappedHelper.getKidnappedState(player);
        if (state == null) return;

        // Create a choke collar for pet play
        ItemStack chokeCollar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
            net.minecraft.resources.ResourceLocation.fromNamespaceAndPath("tiedup", "choke_collar")
        );

        // Configure for pet play BEFORE equipping
        if (
            chokeCollar.getItem() instanceof
                com.tiedup.remake.items.base.IHasResistance resistable
        ) {
            resistable.setCurrentResistance(chokeCollar, PET_COLLAR_RESISTANCE);
            resistable.setCanBeStruggledOut(chokeCollar, true); // Can struggle, but very hard
        }
        if (
            chokeCollar.getItem() instanceof
                com.tiedup.remake.items.base.ILockable lockable
        ) {
            lockable.setLocked(chokeCollar, true);
            lockable.setLockable(chokeCollar, false); // Cannot be lockpicked
        }

        // Add this Master as owner
        CollarHelper.addOwner(chokeCollar, master.getUUID(), master.getNpcName());

        // Set NBT flag for pet play mode
        CollarHelper.setPetPlayMode(chokeCollar, true);
        chokeCollar
            .getOrCreateTag()
            .putUUID("masterUUID", master.getUUID());

        // Replace any existing collar (force removal) with the choke collar
        state.replaceEquipment(BodyRegionV2.NECK, chokeCollar, true);

        TiedUpMod.LOGGER.info(
            "[MasterPetManager] {} put choke collar on {}",
            master.getNpcName(),
            player.getName().getString()
        );
    }

    /**
     * Free the pet player (on master death or escape).
     * Removes pet play mode from collar, unlocks it, cleans up temp items,
     * and sends a message to the player.
     *
     * @param player The pet player to free
     */
    public void freePet(ServerPlayer player) {
        TiedUpMod.LOGGER.info(
            "[MasterPetManager] {} freed pet {}",
            master.getNpcName(),
            player.getName().getString()
        );

        stateManager.clearPet();

        // Remove all temporary master event items (blindfold, gag, mittens, bind)
        // Using Long.MAX_VALUE forces all items to expire immediately
        MasterRandomEventGoal.cleanupExpiredTempItems(player, Long.MAX_VALUE);

        // Remove pet play mode from collar
        ItemStack collarStack = V2EquipmentHelper.getInRegion(
            player,
            BodyRegionV2.NECK
        );
        if (!collarStack.isEmpty()) {
            CompoundTag tag = collarStack.getTag();
            if (tag != null) {
                tag.remove("petPlayMode");
                tag.remove("masterUUID");
            }

            // Unlock the collar
            if (collarStack.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
                lockable.setLocked(collarStack, false);
                lockable.setLockable(collarStack, true);
            }
        }

        // Send message to player
        player.sendSystemMessage(
            Component.translatable(
                "entity.tiedup.master.pet_freed", master.getNpcName()
            ).withStyle(Style.EMPTY.withColor(0x00FF00))
        );
    }

    // COLLAR SYNC & RESISTANCE

    /**
     * Synchronize Master data to the pet's collar NBT.
     * This ensures Master data is preserved even if Master entity is in an unloaded chunk
     * when the player disconnects.
     *
     * Called every second during tick() for persistence safety.
     *
     * @param pet The pet player
     */
    public void syncDataToCollar(ServerPlayer pet) {
        ItemStack collarStack = V2EquipmentHelper.getInRegion(
            pet,
            BodyRegionV2.NECK
        );
        if (collarStack.isEmpty()) return;

        CompoundTag tag = collarStack.getOrCreateTag();

        // Store Master persistence data
        tag.putString("masterVariantId", master.getKidnapperVariantId());
        tag.putString("masterState", master.getStateManager().serializeState());
        tag.putString("masterName", master.getNpcName());
        tag.putBoolean("masterDataValid", true);

        // masterUUID and petPlayMode already set by putPetCollar()
    }

    /**
     * Reset the pet collar resistance to maximum (Master "repairs" the lock).
     * Also ends any active struggle session.
     *
     * @param pet The pet player whose collar should be reset
     */
    public void resetCollarResistance(ServerPlayer pet) {
        ItemStack collarStack = V2EquipmentHelper.getInRegion(
            pet,
            BodyRegionV2.NECK
        );
        if (collarStack.isEmpty()) return;

        if (collarStack.getItem() instanceof com.tiedup.remake.items.base.IHasResistance resistable) {
            resistable.setCurrentResistance(collarStack, PET_COLLAR_RESISTANCE);
            TiedUpMod.LOGGER.debug(
                "[MasterPetManager] Reset collar resistance for {}",
                pet.getName().getString()
            );
        }

        // End the struggle session
        StruggleSessionManager.getInstance().endContinuousStruggleSession(
            pet.getUUID(),
            false
        );
    }

    // LEASH MANAGEMENT

    /**
     * Attach a leash from the pet player to this Master.
     * Used during walks and other activities.
     */
    public void attachLeashToPet() {
        ServerPlayer pet = getPetPlayer();
        if (pet == null) return;

        if (pet instanceof com.tiedup.remake.state.IPlayerLeashAccess access) {
            access.tiedup$attachLeash(master);
            TiedUpMod.LOGGER.debug(
                "[MasterPetManager] {} attached leash to {}",
                master.getNpcName(),
                pet.getName().getString()
            );
        }
    }

    /**
     * Detach the leash from the pet player.
     */
    public void detachLeashFromPet() {
        ServerPlayer pet = getPetPlayer();
        if (pet == null) return;

        if (pet instanceof com.tiedup.remake.state.IPlayerLeashAccess access) {
            if (access.tiedup$isLeashed()) {
                access.tiedup$detachLeash();
                TiedUpMod.LOGGER.debug(
                    "[MasterPetManager] {} detached leash from {}",
                    master.getNpcName(),
                    pet.getName().getString()
                );
            }
        }
    }

    /**
     * Check if the pet player is currently leashed to this Master.
     *
     * @return true if pet is leashed to this master
     */
    public boolean isPetLeashed() {
        ServerPlayer pet = getPetPlayer();
        if (pet == null) return false;

        if (pet instanceof com.tiedup.remake.state.IPlayerLeashAccess access) {
            return (
                access.tiedup$isLeashed() &&
                access.tiedup$getLeashHolder() == master
            );
        }
        return false;
    }
}
