package com.tiedup.remake.entities.ai.kidnapper;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.EntityDialogueManager.DialogueCategory;
import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import java.util.EnumSet;
import java.util.UUID;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;

/**
 * AI Goal for EntityKidnapper to recapture escaped captives.
 *
 * Phase: Kidnapper Revamp - Escape System
 *
 * This goal:
 * 1. Activates when the kidnapper has an escaped target remembered
 * 2. Pursues the escaped captive
 * 3. Re-captures them if close enough
 * 4. Has higher priority than BringToCellGoal to prioritize recapture
 */
public class KidnapperRecaptureGoal extends Goal {

    private final EntityKidnapper kidnapper;
    private final double speedModifier;

    /** Maximum distance to pursue escaped target */
    private static final double MAX_PURSUIT_DISTANCE = 50.0;

    /** Distance at which recapture can occur */
    private static final double RECAPTURE_DISTANCE = 2.0;

    /** Dialogue radius */
    private static final int DIALOGUE_RADIUS = 20;

    /** Current target being pursued */
    private LivingEntity target;

    /** Ticks spent pursuing */
    private int pursuitTicks;

    /** Max pursuit time (30 seconds) */
    private static final int MAX_PURSUIT_TICKS = 600;

    public KidnapperRecaptureGoal(EntityKidnapper kidnapper) {
        this(kidnapper, 1.3); // Faster than normal pursuit
    }

    public KidnapperRecaptureGoal(
        EntityKidnapper kidnapper,
        double speedModifier
    ) {
        this.kidnapper = kidnapper;
        this.speedModifier = speedModifier;
        this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
    }

    @Override
    public boolean canUse() {
        // Must have an escaped target
        LivingEntity escaped = this.kidnapper.getEscapedTarget();
        if (escaped == null) {
            return false;
        }

        // Must not be tied up
        if (this.kidnapper.isTiedUp()) {
            return false;
        }

        // Must not already have a captive
        if (this.kidnapper.hasCaptives()) {
            return false;
        }

        // Target must be within range
        if (this.kidnapper.distanceTo(escaped) > MAX_PURSUIT_DISTANCE) {
            this.kidnapper.clearEscapedTarget();
            return false;
        }

        // Target must not be captured by someone else
        IBondageState state = KidnappedHelper.getKidnappedState(escaped);
        if (state != null && state.isCaptive()) {
            this.kidnapper.clearEscapedTarget();
            return false;
        }

        this.target = escaped;
        return true;
    }

    @Override
    public boolean canContinueToUse() {
        if (this.target == null || !this.target.isAlive()) {
            return false;
        }

        if (this.kidnapper.isTiedUp()) {
            return false;
        }

        // Stop if we now have a captive (recapture successful)
        if (this.kidnapper.hasCaptives()) {
            return false;
        }

        // Stop if pursuit time exceeded
        if (this.pursuitTicks > MAX_PURSUIT_TICKS) {
            return false;
        }

        // Stop if target is too far
        if (this.kidnapper.distanceTo(this.target) > MAX_PURSUIT_DISTANCE) {
            return false;
        }

        // Stop if target was captured by someone else
        IBondageState state = KidnappedHelper.getKidnappedState(this.target);
        if (state != null && state.isCaptive()) {
            return false;
        }

        return true;
    }

    @Override
    public void start() {
        this.pursuitTicks = 0;

        // Set AI state to CAPTURE during pursuit (will switch to PUNISH after recapture)
        this.kidnapper.setCurrentState(KidnapperState.CAPTURE);

        // Announce pursuit
        this.kidnapper.talkToPlayersInRadius(
            DialogueCategory.CAPTURE_CHASE,
            DIALOGUE_RADIUS
        );

        TiedUpMod.LOGGER.info(
            "[KidnapperRecaptureGoal] {} pursuing escaped captive {} (state: CAPTURE)",
            this.kidnapper.getNpcName(),
            this.target.getName().getString()
        );
    }

    @Override
    public void stop() {
        // Clear escaped target if we've given up
        if (!this.kidnapper.hasCaptives()) {
            this.kidnapper.clearEscapedTarget();
            // Reset AI state to IDLE if we failed
            this.kidnapper.setCurrentState(KidnapperState.IDLE);
        }
        // Note: If we succeeded, state will be PUNISH (set in attemptRecapture)

        this.target = null;
        this.pursuitTicks = 0;
        this.kidnapper.getNavigation().stop();
    }

    @Override
    public void tick() {
        if (this.target == null) {
            return;
        }

        this.pursuitTicks++;

        // Always look at target
        this.kidnapper.getLookControl().setLookAt(this.target, 30.0F, 30.0F);

        double distance = this.kidnapper.distanceTo(this.target);

        // Recalculate path periodically
        if (this.pursuitTicks % 10 == 0) {
            this.kidnapper.getNavigation().moveTo(
                this.target,
                this.speedModifier
            );
        }

        // Attempt recapture if close enough
        if (distance <= RECAPTURE_DISTANCE) {
            attemptRecapture();
        }
    }

    /**
     * Attempt to recapture the escaped target.
     */
    private void attemptRecapture() {
        IBondageState state = KidnappedHelper.getKidnappedState(this.target);
        if (state == null) {
            return;
        }

        // Check if target can be recaptured
        // They must still be tied up for quick recapture
        if (!state.isTiedUp()) {
            // Not tied anymore - switch to normal capture
            this.kidnapper.setTarget(this.target);
            this.kidnapper.clearEscapedTarget();
            return;
        }

        // Quick recapture via PrisonerService (atomic: PrisonerManager + leash)
        boolean recaptured = false;
        if (
            this.kidnapper.level() instanceof
                net.minecraft.server.level.ServerLevel serverLevel
        ) {
            recaptured =
                com.tiedup.remake.prison.service.PrisonerService.get().capture(
                    serverLevel,
                    this.target,
                    this.kidnapper
                );
        }
        if (recaptured) {
            // Set state to PUNISH - KidnapperPunishGoal will handle punishment
            this.kidnapper.setCurrentState(KidnapperState.PUNISH);

            // Announce success
            this.kidnapper.talkToPlayersInRadius(
                DialogueCategory.CAPTURE_ENSLAVED,
                DIALOGUE_RADIUS
            );

            TiedUpMod.LOGGER.info(
                "[KidnapperRecaptureGoal] {} recaptured {} (state: PUNISH)",
                this.kidnapper.getNpcName(),
                this.target.getName().getString()
            );

            // Clear escaped target on success
            this.kidnapper.clearEscapedTarget();
        }
    }
}
