import { world, ItemStack, system } from "@minecraft/server";
import {
  playerEquippedItem,
  mbEntityGiveItem,
  consumeItem,
  mbEntityDropItem,
} from "./multiblockUtility.js";
import { UPGroupManager } from "./UPGroupManager.js";
import {
  STAMPS,
  COATINGS,
  ORB_ID,
  mapFaceToLogicalSide,
  UP_RECIPES,
} from "./UPRecipeList.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, player } = event;
  if (
    block.typeId === "pb_gat:mb_upgrade_puncher_bottom" ||
    block.typeId === "pb_gat:mb_upgrade_puncher_top"
  ) {
    event.cancel = true;
    multiblockUPInteractionManager(block, player);
  }
});

function multiblockUPInteractionManager(block, player) {
  const groupId = UPGroupManager.getGroupIdAtBlock(block);
  if (!groupId) return;
  const group = UPGroupManager.getGroup(groupId);
  if (group?.running) {
    playSound(player);
    player.sendMessage(
      "§4->§r The Upgrade Puncher is currently running. Please wait."
    );
    return;
  }

  const { selectedItem, equipment } = playerEquippedItem(player);

  // ✅ Empty hand → remove items in priority order
  if (!selectedItem) {
    removeInPriorityOrder(block, player, groupId);
    return;
  }

  // ✅ Handle tinker hammer first
  if (selectedItem.typeId === "pb_gat:tinker_hammer") {
    handleHammerInteraction(group, block, player);
    return;
  }

  // 🛠 Determine slot and position
  let slotType = null; // "left" | "front" | "right"
  let pbPosition = null; // "stamp" | "disk" | "coating"

  if (selectedItem.typeId === ORB_ID) {
    slotType = "front";
    pbPosition = "disk";
  } else if (STAMPS.includes(selectedItem.typeId)) {
    slotType = "left";
    pbPosition = "stamp";
  } else if (COATINGS.includes(selectedItem.typeId)) {
    slotType = "right";
    pbPosition = "coating";
  } else {
    playSound(player);
    player.sendMessage("§4->§r That item has no use in the Upgrade Puncher.");
    return;
  }

  const facing = `${block.permutation.getState(
    "minecraft:cardinal_direction"
  )}`;
  const actualDir = mapLogicalSideToFace(facing, slotType);

  const existing = group.itemEntities.find((e) => e.direction === actualDir);
  if (existing) {
    removeItemUP(block, player, actualDir, groupId);
    return;
  }

  placeItemUP(
    block,
    player,
    actualDir,
    groupId,
    pbPosition,
    equipment,
    selectedItem
  );
}

function placeItemUP(
  block,
  player,
  actualDir,
  groupId,
  pbPosition,
  equipment,
  selectedItem
) {
  const group = UPGroupManager.getGroup(groupId);
  if (!group?.master) {
    return;
  }

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

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

    entity.setProperty("pb_gat:direction", actualDir);
    entity.setProperty("pb_gat:position", pbPosition);

    UPGroupManager.addItemEntity(groupId, entity, actualDir);
    mbEntityGiveItem(entity, selectedItem);
    consumeItem(player, selectedItem, equipment);

    world.playSound("random.pop", spawnLocation);
  });
}

function removeItemUP(block, player, actualDir, groupId) {
  const group = UPGroupManager.getGroup(groupId);
  if (!group) return;

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

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

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

function removeInPriorityOrder(block, player, groupId) {
  const group = UPGroupManager.getGroup(groupId);
  if (!group) return;

  const priority = ["coating", "stamp", "disk"];

  // Get all nearby upgrade puncher entities
  const master = group.master;
  const nearbyEntities = block.dimension.getEntities({
    location: { x: master.x + 0.5, y: master.y + 1, z: master.z + 0.5 },
    type: "pb_gat:mb_up_item_entity",
    maxDistance: 1,
  });
  if (nearbyEntities.length === 0) {
    playSound(player);
    player.sendMessage(
      "§4->§r Please equip an item to place into the puncher."
    );
    return;
  }
  for (const pos of priority) {
    const targetEntity = nearbyEntities.find(
      (e) => e.getProperty("pb_gat:position") === pos
    );
    if (targetEntity) {
      // Find the logical direction from the entity to remove it from the group
      const dir = targetEntity.getProperty("pb_gat:direction");
      removeItemUP(block, player, dir, groupId);
      return;
    }
  }
}

function handleHammerInteraction(group, block, player) {
  const facing = `${block.permutation.getState(
    "minecraft:cardinal_direction"
  )}`;
  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_up_item_entity",
    maxDistance: 1,
  });

  const placedItemsBySide = {};
  const entitiesByPosition = {}; // Store entity references by pbPosition

  for (const entity of nearbyEntities) {
    const inv = entity.getComponent("inventory");
    if (!inv) continue;
    const itemStack = inv.container.getItem(0);
    if (!itemStack) continue;

    const entityDir = entity.getProperty("pb_gat:direction");
    const logicalSide = mapFaceToLogicalSide(facing, entityDir);
    placedItemsBySide[logicalSide] = itemStack.typeId;

    const pbPosition = entity.getProperty("pb_gat:position");
    entitiesByPosition[pbPosition] = entity; // e.g. "coating", "stamp", "disk"
  }

  for (const recipe of UP_RECIPES) {
    if (
      placedItemsBySide.front === recipe.front &&
      placedItemsBySide.left === recipe.left &&
      placedItemsBySide.right === recipe.right
    ) {
      player.sendMessage("§a->§r Crafting started...");

      // Trigger crafting immediately
      system.run(() => {
        upgradePuncherCraftingResult(group, recipe, block);
      });

      // Apply invisibility to coating after short delay
      if (entitiesByPosition.coating && entitiesByPosition.stamp) {
        system.runTimeout(() => {
          try {
            entitiesByPosition.coating.playAnimation(
              "animation.pb_gat.mb_tt_item_entity.shrink",
              {
                blendOutTime: 0,
                stopExpression: "!query.is_alive",
              }
            );
            entitiesByPosition.stamp.playAnimation(
              "animation.pb_gat.mb_tt_item_entity.shrink",
              {
                blendOutTime: 0,
                stopExpression: "!query.is_alive",
              }
            );
          } catch (error) {}
        }, 10); // 10 ticks = 0.5s
      }

      // Apply invisibility to stamp after slightly longer delay

      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."
  );
}

// Helper to map logical "front"/"left"/"right" to actual world-facing direction
function mapLogicalSideToFace(facing, logicalSide) {
  const dirs = {
    north: { front: "south", back: "north", left: "west", right: "east" },
    south: { front: "north", back: "south", left: "east", right: "west" }, // ✅ fixed left/right
    east: { front: "west", back: "east", left: "north", right: "south" },
    west: { front: "east", back: "west", left: "south", right: "north" },
  };
  return dirs[facing]?.[logicalSide] ?? "north";
}

function upgradePuncherCraftingResult(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;
  UPGroupManager.updateGroup(group);

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

  const masterEntity = dim.getEntitiesAtBlockLocation(group.entity)?.[0];
  if (masterEntity) {
    masterEntity.setProperty("pb_gat:running", true);
  }

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

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

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

    const masterLoc = group.master;

    // Check if block still exists and is the correct type
    const blockAtMaster = dim.getBlock({
      x: masterLoc.x,
      y: masterLoc.y,
      z: masterLoc.z,
    });
    if (
      !blockAtMaster ||
      (blockAtMaster.typeId !== "pb_gat:mb_upgrade_puncher_bottom" &&
        blockAtMaster.typeId !== "pb_gat:mb_upgrade_puncher_top")
    ) {
      // Machine has been destroyed, abort spawning
      return;
    }

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

    const resultEntity = dim.spawnEntity(
      "pb_gat:mb_up_item_entity",
      spawnLocation
    );
    try {
      masterEntity.setProperty("pb_gat:running", false);
    } catch (error) {}
    resultEntity.setProperty("pb_gat:direction", mainDir);
    mbEntityGiveItem(resultEntity, new ItemStack(recipe.output, 1));
    UPGroupManager.addItemEntity(group.id, resultEntity, mainDir);
  }, 40); // 2 seconds
}
