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 java.util.List;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.animal.Sheep;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;

/**
 * AI Goal: NPC shears sheep in a work zone.
 *
 * <p>Requires shears in NPC's main hand.</p>
 * <p>Work flow:</p>
 * <ul>
 *   <li>Find un-sheared sheep in zone</li>
 *   <li>Move to sheep</li>
 *   <li>Shear sheep (if holding shears)</li>
 *   <li>Collect wool into inventory</li>
 *   <li>Repeat</li>
 * </ul>
 */
public class NpcShearCommandGoal extends Goal {

    private final EntityDamsel npc;
    private final double speedModifier;

    private static final double WORK_RADIUS = 16.0;
    private static final double SHEAR_DISTANCE = 2.0;
    private static final int SHEAR_COOLDOWN = 40; // 2 seconds

    /** Rest drain intensity for shearing (medium work) */
    private static final float WORK_INTENSITY = 1.0f;

    private enum ShearPhase {
        SEARCHING,
        MOVING,
        SHEARING,
        IDLE,
    }

    private ShearPhase phase;

    @Nullable
    private BlockPos workCenter;

    @Nullable
    private Sheep targetSheep;

    @Nullable
    private Player master;

    private int pathRecalcTimer;
    private int actionTimer;
    private int idleTimer;

    public NpcShearCommandGoal(EntityDamsel npc, double speedModifier) {
        this.npc = npc;
        this.speedModifier = speedModifier;
        this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
    }

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

        this.master = NpcGoalHelper.findCommandingPlayer(npc);
        return this.master != null;
    }

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

    @Override
    public void start() {
        NpcGoalHelper.ensureOutsideCell(npc);
        var state = npc.getPersonalityState();
        if (state != null && state.getCommandTarget() != null) {
            this.workCenter = state.getCommandTarget();
        } else {
            // Use current position as work center
            this.workCenter = npc.blockPosition();
        }

        this.phase = ShearPhase.SEARCHING;
        this.pathRecalcTimer = 0;
        this.actionTimer = 0;
        this.idleTimer = 0;
        this.targetSheep = null;
    }

    @Override
    public void stop() {
        this.workCenter = null;
        this.targetSheep = null;
        this.master = null;
        npc.getNavigation().stop();
    }

    @Override
    public void tick() {
        // Check if holding shears
        ItemStack mainHand = npc.getMainHandItem();
        if (!mainHand.is(Items.SHEARS)) {
            // No shears, just idle
            this.phase = ShearPhase.IDLE;
            this.idleTimer++;
            if (this.idleTimer > 200) {
                // 10 seconds without shears
                // Could trigger dialogue about needing shears
                this.idleTimer = 0;
            }
            return;
        }

        switch (this.phase) {
            case SEARCHING -> tickSearching();
            case MOVING -> tickMoving();
            case SHEARING -> tickShearing();
            case IDLE -> tickIdle();
        }
    }

    private void tickSearching() {
        if (workCenter == null) {
            this.phase = ShearPhase.IDLE;
            return;
        }

        // Find un-sheared sheep in work zone
        Level level = npc.level();
        List<Sheep> sheepList = level.getEntitiesOfClass(
            Sheep.class,
            npc.getBoundingBox().inflate(WORK_RADIUS),
            sheep -> !sheep.isSheared() && sheep.isAlive()
        );

        if (sheepList.isEmpty()) {
            this.phase = ShearPhase.IDLE;
            this.idleTimer = 0;
            return;
        }

        // Find closest sheep
        Sheep closest = null;
        double closestDist = Double.MAX_VALUE;
        for (Sheep sheep : sheepList) {
            double dist = npc.distanceToSqr(sheep);
            if (dist < closestDist) {
                closestDist = dist;
                closest = sheep;
            }
        }

        this.targetSheep = closest;
        this.phase = ShearPhase.MOVING;
        this.pathRecalcTimer = 0;
    }

    private void tickMoving() {
        if (
            targetSheep == null ||
            !targetSheep.isAlive() ||
            targetSheep.isSheared()
        ) {
            this.phase = ShearPhase.SEARCHING;
            return;
        }

        // Move towards sheep
        if (--this.pathRecalcTimer <= 0) {
            this.pathRecalcTimer = 10;
            npc.getNavigation().moveTo(targetSheep, speedModifier);
        }

        // Look at sheep
        npc.getLookControl().setLookAt(targetSheep, 30.0f, 30.0f);

        // Check if close enough
        double dist = npc.distanceToSqr(targetSheep);
        if (dist <= SHEAR_DISTANCE * SHEAR_DISTANCE) {
            npc.getNavigation().stop();
            this.phase = ShearPhase.SHEARING;
            this.actionTimer = SHEAR_COOLDOWN;
        }
    }

    private void tickShearing() {
        if (
            targetSheep == null ||
            !targetSheep.isAlive() ||
            targetSheep.isSheared()
        ) {
            this.phase = ShearPhase.SEARCHING;
            return;
        }

        // Look at sheep while shearing
        npc.getLookControl().setLookAt(targetSheep, 30.0f, 30.0f);

        if (--this.actionTimer > 0) {
            return; // Still shearing animation
        }

        // Perform shear
        Level level = npc.level();
        ItemStack shears = npc.getMainHandItem();

        if (shears.is(Items.SHEARS) && !targetSheep.isSheared()) {
            // Shear the sheep
            targetSheep.shear(SoundSource.NEUTRAL);

            // Apply yield bonus from experience
            float yieldMult = NpcGoalHelper.getJobYieldMultiplier(
                npc,
                NpcCommand.SHEAR
            );
            if (
                yieldMult > 1.0f &&
                npc.getRandom().nextFloat() < (yieldMult - 1.0f)
            ) {
                // Bonus wool - drop extra
                npc.spawnAtLocation(
                    new ItemStack(net.minecraft.world.item.Items.WHITE_WOOL, 1)
                );
            }

            // Damage shears
            shears.hurtAndBreak(1, npc, entity -> {
                // Shears broke
            });

            // Play sound
            level.playSound(
                null,
                npc.getX(),
                npc.getY(),
                npc.getZ(),
                SoundEvents.SHEEP_SHEAR,
                SoundSource.NEUTRAL,
                1.0f,
                1.0f
            );

            // Award XP and experience
            NpcGoalHelper.incrementJobExperience(npc, NpcCommand.SHEAR);
            if (master != null) {
            }

            // Drain rest from work
            PersonalityState personalityState = npc.getPersonalityState();
            if (personalityState != null) {
                personalityState.getNeeds().drainFromWork(WORK_INTENSITY);
            }
        }

        this.targetSheep = null;
        this.phase = ShearPhase.SEARCHING;
    }

    private void tickIdle() {
        this.idleTimer++;

        // Every 3 seconds, search again
        if (this.idleTimer >= 60) {
            this.idleTimer = 0;
            this.phase = ShearPhase.SEARCHING;
        }
    }
}
