// ================= CONFIG =================
var BASE_COOLDOWN = 40;           // Faster casting
var WINDUP_TICKS = 12;            // Quicker windup
var AGGRESSIVE_HP_RATIO = 0.3;    // HP fraction to enter aggressive phase
var SPIKE_BURST_COUNT = 3;        // MORE spikes (increased from 3)
var SPIKE_BURST_DELAY = 3;        // ZERO delay between spikes - INSTANT BURST

var WEIGHTS_BASE = {
    WOOD_BURIAL: 30,
    ARMATTACK: 45,
    SPIKE: 65  // Higher weight for SPIKE
};
var WEIGHTS_AGGRESSIVE = {        // used when HP < AGGRESSIVE_HP_RATIO
    WOOD_BURIAL: 35,
    ARMATTACK: 50,
    SPIKE: 80  // Much higher in aggressive mode
};
var POWERS = {
    WOOD_BURIAL: 1.0,
    ARMATTACK: 1.5,
    SPIKE: 1.0  // Slightly lower power since we're shooting more
};

// ================= ENHANCED SAYINGS =================
var SAYINGS = {
    WOOD_BURIAL: {
        windup: [
            "Mokuton: Roots awaken!",
            "Forest, answer my call!",
            "Witness the power of wood!",
            "Nature's embrace approaches!",
            "The forest rises against you!"
        ],
        cast: [
            "Mokuton: Mokujūheki!",
            "Be consumed by the wood!",
            "Forest Burial Technique!",
            "Wood Style: Entomb!",
            "The trees claim you!"
        ]
    },
    ARMATTACK: {
        windup: [
            "Wood Arm, extend!",
            "Mokuton: Grappling strike!",
            "Feel the grip of nature!",
            "Wood Style: Arm Assault!",
            "Branch and vine, strike!"
        ],
        cast: [
            "Mokuton: Ude no Jutsu!",
            "Wood Arm Technique!",
            "Crushing grip!",
            "Nature's wrath strikes!",
            "Wood Style: Grapple!"
        ]
    },
    SPIKE: {
        windup: [
            "RAPID SPIKE BARRAGE!",
            "Mokuton: Machine Gun Spikes!",
            "Wood Style: Gatling Spikes!",
            "Feel the storm of wood!",
            "Piercing rain of spikes!"
        ],
        cast: [
            "Mokuton: Hari no Jutsu - RAPID FIRE!",
            "SPIKE VOLLEY!",
            "Wood Spike Barrage!",
            "Pierce through!",
            "Sharpened wood, FLY!"
        ]
    }
};

// ================= IMPORTS =================
var ItemMokuton = Java.type("net.narutomod.item.ItemMokuton");
var ItemStack = Java.type("net.minecraft.item.ItemStack");

// ================= HELPERS =================
function getStored(npc, key, defaultVal) {
    var d = npc.getStoreddata();
    if (!d.has(key)) {
        if (defaultVal !== undefined) d.put(key, defaultVal);
        return defaultVal;
    }
    return d.get(key);
}

function setStored(npc, key, val) {
    npc.getStoreddata().put(key, val);
}

function clamp(v, a, b) {
    return v < a ? a : (v > b ? b : v);
}

function weightedPick(weightObj) {
    var keys = [];
    var sum = 0;
    for (var k in weightObj) { keys.push(k); sum += weightObj[k]; }
    if (sum <= 0) return keys[0];
    var r = Math.random() * sum;
    var acc = 0;
    for (var i = 0; i < keys.length; i++) {
        acc += weightObj[keys[i]];
        if (r <= acc) return keys[i];
    }
    return keys[keys.length-1];
}

function isServerSide(npc) {
    try { return !npc.getMCEntity().world.isRemote; } catch (err) { return true; }
}

function callJutsuSafe(jutsuEnum, stack, entity, power) {
    try {
        jutsuEnum.jutsu.createJutsu(stack, entity, power);
        return true;
    } catch (err) {
        return false;
    }
}

function distToTarget(npc, mcTarget) {
    if (!mcTarget) return 9999;
    var e = npc.getMCEntity();
    var dx = e.posX - mcTarget.posX;
    var dy = e.posY - mcTarget.posY;
    var dz = e.posZ - mcTarget.posZ;
    return Math.sqrt(dx*dx + dy*dy + dz*dz);
}

function getRandomSaying(jutsu, type) {
    var sayings = SAYINGS[jutsu][type];
    return sayings[Math.floor(Math.random() * sayings.length)];
}

// ================= ULTRA-FAST SPIKE BURST =================
function executeSpikeBurst(npc, target) {
    var me = npc.getMCEntity();
    var phase = getStored(npc, "mok_phase", 0);
    var burstCount = (phase === 1) ? 6 : SPIKE_BURST_COUNT; // 6 when aggressive
    
    // Mega particle effect
    try {
        npc.spawnParticle("VILLAGER_HAPPY", npc.getX(), npc.getY()+1.5, npc.getZ(), 
            0.3, 0.5, 0.3, 20, 0);
    } catch(e) {}
    
    // FIRE ALL SPIKES AT ONCE - NO DELAY
    for (var i = 0; i < burstCount; i++) {
        var stack = new ItemStack(ItemMokuton.block);
        // Slight power variation for visual effect
        var spikePower = POWERS.SPIKE * (0.9 + (Math.random() * 0.2));
        callJutsuSafe(ItemMokuton.SPIKE, stack, me, spikePower);
    }
    
    return true;
}

// ================= ENHANCED TICK =================
function tick(event) {
    var npc = event.npc;
    if (!npc) return;

    // get MC entity and stored data
    var me;
    try { me = npc.getMCEntity(); } catch(err) { return; }

    // ACQUIRE TARGET: prefer attack target else nearby player
    var target = npc.getAttackTarget();
    if (!target) {
        // quick scan for a player within 18 blocks
        var nearby = npc.getWorld().getAllEntities(18);
        for (var i = 0; i < nearby.length; i++) {
            try { 
                var se = nearby[i]; 
                if (se.isPlayer && se.isPlayer()) { 
                    target = se.getMCEntity(); 
                    npc.setAttackTarget(target);
                    break; 
                } 
            } catch(e) {}
        }
    }
    if (!target) return; // not in combat

    // ================= INITIALIZE STORED VALUES =================
    var stored = npc.getStoreddata();
    if (!stored.has("mok_cd")) setStored(npc, "mok_cd", 0);
    if (!stored.has("mok_wind")) setStored(npc, "mok_wind", 0);
    if (!stored.has("mok_casting")) setStored(npc, "mok_casting", "");
    if (!stored.has("mok_phase")) setStored(npc, "mok_phase", 0);

    // ================= UPDATE COMBAT PHASE =================
    try {
        var hp = me.getHealth ? me.getHealth() : me.getEntityData && me.getEntityData().getFloat ? me.getEntityData().getFloat("Health") : null;
        var maxHp = me.getMaxHealth ? me.getMaxHealth() : null;
        if (hp !== null && maxHp !== null) {
            var ratio = clamp(hp / maxHp, 0.0, 1.0);
            if (ratio <= AGGRESSIVE_HP_RATIO) { 
                setStored(npc, "mok_phase", 1); 
            } else { 
                setStored(npc, "mok_phase", 0);
            }
        }
    } catch (err) { /* ignore */ }

    // ================= HANDLE WIND-UP =================
    var wind = getStored(npc, "mok_wind", 0);
    var casting = getStored(npc, "mok_casting", "");
    
    if (wind > 0) {
        // Visual effects during windup - MORE intense
        if (wind % 2 === 0) { // Every 2 ticks (more frequent)
            try {
                var particleCount = (casting === "WOOD_BURIAL") ? 10 : 7;
                var particleType = "VILLAGER_HAPPY";
                npc.spawnParticle(particleType, npc.getX(), npc.getY()+1, npc.getZ(), 
                    0, 0.4, 0, particleCount, 0);
            } catch(e) {}
        }
        
        // Count down windup
        wind--;
        setStored(npc, "mok_wind", wind);
        
        // Final tick of wind-up -> perform the cast
        if (wind === 0 && casting) {
            performJutsu(npc, casting, target);
            setStored(npc, "mok_casting", "");
        }
        return; // while winding up, do nothing else
    }

    // ================= COOLDOWN HANDLING =================
    var cd = getStored(npc, "mok_cd", 0);
    if (cd > 0) { 
        // Even during cooldown, HIGH chance to start a quick spike in aggressive mode
        var phase = getStored(npc, "mok_phase", 0);
        if (phase === 1 && Math.random() < 0.3) { // 30% chance when aggressive
            // Quick interrupt spike - single spike
            try {
                var stack = new ItemStack(ItemMokuton.block);
                callJutsuSafe(ItemMokuton.SPIKE, stack, me, POWERS.SPIKE * 0.8);
                // Reduce remaining cooldown by half
                setStored(npc, "mok_cd", Math.floor(cd / 2));
            } catch(e) {}
        }
        
        setStored(npc, "mok_cd", cd - 1); 
        return; 
    }

    // ================= CHOOSE AND CAST JUTSU =================
    var phase = getStored(npc, "mok_phase", 0);
    var weights = (phase === 1) ? WEIGHTS_AGGRESSIVE : WEIGHTS_BASE;
    
    // Tactical adjustment based on distance
    var distance = distToTarget(npc, target);
    if (distance > 12) {
        // Far away, prefer ARMATTACK (ranged) but also SPIKE
        weights.ARMATTACK += 15;
        weights.SPIKE += 10; // Spikes can still hit at range
    } else if (distance < 5) {
        // Very close, HEAVILY prefer SPIKE (quick burst)
        weights.SPIKE += 25;
        weights.WOOD_BURIAL += 5;
    }

    // Pick jutsu
    var pick = weightedPick(weights);

    // Determine if windup is needed
    var needsWindup = (pick === "WOOD_BURIAL" || pick === "ARMATTACK");

    if (needsWindup) {
        // Start windup - SHORTER windup for ARMATTACK
        var windupTime = (pick === "WOOD_BURIAL") ? WINDUP_TICKS : Math.floor(WINDUP_TICKS * 0.6);
        setStored(npc, "mok_wind", windupTime);
        setStored(npc, "mok_casting", pick);
        
        // Say windup line
        try { 
            var saying = getRandomSaying(pick, "windup");
            npc.say(saying); 
        } catch(e) {}
        
        return;
    }

    // SPIKE - INSTANT MEGA BURST
    if (pick === "SPIKE") {
        // Say spike line - use the faster, more aggressive sayings
        try { 
            var saying = getRandomSaying("SPIKE", "cast");
            npc.say(saying); 
        } catch(e) {}
        
        // EXECUTE SPIKE BURST IMMEDIATELY
        executeSpikeBurst(npc, target);
        
        // Set cooldown - SHORTER for spikes
        var cdSet = (phase === 1) ? Math.max(5, Math.floor(BASE_COOLDOWN * 0.4)) : Math.floor(BASE_COOLDOWN * 0.7);
        setStored(npc, "mok_cd", cdSet);
        return;
    }
}

// ================= ENHANCED performJutsu HELPER =================
function performJutsu(npc, pick, mcTarget) {
    var me = npc.getMCEntity();
    var stack = new ItemStack(ItemMokuton.block);
    var performed = false;
    var phase = getStored(npc, "mok_phase", 0);

    // Dynamic power adjustment based on phase
    var powerMultiplier = (phase === 1) ? 1.2 : 1.0;
    
    try {
        if (pick === "WOOD_BURIAL") {
            if (!isServerSide(npc)) return false;
            
            // Say cast line
            try { 
                var saying = getRandomSaying("WOOD_BURIAL", "cast");
                npc.say(saying); 
            } catch(e) {}
            
            performed = callJutsuSafe(ItemMokuton.WOODBURIAL, stack, me, POWERS.WOOD_BURIAL * powerMultiplier);
            
            // Post-cast effect
            if (performed) {
                try {
                    npc.spawnParticle("VILLAGER_HAPPY", npc.getX(), npc.getY()+1, npc.getZ(), 
                        0, 0.6, 0, 20, 0);
                } catch(e) {}
            }
            
        } else if (pick === "ARMATTACK") {
            // Say cast line
            try { 
                var saying = getRandomSaying("ARMATTACK", "cast");
                npc.say(saying); 
            } catch(e) {}
            
            performed = callJutsuSafe(ItemMokuton.ARMATTACK, stack, me, POWERS.ARMATTACK * powerMultiplier);
            
            // Post-cast effect for ARMATTACK
            if (performed) {
                try {
                    npc.spawnParticle("VILLAGER_HAPPY", npc.getX(), npc.getY()+1, npc.getZ(), 
                        0.3, 0.4, 0.3, 10, 0);
                } catch(e) {}
            }
            
        } else {
            // fallback to burial if unknown
            if (isServerSide(npc)) {
                performed = callJutsuSafe(ItemMokuton.WOODBURIAL, stack, me, POWERS.WOOD_BURIAL);
            }
        }
    } catch (err) {
        performed = false;
    }

    // Set cooldown based on jutsu and phase
    if (performed) {
        var cdSet = BASE_COOLDOWN;
        
        // Adjust cooldown based on jutsu type
        if (pick === "WOOD_BURIAL") cdSet = Math.floor(BASE_COOLDOWN * 1.1);
        if (pick === "ARMATTACK") cdSet = Math.floor(BASE_COOLDOWN * 0.9); // ARMATTACK gets shorter CD
        
        // MUCH shorter cooldown when aggressive
        if (phase === 1) cdSet = Math.max(8, Math.floor(cdSet * 0.5));
        
        setStored(npc, "mok_cd", cdSet);
    }

    return performed;
}

// ================= ADDITIONAL EVENT HANDLERS =================
function attacked(event) {
    // INSTANT counter-attack when hit
    var npc = event.npc;
    var attacker = event.source.getTrueSource();
    
    if (attacker && Math.random() < 0.6) { // 60% counter chance - HIGHER
        // Drastically reduce current cooldown
        var currentCD = getStored(npc, "mok_cd", 0);
        setStored(npc, "mok_cd", Math.max(0, currentCD - 20)); // More reduction
        
        // INSTANT SPIKE BURST counter (50% chance)
        if (Math.random() < 0.5) {
            try {
                npc.say("REVENGE SPIKE!");
                executeSpikeBurst(npc, attacker);
                setStored(npc, "mok_cd", 3); // Very short cooldown after counter
            } catch(e) {}
        }
    }
}

function target(event) {
    // Opening attack when acquiring target - ALWAYS spike burst
    var npc = event.npc;
    var target = event.target;
    
    if (target) {
        // Reset cooldown for opening attack
        setStored(npc, "mok_cd", 0);
        
        // 90% chance for opening attack - ALMOST ALWAYS
        if (Math.random() < 0.9) {
            // Start with SPIKE BURST
            try {
                npc.say("INITIAL SPIKE BARRAGE!");
                executeSpikeBurst(npc, target);
                setStored(npc, "mok_cd", 5); // Short cooldown after opener
            } catch(e) {}
        }
    }
}

function damaged(event) {
    // When taking damage, chance for immediate spike burst
    var npc = event.npc;
    var damage = event.damage;
    
    if (damage > 5 && Math.random() < 0.4) { // 40% chance when hit hard
        try {
            var target = npc.getAttackTarget();
            if (target) {
                npc.say("RAGE SPIKE!");
                executeSpikeBurst(npc, target);
                setStored(npc, "mok_cd", 4);
            }
        } catch(e) {}
    }
}