package com.tiedup.remake.entities.ai.maid.goals;

import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaid;
import com.tiedup.remake.labor.LaborTaskGenerator;
import com.tiedup.remake.prison.LaborRecord;
import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.prison.PrisonerRecord;
import com.tiedup.remake.prison.PrisonerState;
import com.tiedup.remake.prison.service.ItemService;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;

/**
 * Goal: Detect new prisoners and initialize their labor records.
 *
 * Responsibility: ONE thing - detect new IMPRISONED prisoners and create their ransom.
 *
 * Runs periodically, checks for prisoners in camp cells who don't have ransoms yet,
 * creates ransom records, and confiscates valuables.
 */
public class MaidInitPrisonerGoal extends Goal {

    private static final int CHECK_INTERVAL_TICKS = 100; // 5 seconds
    // Ransom is now calculated dynamically via LaborTaskGenerator.calculateRansomAmount()

    private final EntityMaid maid;
    private int tickCounter = 0;

    public MaidInitPrisonerGoal(EntityMaid maid) {
        this.maid = maid;
        this.setFlags(EnumSet.noneOf(Flag.class)); // No flags - runs in background
    }

    @Override
    public boolean canUse() {
        if (maid.isFreed() || maid.isTiedUp()) {
            return false;
        }
        if (maid.getMasterTraderUUID() == null) {
            return false;
        }
        return true;
    }

    @Override
    public void tick() {
        tickCounter++;
        if (tickCounter < CHECK_INTERVAL_TICKS) {
            return;
        }
        tickCounter = 0;

        if (!(maid.level() instanceof ServerLevel level)) {
            return;
        }

        UUID campId = maid.getCampUUID();
        if (campId == null) {
            return;
        }

        PrisonerManager manager = PrisonerManager.get(level);
        CellRegistryV2 cells = CellRegistryV2.get(level);

        // Get all prisoners in this camp
        Set<UUID> campPrisoners = manager.getPrisonersInCamp(campId);

        for (UUID prisonerId : campPrisoners) {
            PrisonerRecord record = manager.getRecord(prisonerId);

            // Only process IMPRISONED prisoners
            if (record.getState() != PrisonerState.IMPRISONED) {
                continue;
            }

            // Check if they already have a ransom
            if (manager.getRansomRecord(prisonerId) != null) {
                continue;
            }

            // New prisoner - initialize!
            ServerPlayer prisoner = level
                .getServer()
                .getPlayerList()
                .getPlayer(prisonerId);
            if (prisoner == null) {
                continue; // Offline
            }

            initializePrisoner(level, manager, prisoner, campId);
        }
    }

    /**
     * Initialize a new prisoner with ransom and confiscation.
     */
    private void initializePrisoner(
        ServerLevel level,
        PrisonerManager manager,
        ServerPlayer prisoner,
        UUID campId
    ) {
        UUID prisonerId = prisoner.getUUID();
        long currentTime = level.getGameTime();

        // 1. Evaluate player equipment BEFORE confiscation
        boolean hasIronArmor = hasArmorTier(
            prisoner,
            Items.IRON_CHESTPLATE,
            Items.IRON_LEGGINGS,
            Items.IRON_HELMET,
            Items.IRON_BOOTS
        );
        boolean hasDiamondArmor = hasArmorTier(
            prisoner,
            Items.DIAMOND_CHESTPLATE,
            Items.DIAMOND_LEGGINGS,
            Items.DIAMOND_HELMET,
            Items.DIAMOND_BOOTS,
            Items.NETHERITE_CHESTPLATE,
            Items.NETHERITE_LEGGINGS,
            Items.NETHERITE_HELMET,
            Items.NETHERITE_BOOTS
        );
        boolean hasValuables = hasAnyItem(
            prisoner,
            Items.EMERALD,
            Items.DIAMOND,
            Items.EMERALD_BLOCK,
            Items.DIAMOND_BLOCK
        );

        // 2. Confiscate valuables
        List<ItemStack> confiscated = ItemService.get().confiscateValuables(
            prisoner
        );

        // 3. Calculate ransom using centralized formula (100-200+ emeralds)
        int baseRansom = LaborTaskGenerator.calculateRansomAmount(
            hasIronArmor,
            hasDiamondArmor,
            hasValuables
        );
        int confiscatedValue = calculateConfiscatedValue(confiscated);
        int totalRansom = baseRansom + confiscatedValue;

        // 3. Create ransom record
        manager.createRansom(prisonerId, totalRansom, currentTime);

        // 4. Initialize labor record to IDLE
        LaborRecord labor = manager.getLaborRecord(prisonerId);
        labor.setPhase(LaborRecord.WorkPhase.IDLE, currentTime);

        // 5. Store confiscated items in camp chest
        storeConfiscatedItems(level, campId, confiscated);

        // 6. Notify prisoner
        prisoner.sendSystemMessage(
            net.minecraft.network.chat.Component.translatable(
                "goal.tiedup.maid_init.imprisoned",
                totalRansom
            ).withStyle(net.minecraft.ChatFormatting.RED)
        );

        if (!confiscated.isEmpty()) {
            prisoner.sendSystemMessage(
                net.minecraft.network.chat.Component.translatable(
                    "goal.tiedup.maid_init.confiscated"
                ).withStyle(net.minecraft.ChatFormatting.GRAY)
            );
        }

        TiedUpMod.LOGGER.info(
            "[MaidInitPrisonerGoal] Initialized prisoner {} with ransom {}",
            prisoner.getName().getString(),
            totalRansom
        );
    }

    /**
     * Calculate emerald value of confiscated items.
     */
    private int calculateConfiscatedValue(List<ItemStack> items) {
        int value = 0;
        for (ItemStack stack : items) {
            value += getItemValue(stack) * stack.getCount();
        }
        return value;
    }

    private int getItemValue(ItemStack stack) {
        var item = stack.getItem();
        if (
            item == Items.NETHERITE_INGOT || item == Items.NETHERITE_BLOCK
        ) return 10;
        if (item == Items.DIAMOND || item == Items.DIAMOND_BLOCK) return 5;
        if (item == Items.EMERALD || item == Items.EMERALD_BLOCK) return 1;
        if (item == Items.GOLD_INGOT || item == Items.GOLD_BLOCK) return 2;
        if (item == Items.IRON_INGOT || item == Items.IRON_BLOCK) return 1;
        return 0;
    }

    /**
     * Check if the player has any armor piece from the given set equipped.
     */
    private boolean hasArmorTier(
        ServerPlayer player,
        net.minecraft.world.item.Item... armorItems
    ) {
        for (ItemStack armorSlot : player.getArmorSlots()) {
            if (armorSlot.isEmpty()) continue;
            for (net.minecraft.world.item.Item target : armorItems) {
                if (armorSlot.getItem() == target) return true;
            }
        }
        return false;
    }

    /**
     * Check if the player has any of the given items in inventory.
     */
    private boolean hasAnyItem(
        ServerPlayer player,
        net.minecraft.world.item.Item... items
    ) {
        var inventory = player.getInventory();
        for (int i = 0; i < inventory.getContainerSize(); i++) {
            ItemStack stack = inventory.getItem(i);
            if (stack.isEmpty()) continue;
            for (net.minecraft.world.item.Item target : items) {
                if (stack.getItem() == target) return true;
            }
        }
        return false;
    }

    /**
     * Store confiscated items in camp chest.
     */
    private void storeConfiscatedItems(
        ServerLevel level,
        UUID campId,
        List<ItemStack> items
    ) {
        if (items.isEmpty()) return;

        var chestPos = ItemService.get().findCampChest(level, campId);
        if (chestPos != null) {
            ItemService.get().storeInChest(level, chestPos, items);
        }
    }

    @Override
    public boolean canContinueToUse() {
        return canUse();
    }
}
