package com.tiedup.remake.dialogue.conversation;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterPlaceBlockGoal;
import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.network.master.PacketOpenPetRequestMenu;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;

/**
 * Manager for handling pet requests to their Master NPC.
 *
 * This is the server-side handler for player-initiated requests in pet play mode.
 * Utilizes existing systems:
 * - PlayerEquipment.equip(BodyRegionV2.ARMS, bind) / takeBindOff() for tie/untie
 * - MasterState.DOGWALK for walk mode
 * - MasterPlaceBlockGoal for feeding/resting
 * - Leash physics via mixin for pulling the player
 */
public class PetRequestManager {

    /** Maximum distance for pet request interaction */
    private static final double MAX_DISTANCE = 6.0;

    /**
     * Open the pet request menu for a pet player.
     * Sends a packet to the client to display the GUI.
     *
     * @param master The master entity
     * @param pet The pet player
     */
    public static void openRequestMenu(EntityMaster master, ServerPlayer pet) {
        if (!master.isPetPlayer(pet)) {
            TiedUpMod.LOGGER.warn(
                "[PetRequestManager] {} is not a pet of {}",
                pet.getName().getString(),
                master.getNpcName()
            );
            return;
        }

        // Check distance
        double dist = master.distanceTo(pet);
        if (dist > MAX_DISTANCE) {
            pet.sendSystemMessage(
                Component.translatable("entity.tiedup.pet.too_far_to_talk")
            );
            return;
        }

        // Send packet to open GUI on client
        ModNetwork.sendToPlayer(
            new PacketOpenPetRequestMenu(master.getId(), master.getNpcName()),
            pet
        );

        TiedUpMod.LOGGER.debug(
            "[PetRequestManager] Opened request menu for {} with {}",
            pet.getName().getString(),
            master.getNpcName()
        );
    }

    /**
     * Handle a request from the pet player.
     * Called when the player selects an option from the pet request menu.
     *
     * @param master The master entity
     * @param pet The pet player making the request
     * @param request The request type
     */
    public static void handleRequest(
        EntityMaster master,
        ServerPlayer pet,
        PetRequest request
    ) {
        if (!master.isPetPlayer(pet)) {
            TiedUpMod.LOGGER.warn(
                "[PetRequestManager] Rejected request from non-pet {} to {}",
                pet.getName().getString(),
                master.getNpcName()
            );
            return;
        }

        // Check distance
        double dist = master.distanceTo(pet);
        if (dist > MAX_DISTANCE) {
            pet.sendSystemMessage(
                Component.translatable("entity.tiedup.pet.too_far_from_master")
            );
            return;
        }

        TiedUpMod.LOGGER.info(
            "[PetRequestManager] {} requested {} from {}",
            pet.getName().getString(),
            request.name(),
            master.getNpcName()
        );

        // Display what the player "says"
        pet.sendSystemMessage(
            Component.translatable("entity.tiedup.pet.you_say", request.getPlayerText())
        );

        // Handle specific request
        switch (request) {
            case REQUEST_FOOD -> triggerFeeding(master, pet);
            case REQUEST_SLEEP -> triggerResting(master, pet);
            case REQUEST_WALK_PASSIVE -> triggerDogwalk(master, pet, false);
            case REQUEST_WALK_ACTIVE -> triggerDogwalk(master, pet, true);
            case REQUEST_TIE -> triggerTie(master, pet);
            case REQUEST_UNTIE -> triggerUntie(master, pet);
            case END_CONVERSATION -> endConversation(master, pet);
        }
    }

    /**
     * Trigger feeding action - Master places bowl for pet.
     */
    private static void triggerFeeding(EntityMaster master, ServerPlayer pet) {
        DialogueBridge.talkTo(master, pet, "petplay.feeding");

        MasterPlaceBlockGoal goal = master.getPlaceBlockGoal();
        if (goal != null) {
            goal.triggerFeeding();
        }
    }

    /**
     * Trigger resting action - Master places pet bed for pet.
     */
    private static void triggerResting(EntityMaster master, ServerPlayer pet) {
        DialogueBridge.talkTo(master, pet, "petplay.resting");

        MasterPlaceBlockGoal goal = master.getPlaceBlockGoal();
        if (goal != null) {
            goal.triggerResting();
        }
    }

    /**
     * Trigger dogwalk mode.
     * Puts dogbind on player and attaches leash.
     *
     * @param masterLeads If true, Master walks and pulls pet. If false, Master follows pet.
     */
    private static void triggerDogwalk(
        EntityMaster master,
        ServerPlayer pet,
        boolean masterLeads
    ) {
        // Get player bind state
        PlayerBindState state = PlayerBindState.getInstance(pet);
        if (state == null) {
            TiedUpMod.LOGGER.warn(
                "[PetRequestManager] Could not get PlayerBindState for {}",
                pet.getName().getString()
            );
            return;
        }

        // Put dogbind on player (if not already tied)
        if (!state.isTiedUp()) {
            ItemStack dogbind = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "dogbinder"));
            state.equip(BodyRegionV2.ARMS, dogbind);
            TiedUpMod.LOGGER.debug(
                "[PetRequestManager] Equipped dogbind on {} for walk",
                pet.getName().getString()
            );
        }

        // Attach leash
        master.attachLeashToPet();

        // Set dogwalk mode
        master.setDogwalkMode(masterLeads);
        master.setMasterState(MasterState.DOGWALK);

        String dialogueId = masterLeads
            ? "petplay.walk_active"
            : "petplay.walk_passive";
        DialogueBridge.talkTo(master, pet, dialogueId);

        TiedUpMod.LOGGER.info(
            "[PetRequestManager] {} entered DOGWALK mode with {} (masterLeads={})",
            master.getNpcName(),
            pet.getName().getString(),
            masterLeads
        );
    }

    /**
     * Trigger tie request - Master ties up the pet.
     */
    private static void triggerTie(EntityMaster master, ServerPlayer pet) {
        // Don't allow tie requests during dogwalk
        if (master.getStateManager().getCurrentState() == MasterState.DOGWALK) {
            DialogueBridge.talkTo(master, pet, "petplay.busy");
            return;
        }

        // Get player bind state
        PlayerBindState state = PlayerBindState.getInstance(pet);
        if (state == null) {
            TiedUpMod.LOGGER.warn(
                "[PetRequestManager] Could not get PlayerBindState for {}",
                pet.getName().getString()
            );
            return;
        }

        // Check if already tied
        if (state.isTiedUp()) {
            DialogueBridge.talkTo(master, pet, "petplay.already_tied");
            return;
        }

        // Master equips armbinder on pet (classic pet play restraint)
        ItemStack bind = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "armbinder"));
        state.equip(BodyRegionV2.ARMS, bind);

        DialogueBridge.talkTo(master, pet, "petplay.tie_accept");

        TiedUpMod.LOGGER.info(
            "[PetRequestManager] {} tied up {} with armbinder",
            master.getNpcName(),
            pet.getName().getString()
        );
    }

    /**
     * Trigger untie request - Master unties the pet.
     */
    private static void triggerUntie(EntityMaster master, ServerPlayer pet) {
        // Don't allow untie requests during dogwalk
        if (master.getStateManager().getCurrentState() == MasterState.DOGWALK) {
            DialogueBridge.talkTo(master, pet, "petplay.busy");
            return;
        }

        // Get player bind state
        PlayerBindState state = PlayerBindState.getInstance(pet);
        if (state == null) {
            TiedUpMod.LOGGER.warn(
                "[PetRequestManager] Could not get PlayerBindState for {}",
                pet.getName().getString()
            );
            return;
        }

        // Check if actually tied
        if (!state.isTiedUp()) {
            DialogueBridge.talkTo(master, pet, "petplay.not_tied");
            return;
        }

        // Master removes bind from pet
        state.unequip(BodyRegionV2.ARMS);

        DialogueBridge.talkTo(master, pet, "petplay.untie_accept");

        TiedUpMod.LOGGER.info(
            "[PetRequestManager] {} untied {}",
            master.getNpcName(),
            pet.getName().getString()
        );
    }

    /**
     * End the conversation gracefully.
     */
    private static void endConversation(EntityMaster master, ServerPlayer pet) {
        DialogueBridge.talkTo(master, pet, "petplay.dismiss");
    }
}
