package com.tiedup.remake.entities;

import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.MessageDispatcher;
import com.tiedup.remake.util.teleport.Position;
import com.tiedup.remake.util.time.Timer;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import net.minecraft.ChatFormatting;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 * Handles the bondage service system for TiedUp NPCs.
 * When enabled via collar settings, players who attack the NPC
 * will be captured and teleported to the configured prison.
 *
 * <p>Flow:
 * <ul>
 *   <li>First hit: Warning message + 10 second timer</li>
 *   <li>Second hit within timer: Capture and teleport to prison</li>
 * </ul>
 *
 * <p>This system is transient - serviceTargets are not persisted.
 */
public class BondageServiceHandler {

    private static final String DEFAULT_MESSAGE =
        "Hello! Would you like to be tied up in my owner's prison?";
    private static final int WARNING_TIMER_SECONDS = 10;

    private final AbstractTiedUpNpc npc;
    private final Map<UUID, Timer> serviceTargets = new HashMap<>();

    public BondageServiceHandler(AbstractTiedUpNpc npc) {
        this.npc = npc;
    }

    /**
     * Check if bondage service is enabled for this damsel.
     * Requires: collar with bondage service flag ON and cell assigned.
     *
     * @return true if bondage service is active
     */
    public boolean isEnabled() {
        if (!npc.hasCollar()) return false;

        ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
        return (
            CollarHelper.hasCellAssigned(collar) &&
            CollarHelper.isBondageServiceEnabled(collar)
        );
    }

    /**
     * Get the custom bondage service message from the collar.
     *
     * @return Custom message or default message
     */
    public String getMessage() {
        if (npc.hasCollar()) {
            ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
            String message = CollarHelper.getServiceSentence(collar);
            if (message != null && !message.isEmpty()) {
                return message;
            }
        }
        return DEFAULT_MESSAGE;
    }

    /**
     * Handle a player attack on the damsel.
     * If bondage service is enabled, intercepts the attack.
     *
     * @param player The attacking player
     * @return true if the attack was intercepted (damage should be cancelled)
     */
    public boolean handlePlayerAttack(Player player) {
        if (player == null || npc.isTiedUp() || !isEnabled()) {
            return false;
        }

        UUID playerID = player.getUUID();
        Timer timer = serviceTargets.get(playerID);

        if (timer != null && !timer.isExpired()) {
            // SECOND HIT - Capture!
            capturePlayer(player);
            serviceTargets.remove(playerID);
        } else {
            // FIRST HIT - Warning
            String message = getMessage() + " Hit me again!";
            MessageDispatcher.talkTo(npc, player, message);
            serviceTargets.put(
                playerID,
                new Timer(WARNING_TIMER_SECONDS, npc.level())
            );
        }

        return true; // Attack intercepted
    }

    /**
     * Capture a player and teleport them to the configured cell.
     *
     * @param player The player to capture
     */
    private void capturePlayer(Player player) {
        ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
        if (!CollarHelper.isCollar(collar)) return;

        java.util.UUID cellId = CollarHelper.getCellId(collar);
        if (cellId == null) return;

        // Get cell position from registry
        if (
            !(npc.level() instanceof
                    net.minecraft.server.level.ServerLevel serverLevel)
        ) return;
        com.tiedup.remake.cells.CellDataV2 cell =
            com.tiedup.remake.cells.CellRegistryV2.get(serverLevel).getCell(
                cellId
            );
        if (cell == null) return;

        Position cellPosition = new Position(
            cell.getSpawnPoint().above(),
            serverLevel.dimension()
        );

        // Warn masters if configured
        warnOwners(player, collar);

        // Get player's kidnapped state
        PlayerBindState state = PlayerBindState.getInstance(player);
        if (state != null) {
            // Apply bondage
            state.equip(
                BodyRegionV2.ARMS,
                DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "ropes"))
            );
            state.equip(
                BodyRegionV2.MOUTH,
                DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "ball_gag"))
            );

            // Teleport to cell
            state.teleportToPosition(cellPosition);

            // Tie to pole if configured on collar
            if (CollarHelper.shouldTieToPole(collar)) {
                state.tieToClosestPole(3);
            }
        }

        // Announce capture
        MessageDispatcher.talkTo(npc, player, "Welcome to my owner's cell!");
    }

    /**
     * Warn collar owners about a capture via bondage service.
     *
     * @param capturedPlayer The player who was captured
     * @param itemCollar The collar item
     * @param collarStack The collar ItemStack
     */
    private void warnOwners(
        Player capturedPlayer,
        ItemStack collarStack
    ) {
        if (!CollarHelper.shouldWarnMasters(collarStack)) {
            return;
        }

        String message =
            npc.getNpcName() +
            " captured " +
            capturedPlayer.getName().getString() +
            " via bondage service!";

        for (UUID ownerUUID : CollarHelper.getOwners(collarStack)) {
            Player owner = npc.level().getPlayerByUUID(ownerUUID);
            if (owner != null) {
                SystemMessageManager.sendChatToPlayer(
                    owner,
                    message,
                    ChatFormatting.GOLD
                );
            }
        }
    }
}
