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 = `mlrs${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 handleMLRSFire(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 > 2000) {
        player.onScreenDisplay.setActionBar("§c目标超出范围！最大范围为2000个方块.");
        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_3", "multi_5", "multi_all"].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_3")) shotCount = 3;
    if (tank.hasTag("multi_5")) shotCount = 5;
    if (tank.hasTag("multi_all")) shotCount = currentAmmo;

    if (tank.hasTag("multi_all")) {
        if (currentAmmo <= 0) {
            player.onScreenDisplay.setActionBar(`§c没有弹药!`);
            player.playSound("note.bass", { pitch: 1.0, volume: 1.0 });
            return false;
        }
    } else 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;
        }

        let currentShot = animationsPlayed + 1;
        let animationName;

        if (tank.hasTag("single_fire")) {
            animationName = "animation.mlrs107.shot1";
        } else if (tank.hasTag("multi_3")) {
            animationName = `animation.mlrs107.shot${currentShot}`;
        } else if (tank.hasTag("multi_5")) {
            animationName = `animation.mlrs107.shot${currentShot}`;
        } else if (tank.hasTag("multi_all")) {
            currentShot = (animationsPlayed % 5) + 1;
            animationName = `animation.mlrs107.shot${currentShot}`;
        }

        tank.playAnimation(animationName);
        const tankPos = tank.location;
        const block = tank.dimension.getBlock({ x: Math.floor(tankPos.x), y: Math.floor(tankPos.y), z: Math.floor(tankPos.z) });
        block.setType("minecraft:light_block_15");

        system.runTimeout(() => {
            const block = tank.dimension.getBlock({ x: Math.floor(tankPos.x), y: Math.floor(tankPos.y), z: Math.floor(tankPos.z) });
            block.setType("minecraft:air");
        }, 5);

        const tankRotation = tank.getRotation();
        const missile = tank.dimension.spawnEntity("ttav:mlrs_missile",
            {
                x: tank.location.x,
                y: tank.location.y + 11,
                z: tank.location.z
            }
        );
        missile.setRotation({ x: 0, y: tankRotation.y, z: 0 });

        missileStates.set(missile.id, {
            direction: tankRotation.y,
            startTime: Date.now()
        });

        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 mlrs${i}`);
            } catch (error) {}
        }
    }
   
    nextTickingAreaId = 1;
});

const missileStates = new Map();
const missileVelocities = new Map();

function updateMissile(missile, yRotation) {
    if (!missile || !missile.isValid()) return;

    const velocity = missileVelocities.get(missile.id) ?? { x: 0, y: 0, z: 0 };
   
    const angleRadians = (yRotation + 90) * Math.PI / 180;
    const forwardX = Math.cos(angleRadians);
    const forwardZ = Math.sin(angleRadians);

    const speed = 3;
    velocity.x = forwardX * speed;
    velocity.y = speed;
    velocity.z = forwardZ * speed;

    const newX = missile.location.x + velocity.x;
    const newY = missile.location.y + velocity.y;
    const newZ = missile.location.z + velocity.z;

    missile.teleport(
        { x: newX, y: newY, z: newZ },
        { dimension: missile.dimension }
    );

    missileVelocities.set(missile.id, velocity);
}

system.runInterval(() => {
    for (const dimension of dimensions) {
        const dim = world.getDimension(dimension);
        if (!dim) continue;
       
        const missiles = dim.getEntities({ type: "ttav:mlrs_missile" });
        for (const missile of missiles) {
            const state = missileStates.get(missile.id);
            if (state) {
                updateMissile(missile, state.direction);
            }
        }
    }
}, 1);
