/*
 *  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.content.entity;


import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkHooks;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
import top.r3944realms.eroticdungeongame.core.service.SeatService;
import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.util.nbt.NBTWriter;

/**
 * 座椅实体 - 用于处理玩家坐在束缚设备上的逻辑
 */
public class SeatEntity extends Entity {
    public static final String LINKED_BLOCKED_POS = "linkedBlockedPos";
    private static final EntityDataAccessor<BlockPos> DATA_BE = SynchedEntityData.defineId(SeatEntity.class, EntityDataSerializers.BLOCK_POS);
    private BlockPos linkedBlockPos;
    private BaseSeatBlockEntity be;
    private boolean isRemoving;

    public SeatEntity(EntityType<? extends SeatEntity> entityType, Level level) {
        super(entityType, level);
        this.noPhysics = true;
        this.isRemoving = false;
    }

    @Override
    public void tick() {
        super.tick();

        if (!this.level().isClientSide) {
            // 简化的检查逻辑
            if (shouldRemove() && linkedBlockPos != null) {
                SeatService.releasePlayerFromBlock(this.level(), this.linkedBlockPos);
                this.discard();
            }
        } else {
            if (be == null) {
                BlockPos blockPos = entityData.get(DATA_BE);
                if (linkedBlockPos == null) {
                    if (!blockPos.equals(BlockPos.ZERO)) {
                        linkedBlockPos = blockPos;
                        updateLinkedBlock();
                    }
                }
            }
            // 客户端只处理乘客的朝向同步
            syncPassengerRotation();
        }
    }

    private boolean shouldRemove() {
        return this.getPassengers().isEmpty() ||
                this.level().isEmptyBlock(this.linkedBlockPos) ||
                this.isRemoving;
    }

    private void syncPassengerRotation() {
        Entity passenger = getFirstPassenger();
        if (passenger instanceof LivingEntity living) {
            if (be == null) {
                passengerRot(living);
            } else {
                be.passengerRot(living, this);
            }
        }
    }

    @Override
    public void removePassenger(@NotNull Entity passenger) {
        super.removePassenger(passenger);

        // 只在服务端处理，且确保没有其他乘客
        if (this.level().isClientSide() || !getPassengers().isEmpty()) {
            return;
        }

        updateLinkedBlock();
    }


    public void passengerRot(@NotNull Entity passenger) {
        // 固定身体旋转
        passenger.setYBodyRot(this.getYRot());

        if (passenger instanceof LivingEntity livingEntity) {
            // 获取当前头部旋转
            float currentHeadYaw = livingEntity.getYRot();
            float seatYaw = this.getYRot();

            // 限制头部旋转范围（例如 ±90度）
            float maxHeadTurn = 45.0f;
            float diff = Mth.wrapDegrees(currentHeadYaw - seatYaw);

            // 应用限制
            if (Math.abs(diff) > maxHeadTurn) {
                if (diff > 0) {
                    livingEntity.setYRot(seatYaw + maxHeadTurn);
                } else {
                    livingEntity.setYRot(seatYaw - maxHeadTurn);
                }
                livingEntity.yHeadRot = livingEntity.getYRot();
            }

            // 保持身体固定
            livingEntity.yBodyRot = seatYaw;
        }
    }


    @Override
    protected boolean canRide(@NotNull Entity vehicle) {
        return true;
    }

    @Override
    public boolean shouldRiderSit() {
        return false;
    }

    @Override
    public boolean isPickable() {
        return false;
    }

    /**
     * 更新链接的方块状态
     */
    private void updateLinkedBlock() {
        if (this.linkedBlockPos != null) {
            this.level().blockUpdated(this.linkedBlockPos,
                    this.level().getBlockState(this.linkedBlockPos).getBlock());
            BlockEntity blockEntity = this.level().getBlockEntity(this.linkedBlockPos);
            if (blockEntity instanceof BaseSeatBlockEntity baseSeatBlockEntity){
                be = baseSeatBlockEntity;
            }
        }
    }

    @Override
    @NotNull
    public Vec3 getDismountLocationForPassenger(@NotNull LivingEntity passenger) {
        Direction original = this.getDirection();
        Direction[] offsets = {original, original.getClockWise(), original.getCounterClockWise(), original.getOpposite()};
        for (Direction dir : offsets) {
            Vec3 safeVec = DismountHelper.findSafeDismountLocation(passenger.getType(), this.level(), this.blockPosition().relative(dir), false);
            if (safeVec != null) {
                return safeVec.add(0, 0.25, 0);
            }
        }
        return super.getDismountLocationForPassenger(passenger);
    }

    @Override
    @NotNull
    public Packet<ClientGamePacketListener> getAddEntityPacket() {
        return NetworkHooks.getEntitySpawningPacket(this);
    }

    @Override
    public boolean isAttackable() {
        return false;
    }

    @Override
    protected void defineSynchedData() {
        this.entityData.define(DATA_BE, BlockPos.ZERO);
    }

    @Override
    public void addAdditionalSaveData(@NotNull CompoundTag compound) {
        NBTWriter.of(compound)
                .compoundIf(LINKED_BLOCKED_POS, linkedBlockPos != null, () -> NbtUtils.writeBlockPos(linkedBlockPos));
    }

    @Override
    public void readAdditionalSaveData(@NotNull CompoundTag compound) {
        NBTReader.of(compound)
                .compound(LINKED_BLOCKED_POS, i -> setLinkedBlockPos(NbtUtils.readBlockPos(i)));
    }

    // Getter 和 Setter 方法

    public BlockPos getLinkedBlockPos() {
        return this.linkedBlockPos;
    }

    public void setLinkedBlockPos(BlockPos blockPos) {
        this.linkedBlockPos = blockPos;
        entityData.set(DATA_BE, blockPos);
    }

    public boolean isActive() {
        return !this.isRemoving;
    }

    public void setRemoving(boolean removing) {
        this.isRemoving = removing;
    }

    @Override
    public void remove(@NotNull RemovalReason reason) {
        if (!level().isClientSide && this.linkedBlockPos != null) {
            SeatService.releasePlayerFromBlock(level(), this.linkedBlockPos);
        }
        super.remove(reason);
    }

}
