import {
  EntityEquippableComponent,
  EquipmentSlot,
  TicksPerSecond,
  world,
  Player
} from "@minecraft/server";

// ——————————————
// Lista de capturas
// ——————————————
const CAPTURE_REWARDS = {
  "dungeon:butterfly": "dungeon:butterfly_normal",
};
const caughtEntities = new Set();

const VALID_CATCH = new Set(Object.keys(CAPTURE_REWARDS));

// ——————————————
// Parámetros Crítico
// ——————————————
const CRIT_CHANCE = 0.05;
const SWORD_CRIT_CHANCE = 0.2;
const AXE_CRIT_CHANCE = 0.1;

const damageMap = {
  "dungeon:bone_dagger": 1,
  "dungeon:bone_sword": 2,
  "dungeon:tungsten_dagger": 3,
  "minecraft:wooden_sword": 4,
  "minecraft:wooden_axe": 5,
  "dungeon:bone_battleaxe": 5,
  "minecraft:golden_sword": 4,
  "minecraft:golden_axe": 5,
  "minecraft:stone_sword": 5,
  "minecraft:stone_axe": 6,
  "dungeon:silver_sword": 5,
  "dungeon:silver_axe": 6,
  "dungeon:super_bone_sword": 6,
  "dungeon:cobalt_sword": 5,
  "dungeon:cobalt_axe": 8,
  "minecraft:iron_sword": 6,
  "minecraft:iron_axe": 7,
  "dungeon:tungsten_sword": 6,
  "dungeon:tungsten_battleaxe": 9,
  "minecraft:diamond_sword": 7,
  "minecraft:diamond_axe": 8,
  "minecraft:netherite_sword": 8,
  "minecraft:netherite_axe": 9,
  "dungeon:jade_sword": 7,
  "dungeon:obsidian_sword": 10,
  "dungeon:titanium_sword": 8,
  "dungeon:titanium_axe": 9,
  "dungeon:viritum_sword": 10,
  "dungeon:spider_fang": 4,
  "dungeon:spectrum_spike": 6,
  "dungeon:lunar_sword": 6,
  "dungeon:flyswatter": 4,
  "dungeon:wither_spike": 6,
  "dungeon:ancient_copper_sword": 4,
  "dungeon:cursed_sickle": 10,
  "dungeon:ancient_battleaxe": 10
};

// ——————————————
// Combo inicialización
// ——————————————
const COMBO_KEY = "comboData";

world.afterEvents.playerSpawn.subscribe(({ player }) => {
  player.setDynamicProperty(COMBO_KEY, JSON.stringify({ count: 0, last: 0 }));
});

// ——————————————
// Knockback con heavy_rock
// ——————————————
function applyKnockback(attacker, target, hForce, vForce) {
  try {
    if (!attacker?.location || !target?.location) return;
  } catch (error) {

  }
  const dx = target.location.x - attacker.location.x;
  const dz = target.location.z - attacker.location.z;
  const mag = Math.hypot(dx, dz);
  if (mag === 0) return;
  const dirX = dx / mag;
  const dirZ = dz / mag;

  if (attacker.hasTag("heavy_rock")) {
    hForce *= 3.5;
    vForce *= 2.3;
  }

  target.applyKnockback({ x: dirX * hForce, z: dirZ * hForce }, vForce);
}

// ——————————————
// Combo + evento de daño
// ——————————————
world.afterEvents.entityHurt.subscribe(({ damageSource, hurtEntity, damage }) => {
  if (damage <= 0) return;

  const attacker = damageSource.damagingEntity;
  if (!(attacker instanceof Player)) return;

  applyKnockback(attacker, hurtEntity, 0.25, 0.25);
  hurtEntity.dimension.spawnParticle("dungeon:heart_particle", {
    x: hurtEntity.location.x + 0.1,
    y: hurtEntity.location.y + 0.5,
    z: hurtEntity.location.z
  });
  hurtEntity.dimension.spawnParticle("dungeon:heart_particle", {
    x: hurtEntity.location.x,
    y: hurtEntity.location.y + 0.3,
    z: hurtEntity.location.z
  });
  hurtEntity.dimension.spawnParticle("dungeon:heart_particle", {
    x: hurtEntity.location.x - 0.1,
    y: hurtEntity.location.y + 0.2,
    z: hurtEntity.location.z
  });

  const raw = attacker.getDynamicProperty(COMBO_KEY) || '{"count":0,"last":0}';
  let combo = JSON.parse(raw);
  const now = Date.now();
  combo.count = now - combo.last < 1000 ? combo.count + 1 : 1;
  combo.last = now;
  attacker.setDynamicProperty(COMBO_KEY, JSON.stringify(combo));

  if (combo.count === 3) {
    applyKnockback(attacker, hurtEntity, 0.85, 0.4);

    hurtEntity.dimension.spawnParticle("minecraft:camera_shoot_explosion", {
      x: hurtEntity.location.x,
      y: hurtEntity.location.y + 1.4,
      z: hurtEntity.location.z
    });

    hurtEntity.dimension.playSound("game.player.hurt", hurtEntity.location);

    combo.count = 0;
    attacker.setDynamicProperty(COMBO_KEY, JSON.stringify(combo));
  }

  toolseffects(attacker, hurtEntity);
});

// ——————————————
// Checks de sets
// ——————————————
function isWearingFullJade(player) {
  const equip = player.getComponent("minecraft:equippable");
  if (!equip) return false;

  const h = equip.getEquipment(EquipmentSlot.Head)?.typeId;
  const c = equip.getEquipment(EquipmentSlot.Chest)?.typeId;
  const l = equip.getEquipment(EquipmentSlot.Legs)?.typeId;
  const f = equip.getEquipment(EquipmentSlot.Feet)?.typeId;

  const slots = [h, c, l, f];

  return slots.every(id => {
    if (!id) return false; 
    const part = id.split("_")[1]; 
    return id === `dungeon:jade_${part}`;
  });
}


function isWearingFullViritum(player) {
  const equip = player.getComponent("minecraft:equippable");
  if (!equip) return false;

  const h = equip.getEquipment(EquipmentSlot.Head)?.typeId;
  const c = equip.getEquipment(EquipmentSlot.Chest)?.typeId;
  const l = equip.getEquipment(EquipmentSlot.Legs)?.typeId;
  const f = equip.getEquipment(EquipmentSlot.Feet)?.typeId;

  const slots = [h, c, l, f];

  return slots.every(id => {
    if (!id) return false;
    const part = id.split("_")[1]; 
    return id === `dungeon:viritum_${part}`;
  });
}


// ——————————————
// Efectos por arma
// ——————————————
export function toolseffects(player, entity) {
  const RNG = { axe: [50, 100], sword: [10, 50], other: [5, 25] };
  const SHARP_STEP = 1;
  const BONUS_PERC_CAP = 100;
  const randInt = (lo, hi) => (Math.random() * (hi - lo + 1) | 0) + lo;
  const clamp = (v, hi) => (v > hi ? hi : v);

  const equip = player.getComponent(EntityEquippableComponent.componentId);
  if (!equip) return;

  const hand = equip.getEquipment(EquipmentSlot.Mainhand);
  if (!hand) return;

  const itemId = hand.typeId;
  const isSword = itemId.includes("_sword");
  const isAxe = itemId.includes("_axe") || itemId.includes("_battleaxe");

  const chance = isAxe ? AXE_CRIT_CHANCE : isSword ? SWORD_CRIT_CHANCE : CRIT_CHANCE;

  const itemEnchantable = hand.getComponent("enchantable");
  const sharp = itemEnchantable?.getEnchantment("sharpness")?.level || 0;
  const base = (damageMap[itemId] ?? 1) + sharp * SHARP_STEP;

  let bonusPerc = isAxe ? randInt(...RNG.axe)
    : isSword ? randInt(...RNG.sword)
      : randInt(...RNG.other);
  bonusPerc = clamp(bonusPerc, BONUS_PERC_CAP);

  if (Math.random() < chance) {
    const critMult = 1 + bonusPerc / 100;
    const critRaw = Math.ceil(base * critMult);
    const critDmg = Math.min(critRaw, base * 2);

    entity.dimension.spawnParticle("minecraft:critical_hit_emitter", {
      x: entity.location.x, y: entity.location.y + 1.4, z: entity.location.z
    });
    entity.dimension.playSound("entity.player.attack.strong", entity.location);
    applyKnockback(player, entity, 0.1, 0.1);

    entity.runCommand(`damage @s ${critDmg} entity_attack`);
  }

  const type = entity.typeId;

  switch (itemId) {
    case "dungeon:viritum_sword":
      if (isWearingFullViritum(player)) {
        player.addEffect("regeneration", TicksPerSecond * 5);
        entity.runCommand("damage @s 7 entity_attack");
      }
      break;

    case "dungeon:spider_fang":
      applyKnockback(player, entity, 0.01, 0.1);
      entity.addEffect("instant_damage", TicksPerSecond * 6);
      entity.runCommand("damage @s 4 entity_attack");
      break;

    case "dungeon:spectrum_spike":
      applyKnockback(player, entity, 0.01, 0.1);
      entity.addEffect("slowness", TicksPerSecond * 10, { amplifier: 2 });
      entity.runCommand("damage @s 1 entity_attack");
      break;

    case "dungeon:lunar_sword":
      const t = world.getTimeOfDay();
      if (t >= 13000 && t <= 23000) player.addEffect("strength", TicksPerSecond * 1, { amplifier: 5 });
      entity.addEffect("weakness", TicksPerSecond * 5, { amplifier: 1 });
      entity.runCommand("damage @s 6 entity_attack");
      break;

    case "dungeon:flyswatter":
      if (entity.getTags().includes("flymob")) {
        applyKnockback(player, entity, 0.01, -5.0);
        entity.runCommand("damage @s 80 magic");
      }
      applyKnockback(player, entity, 2, 1);
      entity.runCommand("damage @s 4 entity_attack");
      break;

    case "dungeon:wither_spike":
      applyKnockback(player, entity, 0.01, 0.1);
      player.addEffect("wither", TicksPerSecond * 1, { amplifier: 255 });
      player.addEffect("instant_damage", TicksPerSecond * 0.5);
      if (entity.getTags().includes("armored")) entity.runCommand("damage @s 7 magic");
      entity.runCommand("damage @s 6 magic");
      break;

    case "dungeon:ancient_copper_sword":
      entity.addEffect("poison", TicksPerSecond * 10);
      entity.runCommand("damage @s 4 magic");
      break;

    case "dungeon:cursed_sickle":
      applyKnockback(player, entity, 0.1, 0.1);
      player.addEffect("weakness", TicksPerSecond * 2, { amplifier: 255 });
      player.addEffect("slowness", TicksPerSecond * 2);
      entity.runCommand("damage @s[family=!monster] 6 magic");
      entity.runCommand("damage @e[family=monster,r=3] 10 magic");
      break;

    case "dungeon:jade_sword":
      if (isWearingFullJade(player)) {
        entity.addEffect("fatal_poison", TicksPerSecond * 10, { amplifier: 3 });
      }
      break;

    case "dungeon:storm_sword":
      entity.runCommand("summon dungeon:beam ~ ~1 ~ ~ ~ minecraft:player_beam");
      break;

    case "dungeon:titanium_sword":
      applyKnockback(player, entity, 1.1, 0.3);
      entity.addEffect("weakness", TicksPerSecond * 2, { amplifier: 1 });
      break;

    case "dungeon:titanium_axe":
      applyKnockback(player, entity, 1.2, 0.4);
      entity.addEffect("weakness", TicksPerSecond * 2);
      entity.addEffect("slowness", TicksPerSecond * 2);
      break;

      case "dungeon:ancient_sword":
      entity.runCommand("tag @s[tag=!dcursed] add dcursed");
      entity.addEffect("slowness", TicksPerSecond * 2, { amplifier: 1 });
      entity.runCommand("summon dungeon:nocturnal_shade ~ ~-3 ~ ~ ~ minecraft:event_player_minion");
      break;

    case "dungeon:bug_net":
      if (!VALID_CATCH.has(type)) break;

      if (caughtEntities.has(entity.id)) break; // ya fue capturado
      caughtEntities.add(entity.id);

      const reward = CAPTURE_REWARDS[type];
      if (reward) {
        player.runCommand(`give @s ${reward}`);
        try { entity.remove(); } catch (e) { }
      }
      break;
  }
}