const CUNICULUM_FIRST_JOIN_TAG = 'cuniculum_first_join_v1';

const CUNICULUM_LOOTR_BLOCKS = [
  'lootr:lootr_chest',
  'lootr:lootr_trapped_chest',
  'lootr:lootr_barrel',
  'lootr:lootr_shulker',
  'lootr:lootr_inventory'
];

const CUNICULUM_RESTRICTED_GRIEF_ITEMS = [
  'minecraft:tnt',
  'minecraft:tnt_minecart',
  'minecraft:end_crystal',
  'minecraft:respawn_anchor'
];

const CUNICULUM_FORBIDDEN_SPAWNER_ITEMS = [
  'minecraft:spawner',
  'minecraft:trial_spawner'
];

const CUNICULUM_BLOCKED_DIMENSIONS = [
  'minecraft:the_end'
];

const CUNICULUM_MINING_REQUIREMENTS = [
  { level: 3, label: 'pico de diamante o netherite', blocks: ['minecraft:obsidian', 'minecraft:crying_obsidian', 'minecraft:ancient_debris', 'minecraft:netherite_block'] },
  { level: 2, label: 'pico de hierro o superior', blocks: ['minecraft:diamond_ore', 'minecraft:deepslate_diamond_ore', 'minecraft:emerald_ore', 'minecraft:deepslate_emerald_ore', 'minecraft:gold_ore', 'minecraft:deepslate_gold_ore', 'minecraft:redstone_ore', 'minecraft:deepslate_redstone_ore'] },
  { level: 1, label: 'pico de piedra o superior', blocks: ['minecraft:iron_ore', 'minecraft:deepslate_iron_ore', 'minecraft:copper_ore', 'minecraft:deepslate_copper_ore', 'minecraft:lapis_ore', 'minecraft:deepslate_lapis_ore', 'minecraft:coal_ore', 'minecraft:deepslate_coal_ore'] }
];

function cuniculumJson(text, color) {
  return JSON.stringify({ text: text, color: color, italic: false });
}

function cuniculumTell(server, target, text, color) {
  server.runCommandSilent(`tellraw ${target} ${cuniculumJson(text, color)}`);
}

function cuniculumIsSneaking(player) {
  try {
    return player.isShiftKeyDown();
  } catch (ignored) {
    return false;
  }
}

function cuniculumDimension(event) {
  try {
    return String(event.level.dimension);
  } catch (ignored) {
    return '';
  }
}

function cuniculumActionbar(server, target, text, color) {
  server.runCommandSilent(`title ${target} actionbar ${cuniculumJson(text, color)}`);
}

function cuniculumStackId(stack) {
  try { return String(stack.id || '').toLowerCase(); } catch (ignored) { }
  try { return String(stack.getId()).toLowerCase(); } catch (ignored) { }
  try {
    const text = String(stack || '').toLowerCase();
    const match = text.match(/[a-z0-9_.-]+:[a-z0-9_./-]+/);
    return match ? match[0] : '';
  } catch (ignored) {
  }
  return '';
}

function cuniculumToolTier(itemId) {
  const id = String(itemId || '').toLowerCase();
  if (!id || id.indexOf('pickaxe') < 0) {
    return -1;
  }
  if (id.indexOf('netherite') >= 0 || id.indexOf('diamond') >= 0 || id.indexOf('aeternium') >= 0) {
    return 3;
  }
  if (id.indexOf('iron') >= 0) {
    return 2;
  }
  if (id.indexOf('stone') >= 0) {
    return 1;
  }
  return 0;
}

function cuniculumMiningRequirement(blockId) {
  const id = String(blockId || '').toLowerCase();
  for (let i = 0; i < CUNICULUM_MINING_REQUIREMENTS.length; i++) {
    const rule = CUNICULUM_MINING_REQUIREMENTS[i];
    if (rule.blocks.includes(id)) {
      return rule;
    }
  }
  if (id.indexOf('_ore') >= 0 && id.indexOf('deepslate') >= 0) {
    return { level: 1, label: 'pico de piedra o superior' };
  }
  return null;
}

function cuniculumWarnBadMiningTool(event) {
  const player = event.player;
  if (!player || !event.block) {
    return false;
  }
  const blockId = String(event.block.id || '').toLowerCase();
  const rule = cuniculumMiningRequirement(blockId);
  if (!rule) {
    return false;
  }
  const held = cuniculumStackId(event.item || player.mainHandItem);
  if (cuniculumToolTier(held) >= rule.level) {
    return false;
  }

  const now = Date.now();
  try {
    if (Number(player.persistentData.cuniculum_bad_tool_msg_ms || 0) + 1600 > now) {
      return true;
    }
    player.persistentData.cuniculum_bad_tool_msg_ms = now;
  } catch (ignored) {
  }
  cuniculumActionbar(event.server, player.username, 'Tu herramienta no cumple los requisitos. Necesitas ' + rule.label + '.', 'red');
  return true;
}

function cuniculumCancelRestrictedItem(event, reason) {
  const player = event.player;
  if (!player || !event.item) {
    return false;
  }

  const itemId = String(event.item.id);
  if (!CUNICULUM_RESTRICTED_GRIEF_ITEMS.includes(itemId)) {
    return false;
  }

  event.cancel();
  cuniculumTell(event.server, player.username, reason, 'red');
  return true;
}

function cuniculumClearForbiddenSpawners(server, player) {
  if (!server || !player) {
    return;
  }

  CUNICULUM_FORBIDDEN_SPAWNER_ITEMS.forEach(itemId => {
    server.runCommandSilent(`clear ${player.username} ${itemId}`);
  });
}

function cuniculumCanBypassDimensionLock(player) {
  return false;
}

function cuniculumPlayerTick(player) {
  try {
    return player.age;
  } catch (ignored) {
    return 0;
  }
}

ServerEvents.recipes(event => {
  CUNICULUM_RESTRICTED_GRIEF_ITEMS.forEach(itemId => {
    event.remove({ output: itemId });
  });

  CUNICULUM_FORBIDDEN_SPAWNER_ITEMS.forEach(itemId => {
    event.remove({ output: itemId });
  });
});

PlayerEvents.loggedIn(event => {
  const player = event.player;
  const server = event.server;
  const name = player.username;

  cuniculumClearForbiddenSpawners(server, player);

  if (!player.persistentData[CUNICULUM_FIRST_JOIN_TAG]) {
    player.persistentData[CUNICULUM_FIRST_JOIN_TAG] = true;
  }
});

PlayerEvents.tick(event => {
  const player = event.player;
  if (!player) {
    return;
  }

  if (cuniculumPlayerTick(player) % 100 === 0) {
    cuniculumClearForbiddenSpawners(event.server, player);
  }

  const dimension = cuniculumDimension(event);
  if (!CUNICULUM_BLOCKED_DIMENSIONS.includes(dimension)) {
    return;
  }

  if (cuniculumPlayerTick(player) % 5 !== 0) {
    return;
  }

  const message = 'The End esta bloqueado en CUNICULUM. Has vuelto al spawn.';
  try {
    if (typeof cuniculumLobbyPrepare === 'function') {
      cuniculumLobbyPrepare(event.server, true);
    }
    if (typeof cuniculumLobbyPrepareMainWorldBorders === 'function') {
      cuniculumLobbyPrepareMainWorldBorders(event.server);
    }
  } catch (ignored) {
  }
  event.server.runCommandSilent(`effect give ${player.username} minecraft:slow_falling 8 0 true`);
  event.server.runCommandSilent(`effect give ${player.username} minecraft:resistance 8 4 true`);
  event.server.runCommandSilent(`execute in cuniculum:spawn_void run tp ${player.username} 0 81 0`);
  event.server.runCommandSilent(`execute in cuniculum:spawn_void run spawnpoint ${player.username} 0 81 0`);
  cuniculumTell(event.server, player.username, message, 'red');
});

BlockEvents.leftClicked(event => {
  const player = event.player;
  if (!player) {
    return;
  }

  const blockId = String(event.block.id);
  if (!CUNICULUM_LOOTR_BLOCKS.includes(blockId)) {
    return;
  }

  if (cuniculumIsSneaking(player)) {
    return;
  }

  event.cancel();
  cuniculumTell(event.server, player.username, 'Agachate para romper cofres Lootr.', 'gold');
});

BlockEvents.leftClicked(event => {
  cuniculumWarnBadMiningTool(event);
});

BlockEvents.rightClicked(event => {
  if (cuniculumCancelRestrictedItem(event, 'Ese objeto explosivo esta restringido en CUNICULUM.')) {
    return;
  }

  const player = event.player;
  if (!player || !event.block) {
    return;
  }

  const blockId = String(event.block.id);
  const dimension = cuniculumDimension(event);
  if (blockId === 'minecraft:spawner') {
    event.cancel();
    cuniculumTell(event.server, player.username, 'Los spawners no se pueden modificar en CUNICULUM.', 'red');
    return;
  }

  if (blockId.endsWith('_bed') && dimension !== 'minecraft:overworld') {
    event.cancel();
    cuniculumTell(event.server, player.username, 'Las camas explosivas estan bloqueadas fuera del Overworld.', 'red');
  }
});

BlockEvents.placed(event => {
  const player = event.player;
  if (!player || !event.block) {
    return;
  }

  const blockId = String(event.block.id);
  if (!CUNICULUM_RESTRICTED_GRIEF_ITEMS.includes(blockId)) {
    return;
  }

  event.cancel();
  cuniculumTell(event.server, player.username, 'Ese bloque esta restringido por proteccion antigrief.', 'red');
});
