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

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.ai.kidnapper.KidnapperState;
import java.util.List;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import org.jetbrains.annotations.Nullable;

/**
 * KidnapperAlertManager - Manages alert system between kidnappers.
 *
 * Handles:
 * - Broadcasting alerts about escaped captives to nearby kidnappers
 * - Receiving alert broadcasts from other kidnappers
 * - Alert cooldown to prevent spam (5 second cooldown = 100 ticks)
 * - Alert target tracking for ALERT state
 *
 * <p><b>Low complexity</b> - Simple broadcast/receive pattern with cooldown.</p>
 */
public class KidnapperAlertManager {

    // CONSTANTS

    /** Cooldown duration before receiving another alert (5 seconds = 100 ticks) */
    private static final int ALERT_COOLDOWN_DURATION = 100;

    /** Broadcast radius for alerts (50 blocks horizontal, 20 blocks vertical) */
    private static final double BROADCAST_RADIUS_HORIZONTAL = 50.0;
    private static final double BROADCAST_RADIUS_VERTICAL = 20.0;

    // FIELDS

    /** Host callbacks */
    private final IAlertHost host;

    /** Entity reference (needed for getEntitiesOfClass filtering) */
    private final EntityKidnapper entity;

    /** Target entity being searched for during ALERT state */
    @Nullable
    private LivingEntity alertTarget;

    /** Cooldown before receiving another alert broadcast (in ticks) */
    private int alertCooldown = 0;

    // CONSTRUCTOR

    public KidnapperAlertManager(EntityKidnapper entity, IAlertHost host) {
        this.entity = entity;
        this.host = host;
    }

    // ALERT TARGET TRACKING

    /**
     * Get the current alert target.
     *
     * @return The target entity being searched for, or null if none
     */
    @Nullable
    public LivingEntity getAlertTarget() {
        return this.alertTarget;
    }

    /**
     * Set the alert target.
     *
     * @param target The target to search for
     */
    public void setAlertTarget(@Nullable LivingEntity target) {
        this.alertTarget = target;
    }

    // ALERT BROADCASTING

    /**
     * Broadcast an alert about an escaped captive to nearby kidnappers.
     * Searches for kidnappers within 50 blocks horizontally and 20 blocks vertically.
     * Only kidnappers in states that can receive alerts will be notified.
     *
     * @param escapee The entity that escaped
     */
    public void broadcastAlert(LivingEntity escapee) {
        if (!(host.level() instanceof ServerLevel serverLevel)) {
            return;
        }
        if (escapee == null) {
            return;
        }

        // Find nearby kidnappers that can receive alerts
        List<EntityKidnapper> nearby = serverLevel.getEntitiesOfClass(
            EntityKidnapper.class,
            host
                .getBoundingBox()
                .inflate(
                    BROADCAST_RADIUS_HORIZONTAL,
                    BROADCAST_RADIUS_VERTICAL,
                    BROADCAST_RADIUS_HORIZONTAL
                ),
            k -> k != this.entity && k.getCurrentState().canReceiveAlerts()
        );

        TiedUpMod.LOGGER.info(
            "[KidnapperAlertManager] {} broadcasting alert about {} to {} kidnappers",
            host.getNpcName(),
            escapee.getName().getString(),
            nearby.size()
        );

        // Send alert to each nearby kidnapper
        for (EntityKidnapper other : nearby) {
            other.receiveAlertBroadcast(escapee, this.entity);
        }
    }

    // ALERT RECEIVING

    /**
     * Receive an alert broadcast from another kidnapper.
     * Ignores alerts if:
     * - On cooldown (prevents spam)
     * - Already has captives
     * - Is tied up
     *
     * If accepted, sets alert target and switches to ALERT state.
     *
     * @param escapee The entity that escaped
     * @param source The kidnapper that sent the alert
     */
    public void receiveAlertBroadcast(
        LivingEntity escapee,
        EntityKidnapper source
    ) {
        // On cooldown, ignore alert
        if (this.alertCooldown > 0) {
            return;
        }

        // Don't respond if we already have a captive or are tied up
        if (host.hasCaptives() || host.isTiedUp()) {
            return;
        }

        // Set alert target and state
        this.setAlertTarget(escapee);
        host.setCurrentState(KidnapperState.ALERT);
        this.alertCooldown = ALERT_COOLDOWN_DURATION; // 5 second cooldown

        TiedUpMod.LOGGER.info(
            "[KidnapperAlertManager] {} received alert from {} about {}",
            host.getNpcName(),
            source.getNpcName(),
            escapee.getName().getString()
        );
    }

    // TICK PROCESSING

    /**
     * Called each tick to update alert system state.
     * Decrements the alert cooldown timer.
     */
    public void tick() {
        // Decrement alert cooldown
        if (this.alertCooldown > 0) {
            this.alertCooldown--;
        }
    }

    // NBT SERIALIZATION

    /**
     * Save alert data to NBT.
     * Note: alertTarget is transient and not saved (recalculated on load).
     * Note: alertCooldown is transient and not saved (resets on load).
     */
    public void saveToNBT(net.minecraft.nbt.CompoundTag tag) {
        // Alert system uses only transient runtime state
        // No persistent data needs to be saved
    }

    /**
     * Load alert data from NBT.
     * Note: alertTarget is transient and not loaded.
     * Note: alertCooldown is transient and not loaded.
     */
    public void loadFromNBT(net.minecraft.nbt.CompoundTag tag) {
        // Alert system uses only transient runtime state
        // No persistent data needs to be loaded
    }
}
