package com.tiedup.remake.state.components;

import com.tiedup.remake.cells.CampOwnership;
import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

/**
 * Component responsible for player lifecycle management.
 * Handles connection, death, respawn scenarios.
 *
 * Single Responsibility: Lifecycle events and registry coordination
 * Complexity: HIGH (coordinates 4+ registries on death)
 * Risk: HIGH (critical path, must maintain registry cleanup order)
 *
 * Registry Cleanup Order (on death):
 * 1. CellRegistryV2 - remove from cells
 * 2. PrisonerManager - release prisoner (via PrisonerService)
 */
public class PlayerLifecycle {

    private final IPlayerBindStateHost host;

    public PlayerLifecycle(IPlayerBindStateHost host) {
        this.host = host;
    }

    // ========== Lifecycle Methods ==========

    /**
     * Resets the player instance upon reconnection or respawn.
     *
     * IMPORTANT: Handle transport restoration for pole binding.
     * With proxy-based leash system, leashes are not persisted through disconnection.
     * The leash proxy is ephemeral and will be recreated if needed.
     *
     * Leg Binding: Speed reduction based on hasLegsBound(), not isTiedUp().
     */
    public void resetNewConnection(Player player) {
        // Update player reference
        host.setOnline(true);

        host.setCaptor(null);

        // Reset struggle animation state (prevent stuck animations)
        host.setStrugglingClient(false);

        // Leash proxy doesn't persist through disconnection
        // If player was leashed, they are now freed

        // H6 fix: V1 speed reduction re-application is no longer needed for players.
        // MovementStyleManager (V2 tick-based system) re-resolves the active movement
        // style on the first tick after login (clearMovementState() resets activeMovementStyle
        // to null, triggering a fresh activation). The V1 RestraintEffectUtils call here would
        // cause double stacking with the V2 MULTIPLY_BASE modifier.
    }

    /**
     * Called when the kidnapped player dies.
     * Comprehensive cleanup: unlock items, drop items, free captivity, cleanup registries.
     *
     * @param world The world/level where death occurred
     * @return true if death was handled
     */
    public boolean onDeathKidnapped(Level world) {
        Player player = host.getPlayer();

        // Mark player as offline
        host.setOnline(false);

        // Clean up all registries on death (server-side only)
        if (world instanceof ServerLevel serverLevel) {
            UUID playerId = player.getUUID();
            cleanupRegistries(serverLevel, playerId);
        }

        TiedUpMod.LOGGER.debug(
            "[PlayerLifecycle] {} died while kidnapped",
            player.getName().getString()
        );
        return true;
    }

    /**
     * Coordinates cleanup of all registries when player dies.
     * Order matters: Cell → Camp → Ransom → Prisoner
     *
     * @param serverLevel The server level
     * @param playerId The player's UUID
     */
    private void cleanupRegistries(ServerLevel serverLevel, UUID playerId) {
        String playerName = host.getPlayer().getName().getString();

        // 1. Clean up CellRegistryV2 - remove from any cells
        CellRegistryV2 cellRegistry = CellRegistryV2.get(serverLevel);
        int cellsRemoved = cellRegistry.releasePrisonerFromAllCells(playerId);
        if (cellsRemoved > 0) {
            TiedUpMod.LOGGER.debug(
                "[PlayerLifecycle] Removed {} from {} cells on death",
                playerName,
                cellsRemoved
            );
        }

        // 2. Clean up prisoner state - release from imprisonment
        com.tiedup.remake.prison.PrisonerManager manager =
            com.tiedup.remake.prison.PrisonerManager.get(serverLevel);
        com.tiedup.remake.prison.PrisonerState state = manager.getState(
            playerId
        );

        // Release if imprisoned or working (player died)
        if (
            state == com.tiedup.remake.prison.PrisonerState.IMPRISONED ||
            state == com.tiedup.remake.prison.PrisonerState.WORKING
        ) {
            // Use centralized escape service for complete cleanup
            com.tiedup.remake.prison.service.EscapeMonitorService.get().escape(
                serverLevel,
                playerId,
                "player_death"
            );
        }
    }

    // ========== Helper Methods ==========

    /**
     * Get the current bind ItemStack.
     * Epic 5F: Migrated to V2EquipmentHelper.
     */
    private ItemStack getCurrentBind() {
        return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getInRegion(
            host.getPlayer(),
            com.tiedup.remake.v2.BodyRegionV2.ARMS
        );
    }

    /**
     * Check if player has legs bound.
     */
    private boolean hasLegsBound(ItemStack bind) {
        if (bind.isEmpty()) return false;
        if (!BindModeHelper.isBindItem(bind)) return false;
        return BindModeHelper.hasLegsBound(bind);
    }
}
