import { world, system } from "@minecraft/server";

/**
 * MineCollect Game Logic (English Ver 1.3)
 */

// Game State Management
const GameState = {
    IDLE: "idle",
    RUNNING: "running"
};

// Game Rule Definitions
const RuleType = {
    ENTRY: "entry",             // Victory upon obtaining the specified item first
    DELIVERY: "delivery",       // Victory upon bringing the specified item to the goal
    FLOOR: "floor",             // Compete for score by collecting items from a public list
    RANDOM_FLOOR: "random",     // Floor rule with bonus and normal items
    COMPLETE: "complete",       // Victory upon collecting all specified items
    MISSION: "mission",         // Individual missions for each player
    MYSTERY: "mystery"          // Victory based on holding the hidden target item at the end
};

// Default Survival Item List
const DEFAULT_SURVIVAL_ITEMS = [
    // Wood & Plants
    "minecraft:oak_log", "minecraft:spruce_log", "minecraft:birch_log", "minecraft:jungle_log", "minecraft:acacia_log", "minecraft:dark_oak_log", "minecraft:cherry_log", "minecraft:mangrove_log",
    "minecraft:wheat_seeds", "minecraft:pumpkin_seeds", "minecraft:melon_seeds", "minecraft:beetroot_seeds", "minecraft:carrot", "minecraft:potato",
    "minecraft:bamboo", "minecraft:sugar_cane", "minecraft:cactus", "minecraft:brown_mushroom", "minecraft:red_mushroom", "minecraft:sweet_berries",
    // Stones & Ores
    "minecraft:cobblestone", "minecraft:granite", "minecraft:diorite", "minecraft:andesite", "minecraft:sand", "minecraft:red_sand", "minecraft:gravel", "minecraft:clay_ball",
    "minecraft:coal", "minecraft:raw_iron", "minecraft:raw_copper", "minecraft:raw_gold", "minecraft:redstone", "minecraft:lapis_lazuli", "minecraft:diamond", "minecraft:emerald", "minecraft:amethyst_shard",
    // Mob Drops
    "minecraft:rotten_flesh", "minecraft:bone", "minecraft:spider_eye", "minecraft:string", "minecraft:gunpowder", "minecraft:ender_pearl", "minecraft:slime_ball",
    // Animals & Food
    "minecraft:beef", "minecraft:porkchop", "minecraft:chicken", "minecraft:mutton", "minecraft:rabbit", "minecraft:cod", "minecraft:salmon", "minecraft:leather", "minecraft:feather", "minecraft:egg", "minecraft:white_wool",
    // Nether
    "minecraft:netherrack", "minecraft:soul_sand", "minecraft:magma", "minecraft:quartz", "minecraft:gold_nugget", "minecraft:blaze_rod", "minecraft:ghast_tear", "minecraft:nether_wart",
    // Misc
    "minecraft:flint", "minecraft:snowball", "minecraft:obsidian", "minecraft:honeycomb", "minecraft:ink_sac", "minecraft:kelp"
];

// Nether Survival Item List
const NETHER_SURVIVAL_ITEMS = [
    "minecraft:netherrack", "minecraft:soul_sand", "minecraft:soul_soil", "minecraft:magma", "minecraft:glowstone_dust",
    "minecraft:quartz", "minecraft:gold_nugget", "minecraft:blaze_rod", "minecraft:ghast_tear", "minecraft:nether_wart",
    "minecraft:crimson_nylium", "minecraft:warped_nylium", "minecraft:crimson_stem", "minecraft:warped_stem", "minecraft:shroomlight",
    "minecraft:blackstone", "minecraft:basalt", "minecraft:magma_cream", "minecraft:ender_pearl", "minecraft:crying_obsidian"
];

// End Survival Item List
const END_SURVIVAL_ITEMS = [
    "minecraft:end_stone", "minecraft:chorus_fruit", "minecraft:popped_chorus_fruit", "minecraft:purpur_block",
    "minecraft:end_rod", "minecraft:ender_pearl", "minecraft:dragon_head", "minecraft:dragon_egg", "minecraft:shulker_shell", "minecraft:dragon_breath"
];

class MineCollect {
    constructor() {
        this.state = GameState.IDLE;
        this.mode = RuleType.ENTRY; // Default rule
        this.targetItems = [];      // List of target item IDs
        this.bonusItems = [];       // Bonus items for Random Floor mode
        this.playerMissions = new Map(); // Player missions assignment
        this.collectedItems = new Set(); // Items already collected in Floor modes
        this.collectionHistory = new Map(); // Item ID -> Finder Name record
        this.currentTargetItem = null;   // Single target for Entry/Delivery/Mystery
        this.startTime = 0;
        this.timeLimit = 300;       // Seconds
        this.startPosition = null;  // Game start position (for Delivery goal)
        this.scoreboardId = "mc_score";
        this.gameCount = 0;         // Game round counter
        
        this.adminParticipates = true; // Does admin participate in the game?
        this.spectatorCooldown = 0;    // Cooldown for spectator teleport

        system.run(() => {
            this.init();
        });
    }

    init() {
        if (!world.scoreboard.getObjective(this.scoreboardId)) {
            world.scoreboard.addObjective(this.scoreboardId, "§lMineCollect Score");
        }

        // V1.1 & V1.2: Force enable coordinates & Set difficulty to Peaceful on init
        system.run(() => {
            try {
                const overworld = world.getDimension("overworld");
                if (overworld) {
                    overworld.runCommand("gamerule showcoordinates true");
                    overworld.runCommand("difficulty peaceful"); // V1.2
                }
            } catch (e) {}
        });

        system.runInterval(() => {
            this.gameLoop();
        }, 5);

        world.beforeEvents.chatSend.subscribe((event) => this.handleChat(event));
        world.beforeEvents.playerInteractWithBlock.subscribe((event) => this.handleBlockInteract(event));
        
        // Player spawn event -> Grant Admin & V1.1 Force coordinates
        world.afterEvents.playerSpawn.subscribe((event) => {
            this.checkAdminTag(event.player);
            try {
                const dim = event.player.dimension;
                dim.runCommand("gamerule showcoordinates true");
            } catch (e) {}
        });
    }

    checkAdminTag(player) {
        const allPlayers = world.getAllPlayers();
        const hasAdmin = allPlayers.some(p => p.hasTag("admin"));
        if (!hasAdmin) {
            player.addTag("admin");
            player.sendMessage("§a[System] You have been granted admin privileges (admin tag).");
        }
    }

    handleChat(event) {
        const msg = event.message;
        const player = event.sender;
        
        if (!msg.startsWith(".mc")) return;
        
        event.cancel = true;

        if (!player.hasTag("admin")) {
            player.sendMessage("§cOnly players with admin privileges can execute this command.");
            return;
        }

        system.run(() => {
            const args = msg.trim().split(/\s+/);
            const command = args[1];

            if (!command) {
                this.showHelp(player);
                return;
            }
            
            switch (command) {
                case "setting":
                    if (args[2] === "default" || args[2] === "nether" || args[2] === "end") {
                        this.loadPresetItems(player, args[2]);
                    } else {
                        this.handleSettingCommand(player);
                    }
                    break;
                case "setitems":
                    this.registerItemsFromInventory(player);
                    break;
                case "setrule":
                    const mode = args[2];
                    const time = parseInt(args[3]);
                    this.setRule(player, mode, time);
                    break;
                case "admin":
                    const sub = args[2];
                    if (sub === "join") {
                        this.adminParticipates = true;
                        player.sendMessage("§a[Setting] Admin will participate in the game.");
                    } else if (sub === "spec") {
                        this.adminParticipates = false;
                        player.sendMessage("§e[Setting] Admin will be in Spectator mode.");
                    } else {
                        player.sendMessage("§cUsage: .mc admin <join|spec>");
                    }
                    break;
                case "start":
                    this.startGame(player);
                    break;
                case "end":
                    this.endGame("Forced termination.");
                    break;
                case "help":
                    this.showHelp(player);
                    break;
                default:
                    player.sendMessage("§cUnknown command.");
                    this.showHelp(player);
            }
        });
    }

    showHelp(player) {
        player.sendMessage("§l§a=== MineCollect Commands ===");
        player.sendMessage("§e.mc setting [default|nether|end] §7- Toggle setup mode / Register presets");
        player.sendMessage("§e.mc admin <join|spec> §7- Toggle Admin participation");
        player.sendMessage("§e.mc start §7- Start Game");
        player.sendMessage("§e.mc end §7- End Game");
        player.sendMessage("§e.mc setrule <mode> [time] §7- Set Rules");
        player.sendMessage("§7Modes: entry, delivery, floor, random, complete, mission, mystery");
    }

    resetPlayerStatus(player) {
        const dimension = player.dimension;
        const playerName = `"${player.name}"`;
        
        try {
            const inventory = player.getComponent("inventory");
            if (inventory && inventory.container) {
                inventory.container.clearAll();
            }
            
            dimension.runCommand(`clear ${playerName}`);
            dimension.runCommand(`effect ${playerName} clear`);
            dimension.runCommand(`effect ${playerName} saturation 1 255 true`);
            dimension.runCommand(`effect ${playerName} instant_health 1 255 true`);
            dimension.runCommand(`gamemode survival ${playerName}`);
            
        } catch (e) {}
    }

    // Standardize coordinate string format
    formatCoordinate(x, y, z) {
        return `X: ${Math.floor(x)}, Y: ${Math.floor(y)}, Z: ${Math.floor(z)}`;
    }

    // Search for ground (non-air block) downwards from current position
    findGroundY(dimension, x, startY, z) {
        for (let y = startY; y > -64; y--) {
            try {
                const block = dimension.getBlock({ x: Math.floor(x), y: y - 1, z: Math.floor(z) });
                if (block && block.typeId !== "minecraft:air") {
                    return y;
                }
            } catch (e) {
                break;
            }
        }
        return startY;
    }

    handleSettingCommand(player) {
        const isSettingMode = player.hasTag("mc_setting");
        const dimension = player.dimension;
        const playerName = `"${player.name}"`;

        const registeredCount = this.registerItemsFromInventory(player);

        if (registeredCount > 0) {
            player.removeTag("mc_setting");

            const inventory = player.getComponent("inventory");
            if (inventory && inventory.container) {
                inventory.container.clearAll();
            }

            dimension.runCommand(`effect ${playerName} clear`); 
            dimension.runCommand(`gamemode survival ${playerName}`); 
            
            player.sendMessage("§a[Setup Complete] Items have been registered.");
            player.sendMessage("§7Inventory and effects cleared. Returned to Survival mode.");

        } else {
            if (!isSettingMode) {
                player.addTag("mc_setting");
                dimension.runCommand(`gamemode creative ${playerName}`);
                player.sendMessage("§e[Setup Mode] Switched to Creative mode.");
                player.sendMessage("§7Please prepare the items for the game in your inventory.");
                player.sendMessage("§7When ready, type §f.mc setting §7 again to register and return.");
            } else {
                player.removeTag("mc_setting");
                dimension.runCommand(`gamemode survival ${playerName}`);
                player.sendMessage("§e[Setup Reset] No items registered. Setup mode reset.");
                player.sendMessage("§7Type §f.mc setting §7 again to start setup mode.");
            }
        }
    }

    loadPresetItems(player, type) {
        if (type === "default") {
            this.targetItems = [...DEFAULT_SURVIVAL_ITEMS];
            player.sendMessage(`§a[Default Setting] Registered ${this.targetItems.length} overworld items.`);
        } else if (type === "nether") {
            this.targetItems = [...NETHER_SURVIVAL_ITEMS];
            player.sendMessage(`§a[Nether Setting] Registered ${this.targetItems.length} nether items.`);
        } else if (type === "end") {
            this.targetItems = [...END_SURVIVAL_ITEMS];
            player.sendMessage(`§a[End Setting] Registered ${this.targetItems.length} end items.`);
        }
    }

    registerItemsFromInventory(player) {
        const inventory = player.getComponent("inventory").container;
        const tempItems = [];
        for (let i = 0; i < inventory.size; i++) {
            const item = inventory.getItem(i);
            if (item) {
                tempItems.push(item.typeId);
            }
        }
        if (tempItems.length > 0) {
            this.targetItems = tempItems;
            return tempItems.length;
        } else {
            return 0;
        }
    }

    setRule(player, mode, time) {
        const validModes = Object.values(RuleType);
        if (!validModes.includes(mode)) {
            player.sendMessage(`§cInvalid mode. Available: ${validModes.join(", ")}`);
            return;
        }
        this.mode = mode;
        if (time) this.timeLimit = time;

        const isUnlimited = [RuleType.ENTRY, RuleType.DELIVERY, RuleType.COMPLETE, RuleType.MISSION].includes(mode);
        const timeMsg = isUnlimited ? "None" : `${this.timeLimit}s`;
        player.sendMessage(`§aRule set to [${mode}]. Time Limit: ${timeMsg}`);
    }

    startGame(player) {
        if (this.targetItems.length === 0 && this.mode !== RuleType.MYSTERY) {
            player.sendMessage("§cTarget items not set. Please run .mc setting or .mc setitems.");
            return;
        }

        // V1.2: Set difficulty to normal on start
        player.dimension.runCommand("difficulty normal");

        this.gameCount++;
        const tpCoord = this.gameCount * 1000;
        const dimension = player.dimension;
        
        let participants = [];
        if (this.adminParticipates) {
            participants = world.getAllPlayers();
        } else {
            participants = world.getAllPlayers().filter(p => !p.hasTag("admin"));
        }

        if (participants.length === 0) {
            player.sendMessage("§cNo participants found.");
            return;
        }

        participants.forEach(p => {
            this.resetPlayerStatus(p);
        });
        
        world.getAllPlayers().forEach(p => p.removeTag("participant"));
        participants.forEach(p => p.addTag("participant"));

        dimension.runCommand(`spreadplayers ${tpCoord} ${tpCoord} 1 10 @a[tag=participant]`);
        dimension.runCommand(`effect @a[tag=participant] resistance 30 255 true`);

        if (!this.adminParticipates) {
            world.getAllPlayers().forEach(p => {
                if (p.hasTag("admin")) {
                    p.dimension.runCommand(`gamemode spectator "${p.name}"`);
                    p.sendMessage("§eYou are in Spectator mode. Look straight up to teleport to a random player.");
                }
            });
        }

        const pendingPlayers = new Set(participants.map(p => p.id));
        this.startPosition = null; // Reset goal position

        const checkInterval = system.runInterval(() => {
            if (pendingPlayers.size === 0) {
                system.clearRun(checkInterval);
                return;
            }

            world.getAllPlayers().forEach(p => {
                if (pendingPlayers.has(p.id)) {
                    const distCheck = Math.abs(p.location.x - tpCoord) < 200 && Math.abs(p.location.z - tpCoord) < 200;
                    
                    let isSafeGround = false;
                    try {
                        const y = Math.floor(p.location.y - 1);
                        if (y > -64 && y < 320) {
                            const block = p.dimension.getBlock({ x: Math.floor(p.location.x), y: y, z: Math.floor(p.location.z) });
                            if (block && block.typeId !== "minecraft:air") {
                                isSafeGround = true;
                            }
                        }
                    } catch (e) {}

                    if (p.isOnGround && distCheck && isSafeGround) {
                        const playerName = `"${p.name}"`;
                        try {
                            const x = Math.floor(p.location.x);
                            const y = Math.floor(p.location.y);
                            const z = Math.floor(p.location.z);
                            p.dimension.runCommand(`spawnpoint ${playerName} ${x} ${y} ${z}`);
                            p.sendMessage(`§aSpawn point set at (${this.formatCoordinate(x, y, z)})`);

                            if (this.mode === RuleType.DELIVERY && !this.startPosition) {
                                const gy = this.findGroundY(dimension, x, y, z);
                                this.startPosition = { x: x, y: gy + 3, z: z };
                                
                                dimension.runCommand(`setblock ${x} ${gy} ${z} bedrock`);
                                dimension.runCommand(`setblock ${x} ${gy + 1} ${z} bedrock`);
                                dimension.runCommand(`setblock ${x} ${gy + 2} ${z} gold_block`);
                                dimension.runCommand(`setblock ${x} ${gy + 3} ${z} beacon`);
                                world.sendMessage(`§eGoal (Beacon) generated! (${this.formatCoordinate(x, gy + 3, z)})`);
                            }

                        } catch(e) {}
                        pendingPlayers.delete(p.id);
                    }
                }
            });
        }, 10);

        system.runTimeout(() => {
            if (pendingPlayers.size > 0) {
                system.clearRun(checkInterval);
            }
        }, 400);

        system.runTimeout(() => {
            this.state = GameState.RUNNING;
            this.startTime = system.currentTick;
            this.collectedItems.clear();
            this.collectionHistory.clear(); // Reset history
            this.currentTargetItem = null;

            if (this.mode === RuleType.DELIVERY && !this.startPosition) {
                const fallbackP = participants[0];
                if (fallbackP) {
                    const x = Math.floor(fallbackP.location.x);
                    let y = Math.floor(fallbackP.location.y);
                    const z = Math.floor(fallbackP.location.z);
                    y = this.findGroundY(dimension, x, y, z);

                    this.startPosition = { x: x, y: y + 3, z: z };
                    dimension.runCommand(`setblock ${x} ${y} ${z} bedrock`);
                    dimension.runCommand(`setblock ${x} ${y + 1} ${z} bedrock`);
                    dimension.runCommand(`setblock ${x} ${y + 2} ${z} gold_block`);
                    dimension.runCommand(`setblock ${x} ${y + 3} ${z} beacon`);
                    world.sendMessage(`§eGoal generated (Fallback) (${this.formatCoordinate(x, y + 3, z)})`);
                }
            }

            world.scoreboard.removeObjective(this.scoreboardId);
            world.scoreboard.addObjective(this.scoreboardId, "§lMineCollect Score");
            const objective = world.scoreboard.getObjective(this.scoreboardId);

            if (this.mode === RuleType.MISSION) {
                const shuffledItems = [...this.targetItems].sort(() => 0.5 - Math.random());
                participants.forEach((p, index) => {
                    objective.setScore(p, 0);
                    const item = shuffledItems[index % shuffledItems.length];
                    this.playerMissions.set(p.name, item);
                    p.sendMessage(`§bYour Mission Item: ${item.replace("minecraft:", "")}`);
                });
            } else {
                participants.forEach(p => objective.setScore(p, 0));
            }

            // Decide single target for Entry, Delivery, Mystery
            if (this.mode === RuleType.ENTRY || this.mode === RuleType.DELIVERY || this.mode === RuleType.MYSTERY) {
                const randomIndex = Math.floor(Math.random() * this.targetItems.length);
                this.currentTargetItem = this.targetItems[randomIndex];
            }

            if (this.mode === RuleType.RANDOM_FLOOR) {
                const shuffled = [...this.targetItems].sort(() => 0.5 - Math.random());
                this.bonusItems = shuffled.slice(0, Math.ceil(this.targetItems.length / 2));
            }

            world.sendMessage(`§l§e=== MineCollect GAME START! (Round ${this.gameCount}) ===`);
            world.sendMessage(`§eMode: ${this.mode}`);

            if ([RuleType.ENTRY, RuleType.DELIVERY, RuleType.COMPLETE, RuleType.MISSION].includes(this.mode)) {
                world.sendMessage(`§eTime Limit: None`);
            } else {
                world.sendMessage(`§eTime Limit: ${this.timeLimit}s`);
            }

            // Notification: Hide target for Mystery mode
            if (this.mode === RuleType.ENTRY || this.mode === RuleType.DELIVERY) {
                if (this.currentTargetItem) {
                    world.sendMessage(`§a[Target Item] §f${this.currentTargetItem.replace("minecraft:", "")}`);
                }
            } else if (this.mode !== RuleType.MISSION && this.mode !== RuleType.MYSTERY) {
                const itemList = this.targetItems.map(id => id.replace("minecraft:", "")).join(", ");
                world.sendMessage(`§a[Target Items List] §f${itemList}`);
            } else if (this.mode === RuleType.MYSTERY) {
                // Show candidates for Mystery
                const itemList = this.targetItems.map(id => id.replace("minecraft:", "")).join(", ");
                world.sendMessage(`§a[Candidate Items (One is the target)] §f${itemList}`);
            }

        }, 100);
    }

    endGame(reason, winner = null) {
        system.run(() => {
            this.state = GameState.IDLE;
            world.sendMessage("§l§c=== GAME FINISHED ===");
            world.sendMessage(`§eReason: ${reason}`);

            if (winner) {
                world.sendMessage(`§l§6Winner: ${winner.name}!`);
                world.getAllPlayers().forEach(p => p.playSound("random.levelup"));
            } else {
                this.announceScoreResults();
            }

            world.getAllPlayers().forEach(p => {
                this.resetPlayerStatus(p);
            });

            // V1.2: Set difficulty back to peaceful on end
            try {
                const overworld = world.getDimension("overworld");
                overworld.runCommand("difficulty peaceful");
            } catch(e) {}
        });
    }

    announceScoreResults() {
        try {
            const objective = world.scoreboard.getObjective(this.scoreboardId);
            if (!objective) return;

            const players = world.getAllPlayers();
            let topScore = -1;
            let topPlayers = [];

            players.forEach(p => {
                if (!this.adminParticipates && p.hasTag("admin")) return;

                if (this.mode === RuleType.MYSTERY) {
                    let score = 0;
                    const inv = p.getComponent("inventory").container;
                    for (let i = 0; i < inv.size; i++) {
                        const item = inv.getItem(i);
                        // Fix: Only count the hidden target item
                        if (item && item.typeId === this.currentTargetItem) {
                            score += item.amount;
                        }
                    }
                    objective.setScore(p, score);
                }

                const score = objective.getScore(p) ?? 0;
                if (score > topScore) {
                    topScore = score;
                    topPlayers = [p.name];
                } else if (score === topScore) {
                    topPlayers.push(p.name);
                }
            });

            world.sendMessage(`§aHigh Score: ${topScore} points (${topPlayers.join(", ")})`);

            // --- Detailed Report ---
            
            // Mystery: Reveal target
            if (this.mode === RuleType.MYSTERY) {
                const hit = this.currentTargetItem.replace("minecraft:", "");
                world.sendMessage(`§b[Target Item Revealed] §f${hit}`);
            }

            // Floor / Random Floor: History
            if (this.mode === RuleType.FLOOR || this.mode === RuleType.RANDOM_FLOOR) {
                world.sendMessage("§b=== Collection History ===");
                for (const itemId of this.targetItems) {
                    const shortName = itemId.replace("minecraft:", "");
                    const finder = this.collectionHistory.get(itemId);
                    let status = "";

                    if (this.mode === RuleType.RANDOM_FLOOR) {
                        const isBonus = this.bonusItems.includes(itemId);
                        status = isBonus ? " §e(Bonus/10pts)" : " §8(Normal/0pts)";
                    }

                    if (finder) {
                        world.sendMessage(`§7- ${shortName}${status} : §a${finder}`);
                    } else {
                        world.sendMessage(`§7- ${shortName}${status} : §8Not Found`);
                    }
                }
            }

        } catch (e) {
            world.sendMessage("§cError calculating scores.");
        }
    }

    gameLoop() {
        if (this.spectatorCooldown > 0) {
            this.spectatorCooldown--;
        } else if (!this.adminParticipates && this.state === GameState.RUNNING) {
            for (const p of world.getAllPlayers()) {
                if (p.hasTag("admin")) {
                    const rot = p.getRotation();
                    if (rot.x < -85) {
                        this.teleportSpectatorToRandomPlayer(p);
                        this.spectatorCooldown = 20;
                    }
                }
            }
        }

        if (this.state !== GameState.RUNNING) return;

        const isTimeLimitEnabled = ![
            RuleType.ENTRY,
            RuleType.DELIVERY,
            RuleType.COMPLETE,
            RuleType.MISSION
        ].includes(this.mode);

        if (isTimeLimitEnabled) {
            const elapsedTicks = system.currentTick - this.startTime;
            const remainingSeconds = this.timeLimit - Math.floor(elapsedTicks / 20);

            if (remainingSeconds <= 0) {
                this.endGame("Time's up");
                return;
            }

            world.getAllPlayers().forEach(p => {
                p.onScreenDisplay.setActionBar(`Time Remaining: ${remainingSeconds}s`);
            });
        } else {
            const elapsedTicks = system.currentTick - this.startTime;
            const totalSeconds = Math.floor(elapsedTicks / 20);
            const minutes = Math.floor(totalSeconds / 60);
            const seconds = totalSeconds % 60;
            const timeString = `${minutes}:${seconds.toString().padStart(2, '0')}`;

            world.getAllPlayers().forEach(p => {
                p.onScreenDisplay.setActionBar(`§aElapsed Time: ${timeString}`);
            });
        }

        let participants = [];
        if (this.adminParticipates) {
            participants = world.getAllPlayers();
        } else {
            participants = world.getAllPlayers().filter(p => !p.hasTag("admin"));
        }

        switch (this.mode) {
            case RuleType.ENTRY:
                this.checkEntryMode(participants);
                break;
            case RuleType.COMPLETE:
                this.checkCompleteMode(participants);
                break;
            case RuleType.MISSION:
                this.checkMissionMode(participants);
                break;
            case RuleType.FLOOR:
                this.checkFloorMode(participants, false);
                break;
            case RuleType.RANDOM_FLOOR:
                this.checkFloorMode(participants, true);
                break;
        }
    }

    teleportSpectatorToRandomPlayer(admin) {
        const targets = world.getAllPlayers().filter(p => !p.hasTag("admin"));
        if (targets.length === 0) return;

        const target = targets[Math.floor(Math.random() * targets.length)];
        const targetName = `"${target.name}"`;
        const adminName = `"${admin.name}"`;

        try {
            admin.dimension.runCommand(`tp ${adminName} ${targetName}`);
            admin.sendMessage(`§eTeleported to ${target.name}.`);
        } catch(e) {}
    }

    checkEntryMode(players) {
        for (const player of players) {
            const inv = player.getComponent("inventory").container;
            for (let i = 0; i < inv.size; i++) {
                const item = inv.getItem(i);
                if (item && item.typeId === this.currentTargetItem) {
                    this.endGame(`Obtained ${item.typeId}`, player);
                    return;
                }
            }
        }
    }

    checkCompleteMode(players) {
        for (const player of players) {
            const inv = player.getComponent("inventory").container;
            const heldItems = new Set();
            for (let i = 0; i < inv.size; i++) {
                const item = inv.getItem(i);
                if (item) heldItems.add(item.typeId);
            }

            const isComplete = this.targetItems.every(target => heldItems.has(target));
            if (isComplete) {
                this.endGame("All items completed", player);
                return;
            }
        }
    }

    checkMissionMode(players) {
        for (const player of players) {
            const target = this.playerMissions.get(player.name);
            if (!target) continue;

            const inv = player.getComponent("inventory").container;
            for (let i = 0; i < inv.size; i++) {
                const item = inv.getItem(i);
                if (item && item.typeId === target) {
                    this.endGame(`Mission item (${target}) obtained`, player);
                    return;
                }
            }
        }
    }

    checkFloorMode(players, isRandom) {
        const objective = world.scoreboard.getObjective(this.scoreboardId);
        let allCollected = true;

        for (const target of this.targetItems) {
            if (!this.collectedItems.has(target)) {
                allCollected = false;
                break;
            }
        }

        if (isRandom) {
            const allBonusCollected = this.bonusItems.every(id => this.collectedItems.has(id));
            if (allBonusCollected) {
                this.endGame("All bonus items collected");
                return;
            }
        } else {
            if (allCollected && this.targetItems.length > 0) {
                this.endGame("All items collected");
                return;
            }
        }

        for (const player of players) {
            const inv = player.getComponent("inventory").container;
            for (let i = 0; i < inv.size; i++) {
                const item = inv.getItem(i);
                if (item && this.targetItems.includes(item.typeId) && !this.collectedItems.has(item.typeId)) {
                    this.collectedItems.add(item.typeId);
                    
                    // Add to history
                    if (!this.collectionHistory.has(item.typeId)) {
                        this.collectionHistory.set(item.typeId, player.name);
                    }

                    let points = 0;
                    if (isRandom) {
                        if (this.bonusItems.includes(item.typeId)) {
                            points = 10;
                            world.sendMessage(`§a${player.name} found BONUS (${item.typeId})! +10pts`);
                        } else {
                            points = 0;
                            world.sendMessage(`§7${player.name} found normal item (${item.typeId})... 0pts`);
                        }
                    } else {
                        points = 1;
                        world.sendMessage(`§a${player.name} found ${item.typeId}! +1pt`);
                    }

                    if (points > 0) {
                        const currentScore = objective.getScore(player) ?? 0;
                        objective.setScore(player, currentScore + points);
                    }
                    inv.setItem(i, undefined); 
                }
            }
        }
    }

    handleBlockInteract(event) {
        if (this.state === GameState.RUNNING && 
            this.mode === RuleType.DELIVERY && 
            this.startPosition) {
            
            const block = event.block;
            if (block.typeId === "minecraft:beacon" &&
                block.x === this.startPosition.x &&
                block.y === this.startPosition.y &&
                block.z === this.startPosition.z) {
                
                event.cancel = true;

                const player = event.player;
                if (!this.adminParticipates && player.hasTag("admin")) return;

                const inv = player.getComponent("inventory").container;
                for (let i = 0; i < inv.size; i++) {
                    const item = inv.getItem(i);
                    if (item && item.typeId === this.currentTargetItem) {
                        this.endGame(`Delivered ${item.typeId} to the goal`, player);
                        return;
                    }
                }
                player.sendMessage("§cYou don't have the required item!");
            }
        }
    }
}

const game = new MineCollect();