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

import com.remains_cave.config.RemainsCaveConfig;
import com.remains_cave.entity.SkeletonKingEntity;
import com.remains_cave.util.ConfigHelper;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;

import java.util.EnumSet;
import java.util.List;

public class KingDashGoal extends Goal {
    private final SkeletonKingEntity king;
    private LivingEntity target;
    private int phaseTimer = 0;
    private int phase = 0;
    private Vec3 dashDirection;

    private final int windupTicks;
    private final int dashTicks;
    private final int recoveryTicks;
    private final double dashSpeed;
    private final int baseCooldownTicks;
    private final float dashDamage;

    public KingDashGoal(SkeletonKingEntity king) {
        this.king = king;
        this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
        this.windupTicks = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashWindupTicks::get, 5);
        this.dashTicks = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashTicks::get, 3);
        this.recoveryTicks = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashRecoveryTicks::get, 7);
        this.dashSpeed = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashSpeed::get, 3.0);
        this.baseCooldownTicks = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashCooldown::get, 160);
        this.dashDamage = ConfigHelper.getOrFallback(RemainsCaveConfig.COMMON.dashDamage::get, 25.0).floatValue();
    }

    @Override
    public boolean canUse() {
        if (king.isSummoning()) return false;
        target = king.getTarget();
        if (target == null || !target.isAlive()) return false;
        double distSq = king.distanceToSqr(target);
        return distSq > 36 && distSq < 144 && king.getDashCooldown() == 0;
    }

    @Override
    public boolean canContinueToUse() {
        return phase != 0 && phaseTimer > 0;
    }

    @Override
    public void start() {
        if (target == null) return;
        double dx = target.getX() - king.getX();
        double dz = target.getZ() - king.getZ();
        double len = Math.sqrt(dx * dx + dz * dz);
        if (len < 0.01) return;
        dashDirection = new Vec3(dx / len, 0, dz / len);
        phase = 1;
        phaseTimer = windupTicks;
        king.triggerDashAnim();
        king.setDashing(true);
    }

    @Override
    public void tick() {
        if (phase == 0) return;
        phaseTimer--;

        if (target != null) {
            king.getLookControl().setLookAt(target, 30, 30);
        }

        switch (phase) {
            case 1:
                if (phaseTimer <= 0) {
                    phase = 2;
                    phaseTimer = dashTicks;
                }
                break;
            case 2:
                king.setDeltaMovement(dashDirection.x * dashSpeed, king.getDeltaMovement().y, dashDirection.z * dashSpeed);
                hurtEntitiesInFront();
                if (phaseTimer == dashTicks) {
                    king.level().playSound(null, king.getX(), king.getY(), king.getZ(),
                            SoundEvents.PLAYER_ATTACK_SWEEP, king.getSoundSource(), 1.0F, 1.0F);
                }
                if (phaseTimer <= 0) {
                    phase = 3;
                    phaseTimer = recoveryTicks;
                    king.setDeltaMovement(0, king.getDeltaMovement().y, 0);
                }
                break;
            case 3:
                if (phaseTimer <= 0) {
                    phase = 0;
                    king.setDashCooldown(getCurrentCooldown());
                }
                break;
        }
    }

    @Override
    public void stop() {
        if (phase != 0 && king.getDashCooldown() == 0) {
            king.setDashCooldown(getCurrentCooldown() / 2);
        }
        phase = 0;
        phaseTimer = 0;
        king.setDeltaMovement(0, king.getDeltaMovement().y, 0);
        king.setDashing(false);
    }

    private int getCurrentCooldown() {
        int cooldown = baseCooldownTicks;
        if (king.isEnraged()) cooldown = (int) (cooldown * 0.75);
        return cooldown;
    }

    private void hurtEntitiesInFront() {
        Vec3 front = dashDirection.scale(3.0);
        AABB area = king.getBoundingBox()
                .expandTowards(front)
                .inflate(1.0, 0.5, 1.0);

        List<LivingEntity> entities = king.level().getEntitiesOfClass(LivingEntity.class, area,
                e -> e != king && e.isAlive() && !king.isAlliedTo(e));

        for (LivingEntity entity : entities) {
            // 破盾逻辑已移除
            entity.hurt(king.damageSources().mobAttack(king), dashDamage);
            king.level().playSound(null, entity.getX(), entity.getY(), entity.getZ(),
                    SoundEvents.IRON_GOLEM_DAMAGE, entity.getSoundSource(), 1.0F, 1.0F);
            Vec3 knockback = entity.position().subtract(king.position()).normalize().scale(1.5);
            entity.setDeltaMovement(entity.getDeltaMovement().add(knockback.x, 0.2, knockback.z));
        }
    }
}