import { world, system, BlockVolume, MolangVariableMap } from "@minecraft/server";
import { getGamemode } from "../utilities/helpers";
import { MainHandDurabilityAxe } from "../utilities/item_durability";

// ---- Tree configuration ----
// Each entry defines one "tree type":
// - id: internal name (purely for you)
// - triggerBlocks: blocks that can start the chainsaw logic when broken
// - connectedBlocks: all blocks that should be removed as part of that tree
// - maxRange: recursion limit / size of tree
export const TREE_DEFINITIONS = [
  {
    id: "cursed",
    triggerBlocks: [
      "hb_hr:cursed_log",
      "hb_hr:cursed_ripped_log",
      "hb_hr:cursed_wood",
      "hb_hr:cursed_vine",
      "hb_hr:cursed_vine_carpet"
    ],
    connectedBlocks: [
      "hb_hr:cursed_log",
      "hb_hr:cursed_ripped_log",
      "hb_hr:cursed_wood",
      "hb_hr:cursed_vine",
      "hb_hr:cursed_vine_carpet"
    ],
    maxRange: 25
  },
  {
    id: "black",
    triggerBlocks: ["hb_hr:black_log", "hb_hr:black_wood"],
    connectedBlocks: ["hb_hr:black_log", "hb_hr:black_wood", "hb_hr:black_wood","hb_hr:black_vine","hb_hr:black_vine_carpet"],
    maxRange: 10
  },
  {
    id: "blight",
    triggerBlocks: ["hb_hr:blight_log", "hb_hr:blight_wood"],
    connectedBlocks: ["hb_hr:blight_log", "hb_hr:blight_wood"],
    maxRange: 27
  },
  {
    id: "dead_roots",
    triggerBlocks: ["hb_hr:dead_roots"],
    connectedBlocks: ["hb_hr:dead_roots"],
    maxRange: 3
  },

  // Vanilla overworld trees
  {
    id: "birch",
    triggerBlocks: ["minecraft:birch_log"],
    connectedBlocks: ["minecraft:birch_log", "minecraft:birch_wood"],
    maxRange: 50
  },
  {
    id: "spruce",
    triggerBlocks: ["minecraft:spruce_log"],
    connectedBlocks: ["minecraft:spruce_log", "minecraft:spruce_wood"],
    maxRange: 150
  },
  {
    id: "jungle",
    triggerBlocks: ["minecraft:jungle_log"],
    connectedBlocks: ["minecraft:jungle_log", "minecraft:jungle_wood"],
    maxRange: 150
  },
  {
    id: "oak",
    triggerBlocks: ["minecraft:oak_log"],
    connectedBlocks: ["minecraft:oak_log", "minecraft:oak_wood"],
    maxRange: 50
  },
  {
    id: "dark_oak",
    triggerBlocks: ["minecraft:dark_oak_log"],
    connectedBlocks: ["minecraft:dark_oak_log", "minecraft:dark_oak_wood"],
    maxRange: 50
  },
  {
    id: "acacia",
    triggerBlocks: ["minecraft:acacia_log"],
    connectedBlocks: ["minecraft:acacia_log", "minecraft:acacia_wood"],
    maxRange: 50
  },
  {
    id: "mangrove",
    triggerBlocks: [
      "minecraft:mangrove_log",
      "minecraft:mangrove_roots"
    ],
    connectedBlocks: [
      "minecraft:mangrove_log",
      "minecraft:mangrove_wood",
      "minecraft:mangrove_roots"
    ],
    maxRange: 50
  },
  {
    id: "cherry",
    triggerBlocks: ["minecraft:cherry_log"],
    connectedBlocks: ["minecraft:cherry_log", "minecraft:cherry_wood"],
    maxRange: 50
  },
  {
    id: "pale_oak",
    triggerBlocks: ["minecraft:pale_oak_log"],
    connectedBlocks: ["minecraft:pale_oak_log", "minecraft:pale_oak_wood"],
    maxRange: 50
  },

  // Nether trees
  {
    id: "crimson",
    triggerBlocks: ["minecraft:crimson_stem"],
    connectedBlocks: ["minecraft:crimson_stem", "minecraft:crimson_hyphae"],
    maxRange: 50
  },
  {
    id: "warped",
    triggerBlocks: ["minecraft:warped_stem"],
    connectedBlocks: ["minecraft:warped_stem", "minecraft:warped_hyphae"],
    maxRange: 50
  }
];

// All blocks that can start the chainsaw logic
export const allTrees = TREE_DEFINITIONS.flatMap((t) => t.triggerBlocks);

// Helper: find which tree definition we’re dealing with from a block permutation
function getTreeFromPermutation(permutation) {
  const id = permutation.type.id;
  return TREE_DEFINITIONS.find((tree) => tree.triggerBlocks.includes(id));
}

// Entry point: attach the chainsaw behavior to block breaking
export function chainSaw() {
  world.afterEvents.playerBreakBlock.subscribe((event) => {
    const player = event.player;
    if (!player || player.typeId !== "minecraft:player") return;

    const equippable = player.getComponent("equippable");
    if (!equippable) return;

    const holdingItem = equippable.getEquipment("Mainhand");
    if (!holdingItem) return;
    if (holdingItem.typeId !== "hb_hr:chainsaw") return;

    const tree = getTreeFromPermutation(event.brokenBlockPermutation);
    if (!tree) return;

    lumberjackInit(holdingItem, event, tree);
  });
}

export function lumberjackInit(item, event, tree) {
  const player = event.player;
  const gamemode = getGamemode(player, 0);

  const equippable = player.getComponent("equippable");
  if (!equippable) return;

  const holdingItem = equippable.getEquipment("Mainhand");
  // Ensure the player is holding an item and (for you) is in creative mode
  if (!holdingItem || gamemode !== 1) {
    return;
  }

  const block = event.block;
  const neighboringBlocks = getNeighbors(block.dimension, block.location);

  for (const neighbor of neighboringBlocks) {
    const id = neighbor.permutation.type.id;
    if (!tree.triggerBlocks.includes(id)) continue;

    system.runTimeout(() => {
      MainHandDurabilityAxe(player, item, 0);

      neighbor.dimension.runCommand(
        `fill ${neighbor.x} ${neighbor.y} ${neighbor.z} ${neighbor.x} ${neighbor.y} ${neighbor.z} air destroy`
      );

      player.dimension.playSound("hb_hr:lumberjack_use", block.location);

      const dir = player.getViewDirection();
      const molangMap = new MolangVariableMap();
      molangMap.setSpeedAndDirection("variable.custom_direction", 2, {
        x: dir.x,
        y: dir.y,
        z: dir.z
      });

      try {
        player.dimension.spawnParticle(
          "hb_hr:lumberjack",
          {
            x: block.location.x + 0.5,
            y: block.location.y + 0.5,
            z: block.location.z + 0.5
          },
          molangMap
        );
      } catch (error) {
        // ignore particle errors
      }

      lumberjack(neighbor, 0, tree, player, item);
    }, 2);
  }
}

// Recursive function to mine matching tree blocks within range
function lumberjack(block, range, tree, player, item) {
  if (range > tree.maxRange) {
    return;
  }

  const equippable = player.getComponent("equippable");
  if (!equippable) return;

  const currentItem = equippable.getEquipment("Mainhand");
  // Stop recursion if item is gone or replaced
  if (!currentItem || currentItem.typeId !== item.typeId) {
    return;
  }

  const newRange = range + 1;
  const neighboringBlocks = getNeighbors(block.dimension, block.location);

  for (const neighbor of neighboringBlocks) {
    const id = neighbor.permutation.type.id;

    // Only break blocks that belong to this tree type
    if (!tree.connectedBlocks.includes(id)) continue;

    // Break block
    neighbor.dimension.runCommand(
      `fill ${neighbor.x} ${neighbor.y} ${neighbor.z} ${neighbor.x} ${neighbor.y} ${neighbor.z} air destroy`
    );

    system.runTimeout(() => {
      const equippableNow = player.getComponent("equippable");
      if (!equippableNow) return;

      const currentItemNow = equippableNow.getEquipment("Mainhand");
      // Stop if tool is broken or swapped
      if (!currentItemNow || currentItemNow.typeId !== item.typeId) {
        return;
      }

      // 🔧 Now: reduce durability on EVERY block
      MainHandDurabilityAxe(player, currentItemNow, 0);

      // Continue recursion with current item
      lumberjack(neighbor, newRange, tree, player, currentItemNow);
    }, 2);
  }
}





function getNeighbors(dimension, location, volumeSize = 1) {
  const min = {
    x: location.x - volumeSize,
    y: location.y - volumeSize,
    z: location.z - volumeSize
  };
  const max = {
    x: location.x + volumeSize,
    y: location.y + volumeSize,
    z: location.z + volumeSize
  };

  const volume = new BlockVolume(min, max);
  const locations = volume.getBlockLocationIterator();

  const neighboringBlocks = [];

  for (const loc of locations) {
    const block = dimension.getBlock(loc);
    if (!block || block.typeId === "minecraft:air") continue;
    neighboringBlocks.push(block);
  }

  return neighboringBlocks;
}
