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

import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.items.ItemTaser;
import com.tiedup.remake.items.ModItems;
import java.util.EnumSet;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 * AI Goal: Kidnapper fights back when attacked, regardless of captive status.
 *
 * Unlike KidnapperFightBackGoal, this does NOT require hasCaptives().
 * This prevents the exploit where PROTECTED players attack with impunity
 * because the kidnapper has no captives and thus no self-defense.
 *
 * Behavior:
 * - Triggers when kidnapper is hurt by a non-master player
 * - Equips taser and pursues attacker for 10 seconds
 * - Does NOT attempt to capture — only melee retaliation
 */
public class KidnapperSelfDefenseGoal extends Goal {

    private final EntityKidnapper kidnapper;
    private LivingEntity attacker;
    private int aggressionTimer;

    /** Duration of aggression in ticks (10 seconds = 200 ticks) */
    private static final int AGGRESSION_DURATION = 200;

    /** Attack cooldown in ticks */
    private int attackCooldown = 0;

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

    @Override
    public boolean canUse() {
        // If kidnapper has captives, KidnapperFightBackGoal handles it
        if (
            kidnapper.hasCaptives() || kidnapper.isWaitingForJobToBeCompleted()
        ) {
            return false;
        }

        // Must have been attacked recently
        LivingEntity lastAttacker = kidnapper.getLastAttacker();
        if (lastAttacker == null || !(lastAttacker instanceof Player)) {
            return false;
        }

        // Attacker must not be the master
        if (kidnapper.isMaster((Player) lastAttacker)) {
            return false;
        }

        if (!lastAttacker.isAlive()) {
            return false;
        }

        this.attacker = lastAttacker;
        return true;
    }

    @Override
    public void start() {
        // Equip taser
        kidnapper.setItemInHand(
            InteractionHand.MAIN_HAND,
            new ItemStack(ModItems.TASER.get())
        );

        // Broadcast threatening dialogue
        kidnapper.talkToPlayersInRadius("You'll regret that!", 20);

        this.aggressionTimer = AGGRESSION_DURATION;
        this.attackCooldown = 0;
    }

    @Override
    public void tick() {
        aggressionTimer--;
        if (attackCooldown > 0) {
            attackCooldown--;
        }

        if (attacker != null && attacker.isAlive()) {
            // Look at attacker
            kidnapper.getLookControl().setLookAt(attacker);

            // Pursue
            kidnapper.getNavigation().moveTo(attacker, 1.3);

            // Attack if close enough and cooldown is ready
            if (kidnapper.distanceTo(attacker) < 2.0 && attackCooldown <= 0) {
                // Swing arm animation
                kidnapper.swing(InteractionHand.MAIN_HAND);

                // Attack using standard mob attack (uses ATTACK_DAMAGE attribute)
                boolean damaged = kidnapper.doHurtTarget(attacker);

                // Apply taser effects if damage was dealt
                if (damaged) {
                    ItemStack heldItem = kidnapper.getItemInHand(
                        InteractionHand.MAIN_HAND
                    );
                    if (heldItem.getItem() instanceof ItemTaser taserItem) {
                        taserItem.hurtEnemy(heldItem, attacker, kidnapper);
                    }
                }

                attackCooldown = 20; // 1 second cooldown
            }
        }
    }

    @Override
    public boolean canContinueToUse() {
        // Stop if timer expired
        if (aggressionTimer <= 0) return false;

        // Stop if attacker dead or gone
        if (attacker == null || !attacker.isAlive()) return false;

        // Stop if attacker too far
        if (kidnapper.distanceTo(attacker) > 30) return false;

        return true;
    }

    @Override
    public void stop() {
        // Unequip taser
        kidnapper.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY);
        kidnapper.getNavigation().stop();
        this.attacker = null;
        this.aggressionTimer = 0;
    }
}
