import { world, ItemStack, system } from "@minecraft/server";
import {
  getAdjacentBlock,
  playerEquippedItem,
  mbEntityGiveItem,
  consumeItem,
  getMultiblockEntity,
  mbEntityDropItem,
} from "./multiblockUtility.js";
import { TTGroupManager } from "./TTGroupManager.js";
import { TT_RECIPES } from "./TTRecipeList.js";

const flippedDirection = {
  north: "south",
  south: "north",
  east: "west",
  west: "east",
};

function playSound(player) {
  system.run(() => {
    player.playSound("note.bass", {
      pitch: 0.9,
      volume: 0.6,
      location: player.location,
    });
  });
}

world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
  const block = event.block;
  const player = event.player;

  if (
    block.typeId === "pb_gat:mb_tinker_table_bottom" ||
    block.typeId === "pb_gat:mb_tinker_table_top"
  ) {
    event.cancel = true; // Prevent default interaction
    multiblockTTInteractionManager(block, player, event);
  }
});

function multiblockTTInteractionManager(block, player, event) {
  const groupId = TTGroupManager.getGroupIdAtBlock(block);
  if (!groupId) return;

  const group = TTGroupManager.getGroup(groupId);

  if (group?.running) {
    playSound(player);
    player.sendMessage(
      "§4->§r The Tinker Table is currently running. Please wait."
    );
    return;
  }
  const item = playerEquippedItem(player);
  if (item.selectedItem?.typeId === "pb_gat:tinker_hammer") {
    const itemIds = [];

    // ✅ Use a Set to avoid duplicate entity IDs
    const seenEntityIds = new Set();

    // 🔍 Use master block to scan nearby item entities
    const center = group.master;
    const nearbyEntities = block.dimension.getEntities({
      location: { x: center.x + 0.5, y: center.y + 1, z: center.z + 0.5 },
      type: "pb_gat:mb_tt_item_entity",
      maxDistance: 1,
    });

    for (const entity of nearbyEntities) {
      if (seenEntityIds.has(entity.id)) continue;
      seenEntityIds.add(entity.id);

      const inv = entity.getComponent("inventory");
      if (!inv) continue;

      const itemStack = inv.container.getItem(0);
      if (itemStack) {
        itemIds.push(itemStack.typeId);
      }
    }

    for (const recipe of TT_RECIPES) {
      const required = [...recipe.input].sort();
      const provided = [...itemIds].sort();

      if (JSON.stringify(required) === JSON.stringify(provided)) {
        player.sendMessage("§a->§r Crafting started...");
        system.run(() => {
          triggerTinkerCraftingResult(group, recipe, block);
        });
        return;
      }
    }

    playSound(player);
    player.sendMessage(
      "§4->§r Recipe not recognized. Please use an empty hand to remove items, or equip a valid item to place."
    );
    return;
  }

  const face = event.blockFace;
  const normalizedFace = face.toLowerCase(); // Ensure it's lowercase here

  // Block placement on the back face is not allowed
  const facing = `${block.permutation.getState(
    "minecraft:cardinal_direction"
  )}`; // force string
  const forbiddenFace = facing; // no flip needed

  if (normalizedFace === forbiddenFace) {
    playSound(player);
    player.sendMessage(
      "§4->§r You can't place items on the back of the tinker table."
    );
    return;
  }

  const existing = group.itemEntities.find(
    (e) => e.direction === normalizedFace
  );
  // Create a Set of all valid recipe input item IDs

  if (existing) {
    removeItemTT(block, player, normalizedFace, groupId);
  } else {
    placeItemTT(block, player, normalizedFace, groupId);
  }
}
const VALID_RECIPE_ITEMS = new Set();
for (const recipe of TT_RECIPES) {
  for (const itemId of recipe.input) {
    VALID_RECIPE_ITEMS.add(itemId);
  }
}
function placeItemTT(block, player, normalizedFace, groupId) {
  system.run(() => {
    const { selectedItem, equipment } = playerEquippedItem(player);
    if (!selectedItem) {
      playSound(player);
      player.sendMessage("§4->§r You have nothing equipped to place here.");
      return;
    }
    if (!VALID_RECIPE_ITEMS.has(selectedItem.typeId)) {
      playSound(player);
      player.sendMessage("§4->§r That item has no use in the Tinker Table.");
      return;
    }
    const group = TTGroupManager.getGroup(groupId);
    if (!group || !group.master) {
      return;
    }

    const masterLoc = group.master;
    const spawnLocation = {
      x: masterLoc.x + 0.5,
      y: masterLoc.y + 0.7,
      z: masterLoc.z + 0.5,
    };

    const entity = block.dimension.spawnEntity(
      "pb_gat:mb_tt_item_entity",
      spawnLocation
    );
    if (!entity) {
      return;
    }

    entity.setProperty("pb_gat:direction", normalizedFace);
    TTGroupManager.addItemEntity(groupId, entity, normalizedFace);
    mbEntityGiveItem(entity, selectedItem);
    consumeItem(player, selectedItem, equipment);

    world.playSound("random.pop", spawnLocation); // use spawnLocation for sound too
  });
}

function removeItemTT(block, player, normalizedFace, groupId) {
  const group = TTGroupManager.getGroup(groupId);
  if (!group) return;

  const item = group.itemEntities.find((e) => e.direction === normalizedFace);
  if (!item) return;

  const entities = block.dimension.getEntities({
    location: item,
    type: "pb_gat:mb_tt_item_entity",
    maxDistance: 1,
  });

  for (const e of entities) {
    if (e.id === item.id) {
      system.run(() => {
        mbEntityDropItem(e, block, player);
        TTGroupManager.removeItemEntity(groupId, e.id);
        world.playSound("random.pop2", block.location);
      });
      return;
    }
  }
}

function triggerTinkerCraftingResult(group, recipe, block) {
  const dim = block.dimension;
  const masterPos = group.master;
  const spawnLocation = {
    x: masterPos.x + 0.5,
    y: masterPos.y + 0.7,
    z: masterPos.z + 0.5,
  };

  group.running = true;
  TTGroupManager.updateGroup(group);

  // Step 1: Animate master + item entities
  const allEntities = dim.getEntities({
    location: spawnLocation,
    maxDistance: 1,
    type: "pb_gat:mb_tt_item_entity",
  });

  const masterEntity = dim.getEntitiesAtBlockLocation(group.entity)?.[0];
  if (masterEntity) {
    masterEntity.setProperty("pb_gat:open", false);
  }
  for (const entity of allEntities) {
    entity.playAnimation("animation.pb_gat.mb_tt_item_entity.going_down", {
      blendOutTime: 0,
      stopExpression: "query.any_animation_finished",
    });
  }

  world.playSound("item.spyglass.use", spawnLocation, {
    pitch: 0.5,
    volume: 5.0,
  });

  // Step 2: Wait and finish crafting
  system.runTimeout(() => {
    // Despawn inputs
    for (const entity of allEntities) {
      entity.remove();
    }

    group.itemEntities = [];
    group.hasResult = true;
    group.running = false;
    TTGroupManager.updateGroup(group);

    // Step 3: Spawn result item entity (on "main" face)
    const mainDir = flippedDirection[group.direction]; // e.g. "north"

    const masterLoc = group.master;
    const spawnLocation = {
      x: masterLoc.x + 0.5,
      y: masterLoc.y - 0.3,
      z: masterLoc.z + 0.5,
    };

    const resultEntity = dim.spawnEntity(
      "pb_gat:mb_tt_item_entity",
      spawnLocation
    );
    masterEntity.setProperty("pb_gat:open", true);
    resultEntity.setProperty("pb_gat:direction", mainDir);
    mbEntityGiveItem(resultEntity, new ItemStack(recipe.output, 1));
    TTGroupManager.addItemEntity(group.id, resultEntity, mainDir);
    system.runTimeout(() => {
      resultEntity.teleport(
        {
          x: resultEntity.location.x,
          y: resultEntity.location.y + 1,
          z: resultEntity.location.z,
        },
        {
          dimension: resultEntity.dimension,
        }
      );
      resultEntity.playAnimation(
        "animation.pb_gat.mb_tt_item_entity.going_up",
        {
          blendOutTime: 0,
          stopExpression: "query.any_animation_finished",
        }
      );
      world.playSound("item.spyglass.use", spawnLocation, {
        pitch: 0.6,
        volume: 5.0,
      });
    }, 2);
  }, 40); // 2 seconds
}
