import { world, system, Player, EntityDamageCause } from "@minecraft/server";
import * as attackUtils from "../attackUtils.js";


function applyTornadoSpiralForce(owner, entity, tornado, maxRange = 10, damageRange = 5, damage = 1, baseStrength = 0.2, swirlFactor = 0.1, liftStrength = 0.2) {
    const pos = entity.location;
    const origin = tornado.location;
    const liftRange = maxRange * 1.0;

    const dx = origin.x - pos.x;
    const dy = origin.y - pos.y;
    const dz = origin.z - pos.z;

    const distXZ = Math.sqrt(dx * dx + dz * dz);
    if (distXZ < 0.01 || distXZ > maxRange) return;

    // ----- Horizontal Spiral (XZ) -----
    const distXZInv = 1 / distXZ;
    const pullDirX = dx * distXZInv;
    const pullDirZ = dz * distXZInv;

    const swirlX = -pullDirZ;
    const swirlZ = pullDirX;

    const fadeXZ = 1 - distXZ / maxRange;

    const horizontalForce = baseStrength * fadeXZ;
    const swirlForce = swirlFactor * fadeXZ;

    const forceX = (pullDirX * horizontalForce + swirlX * swirlForce);
    const forceZ = (pullDirZ * horizontalForce + swirlZ * swirlForce);

    // ----- Vertical Lift (Y) -----
    const dist3D = Math.sqrt(dx * dx + dy * dy + dz * dz);
    const liftFade = 1 - Math.min(dist3D / liftRange, 1);
    const forceY = liftStrength * liftFade;

    // ----- Apply Forces -----
    if (entity instanceof Player) {
        // Apply the knockback in the correct direction
        entity.applyKnockback(forceX, forceZ, horizontalForce * 3, forceY);
    } else {
        // Apply impulse for non-player entities
        entity.applyImpulse({ x: forceX, y: forceY, z: forceZ });
    }

    // Apply damage
    if (dist3D < damageRange) {
        attackUtils.applyModifiedDamage(entity, damage, {
            cause: EntityDamageCause.contact,
            damagingEntity: owner
        });
    }
}

export function tornadoTick(tornado) {
    if (!tornado.isValid()) {
        tornado?.remove();
        return;

    }
    const timeCreated = tornado.getDynamicProperty("oct_eg:time_created");
    const lifeTime = tornado.getDynamicProperty("oct_eg:life_time");
    const owner = tornado.getComponent("minecraft:tameable")?.tamedToPlayer;

    const range = tornado.getDynamicProperty("oct_eg:pull_range");
    const damage = tornado.getDynamicProperty("oct_eg:damage");


    if (system.currentTick % 10 === 0
        && system.currentTick !== timeCreated
        && system.currentTick - timeCreated < (lifeTime - 1) * 20
    ) {
        //world.sendMessage(`Life Left: ${lifeTime - (system.currentTick - timeCreated) / 20}`);
        tornado.dimension.spawnParticle(
            "oct_eg:tornado.spin",
            tornado.location
        );
        tornado.runCommand(`/camerashake add @a[r=${range}] 0.2 1 positional`);
    };

    const pullRange = range;
    const damageRange = (pullRange / 2) + 2;
    const location = {
        x: tornado.location.x,
        y: tornado.location.y + 5,
        z: tornado.location.z
    };

    if (system.currentTick - timeCreated >= lifeTime * 20) { // Despawn
        tornado?.triggerEvent("oct_eg:to_despawn");
        tornado.dimension.playSound(
            "octovon.eg.gauntlet.anemo.tornado.end",
            tornado.location,
        )
        return;

    } else { // Pull targets
        for (const entity of attackUtils.getValidTargetsInRange(tornado,
            {
                startLocation: location,
                maxDistance: pullRange,
                excludedEntities: [owner]
            }).filter(entity => attackUtils.isValidPullTarget(entity))
        ) {
            //applyForce(tornado, entity, location, pullRange, damageRange);
            applyTornadoSpiralForce(owner, entity, tornado, pullRange, damageRange, damage);
        }
    }
}