const CUNICULUM_BLOCKED_RELICS_RPGS_ACTIVE_USE = [
  'relics_rpgs:lesser_use_damage',
  'relics_rpgs:lesser_use_dex',
  'relics_rpgs:lesser_use_ranged',
  'relics_rpgs:lesser_use_health',
  'relics_rpgs:lesser_use_spell_power',
  'relics_rpgs:lesser_use_spell_haste',
  'relics_rpgs:medium_proc_arcane_power',
  'relics_rpgs:medium_proc_fire_power',
  'relics_rpgs:medium_proc_frost_power',
  'relics_rpgs:medium_proc_healing_power',
  'relics_rpgs:superior_use_area_attack_damage',
  'relics_rpgs:superior_use_area_defense_health',
  'relics_rpgs:superior_use_zone_spell_power',
  'relics_rpgs:superior_use_zone_healing_taken'
];

// Las reliquias base de `relics:*` vuelven a ser equipables. El bloqueo queda
// limitado a reliquias activas de RPG que disparan efectos más agresivos.
const CUNICULUM_BLOCKED_RELICS_SPELLCAST_EQUIP = [
  'artifacts:helium_flamingo'
];

const CUNICULUM_BLOCKED_RELICS_ACTIVE_EQUIP = CUNICULUM_BLOCKED_RELICS_RPGS_ACTIVE_USE.concat(CUNICULUM_BLOCKED_RELICS_SPELLCAST_EQUIP);
const CUNICULUM_BLOCKED_RELICS_ACTIVE_SET = {};
CUNICULUM_BLOCKED_RELICS_ACTIVE_EQUIP.forEach(itemId => {
  CUNICULUM_BLOCKED_RELICS_ACTIVE_SET[itemId] = true;
});

const CUNICULUM_CURIOS_API = Java.loadClass('top.theillusivec4.curios.api.CuriosApi');
const CUNICULUM_ITEM_STACK = Java.loadClass('net.minecraft.world.item.ItemStack');
const CUNICULUM_BUILT_IN_REGISTRIES = Java.loadClass('net.minecraft.core.registries.BuiltInRegistries');
const CUNICULUM_TRISTATE = Java.loadClass('net.neoforged.neoforge.common.util.TriState');

function cuniculumRelicStackId(stack) {
  try {
    if (!stack || stack.isEmpty()) {
      return '';
    }

    return String(CUNICULUM_BUILT_IN_REGISTRIES.ITEM.getKey(stack.getItem()));
  } catch (ignored) {
  }

  try {
    return String(stack.id || '');
  } catch (ignored) {
  }

  return '';
}

function cuniculumIsBlockedActiveRelic(itemId) {
  return Object.prototype.hasOwnProperty.call(CUNICULUM_BLOCKED_RELICS_ACTIVE_SET, String(itemId));
}

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

  server.runCommandSilent(`tellraw ${player.username} ${JSON.stringify({ text: text, color: 'gold', italic: false })}`);
}

function cuniculumReturnRelicToPlayer(player, stack) {
  if (!player || !stack || stack.isEmpty()) {
    return false;
  }

  const copy = stack.copy();
  try {
    if (player.getInventory().add(copy)) {
      return true;
    }
  } catch (ignored) {
  }

  try {
    player.spawnAtLocation(copy);
    return true;
  } catch (ignored) {
  }

  try {
    player.drop(copy, false);
    return true;
  } catch (ignored) {
  }

  return false;
}

function cuniculumUnequipBlockedCuriosRelics(player, server) {
  if (!player) {
    return 0;
  }

  let changed = 0;
  try {
    const optionalHandler = CUNICULUM_CURIOS_API.getCuriosInventory(player);
    if (!optionalHandler || !optionalHandler.isPresent()) {
      return 0;
    }

    const handler = optionalHandler.get();
    const curios = handler.getCurios();
    const iterator = curios.entrySet().iterator();
    while (iterator.hasNext()) {
      const entry = iterator.next();
      const slotType = String(entry.getKey());
      const stacksHandler = entry.getValue();
      const stacks = stacksHandler.getStacks();
      const slots = stacks.getSlots();

      for (let index = 0; index < slots; index++) {
        const stack = stacks.getStackInSlot(index);
        const itemId = cuniculumRelicStackId(stack);
        if (!cuniculumIsBlockedActiveRelic(itemId)) {
          continue;
        }

        cuniculumReturnRelicToPlayer(player, stack);
        try {
          handler.setEquippedCurio(slotType, index, CUNICULUM_ITEM_STACK.EMPTY);
        } catch (ignored) {
          stacks.setStackInSlot(index, CUNICULUM_ITEM_STACK.EMPTY);
        }
        changed++;
      }
    }
  } catch (error) {
    // Silenciado: este aviso era ruidoso para jugadores y no aporta accion inmediata.
  }

  if (changed > 0) {
    cuniculumTellRelicHotfix(server, player, 'Una reliquia activa inestable fue retirada de tus slots y devuelta al inventario. Su uso queda pausado para proteger el servidor.');
  }

  return changed;
}

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

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

  cuniculumUnequipBlockedCuriosRelics(player, server);
}

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

ServerEvents.tags('item', event => {
  CUNICULUM_BLOCKED_RELICS_ACTIVE_EQUIP.forEach(itemId => {
    event.add('kubejs:cuniculum_blocked_relics_active_spellcast', itemId);
  });
});

if (typeof CuriosJSEvents !== 'undefined') {
  CuriosJSEvents.canEquip(event => {
    const itemId = cuniculumRelicStackId(event.stack);
    if (cuniculumIsBlockedActiveRelic(itemId)) {
      event.setResult(CUNICULUM_TRISTATE.FALSE);
    }
  });
}

PlayerEvents.loggedIn(event => {
  cuniculumClearBlockedRelics(event.player, event.server);
});

PlayerEvents.tick(event => {
  const player = event.player;
  if (!player || player.age % 100 !== 0) {
    return;
  }

  cuniculumClearBlockedRelics(player, event.server);
});
