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

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TieredItem;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.eroticdungeongame.client.model.EDGArmPose;
import top.r3944realms.eroticdungeongame.content.EDGToolTier;
import top.r3944realms.eroticdungeongame.content.enchantment.CarrotAndStickEnchantment;
import top.r3944realms.eroticdungeongame.core.register.EDGEnchantments;
import top.r3944realms.eroticdungeongame.core.register.EDGParticleTypes;
import top.r3944realms.eroticdungeongame.core.register.EDGSoundEvents;

import java.util.Map;

@SuppressWarnings("deprecation")
public class WhipItem extends TieredItem {
    private final float attackDamage;
    private final Multimap<Attribute, AttributeModifier> defaultModifiers;

    public WhipItem(int attackDamageModifier) {
        super(EDGToolTier.LEATHER, new Properties().durability(512).setNoRepair());
        this.attackDamage = attackDamageModifier;
        ImmutableMultimap.Builder<Attribute, AttributeModifier> builder = ImmutableMultimap.builder();
        builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", this.attackDamage, AttributeModifier.Operation.ADDITION));
        this.defaultModifiers = builder.build();
    }

    @Override
    public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand usedHand) {
        ItemStack itemStack = player.getItemInHand(usedHand);

        // 开始使用动画
        player.startUsingItem(usedHand);
        return InteractionResultHolder.consume(itemStack);
    }

    @Override
    public @NotNull UseAnim getUseAnimation(@NotNull ItemStack stack) {
        return UseAnim.CUSTOM;
    }

    @Override
    public void onUseTick(@NotNull Level level, @NotNull LivingEntity livingEntity, @NotNull ItemStack stack, int remainingUseDuration) {
        int totalDuration = this.getUseDuration(stack);
        int elapsedTime = totalDuration - remainingUseDuration;

        // 在整个使用过程中持续生成鞭扫粒子（客户端）
        if (level.isClientSide) {
            createWhipSwingParticle(level, livingEntity);
        }

        // 在10tick时应用伤害（服务端）
        if (elapsedTime == 10 && !level.isClientSide) {
            if (livingEntity instanceof Player player && !player.isCreative()) {
                InteractionHand useHand = livingEntity.getUsedItemHand();
                stack.hurtAndBreak(1, livingEntity, e -> e.broadcastBreakEvent(useHand));
            }
            applyVerticalSweepDamage(level, livingEntity, livingEntity instanceof Player p && p.isCreative(), stack);
        }
    }
    private Vec3 calculateHandFrontPositionSimple(Player player, boolean isRightHand, float progress) {
        Vec3 playerPos = player.position();

        // 获取手臂旋转
        float armXRot = calculateArmXRot(progress, isRightHand);
        float armYRot = calculateArmYRot(progress, isRightHand);

        // 基础位置：玩家前方
        double forwardDistance = 1.2f; // 粒子距离玩家的水平距离

        // 根据手臂yRot决定横向偏移
        double horizontalOffset = armYRot * 0.8; // 缩放因子

        // 根据手臂xRot决定垂直偏移
        // armXRot为负值时向上，正值时向下
        double verticalOffset = -armXRot * 0.4; // 负号转换坐标系

        // 玩家朝向
        Vec3 lookVec = player.getLookAngle();

        // 基础前方位置
        double baseX = playerPos.x + lookVec.x * forwardDistance;
        double baseY = playerPos.y + player.getEyeHeight() * 0.7; // 腰部高度
        double baseZ = playerPos.z + lookVec.z * forwardDistance;

        // 横向偏移向量（垂直于玩家朝向）
        Vec3 rightVec = new Vec3(-lookVec.z, 0, lookVec.x).normalize();
        Vec3 horizontalOffsetVec = rightVec.scale(horizontalOffset);

        return new Vec3(
                baseX + horizontalOffsetVec.x,
                baseY + verticalOffset,  // 直接使用xRot计算的垂直偏移
                baseZ + horizontalOffsetVec.z
        );
    }

    /**
     * 计算手臂xRot（竖向旋转）
     * 基于你的EDGArmPose姿势代码：
     * progress < 0.2f: 准备阶段，向上抬起 -2.8f
     * progress < 0.5f: 挥舞阶段，从上到下 -0.4f + swing * 1.2f
     */
    private float calculateArmXRot(float progress, boolean isRightHand) {
        if (progress < 0.2f) {
            float phase = progress / 0.2f;
            // 准备阶段：向上抬起 -2.8f（负值表示向上）
            return -2.8f * phase;
        } else if (progress < 0.5f) {
            float phase = (progress - 0.2f) / 0.3f;
            float swing = (float) Math.sin(phase * Math.PI);
            // 主要挥舞阶段：从上到下 -0.4f + swing * 1.2f
            // 从-0.4（略向上）到0.8（向下）
            return -0.4f + swing * 1.2f;
        } else {
            // 收尾阶段：逐渐复位到默认姿势
            float phase = (progress - 0.5f) / 0.5f;
            return Mth.lerp(phase, 0.8f, -0.87266463f);
        }
    }

    /**
     * 计算手臂yRot（水平旋转）
     * 基于你的EDGArmPose姿势代码：
     * 右手：从右向左挥舞
     * 左手：从左向右挥舞
     */
    private float calculateArmYRot(float progress, boolean isRightHand) {
        if (progress < 0.2f) {
            float phase = progress / 0.2f;
            // 准备阶段：右手向右偏(0.3f)，左手向左偏(-0.3f)
            return isRightHand ? 0.3f * phase : -0.3f * phase;
        } else if (progress < 0.5f) {
            float phase = (progress - 0.2f) / 0.3f;
            float swing = (float) Math.sin(phase * Math.PI);
            // 主要挥舞阶段：
            // 右手：0.3f - swing * 0.6f（从右向左）
            // 左手：-0.3f + swing * 0.6f（从左向右）
            return isRightHand ? 0.3f - swing * 0.6f : -0.3f + swing * 0.6f;
        } else {
            // 收尾阶段：回正
            return 0.0f;
        }
    }

    /**
     * 创建单个鞭扫粒子效果
     */
    private void createWhipSwingParticle(Level level, LivingEntity entity) {
        if (entity instanceof Player player && level.isClientSide()) {
            // 计算使用进度
            int remainedUseTime = player.getUseItemRemainingTicks();
            int maxUseTime = player.getUseItem().getUseDuration();
            float progress = 1.0f - (float)remainedUseTime / maxUseTime;

            // 只在特定进度范围内生成粒子
            if (progress == 0.25f) {
                // 获取使用的手
                InteractionHand useHand = player.getUsedItemHand();
                boolean isRightHand = (useHand == InteractionHand.MAIN_HAND && player.getMainArm().equals(HumanoidArm.RIGHT)) ||
                        (useHand == InteractionHand.OFF_HAND && !player.getMainArm().equals(HumanoidArm.RIGHT));

                // 使用新的计算方法
                Vec3 particlePos = calculateHandFrontPositionSimple(player, isRightHand, progress);
                createSingleWhipParticle(level, particlePos, progress);
            }
        }
    }

    /**
     * 创建单个鞭扫粒子
     */
    private void createSingleWhipParticle(Level level, Vec3 position, float progress) {
        // 只生成一个竖向横扫粒子
        level.addParticle(EDGParticleTypes.VERTICAL_WHIP_SWEEP.get(),
                position.x,
                position.y,
                position.z,
                0.0, 0.0, 0.0);

        // 播放挥舞音效（只在开始时播放一次）
        if (Math.abs(progress - 0.25f) < 0.01f) {
            level.playSound(null, position.x, position.y, position.z,
                    SoundEvents.PLAYER_ATTACK_SWEEP, SoundSource.PLAYERS,
                    0.8F, 1.0F + level.random.nextFloat() * 0.2F);
        }
    }

    /**
     * 应用竖向横扫伤害并生成鞭痕
     */
    private void applyVerticalSweepDamage(@NotNull Level level, @NotNull LivingEntity entity, boolean isCreative, ItemStack stack) {
        Vec3 playerPos = entity.position();

        // 横扫参数
        float maxDistance = 5.0f; // 最大距离
        float minDistance = 0.0f; // 最小距离
        float height = 3.0f; // 竖向高度

        // 获取使用的手
        InteractionHand useHand = entity.getUsedItemHand();
        boolean isRightHand = (useHand == InteractionHand.MAIN_HAND && entity.getMainArm().equals(HumanoidArm.RIGHT)) ||
                (useHand == InteractionHand.OFF_HAND && !entity.getMainArm().equals(HumanoidArm.RIGHT));

        // 使用较大的AABB先筛选附近的实体
        AABB searchArea = new AABB(
                playerPos.x - maxDistance,
                playerPos.y - height / 2,
                playerPos.z - maxDistance,
                playerPos.x + maxDistance,
                playerPos.y + height / 2,
                playerPos.z + maxDistance
        );

        java.util.List<Entity> entitiesInArea = level.getEntities(entity, searchArea);
        entity.level().playSound(null, playerPos.x, playerPos.y, playerPos.z,
                EDGSoundEvents.WHIP.get(), SoundSource.PLAYERS,
                0.8F, 1.0F + entity.level().random.nextFloat() * 0.2F);

        // 对每个实体检查是否在前方扇形区域内
        for (Entity target : entitiesInArea) {
            if (target instanceof LivingEntity livingTarget && livingTarget != entity) {
                if (isInFrontSector(entity, livingTarget, isRightHand, maxDistance, minDistance, height)) {
                    // 应用伤害
                    if (target instanceof LivingEntity living) {
                        Map<Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(stack);
                        if (!enchantments.isEmpty()) {
                            Integer enLp = enchantments.get(EDGEnchantments.CARROT_AND_STICK.get());
                            if (enLp != null && enLp > 0) {
                                    CarrotAndStickEnchantment.hurt(living, entity , enLp);
                            }

                        }
                    }
                    applyVerticalDamageToEntity(entity, livingTarget);
                    if(!isCreative) stack.hurtAndBreak(2, livingTarget, living -> living.broadcastBreakEvent(useHand));
                }
            }
        }
    }

    /**
     * 检查目标是否在鞭子前方扇形区域内
     */
    private boolean isInFrontSector(LivingEntity entity, LivingEntity target,
                                    boolean isRightHand, float maxDistance,
                                    float minDistance, float height) {
        Vec3 playerPos = entity.position();
        Vec3 targetPos = target.position();

        // 计算相对位置
        Vec3 toTarget = targetPos.subtract(playerPos);
        double distance = toTarget.horizontalDistance();

        if (distance > maxDistance || distance < minDistance) {
            return false;
        }

        // 检查垂直高度
        double targetY = target.getY() + target.getBbHeight() / 2;
        double playerY = playerPos.y + entity.getEyeHeight() * 0.8;
        double verticalDiff = Math.abs(targetY - playerY);
        if (verticalDiff > height / 2) {
            return false;
        }

        // 获取玩家朝向向量
        float yawRad = (float) Math.toRadians(entity.getYRot());
        Vec3 lookVec = new Vec3(-Math.sin(yawRad), 0, Math.cos(yawRad)).normalize();

        // 计算玩家到目标的水平向量
        Vec3 toTargetHorizontal = new Vec3(toTarget.x, 0, toTarget.z).normalize();

        // 计算点积（cosine of angle）
        double dot = lookVec.dot(toTargetHorizontal);

        // 前方扇形角度阈值（cos(60°) = 0.5）
        // 只检查前方60度范围内的目标
        if (dot < 0.5) {
            return false;
        }

        // 计算叉积判断左右
        // 叉积的Y分量：正值为目标在右侧，负值为目标在左侧
        double crossY = lookVec.x * toTargetHorizontal.z - lookVec.z * toTargetHorizontal.x;

        if (isRightHand) {
            // 右手：攻击右侧区域（crossY > 0）
            return crossY > 0;
        } else {
            // 左手：攻击左侧区域（crossY < 0）
            return crossY < 0;
        }
    }

    /**
     * 对实体应用竖向伤害并生成鞭痕粒子
     */
    private void applyVerticalDamageToEntity(LivingEntity entity, LivingEntity target) {
        // 计算基础伤害
        float baseDamage = attackDamage;

        // 根据距离衰减伤害
        double distance = entity.distanceTo(target);
        float distanceMultiplier = (float) Math.max(0.3, 1.0 - (distance - 0.5) / 2.5);

        // 根据高度差调整伤害
        double heightDiff = target.getY() - entity.getY();
        float heightMultiplier = (float) (1.0 + Math.min(heightDiff * 0.1, 0.3));

        // 最终伤害
        float finalDamage = baseDamage * distanceMultiplier * heightMultiplier;

        // 创建伤害源
        DamageSource damageSource = entity.damageSources().mobAttack(entity);

        // 应用伤害
        boolean wasHurt = target.hurt(damageSource, finalDamage);

        if (wasHurt) {
            // 击退效果：向前方击退
            Vec3 lookVec = entity.getLookAngle();
            Vec3 knockbackDir = new Vec3(lookVec.x, 0.2, lookVec.z).normalize();

            // 根据左右手添加侧向击退
            InteractionHand useHand = entity.getUsedItemHand();
            boolean isRightHand = (useHand == InteractionHand.MAIN_HAND && entity.getMainArm().equals(HumanoidArm.RIGHT)) ||
                    (useHand == InteractionHand.OFF_HAND && !entity.getMainArm().equals(HumanoidArm.RIGHT));

            // 侧向击退向量
            Vec3 sideDir = new Vec3(-lookVec.z, 0, lookVec.x);
            if (isRightHand) {
                sideDir = sideDir.scale(0.2); // 右手向右击退
            } else {
                sideDir = sideDir.scale(-0.2); // 左手向左击退
            }

            Vec3 finalKnockback = knockbackDir.add(sideDir).normalize();
            target.knockback(0.5f, finalKnockback.x, finalKnockback.z);


            // 只生成鞭痕粒子（击中时）
            spawnWhipScarParticles(entity.level(), target);
        }
    }

    /**
     * 生成鞭痕粒子（只在目标身上，击中时产生）
     */
    private void spawnWhipScarParticles(Level level, LivingEntity target) {
        Vec3 targetPos = target.position();
        double height = target.getBbHeight();
        double width = target.getBbWidth();

        // 根据目标大小生成不同数量的鞭痕
        int scarCount = (int) (height * 2); // 减少数量

        for (int i = 0; i < scarCount; i++) {
            // 在目标身上随机位置生成鞭痕
            double scarX = targetPos.x + (level.random.nextDouble() - 0.5) * width * 0.6;
            double scarY = targetPos.y + level.random.nextDouble() * height * 0.8 + height * 0.1;
            double scarZ = targetPos.z + (level.random.nextDouble() - 0.5) * width * 0.6;

            // 鞭痕粒子的运动方向（轻微向外扩散）
            double motionX = (level.random.nextDouble() - 0.5) * 0.01;
            double motionY = level.random.nextDouble() * 0.005;
            double motionZ = (level.random.nextDouble() - 0.5) * 0.01;

            // 生成鞭痕粒子
            level.addParticle(EDGParticleTypes.WHIP_SCAR.get(),
                    scarX, scarY, scarZ,
                    motionX, motionY, motionZ);
        }
    }


    @Override
    public int getUseDuration(@NotNull ItemStack stack) {
        return 40; // 2秒的动画
    }

    @OnlyIn(Dist.CLIENT)
    @Override
    public @NotNull Object getRenderPropertiesInternal() {
        return new IClientItemExtensions() {
            @Nullable
            @Override
            public HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack itemStack) {
                return EDGArmPose.WHIP;
            }
        };
    }

    @Override
    public void releaseUsing(@NotNull ItemStack stack, @NotNull Level level,
                             @NotNull LivingEntity livingEntity, int timeLeft) {
        //noop
    }

    @Override
    public @NotNull Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(@NotNull EquipmentSlot slot) {
        return slot.getType().equals(EquipmentSlot.Type.HAND) ? defaultModifiers : super.getDefaultAttributeModifiers(slot);
    }
    @Override
    public boolean hurtEnemy(@NotNull ItemStack stack, @NotNull LivingEntity target, @NotNull LivingEntity attacker) {
        return false;
    }
}