import { world, system, MolangVariableMap } from "@minecraft/server";
import { playTTAVLargeExplosionSounds } from "../TTAVLargeExplosionSoundHandler.js";
import { getMainAmmo, reduceMainAmmo } from "../AmmoSystem.js";

const firingStates = new Map();
let nextTickingAreaId = 1;

const dimensions = [
    "minecraft:overworld",
    "minecraft:nether",
    "minecraft:the_end"
];

function generateTickingAreaName() {
    const areaName = `arti${nextTickingAreaId++}`;
    if (nextTickingAreaId > 999) nextTickingAreaId = 1;
    return areaName;
}

function calculateRandomizedLocation(targetX, targetY, targetZ, dimension) {
    let validLocation = false;
    let location;
    const heightRange = dimension.heightRange;
    const maxAttempts = 50;
    let attempts = 0;

    while (!validLocation && attempts < maxAttempts) {
        attempts++;
        const randomX = targetX + (Math.random() * 60 - 30);
        const randomY = Math.max(heightRange.min, Math.min(heightRange.max, targetY + (Math.random() * 40 - 20)));
        const randomZ = targetZ + (Math.random() * 60 - 30);
       
        try {
            const block = dimension.getBlock({ x: randomX, y: randomY, z: randomZ });
            const blockBelow = dimension.getBlock({ x: randomX, y: randomY - 1, z: randomZ });
            const blockId = block.typeId;
            const blockBelowId = blockBelow.typeId;
           
            const isValidSpawnBlock = blockId === "minecraft:air" ||
                                    blockId === "minecraft:flowing_water" ||
                                    blockId === "minecraft:flowing_lava" ||
                                    blockId.startsWith("minecraft:light_block_");

            const isNotValidGroundBlock = blockBelowId === "minecraft:air" ||
                                        blockBelowId === "minecraft:flowing_water" ||
                                        blockBelowId === "minecraft:flowing_lava" ||
                                        blockBelowId.startsWith("minecraft:light_block_");

            if (isValidSpawnBlock && !isNotValidGroundBlock) {
                location = { x: randomX, y: randomY, z: randomZ };
                validLocation = true;
            }
        } catch (error) {
            continue;
        }
    }

    return location || { x: targetX, y: targetY, z: targetZ };
}

function createTickingArea(dimension, x, y, z) {
    const areaName = generateTickingAreaName();
    try {
        dimension.runCommand(`tickingarea add circle ${Math.floor(x)} ${Math.floor(y)} ${Math.floor(z)} 3 ${areaName}`);
        return areaName;
    } catch (error) {
        return null;
    }
}

function removeTickingArea(areaName) {
    for (const dimId of dimensions) {
        const dimension = world.getDimension(dimId);
        if (!dimension) continue;
        try {
            dimension.runCommand(`tickingarea remove ${areaName}`);
        } catch (error) {}
    }
}

export function handleArtilleryFire(player, tank) {
    const currentAmmo = getMainAmmo(tank);
   
    if (currentAmmo <= 0) {
        player.onScreenDisplay.setActionBar("§c没有弹药!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    if (firingStates.get(tank.id)) {
        player.onScreenDisplay.setActionBar("§c开火!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    if (!tank.hasTag("indirect_fire")) {
        player.onScreenDisplay.setActionBar("§c未设置间接射击模式!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    const x = tank.getDynamicProperty("target_x");
    const y = tank.getDynamicProperty("target_y");
    const z = tank.getDynamicProperty("target_z");
   
    if (x === undefined || y === undefined || z === undefined) {
        player.onScreenDisplay.setActionBar("§c未设置目标坐标!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    const distance = Math.sqrt(
        Math.pow(x - tank.location.x, 2) +
        Math.pow(z - tank.location.z, 2)
    );

    if (distance > 3000) {
        player.onScreenDisplay.setActionBar("§c目标超出范围！最大范围为3000个方块.");
        player.playSound("note.bass", { pitch: 0.5, volume: 1.0 });
        return;
    }

    const deltaX = x - tank.location.x;
    const deltaZ = z - tank.location.z;
    const angleRadians = Math.atan2(deltaZ, deltaX);
    const angleDegrees = (angleRadians * 180 / Math.PI) - 90;
    tank.setRotation({ x: 0, y: angleDegrees });

    const hasFireMode = ["multi_2", "multi_3", "multi_4", "multi_5"].some(tag => tank.hasTag(tag));
    if (!hasFireMode && !tank.hasTag("single_fire")) {
        player.onScreenDisplay.setActionBar("§c未设置开火模式!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    const hasFiringRate = ["firing_rate_1_second", "firing_rate_2_second", "firing_rate_3_second"]
        .some(tag => tank.hasTag(tag));
    if (!hasFiringRate) {
        player.onScreenDisplay.setActionBar("§c未设置射速!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    let entityToSpawn = "";
    if (tank.getProperty("ttav:normal_shell")) {
        entityToSpawn = "ttav:normal_large";
    } else if (tank.getProperty("ttav:thermobaric_shell")) {
        entityToSpawn = "ttav:thermobaric_large";
    } else if (tank.getProperty("ttav:cluster_shell")) {
        entityToSpawn = "ttav:cluster_large";
    } else {
        player.onScreenDisplay.setActionBar("§c未选择子弹类型!");
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    let shotCount = 1;
    if (tank.hasTag("multi_2")) shotCount = 2;
    if (tank.hasTag("multi_3")) shotCount = 3;
    if (tank.hasTag("multi_4")) shotCount = 4;
    if (tank.hasTag("multi_5")) shotCount = 5;

    if (currentAmmo < shotCount) {
        player.onScreenDisplay.setActionBar(`§c弹药不够！需要${shotCount}颗子弹.`);
        player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
        return false;
    }

    let delayTicks = 20;
    if (tank.hasTag("firing_rate_2_second")) delayTicks = 40;
    if (tank.hasTag("firing_rate_3_second")) delayTicks = 60;

    firingStates.set(tank.id, true);

    const targetAreaName = createTickingArea(tank.dimension, x, y, z);
    const sourceAreaName = createTickingArea(tank.dimension, tank.location.x, tank.location.y, tank.location.z);

    if (!targetAreaName || !sourceAreaName) {
        player.onScreenDisplay.setActionBar("§c未能创建区域!");
        return false;
    }

    let animationsPlayed = 0;
    const animationInterval = system.runInterval(() => {
        if (animationsPlayed >= shotCount) {
            system.clearRun(animationInterval);
           
            system.runTimeout(() => {
                let spawned = 0;
                const spawnInterval = system.runInterval(() => {
                    if (spawned >= shotCount) {
                        system.clearRun(spawnInterval);
                        firingStates.delete(tank.id);
                       
                        system.runTimeout(() => {
                            removeTickingArea(targetAreaName);
                            removeTickingArea(sourceAreaName);
                        }, 220);
                       
                        return;
                    }

                    if (reduceMainAmmo(tank)) {
                        const randomLocation = calculateRandomizedLocation(x, y, z, tank.dimension);
                        const spawnedEntity = tank.dimension.spawnEntity(entityToSpawn, randomLocation);
                        if (entityToSpawn !== "ttav:cluster_large") {
                            playTTAVLargeExplosionSounds(spawnedEntity);
                        }
                        spawned++;
                    }
                }, delayTicks);
            }, 100);

            return;
        }

        tank.playAnimation("animation.artillery107.fire_main");
        tank.dimension.spawnParticle("ttav:ground_smoke_aftermath_shoot_large",
            { x: tank.location.x, y: tank.location.y+0.2, z: tank.location.z },
            new MolangVariableMap()
        );
        player.runCommand(`/camerashake add @p[r=4] 0.2 0.2 rotational`);
        animationsPlayed++;
    }, delayTicks);

    return true;
}

world.afterEvents.playerSpawn.subscribe((ev) => {
    const player = ev.player;
   
    for (const dimId of dimensions) {
        const dimension = world.getDimension(dimId);
        if (!dimension) continue;
        for (let i = 1; i <= 100; i++) {
            try {
                dimension.runCommand(`tickingarea remove arti${i}`);
            } catch (error) {}
        }
    }
   
    nextTickingAreaId = 1;
});
