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

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaid;
import com.tiedup.remake.entities.EntitySlaveTrader;
import java.util.EnumSet;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Container;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;

/**
 * AI Goal for EntityMaid to collect ransom/items from a location.
 *
 * Behavior:
 * - Active when state is COLLECTING
 * - Walks to the collectTarget position
 * - Collects items from containers or ground
 * - Returns to trader with collected items
 */
public class MaidCollectRansomGoal extends Goal {

    private final EntityMaid maid;

    /** Distance at which collection starts */
    private static final double COLLECT_DISTANCE = 2.0;

    /** Distance at which to consider "returned to trader" */
    private static final double RETURN_DISTANCE = 3.0;

    /** Maximum ticks before giving up */
    private static final int MAX_COLLECT_TICKS = 1200; // 60 seconds

    /** Radius to search for items on ground */
    private static final double ITEM_SEARCH_RADIUS = 3.0;

    /** Ticks spent on collection task */
    private int collectTicks = 0;

    /** Whether items have been collected */
    private boolean itemsCollected = false;

    /** Cached trader for return journey */
    private EntitySlaveTrader cachedTrader;

    public MaidCollectRansomGoal(EntityMaid maid) {
        this.maid = maid;
        this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
    }

    @Override
    public boolean canUse() {
        // Must be in COLLECTING state
        if (maid.getMaidState() != MaidState.COLLECTING) {
            return false;
        }

        // Must not be tied up
        if (maid.isTiedUp()) {
            return false;
        }

        // Must have an assigned master trader
        if (maid.getMasterTraderUUID() == null) {
            return false;
        }

        // Must have a collect target
        BlockPos target = maid.getCollectTarget();
        if (target == null) {
            return false;
        }

        // Must be on server
        if (!(maid.level() instanceof ServerLevel)) {
            return false;
        }

        // Cache the trader for return journey
        cachedTrader = maid.getMasterTrader();

        return true;
    }

    @Override
    public boolean canContinueToUse() {
        if (maid.getMaidState() != MaidState.COLLECTING) {
            return false;
        }

        if (maid.isTiedUp()) {
            return false;
        }

        // Timeout check
        if (collectTicks > MAX_COLLECT_TICKS) {
            TiedUpMod.LOGGER.warn(
                "[MaidCollectRansomGoal] {} collection timed out",
                maid.getNpcName()
            );
            maid.completeTask();
            return false;
        }

        return true;
    }

    @Override
    public void start() {
        collectTicks = 0;
        itemsCollected = false;

        BlockPos target = maid.getCollectTarget();
        TiedUpMod.LOGGER.info(
            "[MaidCollectRansomGoal] {} starting collection at {}",
            maid.getNpcName(),
            target != null ? target.toShortString() : "unknown"
        );
    }

    @Override
    public void stop() {
        collectTicks = 0;
        itemsCollected = false;
        cachedTrader = null;
        maid.getNavigation().stop();
        maid.setMaidState(MaidState.IDLE);
    }

    @Override
    public void tick() {
        BlockPos target = maid.getCollectTarget();
        if (target == null) {
            return;
        }

        collectTicks++;

        if (!itemsCollected) {
            tickCollectPhase(target);
        } else {
            tickReturnPhase();
        }
    }

    /**
     */
    private void tickCollectPhase(BlockPos target) {
        // Look at target
        maid
            .getLookControl()
            .setLookAt(
                target.getX() + 0.5,
                target.getY() + 0.5,
                target.getZ() + 0.5,
                30.0F,
                30.0F
            );

        double distSq = maid.distanceToSqr(Vec3.atCenterOf(target));

        if (distSq < COLLECT_DISTANCE * COLLECT_DISTANCE) {
            // Close enough - collect items
            collectItems(target);
            itemsCollected = true;

            TiedUpMod.LOGGER.info(
                "[MaidCollectRansomGoal] {} collected items at {}",
                maid.getNpcName(),
                target.toShortString()
            );
        } else {
            // Move towards target
            if (collectTicks % 10 == 0) {
                maid
                    .getNavigation()
                    .moveTo(
                        target.getX() + 0.5,
                        target.getY(),
                        target.getZ() + 0.5,
                        1.2
                    );
            }
        }
    }

    /**
     */
    private void tickReturnPhase() {
        // Refresh trader reference if null
        if (cachedTrader == null || !cachedTrader.isAlive()) {
            cachedTrader = maid.getMasterTrader();
        }

        if (cachedTrader == null) {
            // No trader to return to - just complete
            TiedUpMod.LOGGER.warn(
                "[MaidCollectRansomGoal] {} has no trader to return to",
                maid.getNpcName()
            );
            maid.completeTask();
            return;
        }

        // Look at trader
        maid.getLookControl().setLookAt(cachedTrader, 30.0F, 30.0F);

        double distSq = maid.distanceToSqr(cachedTrader);

        if (distSq < RETURN_DISTANCE * RETURN_DISTANCE) {
            // Returned to trader - complete task
            TiedUpMod.LOGGER.info(
                "[MaidCollectRansomGoal] {} returned to trader {}",
                maid.getNpcName(),
                cachedTrader.getNpcName()
            );
            maid.completeTask();
        } else {
            // Move towards trader
            if (collectTicks % 10 == 0) {
                maid.getNavigation().moveTo(cachedTrader, 1.0);
            }
        }
    }

    /**
     * Collect items from the target location.
     * Checks containers first, then ground items.
     */
    private void collectItems(BlockPos target) {
        if (!(maid.level() instanceof ServerLevel serverLevel)) {
            return;
        }

        // Try to collect from container first
        BlockEntity blockEntity = serverLevel.getBlockEntity(target);
        if (blockEntity instanceof Container container) {
            collectFromContainer(container);
            return;
        }

        // Otherwise, collect items from ground
        collectFromGround(serverLevel, target);
    }

    /**
     * Collect items from a container.
     */
    private void collectFromContainer(Container container) {
        int collected = 0;

        for (int i = 0; i < container.getContainerSize(); i++) {
            ItemStack stack = container.getItem(i);
            if (!stack.isEmpty()) {
                // In a full implementation, we'd transfer to maid's inventory
                // For now, just remove from container (simulating collection)
                container.setItem(i, ItemStack.EMPTY);
                collected++;

                TiedUpMod.LOGGER.debug(
                    "[MaidCollectRansomGoal] Collected {} from container",
                    stack.getDisplayName().getString()
                );
            }
        }

        if (collected > 0) {
            container.setChanged();
        }
    }

    /**
     * Collect items from the ground near the target.
     */
    private void collectFromGround(ServerLevel level, BlockPos target) {
        AABB searchBox = new AABB(target).inflate(ITEM_SEARCH_RADIUS);
        List<ItemEntity> items = level.getEntitiesOfClass(
            ItemEntity.class,
            searchBox
        );

        for (ItemEntity itemEntity : items) {
            if (itemEntity.isAlive()) {
                ItemStack stack = itemEntity.getItem();

                TiedUpMod.LOGGER.debug(
                    "[MaidCollectRansomGoal] Collected {} from ground",
                    stack.getDisplayName().getString()
                );

                // Remove the item from the world
                itemEntity.discard();
            }
        }
    }
}
