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

import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.personality.NpcCommand;
import com.tiedup.remake.personality.PersonalityState;
import java.util.EnumSet;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.ai.goal.Goal;

/**
 * AI Goal for GO_HOME command.
 * Makes NPC walk to their assigned home position.
 *
 * <p>Behavior:
 * <ul>
 *   <li>Walks to home position</li>
 *   <li>Stays there for 2 seconds</li>
 *   <li>Switches to IDLE command near home</li>
 *   <li>Cancels if no home is assigned</li>
 * </ul>
 */
public class NpcGoHomeGoal extends Goal {

    private final EntityDamsel npc;
    private BlockPos targetPos;
    private BlockPos actualHomePos;
    private int ticksAtHome;

    /** Distance considered "arrived" at home */
    private static final int ARRIVAL_DISTANCE = 2;

    /** Ticks to stay at home before completing (2 seconds) */
    private static final int COMPLETION_TICKS = 40;

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

    @Override
    public boolean canUse() {
        PersonalityState state = npc.getPersonalityState();
        if (state == null) return false;

        // Check if GO_HOME command is active
        if (state.getActiveCommand() != NpcCommand.GO_HOME) {
            return false;
        }

        // Check if NPC has a home
        if (!state.hasHome()) {
            // No home - cancel command
            state.clearCommand();
            return false;
        }

        this.actualHomePos = state.getHomePos();
        this.targetPos = NpcGoalHelper.getHomeNavigationTarget(npc);
        return true;
    }

    @Override
    public boolean canContinueToUse() {
        PersonalityState state = npc.getPersonalityState();
        if (state == null) return false;
        return state.getActiveCommand() == NpcCommand.GO_HOME;
    }

    @Override
    public void start() {
        this.ticksAtHome = 0;
        if (targetPos != null) {
            npc
                .getNavigation()
                .moveTo(
                    targetPos.getX() + 0.5,
                    targetPos.getY(),
                    targetPos.getZ() + 0.5,
                    1.0
                );
        }
    }

    @Override
    public void tick() {
        if (targetPos == null) return;

        // Check if arrived
        double distance = npc.distanceToSqr(
            targetPos.getX() + 0.5,
            targetPos.getY(),
            targetPos.getZ() + 0.5
        );

        if (distance < ARRIVAL_DISTANCE * ARRIVAL_DISTANCE) {
            ticksAtHome++;
            npc.getNavigation().stop();

            // If we navigated to deliveryPoint (exterior), teleport to homePos (interior)
            if (
                actualHomePos != null &&
                !targetPos.equals(actualHomePos) &&
                ticksAtHome == 1
            ) {
                NpcGoalHelper.teleportTo(npc, actualHomePos);
            }

            // Complete after staying at home
            if (ticksAtHome >= COMPLETION_TICKS) {
                PersonalityState state = npc.getPersonalityState();
                if (state != null) {
                    state.clearCommand();
                    // Switch to IDLE near home
                    state.setActiveCommand(
                        NpcCommand.IDLE,
                        null,
                        actualHomePos
                    );
                }
            }
        } else {
            // Not there yet, keep moving
            ticksAtHome = 0;
            if (npc.getNavigation().isDone()) {
                npc
                    .getNavigation()
                    .moveTo(
                        targetPos.getX() + 0.5,
                        targetPos.getY(),
                        targetPos.getZ() + 0.5,
                        1.0
                    );
            }
        }
    }

    @Override
    public void stop() {
        NpcGoalHelper.ensureOutsideCell(npc);
        npc.getNavigation().stop();
    }
}
