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

import com.tiedup.remake.cells.CellDataV2;
import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.dialogue.DialogueTriggerSystem;
import com.tiedup.remake.dialogue.EntityDialogueManager;
import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.personality.HomeType;
import com.tiedup.remake.personality.NpcCommand;
import com.tiedup.remake.personality.PersonalityState;
import java.util.EnumSet;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.player.Player;

/**
 * AI Goal: NPC behavior when IDLE command is active.
 *
 * <p>When inside a cell, NPCs exhibit varied idle behaviors:
 * resting at bed, kneeling, sitting, wandering within cell, or standing.
 * When outside a cell, stays in place (original behavior).</p>
 *
 * <p>Also handles idle dialogue and XP awards.</p>
 *
 * Personality System Living Jobs
 */
public class NpcIdleCommandGoal extends Goal {

    private final EntityDamsel npc;

    /** Minimum cooldown for idle dialogue (1 min) */
    private static final int IDLE_TALK_MIN = 1200;

    /** Maximum cooldown for idle dialogue (3 min) */
    private static final int IDLE_TALK_MAX = 3600;

    /** Ticks between XP awards (2 min) */
    private static final int XP_INTERVAL = 2400;

    private int idleTalkCooldown;
    private int xpTimer;

    // --- Cell idle behavior ---

    private enum CellIdleBehavior {
        REST_AT_BED,
        KNEEL,
        SIT,
        WANDER,
        STAND,
    }

    private CellIdleBehavior currentBehavior = CellIdleBehavior.STAND;
    private int behaviorTimer = 0;
    private int behaviorDuration = 0;
    private boolean inCell = false;

    @Nullable
    private BlockPos wanderTarget = null;

    public NpcIdleCommandGoal(EntityDamsel npc) {
        this.npc = npc;
        this.setFlags(EnumSet.of(Goal.Flag.MOVE));
    }

    @Override
    public boolean canUse() {
        if (npc.getActiveCommand() != NpcCommand.IDLE) {
            return false;
        }
        if (!npc.hasCollar()) {
            return false;
        }
        return true;
    }

    @Override
    public boolean canContinueToUse() {
        if (npc.getActiveCommand() != NpcCommand.IDLE) {
            return false;
        }
        if (!npc.hasCollar()) {
            return false;
        }
        return true;
    }

    @Override
    public void start() {
        this.idleTalkCooldown = IDLE_TALK_MIN / 2; // Initial delay shorter
        this.xpTimer = 0;
        npc.getNavigation().stop();

        // Detect if NPC is in a cell
        PersonalityState state = npc.getPersonalityState();
        this.inCell =
            state != null &&
            state.getCellId() != null &&
            state.getHomePos() != null &&
            NpcGoalHelper.isNearPos(npc, state.getHomePos(), 25.0); // 5 blocks
        if (inCell) {
            chooseBehavior();
        }
    }

    @Override
    public void stop() {
        resetPose();
        inCell = false;
        currentBehavior = CellIdleBehavior.STAND;
    }

    @Override
    public void tick() {
        if (inCell) {
            // Cell idle behavior timer
            behaviorTimer++;
            if (behaviorTimer >= behaviorDuration) {
                resetPose();
                chooseBehavior();
            }

            // If WANDER and arrived at destination, stop moving
            if (
                currentBehavior == CellIdleBehavior.WANDER &&
                wanderTarget != null
            ) {
                if (NpcGoalHelper.isNearPos(npc, wanderTarget, 4.0)) {
                    npc.getNavigation().stop();
                    wanderTarget = null;
                }
            }
        } else {
            // Outside cell: stay in place
            npc.getNavigation().stop();
        }

        // Award XP periodically for resting
        if (++this.xpTimer >= XP_INTERVAL) {
            this.xpTimer = 0;
            Player master = NpcGoalHelper.findCommandingPlayer(npc);
            if (master != null) {
            }
        }

        // Idle dialogue
        if (--this.idleTalkCooldown <= 0 && !npc.isGagged()) {
            if (npc.getRandom().nextFloat() < 0.005f) {
                speakIdleDialogue();
                this.idleTalkCooldown =
                    IDLE_TALK_MIN +
                    npc.getRandom().nextInt(IDLE_TALK_MAX - IDLE_TALK_MIN);
            }
        }
    }

    /**
     * Choose a random idle behavior for the NPC in their cell.
     * Weighted random: 25% bed rest, 20% kneel, 20% sit, 20% wander, 15% stand.
     * NPCs tied to a pole can only do stationary behaviors (kneel/sit/stand).
     */
    private void chooseBehavior() {
        PersonalityState state = npc.getPersonalityState();
        if (state == null) return;

        behaviorTimer = 0;
        boolean canMove = !npc.isTiedToPole();

        int roll = npc.getRandom().nextInt(100);

        if (
            roll < 25 &&
            canMove &&
            state.getHomeType() != HomeType.CELL &&
            state.getHomeType() != HomeType.NONE
        ) {
            // 25% - Rest at bed
            currentBehavior = CellIdleBehavior.REST_AT_BED;
            behaviorDuration = 600 + npc.getRandom().nextInt(1200); // 30-90s
            BlockPos bed = state.getHomePos();
            if (bed != null && !NpcGoalHelper.isNearPos(npc, bed, 4.0)) {
                npc
                    .getNavigation()
                    .moveTo(
                        bed.getX() + 0.5,
                        bed.getY(),
                        bed.getZ() + 0.5,
                        0.6
                    );
            }
            npc.setSitting(true);
        } else if (roll < 45 || (!canMove && roll < 55)) {
            // 20% - Kneel (expanded range if can't move)
            currentBehavior = CellIdleBehavior.KNEEL;
            behaviorDuration = 400 + npc.getRandom().nextInt(800); // 20-60s
            npc.setKneeling(true);
        } else if (roll < 65 || (!canMove && roll < 75)) {
            // 20% - Sit (expanded range if can't move)
            currentBehavior = CellIdleBehavior.SIT;
            behaviorDuration = 400 + npc.getRandom().nextInt(800); // 20-60s
            npc.setSitting(true);
        } else if (roll < 85 && canMove) {
            // 20% - Wander in cell
            currentBehavior = CellIdleBehavior.WANDER;
            behaviorDuration = 200 + npc.getRandom().nextInt(400); // 10-30s
            wanderToRandomInterior(state);
        } else {
            // 15% - Stand
            currentBehavior = CellIdleBehavior.STAND;
            behaviorDuration = 300 + npc.getRandom().nextInt(600); // 15-45s
        }
    }

    /**
     * Pick a random interior block in the cell and navigate there.
     */
    private void wanderToRandomInterior(PersonalityState state) {
        UUID cellUuid = state.getCellId();
        if (cellUuid == null) return;

        if (!(npc.level() instanceof ServerLevel serverLevel)) return;
        CellDataV2 cell = CellRegistryV2.get(serverLevel).getCell(cellUuid);
        if (cell == null) return;

        Set<BlockPos> interior = cell.getInteriorBlocks();
        if (interior.size() < 4) return; // Cell too small for wandering

        BlockPos[] blocks = interior.toArray(BlockPos[]::new);
        wanderTarget = blocks[npc.getRandom().nextInt(blocks.length)];
        npc
            .getNavigation()
            .moveTo(
                wanderTarget.getX() + 0.5,
                wanderTarget.getY(),
                wanderTarget.getZ() + 0.5,
                0.4
            );
    }

    /**
     * Reset pose (sitting/kneeling) and navigation.
     */
    private void resetPose() {
        npc.setSitting(false);
        npc.setKneeling(false);
        wanderTarget = null;
        npc.getNavigation().stop();
    }

    /**
     * Speak idle dialogue based on current state.
     * Priority: needs > mood > environment > generic idle
     */
    private void speakIdleDialogue() {
        Player player = NpcGoalHelper.findCommandingPlayer(npc);
        if (player == null) {
            player = npc.level().getNearestPlayer(npc, 16);
        }
        if (player == null) return;

        // Try proactive dialogue first (needs/mood)
        String dialogueId = DialogueTriggerSystem.selectProactiveDialogue(npc);

        // Try environment dialogue
        if (dialogueId == null || dialogueId.startsWith("idle.")) {
            String envDialogue =
                DialogueTriggerSystem.selectEnvironmentDialogue(npc);
            if (envDialogue != null && npc.getRandom().nextFloat() < 0.3f) {
                dialogueId = envDialogue;
            }
        }

        // Fallback to resting idle
        if (dialogueId == null) {
            dialogueId = "idle.resting";
        }

        EntityDialogueManager.talkByDialogueId(npc, player, dialogueId);
    }
}
