/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.core.compat.maid.barin;

import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.behavior.BlockPosTracker;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.schedule.Activity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
import top.r3944realms.eroticdungeongame.content.util.FurnitureHelper;
import top.r3944realms.eroticdungeongame.core.compat.maid.bauble.DungeonFilterBauble;
import top.r3944realms.eroticdungeongame.core.compat.maid.extra.ChatBabbles;
import top.r3944realms.lib39.util.IUniPosOwner;
import top.r3944realms.superleadrope.api.SuperLeadRopeApi;
import top.r3944realms.superleadrope.api.type.util.ILeashHelper;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class LeadTargetPlayerToDevice extends MaidCheckRateTask implements IUniPosOwner {
    private static final int MAX_DELAY_TIME = 10;
    private static final int SEARCH_RADIUS = 10;
    private static final int BIND_RADIUS = 2;
    private int costToFinishUseDevice = 0;
    private List<Player> players = Lists.newArrayList();
    private DungeonFilterBauble currentBauble = null;
    private BlockPos devicePos = null;

    public LeadTargetPlayerToDevice() {
        super(
                ImmutableMap.of()
        );
        this.setMaxCheckRate(MAX_DELAY_TIME);
    }

    @Override
    protected boolean checkExtraStartConditions(@NotNull ServerLevel level, @NotNull EntityMaid maid) {
        if (!super.checkExtraStartConditions(level, maid)) {
            return false;
        }

        if (maid.getScheduleDetail() != Activity.WORK) {
            return false;
        }

        if (!maid.canBrainMoving()) {
            return false;
        }

        Optional<DungeonFilterBauble> baubleOpt = DungeonFilterBauble.getFirstFilterBaubleOpt(maid);
        if (baubleOpt.isEmpty()) {
            return false;
        }

        currentBauble = baubleOpt.get();
        // === 从拴绳中获取玩家目标 ===
        ILeashHelper.IHolder holderHelper = SuperLeadRopeApi.getLeashHelper().getHolderHelper(maid);

        if (holderHelper.getAllLeashedEntities().isEmpty()) {
            return false;
        }
        // 检查设备位置
        if (currentBauble.workPos == null) {
            return false;
        }

        for (Entity entity : holderHelper.getAllLeashedEntities()) {
            if (entity instanceof Player) {
                players.add((Player) entity);
            }
        }

        Optional<BlockPos> posOpt = findNearestVaildSeatBlockEntity(level, maid);
        if (posOpt.isEmpty()) {
            if (devicePos != null) {
                unLock(level, devicePos);
                devicePos = null;
            }
            releaseAllLeashPlayer(holderHelper);
            maid.getChatBubbleManager().addChatBubble(ChatBabbles.createTextChatBubbleData(100, ChatBabbles.getRandomBabbleComponent("no_vaild_device", maid)));
            return false;
        }
        if (devicePos != posOpt.get() && !posOpt.get().equals(devicePos)) {
            if (devicePos != null) {
                unLock(level, devicePos);
            }
            devicePos = posOpt.get();
            if(!tryLock(level, devicePos)) {
                devicePos = null;
                releaseAllLeashPlayer(holderHelper);
                maid.getChatBubbleManager().addChatBubble(ChatBabbles.createTextChatBubbleData(100, ChatBabbles.getRandomBabbleComponent("no_vaild_device", maid)));
                return false;
            }
        }

        return true;
    }
    void releaseAllLeashPlayer(ILeashHelper.IHolder holder) {
        for (Player player : players){
            holder.unleashEntity(player);
        }
    }

    protected boolean timedOut(long gameTime) {
        return costToFinishUseDevice <= 0;
    }

    @Override
    protected boolean canStillUse(@NotNull ServerLevel level, @NotNull EntityMaid entity, long gameTime) {
        return currentBauble != null && currentBauble.workPos != null && !players.isEmpty() && devicePos != null;
    }

    @Override
    protected void start(@NotNull ServerLevel level, @NotNull EntityMaid maid, long gameTime) {
        if (currentBauble == null || currentBauble.workPos == null) {
            return;
        }
        maid.getChatBubbleManager().addChatBubble(ChatBabbles.createTextChatBubbleData(100, ChatBabbles.getRandomBabbleComponent("capture", maid)));
        maid.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
        BehaviorUtils.setWalkAndLookTargetMemories(maid,
                new BlockPosTracker(devicePos), 0.4f, 1);
        costToFinishUseDevice = 400;

    }
    private @NotNull Optional<BlockPos> findNearestVaildSeatBlockEntity(ServerLevel level, EntityMaid maid) {
        BlockPos workPos = currentBauble.workPos;
        AABB searchArea = new AABB(workPos).inflate(SEARCH_RADIUS);

        // 通过遍历区块内的所有方块实体
        return BlockPos.betweenClosedStream(
                        new BlockPos(workPos.getX() - SEARCH_RADIUS,
                                workPos.getY() - SEARCH_RADIUS,
                                workPos.getZ() - SEARCH_RADIUS),
                        new BlockPos(workPos.getX() + SEARCH_RADIUS,
                                workPos.getY() + SEARCH_RADIUS,
                                workPos.getZ() + SEARCH_RADIUS)
                )
                .map(BlockPos::immutable)
                .filter(pos -> {
                    BlockEntity be = level.getBlockEntity(pos);
                    return isValidSeatBlockEntity(be) && canLock(level, pos);
                })
                .min(Comparator.comparingDouble(pos -> pos.distSqr(workPos)));
    }

    private boolean isValidSeatBlockEntity(BlockEntity be) {
        if (be == null) return false;

       if (be instanceof BaseSeatBlockEntity seatBe) {
           return seatBe.getBoundPlayerUUID() == null;
       }
        return false;
    }

    @Override
    protected void tick(@NotNull ServerLevel level, @NotNull EntityMaid maid, long gameTime) {
        players = Lists.newArrayList(players.stream()
                .filter(LivingEntity::isAlive)
                .toList());
        if (players.isEmpty() || currentBauble == null) {
            return;
        }
        if (costToFinishUseDevice > 0) {
            if (maid.tickCount % 20 == 0) {
                if (!isValidSeatBlockEntity(level.getBlockEntity(devicePos))) {
                    devicePos = null;
                    return;
                }
            }
            if (maid.distanceToSqr(devicePos.getCenter()) < BIND_RADIUS * BIND_RADIUS) {
                BaseSeatBlockEntity seatBlockEntity = FurnitureHelper.getSeatBlockEntity(level, devicePos);
                if (seatBlockEntity != null) {
                    ILeashHelper.IHolder holderHelper = SuperLeadRopeApi.getLeashHelper().getHolderHelper(maid);
                    for (Player player: players) {
                        if (holderHelper.unleashEntity(player)) {
                            seatBlockEntity.bindPlayerToSeat(level, devicePos, level.getBlockState(devicePos), player);
                            players.remove(player);
                            unLock(level, devicePos);
                            maid.getChatBubbleManager().addChatBubble(ChatBabbles.createTextChatBubbleData(100, ChatBabbles.getRandomBabbleComponent("bind", maid)));
                            maid.swing(InteractionHand.MAIN_HAND);
                            break;
                        }
                    }

                }
            }
            costToFinishUseDevice--;
        }
    }

    @Override
    protected void stop(@NotNull ServerLevel level, @NotNull EntityMaid maid, long gameTime) {
        releaseAllLeashPlayer(SuperLeadRopeApi.getLeashHelper().getHolderHelper(maid));
        players.clear();
        currentBauble = null;
        devicePos = null;
    }
}
