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

import com.tiedup.remake.cells.CellDataV2;
import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaid;
import com.tiedup.remake.labor.LaborTask;
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.RansomRecord;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.EnumSet;
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;

/**
 * Goal: Assign labor tasks to idle prisoners.
 *
 * Responsibility: ONE thing - assign tasks to IMPRISONED prisoners in IDLE phase.
 *
 * Checks for prisoners who are idle (no task, done resting) and assigns appropriate tasks.
 */
public class MaidAssignTaskGoal extends Goal {

    private static final int CHECK_INTERVAL_TICKS = 100; // 5 seconds
    private static final long GRACE_PERIOD_TICKS = 6000; // 5 minutes protection after release

    private final EntityMaid maid;
    private int tickCounter = 0;

    public MaidAssignTaskGoal(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);
        long currentTime = level.getGameTime();

        // Get all imprisoned prisoners in this camp
        Set<UUID> prisoners = manager.getPrisonersInCampWithState(
            campId,
            PrisonerState.IMPRISONED
        );

        for (UUID prisonerId : prisoners) {
            LaborRecord labor = manager.getLaborRecord(prisonerId);

            // Check if in IDLE or RESTING phase
            LaborRecord.WorkPhase phase = labor.getPhase();

            if (phase == LaborRecord.WorkPhase.RESTING) {
                // Check if rest is complete (config: laborRestSeconds, default 120s)
                long restTicks = SettingsAccessor.getLaborRestSeconds() * 20L;
                long elapsed = labor.getTimeInPhase(currentTime);
                if (elapsed >= restTicks) {
                    labor.finishRest(currentTime);
                    phase = LaborRecord.WorkPhase.IDLE;
                    TiedUpMod.LOGGER.info(
                        "[MaidAssignTaskGoal] {} RESTING→IDLE (rested {}s/{}s)",
                        prisonerId.toString().substring(0, 8),
                        elapsed / 20,
                        restTicks / 20
                    );
                }
            }

            if (phase != LaborRecord.WorkPhase.IDLE) {
                continue; // Not ready for task
            }

            // Check if they still have debt — auto-create ransom if missing
            RansomRecord ransom = manager.getRansomRecord(prisonerId);
            if (ransom == null) {
                // MaidInitPrisonerGoal failed to create ransom (trader was unloaded?) — create fallback
                int fallbackAmount = LaborTaskGenerator.calculateRansomAmount(
                    false,
                    false,
                    false
                );
                manager.createRansom(prisonerId, fallbackAmount, currentTime);
                ransom = manager.getRansomRecord(prisonerId);
                TiedUpMod.LOGGER.warn(
                    "[MaidAssignTaskGoal] Created fallback ransom ({}) for {} — MaidInitPrisonerGoal missed",
                    fallbackAmount,
                    prisonerId.toString().substring(0, 8)
                );
            }
            if (ransom.isPaid()) {
                // Ransom paid while prisoner is in cell — release them now
                ServerPlayer paidPrisoner = level
                    .getServer()
                    .getPlayerList()
                    .getPlayer(prisonerId);
                if (paidPrisoner != null) {
                    releasePaidPrisoner(
                        level,
                        paidPrisoner,
                        manager,
                        currentTime
                    );
                } else {
                    TiedUpMod.LOGGER.info(
                        "[MaidAssignTaskGoal] {} ransom isPaid (paid={}/debt={}) but offline — will release on login",
                        prisonerId.toString().substring(0, 8),
                        ransom.getAmountPaid(),
                        ransom.getTotalDebt()
                    );
                }
                continue;
            }

            // Assign a task
            ServerPlayer prisoner = level
                .getServer()
                .getPlayerList()
                .getPlayer(prisonerId);
            if (prisoner == null) {
                TiedUpMod.LOGGER.debug(
                    "[MaidAssignTaskGoal] {} is IDLE but offline — skipping",
                    prisonerId.toString().substring(0, 8)
                );
                continue; // Offline
            }

            TiedUpMod.LOGGER.info(
                "[MaidAssignTaskGoal] {} ready for assignment (phase={}, ransom={}/{}, online=true)",
                prisonerId.toString().substring(0, 8),
                phase,
                ransom.getAmountPaid(),
                ransom.getTotalDebt()
            );
            assignTask(manager, prisoner, campId, currentTime);
        }
    }

    /**
     * Assign a labor task to a prisoner.
     */
    private void assignTask(
        PrisonerManager manager,
        ServerPlayer prisoner,
        UUID campId,
        long currentTime
    ) {
        UUID prisonerId = prisoner.getUUID();

        // Create a random task
        LaborTask task = createRandomTask(campId);

        // Assign via manager
        if (
            !manager.assignTask(prisonerId, task, maid.getUUID(), currentTime)
        ) {
            LaborRecord failLabor = manager.getLaborRecord(prisonerId);
            TiedUpMod.LOGGER.warn(
                "[MaidAssignTaskGoal] manager.assignTask FAILED for {} (phase={}, canAssign={})",
                prisonerId.toString().substring(0, 8),
                failLabor.getPhase(),
                failLabor.canAssignTask()
            );
            return; // Failed to assign
        }

        // Notify prisoner
        prisoner.sendSystemMessage(
            net.minecraft.network.chat.Component.translatable(
                "goal.tiedup.maid_assign.task_assigned", task.getDescription()
            ).withStyle(net.minecraft.ChatFormatting.YELLOW)
        );
        prisoner.sendSystemMessage(
            net.minecraft.network.chat.Component.translatable(
                "goal.tiedup.maid_assign.task_reward", task.getValue()
            ).withStyle(net.minecraft.ChatFormatting.GRAY)
        );

        TiedUpMod.LOGGER.info(
            "[MaidAssignTaskGoal] Assigned task '{}' to {}",
            task.getDescription(),
            prisoner.getName().getString()
        );
    }

    /**
     * Release a prisoner whose ransom is paid while they're idle in their cell.
     * Same logic as MaidReturnGoal.freePrisoner() but triggered from the background check.
     */
    private void releasePaidPrisoner(
        ServerLevel level,
        ServerPlayer prisoner,
        PrisonerManager manager,
        long currentTime
    ) {
        UUID prisonerId = prisoner.getUUID();

        // 1. Despawn guard if still alive
        LaborRecord labor = manager.getLaborRecord(prisonerId);
        UUID guardId = labor.getGuardId();
        if (guardId != null) {
            net.minecraft.world.entity.Entity guardEntity = level.getEntity(
                guardId
            );
            if (guardEntity != null) {
                guardEntity.discard();
            }
            labor.setGuardId(null);
        }

        // 2. Get cell ID BEFORE releasing (manager.release() clears cellId from the record)
        PrisonerRecord record = manager.getRecord(prisonerId);
        UUID cellId = record.getCellId();

        // 3. Teleport prisoner out of cell to maid's position
        net.minecraft.core.BlockPos maidPos = maid.blockPosition();
        prisoner.teleportTo(
            maidPos.getX() + 0.5,
            maidPos.getY(),
            maidPos.getZ() + 0.5
        );

        // 4. Release with grace period
        manager.release(prisonerId, currentTime, GRACE_PERIOD_TICKS);

        // 5. Remove from cell registry
        if (cellId != null) {
            CellRegistryV2.get(level).releasePrisoner(
                cellId,
                prisonerId,
                level.getServer()
            );
        }

        // 6. Clear collar registry
        com.tiedup.remake.state.CollarRegistry.get(level).unregisterWearer(
            prisonerId
        );

        // 7. Free kidnapped state and remove all restraints
        IBondageState cap = KidnappedHelper.getKidnappedState(prisoner);
        if (cap != null) {
            net.minecraft.world.item.ItemStack collar = cap.getEquipment(
                BodyRegionV2.NECK
            );
            if (!collar.isEmpty()) {
                com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.unequipFromRegion(
                    prisoner,
                    com.tiedup.remake.v2.BodyRegionV2.NECK,
                    true
                );
            }
            cap.untie(true);
            cap.free(false);
        }

        prisoner.sendSystemMessage(
            net.minecraft.network.chat.Component.translatable(
                "goal.tiedup.maid.debt_paid_free"
            ).withStyle(
                net.minecraft.ChatFormatting.GREEN,
                net.minecraft.ChatFormatting.BOLD
            )
        );

        TiedUpMod.LOGGER.info(
            "[MaidAssignTaskGoal] Released {} — ransom paid (debt satisfied while in cell)",
            prisoner.getName().getString()
        );
    }

    /**
     * Create a random labor task using the centralized task generator.
     */
    private LaborTask createRandomTask(UUID campId) {
        ServerLevel level = (maid.level() instanceof ServerLevel sl)
            ? sl
            : null;
        LaborTask task =
            com.tiedup.remake.labor.LaborTaskGenerator.generateRandom(level);
        task.setCampId(campId);
        return task;
    }

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