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

const REDSTONE_BLOCK_ID = "mebesm:access_card_slot_redstone";
const NORMAL_BLOCK_ID = "mebesm:access_card_slot";
const KEYCARD_ITEM_ID = "mebesm:vsc_keycard";

const FUSE_PANEL = "mebesm:fuse_panel";
const FUSE_RED = "mebesm:color_fuses_red";
const FUSE_BLUE = "mebesm:color_fuses_blue";
const FUSE_YELLOW = "mebesm:color_fuses_yellow";
const FUSE_GREEN = "mebesm:color_fuses_green";
const ALL_FUSES = [FUSE_RED, FUSE_BLUE, FUSE_YELLOW, FUSE_GREEN];

const CAT_BEE_ITEM_ID = "mebesm:cat_bee";
const GRABPACK_RED_ITEM_ID = "mebesm:grabpack_red";

const SCANNER_OFF_ID = "mebesm:toy_scanner";
const SCANNER_ON_ID = "mebesm:toy_scanner_on";

const RED_HAND_ON_ID = "mebesm:red_hand_exhibit";
const RED_HAND_OFF_ID = "mebesm:red_hand_exhibit_off";

const LAMP_TRANSITIONS = {
    "mebesm:wall_lamp_off": "mebesm:wall_lamp_on",
    "mebesm:large_ceiling_lamp_off": "mebesm:large_ceiling_lamp",
    "mebesm:signal_lamp_off": "mebesm:signal_lamp",
    "mebesm:wall_ceiling_lamp_off": "mebesm:wall_ceiling_lamp",
    "mebesm:lamp_on_the_wall_off": "mebesm:lamp_on_the_wall"
};

const LAMP_TRANSITIONS_REVERSE = {};
for (const [offId, onId] of Object.entries(LAMP_TRANSITIONS)) {
    LAMP_TRANSITIONS_REVERSE[onId] = offId;
}

const ALL_LAMP_IDS = new Set([
    ...Object.keys(LAMP_TRANSITIONS),
    ...Object.keys(LAMP_TRANSITIONS_REVERSE)
]);

const PANEL_TRANSITIONS_FORWARD = [
    [FUSE_PANEL, FUSE_RED, "mebesm:fuse_panel1"],
    ["mebesm:fuse_panel1", FUSE_BLUE, "mebesm:fuse_panel2"],
    ["mebesm:fuse_panel2", FUSE_YELLOW, "mebesm:fuse_panel3"],
    ["mebesm:fuse_panel3", FUSE_GREEN, "mebesm:fuse_panel4"]
];

const PANEL_TRANSITIONS_BACKWARD = [
    ["mebesm:fuse_panel4", FUSE_GREEN, "mebesm:fuse_panel3"],
    ["mebesm:fuse_panel3", FUSE_YELLOW, "mebesm:fuse_panel2"],
    ["mebesm:fuse_panel2", FUSE_BLUE, "mebesm:fuse_panel1"],
    ["mebesm:fuse_panel1", FUSE_RED, FUSE_PANEL]
];

function getBlockDirectionState(block) {
    let blockStates = {};
    try {
        const direction = block.permutation.getState("minecraft:cardinal_direction");
        if (direction) blockStates = { "minecraft:cardinal_direction": direction };
    } catch { }
    return blockStates;
}

world.beforeEvents.itemUseOn.subscribe(event => {
    const { source, itemStack, block } = event;
    if (!(source instanceof Player) || !itemStack || block.typeId !== NORMAL_BLOCK_ID || itemStack.typeId !== KEYCARD_ITEM_ID) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(REDSTONE_BLOCK_ID, directionStates));
        source.runCommandAsync(`clear @s ${KEYCARD_ITEM_ID} 0 1`);
    });
});

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
    const { player, block, itemStack } = event;
    if (block.typeId !== REDSTONE_BLOCK_ID || (itemStack && itemStack.typeId === KEYCARD_ITEM_ID)) return;
    if (block.typeId.startsWith("mebesm:fuse_panel") || block.typeId.startsWith("mebesm:wall_lamp") || block.typeId.startsWith("mebesm:toy_scanner") || block.typeId.startsWith("mebesm:red_hand")) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(NORMAL_BLOCK_ID, directionStates));
        player.runCommandAsync(`give @s ${KEYCARD_ITEM_ID} 1`);
    });
});

world.beforeEvents.itemUseOn.subscribe(event => {
    const { source, itemStack, block } = event;
    if (!(source instanceof Player) || !itemStack) return;
    const transition = PANEL_TRANSITIONS_FORWARD.find(([current, fuse]) => current === block.typeId && fuse === itemStack.typeId);
    if (transition) {
        const [, , nextBlockId] = transition;
        event.cancel = true;
        system.run(() => {
            const directionStates = getBlockDirectionState(block);
            block.setPermutation(BlockPermutation.resolve(nextBlockId, directionStates));
            source.runCommandAsync(`clear @s ${itemStack.typeId} 0 1`);
        });
    }
});

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
    const { player, block, itemStack } = event;
    if (itemStack && ALL_FUSES.includes(itemStack.typeId)) return;
    const transition = PANEL_TRANSITIONS_BACKWARD.find(([current]) => current === block.typeId);
    if (transition) {
        const [, returnedItemId, prevBlockId] = transition;
        event.cancel = true;
        system.run(() => {
            const directionStates = getBlockDirectionState(block);
            block.setPermutation(BlockPermutation.resolve(prevBlockId, directionStates));
            player.runCommandAsync(`give @s ${returnedItemId} 1`);
        });
    }
});

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
    const { player, block, itemStack } = event;
    if (!(player instanceof Player)) return;
    if (!ALL_LAMP_IDS.has(block.typeId)) return;
    if (itemStack && (itemStack.typeId === KEYCARD_ITEM_ID || ALL_FUSES.includes(itemStack.typeId) || itemStack.typeId === CAT_BEE_ITEM_ID || itemStack.typeId === GRABPACK_RED_ITEM_ID)) return;

    const targetBlockId = LAMP_TRANSITIONS[block.typeId] || LAMP_TRANSITIONS_REVERSE[block.typeId] || null;
    if (!targetBlockId) return;

    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(targetBlockId, directionStates));
    });
});

world.beforeEvents.itemUseOn.subscribe(event => {
    const { source, itemStack, block } = event;
    if (!(source instanceof Player) || !itemStack || block.typeId !== SCANNER_OFF_ID || itemStack.typeId !== CAT_BEE_ITEM_ID) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(SCANNER_ON_ID, directionStates));
        source.runCommandAsync(`clear @s ${CAT_BEE_ITEM_ID} 0 1`);
    });
});

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
    const { player, block, itemStack } = event;
    if (block.typeId !== SCANNER_ON_ID) return;
    if (itemStack && (itemStack.typeId === CAT_BEE_ITEM_ID || itemStack.typeId === KEYCARD_ITEM_ID || ALL_FUSES.includes(itemStack.typeId))) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(SCANNER_OFF_ID, directionStates));
        player.runCommandAsync(`give @s ${CAT_BEE_ITEM_ID} 1`);
    });
});

world.beforeEvents.itemUseOn.subscribe(event => {
    const { source, itemStack, block } = event;
    if (!(source instanceof Player) || !itemStack || block.typeId !== RED_HAND_OFF_ID || itemStack.typeId !== GRABPACK_RED_ITEM_ID) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(RED_HAND_ON_ID, directionStates));
        source.runCommandAsync(`clear @s ${GRABPACK_RED_ITEM_ID} 0 1`);
    });
});

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
    const { player, block, itemStack } = event;
    if (block.typeId !== RED_HAND_ON_ID) return;
    if (itemStack) return;
    event.cancel = true;
    system.run(() => {
        const directionStates = getBlockDirectionState(block);
        block.setPermutation(BlockPermutation.resolve(RED_HAND_OFF_ID, directionStates));
        player.runCommandAsync(`give @s ${GRABPACK_RED_ITEM_ID} 1`);
    });
});