import { world, system } from "@minecraft/server";
import { GAMGroupManager } from "./GAMGroupManager.js";
import { runMultiblockProcess } from "./GAMLeverProcessManager.js";
import { GAM_RECIPES, TAGS } from "./GAMRecipeList.js";

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

world.beforeEvents.playerInteractWithEntity.subscribe((data) => {
  const entity = data.target;
  const player = data.player;

  if (entity.typeId !== "pb_gat:mb_gam_lever_entity") return;

  const groupId = entity.getDynamicProperty("pb_gat:group_id");
  if (!groupId) {
    player.sendMessage("§4->§r This lever is not linked to any structure.");
    return;
  }

  const group = GAMGroupManager.getGroup(groupId);
  if (!group) {
    player.sendMessage("§4->§r Multiblock group not found.");
    return;
  }

  if (group.running) {
    player.sendMessage("§4->§r The multiblock is already running.");
    return;
  }

  const items = getHeldItemsFromGroup(group, entity.dimension);

  if (items.length === 0) {
    playSound(player);
    player.sendMessage("§4->§r The machine has no items to process.");
    return;
  }

  const matched = matchRecipe(items);

  if (!matched) {
    player.sendMessage(
      "§4->§r The placed items do not match any known recipe."
    );
    return;
  }

  player.sendMessage("§aStarting multiblock process...");
  runMultiblockProcess(groupId, player, entity);
  group.running = true;
  GAMGroupManager.updateGroup(group);

  // TODO: Start crafting animation or effect
});

// Helper to collect items held by dummy entities
export function getHeldItemsFromGroup(group, dimension) {
  const itemTypes = [];

  for (const dummyData of group.itemEntities) {
    const entities = dimension.getEntitiesAtBlockLocation(dummyData);
    const dummy = entities.find((e) => e.id === dummyData.id);

    if (!dummy) continue;

    const inventory = dummy.getComponent("minecraft:inventory");
    if (!inventory) continue;

    const itemStack = inventory.container.getItem(0);
    if (itemStack) itemTypes.push(itemStack.typeId);
  }

  return itemTypes.sort();
}

// Compare against GAM_RECIPES
export function matchRecipe(inputs) {
  for (const recipe of GAM_RECIPES) {
    const required = [...recipe.inputs];

    if (inputs.length !== required.length) continue;

    // Try to match items one by one
    const inputsCopy = [...inputs];
    let matched = true;

    for (const req of required) {
      let foundIndex = -1;

      if (req.startsWith("tag:")) {
        const tagName = req.slice(4);
        const options = TAGS[tagName] || [];
        foundIndex = inputsCopy.findIndex((i) => options.includes(i));
      } else {
        foundIndex = inputsCopy.indexOf(req);
      }

      if (foundIndex === -1) {
        matched = false;
        break;
      }

      inputsCopy.splice(foundIndex, 1); // consume the matched item
    }

    if (matched) return recipe;
  }

  return null;
}
