package com.tiedup.remake.events.interaction;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.conversation.ConversationManager;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.conversation.PacketEndConversationS2C;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

/**
 * Server tick handler for dialogue and conversation system maintenance.
 *
 *
 * Handles:
 * - Cleanup of stale/abandoned conversations
 * - Distance checks for active conversations
 * - Entity validity checks (NPC died, etc.)
 */
@Mod.EventBusSubscriber(
    modid = TiedUpMod.MOD_ID,
    bus = Mod.EventBusSubscriber.Bus.FORGE
)
public class DialogueTickHandler {

    /**
     * How often to run cleanup (in ticks).
     * 1200 ticks = 1 minute
     */
    private static final int CLEANUP_INTERVAL = 1200;

    /**
     * How often to check active conversations (in ticks).
     * 20 ticks = 1 second
     */
    private static final int CHECK_INTERVAL = 20;

    /**
     * Maximum distance for conversation before auto-ending.
     */
    private static final double MAX_CONVERSATION_DISTANCE = 8.0;

    /**
     * Handle server tick events for dialogue system maintenance.
     */
    @SubscribeEvent
    public static void onServerTick(TickEvent.ServerTickEvent event) {
        if (event.phase != TickEvent.Phase.END) return;

        long currentTick = event.getServer().getTickCount();

        // Check active conversations every second
        if (currentTick % CHECK_INTERVAL == 0) {
            checkActiveConversations(event.getServer());
        }

        // Cleanup stale conversations every minute
        if (currentTick % CLEANUP_INTERVAL == 0) {
            ConversationManager.cleanupStaleConversations();
        }
    }

    /**
     * Check all active conversations for validity.
     * Ends conversations where player/NPC is too far, dead, or disconnected.
     */
    private static void checkActiveConversations(
        net.minecraft.server.MinecraftServer server
    ) {
        List<ServerPlayer> playersToEnd = new ArrayList<>();

        for (ServerPlayer player : server.getPlayerList().getPlayers()) {
            ConversationManager.ConversationState state =
                ConversationManager.getConversationState(player);
            if (state == null) continue;

            UUID speakerId = state.getSpeakerEntityId();
            boolean shouldEnd = false;
            int entityId = -1;

            // O(1) lookup: get the specific ServerLevel, then getEntity by UUID
            ServerLevel speakerLevel = server.getLevel(
                state.getSpeakerDimension()
            );
            Entity speakerEntity =
                speakerLevel != null ? speakerLevel.getEntity(speakerId) : null;

            if (speakerEntity == null) {
                // Entity no longer exists
                shouldEnd = true;
                TiedUpMod.LOGGER.debug(
                    "[DialogueTickHandler] Ending conversation: NPC no longer exists"
                );
            } else if (!speakerEntity.isAlive()) {
                // Entity died
                shouldEnd = true;
                entityId = speakerEntity.getId();
                TiedUpMod.LOGGER.debug(
                    "[DialogueTickHandler] Ending conversation: NPC died"
                );
            } else if (
                speakerEntity.distanceTo(player) > MAX_CONVERSATION_DISTANCE
            ) {
                // Player moved too far
                shouldEnd = true;
                entityId = speakerEntity.getId();
                TiedUpMod.LOGGER.debug(
                    "[DialogueTickHandler] Ending conversation: Player too far ({})",
                    speakerEntity.distanceTo(player)
                );
            }

            if (shouldEnd) {
                playersToEnd.add(player);
                // Send packet to close client GUI
                if (entityId != -1) {
                    ModNetwork.sendToPlayer(
                        new PacketEndConversationS2C(entityId),
                        player
                    );
                }
            }
        }

        // End conversations outside the iteration
        for (ServerPlayer player : playersToEnd) {
            ConversationManager.endConversation(player);
        }
    }
}
