/*
 * Copyright (c) 2026 盐灯水母
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package com.remains_cave.event;

import com.remains_cave.RemainsCaveMod;
import com.remains_cave.ModCreativeTabs;
import com.remains_cave.attribute.ModAttributes;
import com.remains_cave.block.ChallengeAltarBlock;
import com.remains_cave.config.RemainsCaveConfig;
import com.remains_cave.dungeon.room.RoomManager;
import com.remains_cave.dungeon.room.RoomState;
import com.remains_cave.dungeon.tomb.ChallengeManager;
import com.remains_cave.dungeon.tomb.RoomChallenge;
import com.remains_cave.effect.ModEffects;
import com.remains_cave.entity.*;
import com.remains_cave.item.ModDataComponents;
import com.remains_cave.item.component.QuiverContent;
import com.remains_cave.item.custom.CrimsonBondItem;
import com.remains_cave.item.custom.CustomArrowItem;
import com.remains_cave.item.custom.TombQuiverItem;
import com.remains_cave.util.ConfigHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.item.*;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.entity.living.LivingDamageEvent;
import net.neoforged.neoforge.event.entity.living.LivingDeathEvent;
import net.neoforged.neoforge.event.entity.living.LivingEntityUseItemEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
import net.neoforged.neoforge.event.level.BlockEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import com.remains_cave.item.ModItems;
import net.minecraft.world.item.BlockItem;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@EventBusSubscriber(modid = RemainsCaveMod.MODID)
public class ModEventHandler {

    @SubscribeEvent
    public static void onLivingDamage(LivingDamageEvent.Pre event) {
        // 先应用亡灵杀手抗性（可能修改伤害值）
        applySmiteResistance(event);

        float finalDamage = event.getNewDamage();

        if (event.getSource().getEntity() instanceof LivingEntity attacker) {
            // ===== 原有吸血逻辑（基于 KINGS_AURA 或骷髅王自身）=====
            boolean shouldHealOriginal = attacker.hasEffect(ModEffects.KINGS_AURA) || attacker instanceof SkeletonKingEntity;
            if (shouldHealOriginal) {
                float baseMultiplier = RemainsCaveConfig.COMMON.lifestealMultiplier.get().floatValue();
                float finalMultiplier = baseMultiplier;
                if (attacker instanceof SkeletonKingEntity king && king.getHealth() / king.getMaxHealth() < 0.5f) {
                    finalMultiplier = (float) (baseMultiplier * ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.enragelifestealMultiplier, 1.5));
                }
                float healAmount = finalDamage * finalMultiplier;
                attacker.heal(healAmount);
            }
            // ===== CrimsonBondItem 特殊机制：先自伤，后吸血 =====
            ItemStack mainHand = attacker.getMainHandItem();
            if (mainHand.getItem() instanceof CrimsonBondItem) {
                // 1. 扣除自身最大生命值的5%（使用自定义伤害类型，以实现本地化死亡消息）
                float selfDamage = attacker.getMaxHealth() * 0.1f;

                var damageTypeHolder = attacker.registryAccess()
                        .registryOrThrow(Registries.DAMAGE_TYPE)
                        .getHolder(ModCreativeTabs.CRIMSON_BOND_SELF.getId())
                        .orElseThrow();

                attacker.hurt(new DamageSource(damageTypeHolder, attacker, attacker), selfDamage);

                // 2. 如果攻击者依然存活，则进行吸血
                if (attacker.isAlive()) {
                    float healAmount = finalDamage * 0.25f;
                    attacker.heal(healAmount);
                }
            }
        }
    }
    // 原有亡灵杀手抗性逻辑（保持不变）
    private static void applySmiteResistance(LivingDamageEvent.Pre event) {
        LivingEntity target = event.getEntity();
        if (!(target instanceof SkeletonWarriorEntity ||
                target instanceof SkeletonArcherEntity ||
                target instanceof SkeletonWarlockEntity ||
                target instanceof SkeletonKingEntity)) {
            return;
        }

        double resistance = target.getAttributeValue(ModAttributes.SMITE_RESISTANCE);
        if (resistance <= 0) return;

        if (!(event.getSource().getDirectEntity() instanceof LivingEntity attacker)) return;
        ItemStack weapon = attacker.getMainHandItem();
        if (weapon.isEmpty()) return;

        var enchantmentRegistry = attacker.registryAccess().registryOrThrow(Registries.ENCHANTMENT);
        var smiteHolder = enchantmentRegistry.getHolder(Enchantments.SMITE).orElse(null);
        if (smiteHolder == null) return;

        int smiteLevel = weapon.getEnchantmentLevel(smiteHolder);
        if (smiteLevel <= 0) return;

        float originalDamage = event.getOriginalDamage();
        float baseDamage = originalDamage - smiteLevel * 2.5f;
        if (baseDamage < 0) baseDamage = 0;

        float smiteContribution = originalDamage - baseDamage;
        float reducedSmite = smiteContribution * (float) (1.0 - resistance);
        float newDamage = baseDamage + reducedSmite;

        event.setNewDamage(newDamage);
    }

    @SubscribeEvent
    public static void onRightClickItem(PlayerInteractEvent.RightClickItem event) {
        Player player = event.getEntity();
        InteractionHand hand = event.getHand();
        if (hand != InteractionHand.MAIN_HAND) return;

        ItemStack mainHand = player.getMainHandItem();
        if (!(mainHand.getItem() instanceof BowItem)) return;

        ItemStack offHand = player.getOffhandItem();
        if (!(offHand.getItem() instanceof TombQuiverItem)) return;

        QuiverContent content = offHand.get(ModDataComponents.QUIVER_CONTENT.get());
        if (content == null || content.arrows().stream().allMatch(ItemStack::isEmpty)) return;

        // 取消原版事件，开始使用弓
        event.setCanceled(true);
        player.startUsingItem(InteractionHand.MAIN_HAND);
        event.setCancellationResult(InteractionResultHolder.success(mainHand).getResult());
    }

    @SubscribeEvent
    public static void onItemUseStop(LivingEntityUseItemEvent.Stop event) {
        // 只在服务端执行发射逻辑
        if (event.getEntity().level().isClientSide) return;
        if (!(event.getEntity() instanceof Player player)) return;

        ItemStack bow = event.getItem();
        if (!(bow.getItem() instanceof BowItem)) return;

        ItemStack quiver = player.getOffhandItem();
        if (!(quiver.getItem() instanceof TombQuiverItem)) return;

        // 计算蓄力强度
        int useTicks = player.getTicksUsingItem();
        float power = BowItem.getPowerForTime(useTicks);
        if (power < 0.1F) return; // 蓄力不足，不发射

        QuiverContent content = quiver.get(ModDataComponents.QUIVER_CONTENT.get());
        if (content == null || content.arrows().stream().allMatch(ItemStack::isEmpty)) return;

        // 取消原版行为，防止重复发射
        event.setCanceled(true);

        // 执行发射
        fireArrow(player, bow, quiver, power);
    }

    private static void fireArrow(Player player, ItemStack bow, ItemStack quiver, float power) {
        Level level = player.level();
        QuiverContent content = quiver.get(ModDataComponents.QUIVER_CONTENT.get());
        List<ItemStack> arrows = null;
        if (content != null) {
            arrows = content.arrows();
        }

        // 找到第一支非空箭矢
        int slotIndex = -1;
        ItemStack arrowStack = null;
        if (arrows != null) {
            for (int i = 0; i < arrows.size(); i++) {
                if (!arrows.get(i).isEmpty()) {
                    arrowStack = arrows.get(i);
                    slotIndex = i;
                    break;
                }
            }
        }
        if (arrowStack == null) return;

        // 检查无限附魔
        var enchantRegistry = player.registryAccess().registryOrThrow(Registries.ENCHANTMENT);
        var infinityHolder = enchantRegistry.getHolder(Enchantments.INFINITY).orElse(null);
        boolean hasInfinity = infinityHolder != null && bow.getEnchantmentLevel(infinityHolder) > 0;

        // 创建箭矢实体
        ArrowItem arrowItem = (ArrowItem) arrowStack.getItem();
        AbstractArrow abstractArrow = arrowItem.createArrow(level, arrowStack, player, bow);
        abstractArrow.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, power * 3.0F, 1.0F);
        if (power == 1.0F) {
            abstractArrow.setCritArrow(true);
        }
        // 火焰附魔
        var flameHolder = enchantRegistry.getHolder(Enchantments.FLAME).orElse(null);
        if (flameHolder != null && bow.getEnchantmentLevel(flameHolder) > 0) {
            abstractArrow.setRemainingFireTicks(100);
        }

        // 消耗箭矢和耐久
        if (hasInfinity) {
            abstractArrow.pickup = AbstractArrow.Pickup.DISALLOWED;
            int durabilityCost;
            if (arrowStack.is(Items.ARROW)) {
                durabilityCost = 1;
            } else if (arrowStack.getItem() instanceof CustomArrowItem) {
                durabilityCost = 2;
            } else {
                durabilityCost = 3;
            }
            if (quiver.getDamageValue() + durabilityCost > quiver.getMaxDamage()) {
                // 耐久不足，播放失败音效并返回
                level.playSound(null, player.getX(), player.getY(), player.getZ(),
                        SoundEvents.ITEM_BREAK, SoundSource.PLAYERS, 1.0F, 1.0F);
                return;
            }
            quiver.hurtAndBreak(durabilityCost, player, player.getEquipmentSlotForItem(quiver));
        } else {
            // 先检查耐久是否足够
            if (quiver.getDamageValue() + 1 > quiver.getMaxDamage()) {
                level.playSound(null, player.getX(), player.getY(), player.getZ(),
                        SoundEvents.ITEM_BREAK, SoundSource.PLAYERS, 1.0F, 1.0F);
                return;
            }
            // 消耗一支箭矢
            ItemStack arrowToConsume = arrowStack.split(1);
            List<ItemStack> newArrows = new ArrayList<>(arrows);
            if (arrowStack.isEmpty()) {
                newArrows.remove(slotIndex);
            } else {
                newArrows.set(slotIndex, arrowStack);
            }
            quiver.set(ModDataComponents.QUIVER_CONTENT.get(), new QuiverContent(newArrows));
            quiver.hurtAndBreak(1, player, player.getEquipmentSlotForItem(quiver));
        }

        // 消耗弓的耐久
        bow.hurtAndBreak(1, player, player.getEquipmentSlotForItem(bow));

        // 发射箭矢
        level.addFreshEntity(abstractArrow);
        level.playSound(null, player.getX(), player.getY(), player.getZ(),
                SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS,
                1.0F, 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + 0.5F);
    }
    @SubscribeEvent
    public static void onLivingDeath(LivingDeathEvent event) {
        if (event.getEntity().level().isClientSide) return;
        LivingEntity entity = event.getEntity();
        CompoundTag data = entity.getPersistentData();
        if (data.contains("RoomId")) {
            ChallengeManager manager = ChallengeManager.get(entity.level());
            manager.onMobDeath(entity);
        }
    }
    @SubscribeEvent
    public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
        if (event.getEntity() instanceof ServerPlayer player) {
            ServerLevel level = player.serverLevel();
            ChallengeManager manager = ChallengeManager.get(level);
            // 遍历所有挑战，找到玩家所在的房间
            for (Map.Entry<String, RoomChallenge> entry : manager.getChallenges().entrySet()) {
                RoomChallenge challenge = entry.getValue();
                if (challenge.isActive()) {
                    double distSq = player.distanceToSqr(challenge.getAltarPos().getX() + 0.5,
                            challenge.getAltarPos().getY() + 0.5,
                            challenge.getAltarPos().getZ() + 0.5);
                    if (distSq <= 64 * 64) { // 玩家在房间内
                        // 检查房间内是否还有其他玩家
                        boolean hasOtherPlayer = false;
                        for (ServerPlayer other : level.players()) {
                            if (other != player && other.distanceToSqr(challenge.getAltarPos().getX() + 0.5,
                                    challenge.getAltarPos().getY() + 0.5,
                                    challenge.getAltarPos().getZ() + 0.5) <= 64 * 64) {
                                hasOtherPlayer = true;
                                break;
                            }
                        }
                        if (!hasOtherPlayer) {
                            // 没有其他玩家，清理挑战
                            challenge.failChallenge(level);
                            manager.removeChallenge(entry.getKey());
                        }
                        break;
                    }
                }
            }
        }
    }

    @SubscribeEvent
    public static void onServerStopping(ServerStoppingEvent event) {
        // 遍历所有世界，清理所有挑战
        for (ServerLevel level : event.getServer().getAllLevels()) {
            ChallengeManager manager = ChallengeManager.get(level);
            for (RoomChallenge challenge : manager.getChallenges().values()) {
                if (challenge.isActive()) {
                    challenge.failChallenge(level);
                }
            }
            manager.clearAll(); // 清空挑战列表
        }
    }
    @SubscribeEvent
    public static void onBlockBreak(BlockEvent.BreakEvent event) {
        Player player = event.getPlayer();
        if (player.isCreative()) return;

        Level level = (Level) event.getLevel();
        if (level.isClientSide) return;

        BlockPos pos = event.getPos();
        BlockState state = level.getBlockState(pos);
        if (state.getBlock() instanceof FallingBlock) return;

        RoomManager roomManager = RoomManager.get(level);
        String roomId = findRoomIdByPosition(roomManager, pos);
        if (roomId != null) {
            RoomState room = roomManager.getOrCreateRoom(roomId);
            if (room.isPositionProtected(pos)) {
                event.setCanceled(true);
                // 移除提示消息，仅静默阻止
            }
        }
    }
    private static String findRoomIdByPosition(RoomManager manager, BlockPos pos) {
        for (Map.Entry<String, RoomState> entry : manager.getRooms().entrySet()) {
            RoomState room = entry.getValue();
            if (room.isPositionProtected(pos)) {
                return entry.getKey();
            }
        }
        return null;
    }
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public static void onRightClickBlock(PlayerInteractEvent.RightClickBlock event) {
        Player player = event.getEntity();
        if (player.isCreative()) return;

        Level level = player.level();
        if (level.isClientSide) return;

        BlockPos pos = event.getPos();
        BlockState state = level.getBlockState(pos);
// 祭坛方块特殊处理：潜行时取消事件（阻止放置），非潜行时放行让方块处理交互
        if (state.getBlock() instanceof ChallengeAltarBlock) {
            if (player.isShiftKeyDown()) {
                event.setCanceled(true);
                if (player instanceof ServerPlayer serverPlayer) {
                    InteractionHand hand = event.getHand();
                    int slot = hand == InteractionHand.MAIN_HAND ? player.getInventory().selected : 40;
                    ItemStack stack = event.getItemStack();
                    // 单槽位同步
                    serverPlayer.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, slot, stack));
                    // 全量同步，确保客户端立即刷新
                    if (serverPlayer.containerMenu == serverPlayer.inventoryMenu) {
                        serverPlayer.containerMenu.sendAllDataToRemote();
                    } else {
                        serverPlayer.closeContainer();
                        serverPlayer.inventoryMenu.sendAllDataToRemote();
                    }
                }
            }
            return;
        }

        // 其他方块的保护逻辑（保持不变）
        RoomManager roomManager = RoomManager.get(level);
        String roomId = findRoomIdByPosition(roomManager, pos);
        if (roomId == null) return;

        RoomState room = roomManager.getOrCreateRoom(roomId);
        if (!room.isPositionProtected(pos)) return;

        ItemStack stack = event.getItemStack();
        if (stack.getItem() instanceof BlockItem) {
            event.setCanceled(true);
            if (player instanceof ServerPlayer serverPlayer) {
                InteractionHand hand = event.getHand();
                int slot = hand == InteractionHand.MAIN_HAND ? player.getInventory().selected : 40;
                serverPlayer.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, slot, stack));
                if (serverPlayer.containerMenu == serverPlayer.inventoryMenu) {
                    serverPlayer.containerMenu.sendAllDataToRemote();
                } else {
                    serverPlayer.closeContainer();
                    serverPlayer.inventoryMenu.sendAllDataToRemote();
                }
            }
        }
    }
    @SubscribeEvent
    public static void onEntityJoinLevel(EntityJoinLevelEvent event) {
        if (event.getLevel().isClientSide) return;
        Entity entity = event.getEntity();

        if (!(entity instanceof SkeletonWarriorEntity ||
                entity instanceof SkeletonArcherEntity ||
                entity instanceof SkeletonWarlockEntity)) {
            return;
        }

        BlockPos pos = entity.blockPosition();
        ServerLevel level = (ServerLevel) event.getLevel();
        RoomManager rm = RoomManager.get(level);
        String roomId = rm.getRoomIdAt(pos);

        if (roomId == null) {
            return;
        }

        RoomState room = rm.getRooms().get(roomId);
        if (room == null) {
            return;
        }

        if (room.shouldApplyKingsAura(level)) {
            ((LivingEntity) entity).addEffect(new MobEffectInstance(ModEffects.KINGS_AURA, -1, 0, false, false, true));
        }
    }
}