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

// Group structure template
export const TTGroupTemplate = {
  id: "",
  type: "pb_gat:tt_structure",
  direction: "north",
  master: { x: 0, y: 0, z: 0 },
  blocks: [],
  entity: null, // new
  itemEntities: [],
  loaded: false,
  running: false,
  hasResult: false,
};

export class TTGroupManager {
  static _NEXT_ID_KEY = "pb_gat:group_next_id";

  // Get the next unique group ID
  static getNextGroupId() {
    const usedIds = new Set();

    for (const prop of world.getDynamicPropertyIds()) {
      if (prop.startsWith("mb_group_")) {
        const idNum = parseInt(prop.replace("mb_group_", ""));
        if (!isNaN(idNum)) {
          usedIds.add(idNum);
        }
      }
    }

    // Find the first missing integer starting from 1
    let nextId = 1;
    while (usedIds.has(nextId)) {
      nextId++;
    }

    return `mb_group_${nextId}`;
  }

  // Save group to world
  static saveGroup(group) {
    if (!group?.id) return;
    world.setDynamicProperty(group.id, JSON.stringify(group));
  }

  // Retrieve a group by its ID
  static getGroup(groupId) {
    const raw = world.getDynamicProperty(groupId);
    return raw ? JSON.parse(raw) : null;
  }

  // Create and register a new group
  static createGroup({ direction, master, blocks, entity }) {
    const id = this.getNextGroupId();

    const group = {
      ...TTGroupTemplate,
      id,
      direction,
      master: {
        x: master.location.x,
        y: master.location.y,
        z: master.location.z,
      },
      blocks: blocks.map((b) => ({
        x: b.location.x,
        y: b.location.y,
        z: b.location.z,
      })),
      entity: {
        id: entity.id,
        x: entity.location.x,
        y: entity.location.y,
        z: entity.location.z,
      },
      itemEntities: [],
      running: false,
      hasResult: false,
    };

    this.saveGroup(group);

    // ✅ Only the entity gets a dynamic property
    entity.setDynamicProperty("pb_gat:group_id", id);

    return group;
  }

  // Find the group ID that a given block belongs to
  static getGroupIdAtBlock(block) {
    const loc = block?.location;
    if (!loc) return null;

    for (const prop of world.getDynamicPropertyIds()) {
      if (!prop.startsWith("mb_group_")) continue;

      const raw = world.getDynamicProperty(prop);
      if (!raw) continue;

      try {
        const group = JSON.parse(raw);
        const allBlocks = [group.master, ...group.blocks];
        if (
          allBlocks.some((p) => p.x === loc.x && p.y === loc.y && p.z === loc.z)
        ) {
          return group.id;
        }
      } catch (e) {
      }
    }

    return null;
  }

  // Add an item entity to the group
  static addItemEntity(groupId, entity, direction = null) {
    const group = this.getGroup(groupId);
    if (!group) return;

    const itemData = {
      id: entity.id,
      x: entity.location.x,
      y: entity.location.y,
      z: entity.location.z,
    };

    // Optionally store the face/direction (e.g. "north", "top", etc.)
    if (direction) {
      itemData.direction = direction;
    }

    group.itemEntities.push(itemData);

    entity.setDynamicProperty("pb_gat:group_id", groupId);
    this.saveGroup(group);
  }

  // Remove an item entity from the group
  static removeItemEntity(groupId, entityId) {
    const group = this.getGroup(groupId);
    if (!group) return;

    group.itemEntities = group.itemEntities.filter((e) => e.id !== entityId);
    this.saveGroup(group);
  }

  // Destroy the multiblock and clean up
  static destroyGroup(groupId) {
    const group = this.getGroup(groupId);
    if (!group) return;

    const dim = world.getDimension("overworld");

    const reset = ({ x, y, z }) => {
      const block = dim.getBlock({ x, y, z });
      if (block) {
        try {
          let perm = block.permutation.withState(
            "pb_gat:mb_connection",
            "single"
          );
          perm = perm.withState("pb_gat:mb_has_item", false); // Reset the item state
          block.setPermutation(perm);
        } catch {}
      }
    };

    reset(group.master);
    group.blocks.forEach(reset);

    // Kill lever entity if found at location
    const entityList = dim.getEntitiesAtBlockLocation(group.entity);
    for (const e of entityList) {
      if (e.id === group.entity.id) {
        e.remove();
      }
    }

    // Kill all dummy item entities
    for (const item of group.itemEntities) {
      const entities = dim.getEntitiesAtBlockLocation(item);
      for (const e of entities) {
        if (e.id === item.id) {
          e.triggerEvent("pb_gat:drop_item_despawn"); // Optional custom event
        }
      }
    }

    // Delete the group record
    world.setDynamicProperty(groupId, undefined);
  }
  // Update existing group in world data
  static updateGroup(group) {
    if (!group?.id) return;
    this.saveGroup(group);
  }
}
