/**
 * Unified Interaction Handler for Soul Hunters Mod
 * 
 * This module centralizes all entity interaction logic to prevent conflicts
 * between multiple playerInteractWithEntity event handlers.
 * 
 * Handles:
 * - Soul Altars (weapon infusion with companion lore)
 * - Crafting Altar (weapon upgrading system)
 * - Weapon Companions (behavior control and soul feeding)
 * - Altar Companions (behavior control, no soul system)
 * 
 * @author SoulHunters Team
 * @version 1.0.0
 */
import { world, EquipmentSlot, system, ItemStack } from "@minecraft/server";
import { ActionFormData } from "@minecraft/server-ui";
import { 
  showCompanionControlUI, 
  handleCompanionSoulFeeding,
  updateWeaponLore,
  getWeaponInfo
} from "./companion_manager.js";

// ================================================================================================
// ================================================================================================
// AUTOMATIC COMPANION SWITCHING SYSTEM
// ================================================================================================

// Track players' current weapons to detect changes
const playerWeaponTracker = new Map();

/**
 * Checks if player's weapon has changed and switches companion automatically
 * DISABLED - replaced by companion_manager.js
 */
function checkWeaponChange(player) {
  return; // DISABLED - companion_manager.js handles this now
  
  const playerId = player.id;
  const currentWeapon = player.getComponent("equippable").getEquipment(EquipmentSlot.Mainhand);
  
  // Get previous weapon info
  const previousWeaponInfo = playerWeaponTracker.get(playerId);
  
  // Current weapon info
  let currentWeaponInfo = null;
  if (currentWeapon && SOUL_ALTAR_WEAPONS.includes(currentWeapon.typeId)) {
    const companion = getAnimalFromLore(currentWeapon);
    if (companion) {
      currentWeaponInfo = {
        typeId: currentWeapon.typeId,
        companion: companion,
        hasLore: true
      };
    } else {
      currentWeaponInfo = {
        typeId: currentWeapon.typeId,
        companion: null,
        hasLore: false
      };
    }
  }
  
  // Update tracker
  playerWeaponTracker.set(playerId, currentWeaponInfo);
  
  // Check if weapon changed and has companion
  if (currentWeaponInfo && currentWeaponInfo.hasLore) {
    // Check if it's actually a different companion than before
    const isDifferentCompanion = !previousWeaponInfo || 
      previousWeaponInfo.companion !== currentWeaponInfo.companion ||
      !previousWeaponInfo.hasLore;
    
    if (isDifferentCompanion) {
      // Switch to the new companion automatically
      switchToWeaponCompanion(player, currentWeaponInfo.companion, currentWeapon);
    }
  } else if (currentWeaponInfo && !currentWeaponInfo.hasLore) {
    // Weapon without companion - despawn existing companions if any
    if (previousWeaponInfo && previousWeaponInfo.hasLore) {
      despawnPlayerCompanions(player);
      player.sendMessage("§7Companions despawned - weapon has no companion lore.");
    }
  } else {
    // No valid weapon - despawn companions
    if (previousWeaponInfo && previousWeaponInfo.hasLore) {
      despawnPlayerCompanions(player);
    }
  }
}

/**
 * Removes altar companions of a specific type that belong to the player
 */
function removeAltarCompanionsOfType(player, companionType) {
  const altarCompanionTypeId = `${MOD_PREFIX}altar_companion_${companionType}`;
  const spawnAltarCompanionTypeId = `${MOD_PREFIX}spawn_altar_companion_${companionType}`;
  
  // Find and remove altar companions of this type that belong to this player
  for (const entity of player.dimension.getEntities()) {
    if (entity.typeId === altarCompanionTypeId || entity.typeId === spawnAltarCompanionTypeId) {
      try {
        const tameable = entity.getComponent("minecraft:tameable");
        if (tameable && tameable.isTamed) {
          const owner = tameable.tamedToPlayer;
          if (owner && owner.id === player.id) {
            // This altar companion belongs to this player, despawn it
            entity.triggerEvent("aft_soulhunters:despawn");
          }
        } else {
          // Altar companion might not be tamed, but if it's close to the player, remove it
          const distance = Math.sqrt(
            Math.pow(entity.location.x - player.location.x, 2) +
            Math.pow(entity.location.y - player.location.y, 2) +
            Math.pow(entity.location.z - player.location.z, 2)
          );
          if (distance <= 50) { // Within 50 blocks
            entity.triggerEvent("aft_soulhunters:despawn");
          }
        }
      } catch (e) {
        // If tameable component check fails, check distance
        const distance = Math.sqrt(
          Math.pow(entity.location.x - player.location.x, 2) +
          Math.pow(entity.location.y - player.location.y, 2) +
          Math.pow(entity.location.z - player.location.z, 2)
        );
        if (distance <= 50) { // Within 50 blocks
          entity.triggerEvent("aft_soulhunters:despawn");
        }
      }
    }
  }
}

/**
 * Switches to the companion specified in weapon lore
 */
function switchToWeaponCompanion(player, companionType, weapon) {
  // DISABLED: This function is replaced by companion_manager.js
  return;
  
  try {
    // First despawn existing weapon companions
    despawnPlayerCompanions(player);
    
    // Use the proper altar companion removal function
    removeAltarCompanionsOfType(player, companionType);
    
    // Longer delay to ensure old companions are fully gone
    system.runTimeout(() => {
      const companionId = `${MOD_PREFIX}${companionType}`;
      
      // Summon the new companion
      const location = { 
        x: player.location.x, 
        y: player.location.y + 1, 
        z: player.location.z 
      };
      
      const companion = player.dimension.spawnEntity(companionId, location);
      if (companion) {
        // Proper companion setup following original companion.js logic
        try {
          const tameable = companion.getComponent("minecraft:tameable");
          if (tameable && !tameable.isTamed) {
            tameable.tame(player);
          }
          companion.triggerEvent("aft_soulhunters:tame");
        } catch (e) {
          // Failed to tame companion
        }

        // Set ownership and active state
        companion.setDynamicProperty("ownerId", player.id);
        companion.setDynamicProperty("soulhunters_active", false);
        
        // DO NOT activate the companion - it should start small/deactivated
        // companion.triggerEvent("aft_soulhunters:activate");  // Removed this line
        
        // Keep companion in deactivated state initially
        companion.triggerEvent("aft_soulhunters:remove_activate");
        
        // Update companion with soul count from weapon lore
        const lore = weapon.getLore();
        if (lore.length > 1) {
          const soulsMatch = lore[1].match(/(\d+)\/\d+/);
          if (soulsMatch) {
            const souls = parseInt(soulsMatch[1]);
            const soulsEventName = getSoulsEventName(souls);
            try {
              companion.runCommand(`event entity @s aft_soulhunters:souls_bar_${soulsEventName}`);
            } catch (e) {
              // Fallback to triggerEvent if runCommand fails
              companion.triggerEvent(`aft_soulhunters:souls_bar_${soulsEventName}`);
            }
          }
        }
        
        // Store companion info on player for tracking
        player.setDynamicProperty("soulhunters_companion_id", companion.id);
        player.setDynamicProperty("soulhunters_companion_type", companionType);
        
        // Play activation sound
        try {
          player.playSound("aft_soulhunters_companion_activate");
        } catch (e) {
          // Sound might not exist, ignore
        }
        
        player.sendMessage(`§a§lCompanion Switched! §r§7${getCompanionDisplayName(companionType)} is now active.`);
        player.sendMessage("§8Right-click your companion to access its controls.");
      } else {
        player.sendMessage("§cFailed to summon companion. Please try again.");
      }
    }, 30); // Increased delay to 1.5 seconds for better cleanup
    
  } catch (error) {
    player.sendMessage("§cFailed to switch companion. Please try again.");
  }
}

/**
 * Helper function to get souls event name from number
 */
function getSoulsEventName(souls) {
  const soulNames = ["cero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
  return soulNames[Math.max(0, Math.min(10, souls))];
}

/**
 * Helper function to get display name for companion type
 */
function getCompanionDisplayName(companionType) {
  const displayNames = {
    "dragon": "Dragon",
    "elephant": "Elephant", 
    "fox": "Fox",
    "leopard": "Leopard",
    "manta_ray": "Manta Ray",
    "panda": "Panda",
    "phoenix": "Phoenix",
    "red_panda": "Red Panda",
    "tiger": "Tiger",
    "wolf": "Wolf"
  };
  return displayNames[companionType] || companionType;
}

/**
 * Despawn all companions belonging to a player (both weapon and altar companions)
 */
function despawnPlayerCompanions(player) {
  const playerId = player.id;
  const dimension = player.dimension;
  
  // Get all entities in a reasonable range around the player
  const entities = dimension.getEntities({
    location: player.location,
    maxDistance: 100, // Increased range to catch all companions
  });
  
  entities.forEach(entity => {
    const entityId = entity.typeId;
    const ownerId = entity.getDynamicProperty("ownerId");
    
    // Check if it's a weapon companion
    if (entityId.startsWith("aft_soulhunters:") && 
        (entityId.includes("dragon") || entityId.includes("elephant") || entityId.includes("fox") || 
         entityId.includes("leopard") || entityId.includes("manta_ray") || entityId.includes("panda") || 
         entityId.includes("phoenix") || entityId.includes("red_panda") || entityId.includes("tiger") || 
         entityId.includes("wolf")) &&
        ownerId === playerId) {
      
      entity.triggerEvent("aft_soulhunters:despawn");
    }
    
    // Also check for altar companions (baby versions)
    if (entityId.startsWith("aft_soulhunters:altar_companion_") && ownerId === playerId) {
      entity.triggerEvent("aft_soulhunters:despawn");
    }
    
    // Also check for spawn altar companions (transparent spirits)
    if (entityId.startsWith("aft_soulhunters:spawn_altar_companion_") && ownerId === playerId) {
      entity.triggerEvent("aft_soulhunters:despawn");
    }
  });
}

// OLD AUTOMATIC COMPANION SWITCHING - DISABLED (replaced by companion_manager.js)
// Monitor weapon changes every second for all players
/*
system.runInterval(() => {
  for (const player of world.getPlayers()) {
    try {
      checkWeaponChange(player);
    } catch (error) {
      // Silently handle errors to avoid spam
    }
  }
}, 20); // Check every 1 second (20 ticks)
*/

// Clean up tracker when players leave
world.afterEvents.playerLeave.subscribe((event) => {
  playerWeaponTracker.delete(event.playerId);
});

// ================================================================================================
// ================================================================================================
// CONSTANTS AND CONFIGURATION
// ================================================================================================
// Entity type prefixes
const MOD_PREFIX = "aft_soulhunters:";
// Soul Altars - for weapon infusion with companion lore
const SOUL_ALTARS = {
  "aft_soulhunters:dragon_altar": { loreName: "Dragon Companion", id: "dragon" },
  "aft_soulhunters:elephant_altar": { loreName: "Elephant Companion", id: "elephant" },
  "aft_soulhunters:fox_altar": { loreName: "Fox Companion", id: "fox" },
  "aft_soulhunters:leopard_altar": { loreName: "Leopard Companion", id: "leopard" },
  "aft_soulhunters:manta_ray_altar": { loreName: "Manta Ray Companion", id: "manta_ray" },
  "aft_soulhunters:panda_altar": { loreName: "Panda Companion", id: "panda" },
  "aft_soulhunters:phoenix_altar": { loreName: "Phoenix Companion", id: "phoenix" },
  "aft_soulhunters:red_panda_altar": { loreName: "Red Panda Companion", id: "red_panda" },
  "aft_soulhunters:tiger_altar": { loreName: "Tiger Companion", id: "tiger" },
  "aft_soulhunters:wolf_altar": { loreName: "Wolf Companion", id: "wolf" },
};
// Crafting Altar - for weapon upgrading
const CRAFTING_ALTAR_ID = "aft_soulhunters:crafting_altar";
// Valid weapons for various systems
const SOUL_ALTAR_WEAPONS = [
  "aft_soulhunters:charge_fan_2", "aft_soulhunters:fire_katana_2", "aft_soulhunters:flame_tanto_2",
  "aft_soulhunters:hurricane_sai_2", "aft_soulhunters:kunai_knife_2", "aft_soulhunters:rumbling_hammer_2",
  "aft_soulhunters:speed_yari_2", "aft_soulhunters:spirit_masakari_2", "aft_soulhunters:thunder_long_bow_2",
  "aft_soulhunters:wind_naginata_2", "aft_soulhunters:charge_fan_3", "aft_soulhunters:fire_katana_3",
  "aft_soulhunters:flame_tanto_3", "aft_soulhunters:hurricane_sai_3", "aft_soulhunters:kunai_knife_3",
  "aft_soulhunters:rumbling_hammer_3", "aft_soulhunters:speed_yari_3", "aft_soulhunters:spirit_masakari_3",
  "aft_soulhunters:thunder_long_bow_3", "aft_soulhunters:wind_naginata_3", "aft_soulhunters:charge_fan_4",
  "aft_soulhunters:fire_katana_4", "aft_soulhunters:flame_tanto_4", "aft_soulhunters:hurricane_sai_4",
  "aft_soulhunters:kunai_knife_4", "aft_soulhunters:rumbling_hammer_4", "aft_soulhunters:speed_yari_4",
  "aft_soulhunters:spirit_masakari_4", "aft_soulhunters:thunder_long_bow_4", "aft_soulhunters:wind_naginata_4"
];
const CRAFTING_ALTAR_WEAPONS = [
  "aft_soulhunters:charge_fan_1", "aft_soulhunters:fire_katana_1", "aft_soulhunters:flame_tanto_1",
  "aft_soulhunters:hurricane_sai_1", "aft_soulhunters:kunai_knife_1", "aft_soulhunters:rumbling_hammer_1",
  "aft_soulhunters:speed_yari_1", "aft_soulhunters:spirit_masakari_1", "aft_soulhunters:thunder_long_bow_1",
  "aft_soulhunters:wind_naginata_1", 
  "aft_soulhunters:charge_fan_2",
  "aft_soulhunters:fire_katana_2", "aft_soulhunters:flame_tanto_2", "aft_soulhunters:hurricane_sai_2",
  "aft_soulhunters:kunai_knife_2", "aft_soulhunters:rumbling_hammer_2", "aft_soulhunters:speed_yari_2",
  "aft_soulhunters:spirit_masakari_2", "aft_soulhunters:thunder_long_bow_2", "aft_soulhunters:wind_naginata_2",
  "aft_soulhunters:charge_fan_3", "aft_soulhunters:fire_katana_3", "aft_soulhunters:flame_tanto_3",
  "aft_soulhunters:hurricane_sai_3", "aft_soulhunters:kunai_knife_3", "aft_soulhunters:rumbling_hammer_3",
  "aft_soulhunters:speed_yari_3", "aft_soulhunters:spirit_masakari_3", "aft_soulhunters:thunder_long_bow_3",
  "aft_soulhunters:wind_naginata_3"
];
const VALID_GEMS = [
  "aft_soulhunters:apatite", "aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper",
  "aft_soulhunters:iolite", "aft_soulhunters:jade", "aft_soulhunters:jasper",
  "aft_soulhunters:leopard_jasper", "aft_soulhunters:nephrite", "aft_soulhunters:ruby",
  "aft_soulhunters:yellow_aventurine", "minecraft:coal", "minecraft:redstone"
];
// Companion behavior options
const COMPANION_BEHAVIORS = [
  { text: "Attack all monsters", event: "aft_soulhunters:attack_all", texture: "textures/aft/soulhunters/behaviour/follow_and_attack" },
  { text: "Attack only what I attack", event: "aft_soulhunters:attack_only_when_attacked", texture: "textures/aft/soulhunters/behaviour/guard" },
  { text: "Start riding", action: "start_ride", texture: "textures/aft/soulhunters/behaviour/ride" },
];
// Items
const SOUL_ITEM_ID = "aft_soulhunters:soul";
const SOUL_ITEM_ALT_ID = "aft_soulhunters:soul_item";
// ================================================================================================
// CRAFTING ALTAR CONSTANTS AND UTILITIES
// ================================================================================================
// Dynamic properties for crafting altar
const ALTAR_WEAPON_PROP = "altar_weapon";
const ALTAR_WEAPON_DATA_PROP = "altar_weapon_data"; // Store complete ItemStack data
const ALTAR_IRON_PROP = "altar_iron";
const ALTAR_DIAMOND_PROP = "altar_diamond";
const ALTAR_NETHER_STAR_PROP = "altar_nether_star";
const ALTAR_GEMS_PROP = "altar_gems";
const UPGRADE_COMPLETE_PROP = "upgrade_complete";

/**
 * Serializes an ItemStack to JSON for storage
 * @param {ItemStack} itemStack - The item to serialize
 * @returns {string} JSON string representation
 */
function serializeItemStack(itemStack) {
  if (!itemStack) return null;
  
  const data = {
    typeId: itemStack.typeId,
    amount: itemStack.amount
  };
  
  // Include lore if present
  const lore = itemStack.getLore();
  if (lore && lore.length > 0) {
    data.lore = lore;
  }
  
  // Include name if present
  try {
    const nameTag = itemStack.nameTag;
    if (nameTag) {
      data.nameTag = nameTag;
    }
  } catch (e) {
    // nameTag property might not be available in all versions
  }
  
  return JSON.stringify(data);
}

/**
 * Deserializes JSON data back to an ItemStack
 * @param {string} jsonData - JSON string representation
 * @returns {ItemStack|null} Reconstructed ItemStack
 */
function deserializeItemStack(jsonData) {
  if (!jsonData) return null;
  
  try {
    const data = JSON.parse(jsonData);
    const itemStack = new ItemStack(data.typeId, data.amount || 1);
    
    // Restore lore if present
    if (data.lore && data.lore.length > 0) {
      itemStack.setLore(data.lore);
    }
    
    // Restore name if present
    if (data.nameTag) {
      try {
        itemStack.nameTag = data.nameTag;
      } catch (e) {
        // nameTag property might not be available in all versions
      }
    }
    
    return itemStack;
  } catch (e) {
    return null;
  }
}

/**
 * Gets weapon type from weapon ID (removes level suffix)
 * @param {string} weaponId - Full weapon ID
 * @returns {string|null} Weapon type without level
 */
function getWeaponType(weaponId) {
  const match = weaponId.match(/^aft_soulhunters:(.+)_(\d)$/);
  return match ? match[1] : null;
}
/**
 * Gets weapon level from weapon ID
 * @param {string} weaponId - Full weapon ID
 * @returns {number} Weapon level (0 if invalid)
 */
function getWeaponLevel(weaponId) {
  const match = weaponId.match(/^aft_soulhunters:.+_(\d)$/);
  return match ? parseInt(match[1]) : 0;
}
/**
 * Gets gem type from gem ID (removes mod prefix)
 * @param {string} gemId - Full gem ID
 * @returns {string} Gem type
 */
function getGemType(gemId) {
  return gemId.replace("aft_soulhunters:", "").replace("minecraft:", "");
}
/**
 * Gets gem index for rendering
 * @param {string} gemType - Gem type
 * @returns {number} Gem index for rendering
 */
function getGemIndex(gemType) {
  const gemOrder = [
    "apatite", "aventurine", "brecciated_jasper", "iolite", "jade",
    "jasper", "leopard_jasper", "nephrite", "yellow_aventurine", "ruby",
    "coal", "redstone"
  ];
  const index = gemOrder.indexOf(gemType);
  return index >= 0 ? index : 0;
}

/**
 * Formats weapon name for display with proper capitalization and gem information
 * @param {ItemStack} weapon - The weapon item to format
 * @returns {string} Formatted weapon name with gems
 */
function formatWeaponDisplayName(weapon) {
  if (!weapon) return "Unknown Weapon";
  
  // Convert typeId to display name
  let displayName = weapon.typeId
    .replace("aft_soulhunters:", "")
    .replace(/_/g, " ")
    .replace(/\b\w/g, l => l.toUpperCase());
  
  // Get gem information from lore
  const lore = weapon.getLore() || [];
  const gemLines = lore.filter(line => line.includes("Gem:"));
  
  if (gemLines.length > 0) {
    const gemInfo = gemLines.map(line => {
      const match = line.match(/Gem: (.+)/);
      return match ? match[1] : "";
    }).filter(gem => gem).join(", ");
    
    if (gemInfo) {
      displayName += ` §7(${gemInfo})§a`;
    }
  }
  
  return displayName;
}

/**
 * Formats gem name for display with proper capitalization
 * @param {string} gemTypeId - The gem's typeId
 * @returns {string} Formatted gem name
 */
function formatGemDisplayName(gemTypeId) {
  if (!gemTypeId) return "Unknown Gem";
  
  // Remove namespace prefixes and format name
  return gemTypeId
    .replace("aft_soulhunters:", "")
    .replace("minecraft:", "")
    .replace(/_/g, " ")
    .replace(/\b\w/g, l => l.toUpperCase());
}

/**
 * Gets soul altar progress data
 * @param {Entity} altar - The soul altar entity
 * @returns {Object} Progress data
 */
function getSoulAltarProgress(altar) {
  const ALTAR_SOULS_GIVEN_PROP = "aft_altar_souls_given";
  const ALTAR_ANIMATION_PROP = "aft_altar_animation";
  
  const soulsGiven = altar.getDynamicProperty(ALTAR_SOULS_GIVEN_PROP) || 0;
  const animationActive = altar.getDynamicProperty(ALTAR_ANIMATION_PROP) || false;
  
  // Get the current state from the variant component
  let currentState = 0;
  try {
    const variantComponent = altar.getComponent("minecraft:variant");
    if (variantComponent) {
      currentState = variantComponent.value || 0;
    }
  } catch (error) {
    // Ignore error
  }
  
  return {
    soulsGiven: soulsGiven,
    animationActive: animationActive,
    currentState: currentState
  };
}

/**
 * Sets soul altar progress data
 * @param {Entity} altar - The soul altar entity
 * @param {number} soulsGiven - Number of souls given
 * @param {boolean} animationActive - Whether animation is active
 * @param {boolean} weaponPlaced - Whether weapon is placed
 */
function setSoulAltarProgress(altar, soulsGiven, animationActive = false, weaponPlaced = false) {
  const ALTAR_SOULS_GIVEN_PROP = "aft_altar_souls_given";
  const ALTAR_ANIMATION_PROP = "aft_altar_animation";
  
  altar.setDynamicProperty(ALTAR_SOULS_GIVEN_PROP, soulsGiven);
  altar.setDynamicProperty(ALTAR_ANIMATION_PROP, animationActive);
  
  // Set the state property for animations (0-10 for soul count, 11 for final weapon animation)
  let newState = soulsGiven;
  if (weaponPlaced && soulsGiven >= 10) {
    newState = 11; // Final animation state when weapon is placed
  }
  
  // Use events to trigger variant changes
  try {
    altar.triggerEvent(`aft_soulhunters:set_variant_${newState}`);
  } catch (error) {
    // Ignore error
  }
}

/**
 * Gets upgrade requirements for weapon level
 * @param {number} weaponLevel - Current weapon level
 * @returns {Object|null} Requirements object or null if max level
 */
function getUpgradeRequirements(weaponLevel) {
  switch (weaponLevel) {
    case 1: return { item: "iron_ingot", gems: 3 };
    case 2: return { item: "diamond", gems: 3 };
    case 3: return { item: "nether_star", gems: 3 };
    default: return null;
  }
}

/**
 * Gets specific recipe requirements for weapon upgrade
 * @param {string} weaponType - The weapon type (e.g., "kunai_knife")
 * @param {number} weaponLevel - Current weapon level
 * @returns {Object|null} Specific recipe requirements
 */
function getWeaponRecipe(weaponType, weaponLevel) {
  const recipes = {
    "kunai_knife": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:apatite", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:iolite"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:jasper", "aft_soulhunters:leopard_jasper"],
        extras: []
      }
    },
    "rumbling_hammer": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:nephrite", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:ruby", "aft_soulhunters:yellow_aventurine", "aft_soulhunters:jade"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:brecciated_jasper", "aft_soulhunters:apatite", "aft_soulhunters:iolite"],
        extras: []
      }
    },
    "speed_yari": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:aventurine", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:nephrite", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:leopard_jasper"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:iolite", "aft_soulhunters:ruby", "aft_soulhunters:apatite"],
        extras: []
      }
    },
    "spirit_masakari": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:yellow_aventurine", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:ruby", "aft_soulhunters:nephrite", "aft_soulhunters:leopard_jasper"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:apatite", "aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper"],
        extras: []
      }
    },
    "thunder_long_bow": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:brecciated_jasper", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:jasper", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:iolite"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:apatite", "aft_soulhunters:leopard_jasper"],
        extras: []
      }
    },
    "wind_naginata": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:iolite", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:iolite"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:yellow_aventurine", "aft_soulhunters:leopard_jasper"],
        extras: []
      }
    },
    "charge_fan": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:jade", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:iolite"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:jasper", "aft_soulhunters:leopard_jasper"],
        extras: []
      }
    },
    "fire_katana": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:jasper", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:aventurine", "aft_soulhunters:nephrite", "aft_soulhunters:ruby"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:aventurine"],
        extras: []
      }
    },
    "flame_tanto": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:leopard_jasper", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:aventurine", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:iolite"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:jade", "aft_soulhunters:jasper", "aft_soulhunters:leopard_jasper"],
        extras: []
      }
    },
    "hurricane_sai": {
      2: {
        material: "iron_ingot",
        gems: ["aft_soulhunters:ruby", "minecraft:coal", "minecraft:redstone"],
        extras: []
      },
      3: {
        material: "diamond",
        gems: ["aft_soulhunters:apatite", "aft_soulhunters:brecciated_jasper", "aft_soulhunters:yellow_aventurine"],
        extras: []
      },
      4: {
        material: "nether_star",
        gems: ["aft_soulhunters:iolite", "aft_soulhunters:jasper", "aft_soulhunters:aventurine"],
        extras: []
      }
    }
  };

  return recipes[weaponType]?.[weaponLevel] || null;
}
/**
 * Clears all items from the crafting altar
 * @param {Entity} altar - The altar entity
 */
function clearAltar(altar) {
  try {
    altar.setProperty("aft_soulhunters:weapon", "none");
    altar.setProperty("aft_soulhunters:weapon_variant", 0);
    altar.setProperty("aft_soulhunters:item", "none");
    altar.setProperty("aft_soulhunters:gem", 0);
    altar.setProperty("aft_soulhunters:gem_stone", 0);
    altar.setProperty("aft_soulhunters:gem_stone_1", 0);
    altar.setProperty("aft_soulhunters:gem_stone_2", 0);
    altar.setProperty("aft_soulhunters:gem_stone_3", 0);
    altar.setDynamicProperty(ALTAR_WEAPON_PROP, undefined);
    altar.setDynamicProperty(ALTAR_WEAPON_DATA_PROP, undefined);
    altar.setDynamicProperty(ALTAR_IRON_PROP, undefined);
    altar.setDynamicProperty(ALTAR_DIAMOND_PROP, undefined);
    altar.setDynamicProperty(ALTAR_NETHER_STAR_PROP, undefined);
    altar.setDynamicProperty(ALTAR_GEMS_PROP, undefined);
    altar.setDynamicProperty(UPGRADE_COMPLETE_PROP, undefined);
  } catch (error) {
    // Silent catch - property clearing errors are not critical
  }
}
/**
 * Updates altar visual properties based on placed items
 * @param {Entity} altar - The altar entity
 */
function updateAltarVisuals(altar) {
  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP) || false;
  const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP) || false;
  const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP) || false;
  const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
  const gems = gemsStr ? JSON.parse(gemsStr) : [];

  try {
    // Set weapon properties
    if (weapon) {
      const weaponType = getWeaponType(weapon);
      const weaponLevel = getWeaponLevel(weapon);
      if (weaponType) {
        altar.setProperty("aft_soulhunters:weapon", weaponType);
        altar.setProperty("aft_soulhunters:weapon_variant", weaponLevel - 1);
      }
    }

    // Set item property based on what's placed (priority order)
    if (hasIron) {
      altar.setProperty("aft_soulhunters:item", "iron_ingot");
    } else if (hasDiamond) {
      altar.setProperty("aft_soulhunters:item", "diamond");
    } else if (hasNetherStar) {
      altar.setProperty("aft_soulhunters:item", "nether_star");
    } else {
      altar.setProperty("aft_soulhunters:item", "none");
    }

    // Set gem properties
    if (gems.length > 0) {
      altar.setProperty("aft_soulhunters:gem", gems.length);
      
      // Set individual gem stone properties
      for (let i = 0; i < 3; i++) {
        if (i < gems.length) {
          const gemType = getGemType(gems[i]);
          const gemIndex = getGemIndex(gemType);
          altar.setProperty(`aft_soulhunters:gem_stone_${i + 1}`, gemIndex);
        } else {
          altar.setProperty(`aft_soulhunters:gem_stone_${i + 1}`, 0);
        }
      }
      
      // Keep the original property for backward compatibility
      const firstGemType = getGemType(gems[0]);
      const gemIndex = getGemIndex(firstGemType);
      altar.setProperty("aft_soulhunters:gem_stone", gemIndex);
    } else {
      altar.setProperty("aft_soulhunters:gem", 0);
      altar.setProperty("aft_soulhunters:gem_stone", 0);
      altar.setProperty("aft_soulhunters:gem_stone_1", 0);
      altar.setProperty("aft_soulhunters:gem_stone_2", 0);
      altar.setProperty("aft_soulhunters:gem_stone_3", 0);
    }
  } catch (error) {
    // Silent catch - visual update errors are not critical
  }
}
/**
 * Validates if the altar has the correct recipe for upgrade
 * @param {Entity} altar - The altar entity
 * @returns {Object} Validation result with success flag and error details
 */
function validateRecipe(altar) {
  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  if (!weapon) {
    return { success: false, error: "No weapon placed", wrongItems: [] };
  }

  const weaponType = getWeaponType(weapon);
  const weaponLevel = getWeaponLevel(weapon);
  const targetLevel = weaponLevel + 1;

  if (targetLevel > 4) {
    return { success: false, error: "Weapon is already at maximum level", wrongItems: [] };
  }

  const recipe = getWeaponRecipe(weaponType, targetLevel);
  if (!recipe) {
    return { success: false, error: "No recipe found for this weapon", wrongItems: [] };
  }

  // Check materials
  const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP) || false;
  const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP) || false;
  const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP) || false;

  const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
  const gems = gemsStr ? JSON.parse(gemsStr) : [];

  const wrongItems = [];
  let materialCorrect = false;

  // Check required material
  if (recipe.material === "iron_ingot" && hasIron) materialCorrect = true;
  else if (recipe.material === "diamond" && hasDiamond) materialCorrect = true;
  else if (recipe.material === "nether_star" && hasNetherStar) materialCorrect = true;

  // Check for wrong materials and add them to wrongItems
  if (recipe.material !== "iron_ingot" && hasIron) wrongItems.push("minecraft:iron_ingot");
  if (recipe.material !== "diamond" && hasDiamond) wrongItems.push("minecraft:diamond");
  if (recipe.material !== "nether_star" && hasNetherStar) wrongItems.push("minecraft:nether_star");

  // Check gems (including coal and redstone)
  const wrongGems = [];
  for (const gem of gems) {
    if (!recipe.gems.includes(gem)) {
      wrongGems.push(gem);
    }
  }
  wrongItems.push(...wrongGems);

  // Check if we have all required gems
  const missingGems = [];
  for (const requiredGem of recipe.gems) {
    if (!gems.includes(requiredGem)) {
      missingGems.push(requiredGem);
    }
  }

  if (materialCorrect && wrongItems.length === 0 && missingGems.length === 0) {
    return { success: true, error: null, wrongItems: [] };
  } else {
    let error = "Incorrect recipe! ";
    if (!materialCorrect) error += `Need ${recipe.material}. `;
    if (missingGems.length > 0) error += `Missing gems: ${missingGems.join(", ")}. `;
    if (wrongItems.length > 0) error += `Wrong items placed: ${wrongItems.join(", ")}.`;

    return { success: false, error, wrongItems };
  }
}

/**
 * Checks if altar is ready for upgrade (simplified)
 * @param {Entity} altar - The altar entity
 * @returns {boolean} Whether upgrade is possible
 */
function canUpgrade(altar) {
  const validation = validateRecipe(altar);
  return validation.success;
}
/**
 * Spawns items at player location
 * @param {Player} player - The player
 * @param {Array} itemIds - Array of item IDs to spawn
 */
function spawnItemsAtPlayer(player, itemIds) {
  const location = player.location;
  for (const itemId of itemIds) {
    try {
      const itemStack = new ItemStack(itemId, 1);
      const inventory = player.getComponent("minecraft:inventory");
      if (inventory?.container) {
        // Try to add to inventory first
        const remainingItem = inventory.container.addItem(itemStack);
        if (remainingItem) {
          // If inventory is full, spawn in world
          player.dimension.spawnItem(remainingItem, location);
        }
      } else {
        // Fallback: spawn in world
        player.dimension.spawnItem(itemStack, location);
      }
    } catch (error) {
      // Fallback: spawn in world
      try {
        const itemStack = new ItemStack(itemId, 1);
        player.dimension.spawnItem(itemStack, location);
      } catch (e) {
        // Failed to spawn item
      }
    }
  }
}

/**
 * Spawns ItemStack objects at player location (preserves lore and other data)
 * @param {Player} player - The player
 * @param {Array} itemStacks - Array of ItemStack objects to spawn
 */
function spawnItemStacksAtPlayer(player, itemStacks) {
  const location = player.location;
  for (const itemStack of itemStacks) {
    if (!itemStack) continue;
    
    try {
      const inventory = player.getComponent("minecraft:inventory");
      if (inventory?.container) {
        // Try to add to inventory first
        const remainingItem = inventory.container.addItem(itemStack);
        if (remainingItem) {
          // If inventory is full, spawn in world
          player.dimension.spawnItem(remainingItem, location);
        }
      } else {
        // Fallback: spawn in world
        player.dimension.spawnItem(itemStack, location);
      }
    } catch (error) {
      // Fallback: spawn in world
      try {
        player.dimension.spawnItem(itemStack, location);
      } catch (e) {
        // Failed to spawn item
      }
    }
  }
}

/**
 * Returns all items from altar to player (used after animations)
 * @param {Entity} altar - The altar entity
 * @param {Player} player - The player (optional, will try to find nearby player)
 */
function returnAltarItems(altar, player = null) {
  // Find player if not provided
  if (!player) {
    const nearbyPlayers = altar.dimension.getPlayers({ 
      location: altar.location, 
      maxDistance: 10 
    });
    if (nearbyPlayers.length > 0) {
      player = nearbyPlayers[0];
    } else {
      // No player nearby, items will be dropped at altar location
    }
  }

  const weaponDataJson = altar.getDynamicProperty(ALTAR_WEAPON_DATA_PROP);
  const weaponTypeId = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP) || false;
  const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP) || false;
  const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP) || false;
  const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
  const gems = gemsStr ? JSON.parse(gemsStr) : [];

  const itemsToReturn = [];
  const itemStacksToReturn = [];
  
  // Add weapon back
  if (weaponDataJson) {
    try {
      const weaponItemStack = deserializeItemStack(weaponDataJson);
      itemStacksToReturn.push(weaponItemStack);
    } catch (error) {
      if (weaponTypeId) {
        itemsToReturn.push(weaponTypeId);
      }
    }
  } else if (weaponTypeId) {
    itemsToReturn.push(weaponTypeId);
  }
  
  // Add materials back
  if (hasIron) itemsToReturn.push("minecraft:iron_ingot");
  if (hasDiamond) itemsToReturn.push("minecraft:diamond");
  if (hasNetherStar) itemsToReturn.push("minecraft:nether_star");
  
  // Add all gems back
  itemsToReturn.push(...gems);

  // Return items to player or drop at altar
  if (player) {
    if (itemsToReturn.length > 0) {
      spawnItemsAtPlayer(player, itemsToReturn);
    }
    if (itemStacksToReturn.length > 0) {
      spawnItemStacksAtPlayer(player, itemStacksToReturn);
    }
  } else {
    // Drop items at altar location
    const location = altar.location;
    for (const itemId of itemsToReturn) {
      const itemStack = new ItemStack(itemId, 1);
      altar.dimension.spawnItem(itemStack, location);
    }
    for (const itemStack of itemStacksToReturn) {
      altar.dimension.spawnItem(itemStack, location);
    }
  }
}

/**
 * Gives upgraded weapon to player (used after success animation)
 * @param {Entity} altar - The altar entity
 * @param {Player} player - The player (optional, will try to find nearby player)
 */
function giveUpgradedWeapon(altar, player = null) {
  // Find player if not provided
  if (!player) {
    const nearbyPlayers = altar.dimension.getPlayers({ 
      location: altar.location, 
      maxDistance: 10 
    });
    if (nearbyPlayers.length > 0) {
      player = nearbyPlayers[0];
    } else {
      // No player nearby, drop weapon at altar location
      const weaponData = altar.getDynamicProperty(ALTAR_WEAPON_DATA_PROP);
      if (weaponData) {
        try {
          const originalWeapon = deserializeItemStack(weaponData);
          const weaponLevel = getWeaponLevel(originalWeapon.typeId);
          const weaponType = getWeaponType(originalWeapon.typeId);
          const nextLevel = weaponLevel + 1;
          const upgradedWeapon = `aft_soulhunters:${weaponType}_${nextLevel}`;
          
          const itemStack = new ItemStack(upgradedWeapon, 1);
          
          // Preserve lore from original weapon
          if (originalWeapon.lore && originalWeapon.lore.length > 0) {
            itemStack.setLore(originalWeapon.lore);
          }
          
          altar.dimension.spawnItem(itemStack, altar.location);
        } catch (error) {
          // Fallback to basic weapon without lore using the typeId
          const weaponTypeId = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
          if (weaponTypeId) {
            const weaponLevel = getWeaponLevel(weaponTypeId);
            const weaponType = getWeaponType(weaponTypeId);
            const nextLevel = weaponLevel + 1;
            const upgradedWeapon = `aft_soulhunters:${weaponType}_${nextLevel}`;
            const itemStack = new ItemStack(upgradedWeapon, 1);
            altar.dimension.spawnItem(itemStack, altar.location);
          }
        }
      }
      return;
    }
  }

  const weaponData = altar.getDynamicProperty(ALTAR_WEAPON_DATA_PROP);
  if (weaponData && player) {
    try {
      const originalWeapon = deserializeItemStack(weaponData);
      const weaponLevel = getWeaponLevel(originalWeapon.typeId);
      const weaponType = getWeaponType(originalWeapon.typeId);
      const nextLevel = weaponLevel + 1;
      const upgradedWeapon = `aft_soulhunters:${weaponType}_${nextLevel}`;
      
      const upgradedItem = new ItemStack(upgradedWeapon, 1);
      
      const originalLore = originalWeapon.getLore();
      
      // Preserve lore from original weapon
      if (originalLore && originalLore.length > 0) {
        upgradedItem.setLore(originalLore);
      }
      
      // Preserve name tag if present
      try {
        const originalNameTag = originalWeapon.nameTag;
        if (originalNameTag) {
          upgradedItem.nameTag = originalNameTag;
        }
      } catch (e) {
        // nameTag property might not be available in all versions
      }
      
      spawnItemStacksAtPlayer(player, [upgradedItem]);
    } catch (error) {
      // Fallback: create basic weapon without lore and drop at altar using typeId
      const weaponTypeId = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
      if (weaponTypeId) {
        const weaponLevel = getWeaponLevel(weaponTypeId);
        const weaponType = getWeaponType(weaponTypeId);
        const nextLevel = weaponLevel + 1;
        const upgradedWeapon = `aft_soulhunters:${weaponType}_${nextLevel}`;
        const itemStack = new ItemStack(upgradedWeapon, 1);
        altar.dimension.spawnItem(itemStack, altar.location);
      }
    }
  }
}

/**
 * Performs weapon upgrade
 * @param {Player} player - The player
 * @param {Entity} altar - The altar entity
 * @returns {boolean} Success status
 */
function performUpgrade(player, altar) {
  const validation = validateRecipe(altar);

  if (!validation.success) {
    // Trigger fail animation
    altar.setProperty("aft_soulhunters:crafting_altar", "fail");
    
    // Set a timer to clear the animation property and return items after 2 seconds
    system.runTimeout(() => {
      altar.setProperty("aft_soulhunters:crafting_altar", "none");
      
      // Return all items to player after fail animation
      returnAltarItems(altar);
      clearAltar(altar);
    }, 40); // 40 ticks = 2 seconds
    
    player.sendMessage("§cRecipe failed!");
    player.playSound("aft_soulhunters_altar_fail");

    // Items will be returned after animation finishes
    // This prevents immediate return and allows animation to play
    return false;
  }

  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  const weaponLevel = getWeaponLevel(weapon);
  const weaponType = getWeaponType(weapon);
  const nextLevel = weaponLevel + 1;

  // Set animation property based on upgrade level
  let animationState;
  if (nextLevel === 2) {
    animationState = "success_12";
  } else if (nextLevel === 3) {
    animationState = "success_23";
  } else if (nextLevel === 4) {
    animationState = "success_34";
  }

  // Trigger success animation
  altar.setProperty("aft_soulhunters:crafting_altar", animationState);
  
  // Set a timer to clear the animation property after 2 seconds (animation length)
  system.runTimeout(() => {
    altar.setProperty("aft_soulhunters:crafting_altar", "none");
    
    // Don't automatically give weapon - wait for player interaction
    // Set a flag that the weapon is ready to be collected
    altar.setDynamicProperty("upgrade_complete", true);
    
    // Reset weapon visual to show upgraded version
    altar.setProperty("aft_soulhunters:weapon_variant", nextLevel - 1);
  }, 40); // 40 ticks = 2 seconds
  
  // Update weapon visual to show upgraded version
  altar.setProperty("aft_soulhunters:weapon_variant", nextLevel - 1);
  
  player.sendMessage(`§aWeapon upgraded to level ${nextLevel}!`);
  player.playSound("ui.toast.challenge_complete");
  player.playSound("aft_soulhunters_altar_success");
  
  // Note: Items will be cleared and weapon given after animation finishes
  // This is handled by the timer system above
  return true;
}
// ================================================================================================
// COMPANION CONSTANTS AND UTILITIES
// ================================================================================================
// Companion constants
const MAX_SOULS = 10;
const BEHAVIOR_PROP = "soulhunters_behavior";
const ACTIVE_PROP = "active";
const SCORE_TO_EVENT = {
  0: "cero", 1: "one", 2: "two", 3: "three", 4: "four",
  5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine", 10: "ten"
};
/**
 * Gets companion type from weapon lore
 * @param {ItemStack} item - Weapon item
 * @returns {string|null} Companion type
 */
function getAnimalFromLore(item) {
  const lore = item?.getLore();
  if (!lore) return null;
  for (const line of lore) {
    const lower = line.toLowerCase();
    if (lower.includes("dragon companion")) return "dragon";
    if (lower.includes("elephant companion")) return "elephant";
    if (lower.includes("fox companion")) return "fox";
    if (lower.includes("leopard companion")) return "leopard";
    if (lower.includes("manta ray companion")) return "manta_ray";
    if (lower.includes("red panda companion")) return "red_panda";
    if (lower.includes("panda companion")) return "panda";
    if (lower.includes("phoenix companion")) return "phoenix";
    if (lower.includes("tiger companion")) return "tiger";
    if (lower.includes("wolf companion")) return "wolf";
  }
  return null;
}
/**
 * Gets weapon information from item
 * @param {ItemStack} item - Weapon item
 * @returns {Object|null} Weapon info object
 */
// NOTE: getWeaponInfo function moved to companion_manager.js
// NOTE: updateWeaponLore function moved to companion_manager.js

/**
 * Determines the entity type based on typeId
 * @param {string} typeId - Entity type identifier
 * @returns {string} Entity category
 */
function getEntityCategory(typeId) {
  if (!typeId || !typeId.startsWith(MOD_PREFIX)) {
    return "OTHER";
  }
  if (typeId === CRAFTING_ALTAR_ID) {
    return "CRAFTING_ALTAR";
  }
  if (SOUL_ALTARS[typeId]) {
    return "SOUL_ALTAR";
  }
  if (typeId.includes("spawn_altar")) {
    return "OTHER";
  }
  if (typeId.includes("altar_companion_")) {
    return "ALTAR_COMPANION";
  }
  if (typeId.startsWith(MOD_PREFIX) && !typeId.includes("altar")) {
    return "WEAPON_COMPANION";
  }
  return "OTHER";
}
/**
 * Safely gets equipment from player
 * @param {Player} player - The player
 * @param {string} slot - Equipment slot
 * @returns {ItemStack|undefined} The item or undefined
 */
function getPlayerEquipment(player, slot) {
  try {
    const equippable = player.getComponent("minecraft:equippable");
    return equippable?.getEquipment(slot);
  } catch (error) {
    return undefined;
  }
}
/**
 * Safely sets equipment for player
 * @param {Player} player - The player
 * @param {string} slot - Equipment slot
 * @param {ItemStack|undefined} item - Item to set
 * @returns {boolean} Success status
 */
function setPlayerEquipment(player, slot, item) {
  try {
    const equippable = player.getComponent("minecraft:equippable");
    if (equippable) {
      equippable.setEquipment(slot, item);
      return true;
    }
    return false;
  } catch (error) {
    return false;
  }
}
// ================================================================================================
// MAIN INTERACTION HANDLER
// ================================================================================================
/**
 * Main unified interaction handler
 * Routes interactions to appropriate sub-handlers based on entity type
 */
world.afterEvents.playerInteractWithEntity.subscribe(event => {
  const { player, target, itemStack } = event;
  // Basic validation
  if (!player || !target) {
    return;
  }
  // Determine entity category
  const category = getEntityCategory(target.typeId);
  // Route to appropriate handler
  switch (category) {
    case "SOUL_ALTAR":
      handleSoulAltarInteraction(player, target, itemStack);
      break;
    case "CRAFTING_ALTAR":
      handleCraftingAltarInteraction(player, target, itemStack);
      break;
    case "WEAPON_COMPANION":
      handleWeaponCompanionInteraction(player, target, itemStack);
      break;
    case "ALTAR_COMPANION":
      handleAltarCompanionInteraction(player, target, itemStack);
      break;
    case "OTHER":
      break;
    default:
      break;
  }
});
// ================================================================================================
// SOUL ALTAR HANDLERS (Weapon Infusion System)
// ================================================================================================
/**
 * Handles interactions with soul altars (weapon infusion)
 * @param {Player} player - The player
 * @param {Entity} altar - The soul altar entity
 * @param {ItemStack} itemStack - Item being used (if any)
 */
function handleSoulAltarInteraction(player, target, itemStack) {
  const companionData = SOUL_ALTARS[target.typeId];
  if (!companionData) {
    return;
  }
  // Empty hand interaction
  if (!itemStack) {
    handleSoulAltarEmptyHand(player, target, companionData);
    return;
  }
  // Soul item interaction
  if (itemStack.typeId === SOUL_ITEM_ID || itemStack.typeId === SOUL_ITEM_ALT_ID) {
    handleSoulAltarSoulOffering(player, target, itemStack, companionData);
    return;
  }
  // Weapon interaction
  if (SOUL_ALTAR_WEAPONS.includes(itemStack.typeId)) {
    handleSoulAltarWeaponInfusion(player, target, itemStack, companionData);
    return;
  }
  // Invalid item
  player.sendMessage("§cYou need to hold either a soul or a valid weapon to interact with this altar.");
}
/**
 * Handles empty hand interaction with soul altars
 */
function handleSoulAltarEmptyHand(player, altar, companionData) {
  const progress = getSoulAltarProgress(altar);
  player.sendMessage(`§e${companionData.loreName} Altar`);
  
  if (progress.currentState >= 11) {
    player.sendMessage("§c§lThis altar has been permanently used and cannot be used again.");
    player.sendMessage("§eFind another altar of the same type to perform more infusions.");
  } else if (progress.animationActive) {
    player.sendMessage("§6Infusion in progress... Please wait.");
  } else if (progress.soulsGiven >= 10) {
    player.sendMessage("§6All souls collected! Place a weapon (without companion) to begin infusion.");
  } else {
    player.sendMessage(`§aRitual Progress: ${progress.soulsGiven}/10 souls (State: ${progress.currentState})`);
  }
}
/**
 * Handles soul offering to soul altars
 */
function handleSoulAltarSoulOffering(player, altar, soulItem, companionData) {
  // Get current progress for this altar
  let progress = getSoulAltarProgress(altar);
  
  // Check if altar is permanently used (variant 11)
  if (progress.currentState >= 11) {
    player.sendMessage("§cThis altar has already been used and cannot be used again.");
    return;
  }
  
  // Check if already has 10 souls
  if (progress.soulsGiven >= 10) {
    player.sendMessage("§cThis altar ritual already has all souls. Place your weapon to begin infusion!");
    return;
  }
  
  // Check if animation is active
  if (progress.animationActive) {
    player.sendMessage("§cThe altar is currently processing. Please wait...");
    return;
  }
  
  // Add soul to progress
  const newSoulsGiven = progress.soulsGiven + 1;
  setSoulAltarProgress(altar, newSoulsGiven);
  
  // Consume one soul from the stack
  const equippable = player.getComponent("minecraft:equippable");
  if (equippable) {
    if (soulItem.amount > 1) {
      soulItem.amount--;
      equippable.setEquipment(EquipmentSlot.Mainhand, soulItem);
    } else {
      equippable.setEquipment(EquipmentSlot.Mainhand, undefined);
    }
  }
  
  // Show progress
  const remaining = 10 - newSoulsGiven;
  player.sendMessage(`§aSoul accepted! Progress: ${newSoulsGiven}/10 souls given.`);
  
  if (remaining > 0) {
    player.sendMessage(`§eYou need ${remaining} more souls to complete the ritual.`);
    // Play soul placement sound
    try {
      player.playSound("block.enchantment_table.use");
      player.playSound("aft_soulhunters_soul_altar_tilin");
    } catch (e) {}
  } else {
    // All souls collected! Stay at state 10, ready for weapon
    player.sendMessage("§6§lAll souls collected! The altar is ready for your weapon!");
    player.sendMessage("§ePlace a weapon (without companion) on the altar to begin the infusion process.");
    
    // Play completion particle effects
    try {
      // Large explosion of particles
      for (let i = 0; i < 20; i++) {
        player.dimension.spawnParticle("minecraft:totem_particle", {
          x: altar.location.x + (Math.random() - 0.5) * 2,
          y: altar.location.y + 1 + Math.random() * 2,
          z: altar.location.z + (Math.random() - 0.5) * 2
        });
      }
      
      // Ring of particles around altar
      for (let angle = 0; angle < 360; angle += 30) {
        const radians = angle * Math.PI / 180;
        const x = altar.location.x + Math.cos(radians) * 2;
        const z = altar.location.z + Math.sin(radians) * 2;
        player.dimension.spawnParticle("minecraft:enchant_particle", {
          x: x,
          y: altar.location.y + 1,
          z: z
        });
      }
    } catch (e) {}
    
    // Play completion sound
    try {
      player.playSound("block.end_portal.spawn");
      player.playSound("aft_soulhunters_soul_altar_complete");
      player.playSound("aft_soulhunters_altar_success");
    } catch (e) {}
  }
}

/**
 * Completes weapon infusion at soul altar
 * @param {Player} player - The player
 * @param {Entity} altar - The altar entity
 * @param {ItemStack} weapon - The weapon being infused
 * @param {Object} companionData - Companion data
 */
function completeSoulAltarWeaponInfusion(player, altar, weapon, companionData) {
  // Verify player is still there and has the weapon
  const equippable = player.getComponent("minecraft:equippable");
  if (!equippable) {
    // Don't reset altar progress - keep it in final state
    return;
  }
  
  const currentWeapon = equippable.getEquipment(EquipmentSlot.Mainhand);
  if (!currentWeapon || currentWeapon.typeId !== weapon.typeId) {
    player.sendMessage("§cInfusion failed! You must keep the weapon in your hand during the process.");
    player.playSound("aft_soulhunters_altar_fail");
    // Don't reset altar progress - keep it in final state
    return;
  }
  
  const newItem = weapon.clone();
  newItem.setLore([companionData.loreName, "10/10 Souls"]);
  equippable.setEquipment(EquipmentSlot.Mainhand, newItem);
  
  player.sendMessage(`§6§lSuccess! Your weapon has been infused with ${companionData.loreName}!`);
  player.sendMessage("§eYour companion will spawn automatically. Sneak + use your weapon to activate it!");
  player.sendMessage("§eThis altar has completed its purpose and can no longer be used.");
  
  // DO NOT clear altar progress - altar stays permanently used in variant 11
  // The altar will remain in final animation state forever
  
  // Final celebration effects
  try {
    for (let i = 0; i < 30; i++) {
      player.dimension.spawnParticle("minecraft:villager_happy", {
        x: altar.location.x + (Math.random() - 0.5) * 3,
        y: altar.location.y + 1 + Math.random() * 3,
        z: altar.location.z + (Math.random() - 0.5) * 3
      });
    }
  } catch (e) {}
  
  // Play success sound
  try {
    player.playSound("ui.toast.challenge_complete");
    player.playSound("aft_soulhunters_altar_success");
  } catch (e) {}
}

/**
 * Handles weapon infusion at soul altars
 */
function handleSoulAltarWeaponInfusion(player, altar, weapon, companionData) {
  // Timer configuration (in ticks - 20 ticks = 1 second)
  const ANIMATION_TIMER = 100; // 5 seconds
  
  // Get current progress for this altar
  let progress = getSoulAltarProgress(altar);
  
  // Check if altar is permanently used (variant 11)
  if (progress.currentState >= 11) {
    player.sendMessage("§cThis altar has already been used and cannot be used again.");
    player.playSound("aft_soulhunters_altar_fail");
    return;
  }
  
  const existingLore = weapon.getLore() ?? [];
  
  // Check if weapon already has companion lore
  if (existingLore.some(line => line.includes(companionData.loreName))) {
    player.sendMessage("§cThis weapon already has the " + companionData.loreName + " lore.");
    player.playSound("aft_soulhunters_altar_fail");
    return;
  }
  
  // Check if weapon already has any companion lore
  const hasCompanionLore = existingLore.some(line =>
    Object.values(SOUL_ALTARS).some(comp => line.includes(comp.loreName))
  );
  
  if (hasCompanionLore) {
    player.sendMessage("§cThis weapon already has a different companion. Each weapon can only have one companion.");
    player.playSound("aft_soulhunters_altar_fail");
    return;
  }
  
  // Check if altar is ready for weapon (has 10 souls)
  if (progress.soulsGiven < 10) {
    player.sendMessage(`§eYou need to offer souls first. Progress: ${progress.soulsGiven}/10 souls.`);
    player.sendMessage("§eHold souls in your hand and interact with the altar to offer them.");
    return;
  } else if (progress.animationActive) {
    player.sendMessage("§cThe altar is currently processing your weapon. Please wait...");
    return;
  } else {
    // Start infusion animation! Now go to state 11
    setSoulAltarProgress(altar, progress.soulsGiven, true, true); // weaponPlaced = true
    player.sendMessage("§6§lBeginning weapon infusion...");
    player.sendMessage(`§eThe ${companionData.loreName} spirit is merging with your weapon!`);
    
    // Start animation timer
    system.runTimeout(() => {
      completeSoulAltarWeaponInfusion(player, altar, weapon, companionData);
    }, ANIMATION_TIMER);
    
    // Play infusion start sound
    try {
      player.playSound("block.beacon.power_select");
    } catch (e) {}
  }
}
// ================================================================================================
// CRAFTING ALTAR HANDLERS (Weapon Upgrading System)
// ================================================================================================
/**
 * Handles interactions with the crafting altar (weapon upgrading)
 * @param {Player} player - The player
 * @param {Entity} altar - The crafting altar entity
 * @param {ItemStack} itemStack - Item being used (if any)
 */
function handleCraftingAltarInteraction(player, altar, itemStack) {
  // Check if player is sneaking with empty hand to remove altar
  if (!itemStack && player.isSneaking) {
    // Check if altar has any items/state that needs to be saved
    const hasItems = hasAltarItems(altar);
    
    if (hasItems) {
      // Save altar state to player and give items back
      saveAltarStateToPlayer(player, altar);
      returnAltarItems(altar, player);
      clearAltar(altar);
    }
    
    // Give the crafting altar item to player
    removeCraftingAltar(player, altar);
    return;
  }
  
  // Empty hand interaction
  if (!itemStack) {
    // Check if upgrade is complete and ready to collect
    const upgradeComplete = altar.getDynamicProperty(UPGRADE_COMPLETE_PROP);
    if (upgradeComplete) {
      // Give the upgraded weapon and clear the altar
      giveUpgradedWeapon(altar, player);
      altar.setDynamicProperty(UPGRADE_COMPLETE_PROP, undefined);
      clearAltar(altar);
      
      // Reset weapon visual
      altar.setProperty("aft_soulhunters:weapon", "none");
      altar.setProperty("aft_soulhunters:weapon_variant", 0);
      
      player.sendMessage("§aUpgraded weapon collected!");
      return;
    }
    
    // Check if player is sneaking to clear the altar
    if (player.isSneaking) {
      // Check if altar is currently animating
      const animationState = altar.getProperty("aft_soulhunters:crafting_altar");
      if (animationState && animationState !== "none") {
        player.sendMessage("§cWait for the animation to finish before retrieving items!");
        return;
      }
      
      // Return all items to player
      returnAltarItems(altar, player);
      clearAltar(altar);
      player.sendMessage("§aAll items retrieved from altar!");
    } else {
      handleCraftingAltarEmptyHand(player, altar);
    }
    return;
  }

  // Weapon placement
  if (CRAFTING_ALTAR_WEAPONS.includes(itemStack.typeId)) {
    handleCraftingAltarWeaponPlacement(player, altar, itemStack);
    return;
  }

  // Material placement
  if (itemStack.typeId === "minecraft:iron_ingot") {
    handleCraftingAltarMaterialPlacement(player, altar, itemStack, "iron");
    return;
  }
  if (itemStack.typeId === "minecraft:diamond") {
    handleCraftingAltarMaterialPlacement(player, altar, itemStack, "diamond");
    return;
  }
  if (itemStack.typeId === "minecraft:nether_star") {
    handleCraftingAltarMaterialPlacement(player, altar, itemStack, "nether_star");
    return;
  }

  // Gem placement (including coal and redstone)
  if (VALID_GEMS.includes(itemStack.typeId)) {
    handleCraftingAltarGemPlacement(player, altar, itemStack);
    return;
  }

  // Crafting altar component placement
  if (itemStack.typeId === "aft_soulhunters:woodtable") {
    handleCraftingAltarComponentPlacement(player, altar, itemStack, "woodtable");
    return;
  }
  if (itemStack.typeId === "aft_soulhunters:stonetable") {
    handleCraftingAltarComponentPlacement(player, altar, itemStack, "stonetable");
    return;
  }
  if (itemStack.typeId === "aft_soulhunters:centertable") {
    handleCraftingAltarComponentPlacement(player, altar, itemStack, "centertable");
    return;
  }
  if (itemStack.typeId === "aft_soulhunters:gong") {
    handleCraftingAltarComponentPlacement(player, altar, itemStack, "gong");
    return;
  }

  // Invalid item
  player.sendMessage("§cInvalid item for crafting altar!");
}
/**
 * Handles empty hand interaction with crafting altar
 */
function handleCraftingAltarEmptyHand(player, altar) {
  // Check if upgrade is complete and ready to collect
  const upgradeComplete = altar.getDynamicProperty(UPGRADE_COMPLETE_PROP);
  if (upgradeComplete) {
    player.sendMessage("§a§lUpgraded weapon is ready!");
    player.sendMessage("§7Interact with empty hand to collect your upgraded weapon.");
    return;
  }
  
  // Check if altar is currently animating
  const animationState = altar.getProperty("aft_soulhunters:crafting_altar");
  if (animationState && animationState !== "none") {
    player.sendMessage("§cAltar is currently processing. Wait for the animation to finish!");
    return;
  }
  
  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  
  if (weapon && canUpgrade(altar)) {
    // Perfect recipe - perform upgrade
    performUpgrade(player, altar);
  } else if (weapon) {
    // Show status and allow clearing
    const weaponLevel = weapon ? getWeaponLevel(weapon) : 0;
    const weaponType = getWeaponType(weapon);
    const targetLevel = weaponLevel + 1;
    const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP) || false;
    const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP) || false;
    const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP) || false;
    const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
    const gems = gemsStr ? JSON.parse(gemsStr) : [];
    
    if (weaponLevel > 0 && targetLevel <= 4) {
      // Get the specific recipe for this weapon
      const recipe = getWeaponRecipe(weaponType, targetLevel);
      
      if (recipe) {
        // Check if recipe is valid
        const validation = validateRecipe(altar);
        if (validation.success) {
          player.sendMessage("§aReady to upgrade! Interact with empty hand to upgrade.");
        } else {
          player.sendMessage("§cSomething is missing or incorrect. Try different materials or gems.");
          player.playSound("aft_soulhunters_altar_fail");
          player.sendMessage("§6Hold sneak and interact with empty hand to retrieve all items.");
        }
      } else {
        player.sendMessage("§cNo recipe found for this weapon upgrade!");
        player.playSound("aft_soulhunters_altar_fail");
        player.sendMessage("§6Hold sneak and interact with empty hand to retrieve all items.");
      }
    } else if (weaponLevel > 0) {
      player.sendMessage("§cWeapon is already at maximum level!");
      player.playSound("aft_soulhunters_altar_fail");
      player.sendMessage("§6Hold sneak and interact with empty hand to retrieve all items.");
    }
  } else {
    // Empty altar
    player.sendMessage("§7Altar is empty. Place a weapon to start crafting.");
  }
}
/**
 * Handles weapon placement on crafting altar
 */
function handleCraftingAltarWeaponPlacement(player, altar, weapon) {
  // Check if altar is fully assembled first
  const woodState = altar.getProperty("aft_soulhunters:woodtable");
  const stoneState = altar.getProperty("aft_soulhunters:stonetable");
  const centerState = altar.getProperty("aft_soulhunters:centertable");
  const gongState = altar.getProperty("aft_soulhunters:gong");

  if (woodState !== "on" || stoneState !== "on" || centerState !== "on" || gongState !== "on") {
    const missing = [];
    if (woodState !== "on") missing.push("woodtable");
    if (stoneState !== "on") missing.push("stonetable");
    if (centerState !== "on") missing.push("centertable");
    if (gongState !== "on") missing.push("gong");
    player.sendMessage(`§cThe crafting altar must be fully assembled before placing weapons!`);
    player.sendMessage(`§eStill need: §7${missing.join(", ")}`);
    return;
  }

  const currentWeapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  if (currentWeapon) {
    player.sendMessage("§cAltar already has a weapon! Clear it first.");
    return;
  }
  
  // Store both the typeId (for compatibility) and the complete ItemStack data
  altar.setDynamicProperty(ALTAR_WEAPON_PROP, weapon.typeId);
  const serializedData = serializeItemStack(weapon);
  altar.setDynamicProperty(ALTAR_WEAPON_DATA_PROP, serializedData);
  
  updateAltarVisuals(altar);
  
  // Consume item - create new ItemStack or undefined
  if (weapon.amount > 1) {
    const newWeapon = new ItemStack(weapon.typeId, weapon.amount - 1);
    // Copy lore to the remaining items
    const lore = weapon.getLore();
    if (lore && lore.length > 0) {
      newWeapon.setLore(lore);
    }
    // Copy name if present
    try {
      if (weapon.nameTag) {
        newWeapon.nameTag = weapon.nameTag;
      }
    } catch (e) {
      // nameTag property might not be available in all versions
    }
    setPlayerEquipment(player, EquipmentSlot.Mainhand, newWeapon);
  } else {
    setPlayerEquipment(player, EquipmentSlot.Mainhand, undefined);
  }
  const formattedName = formatWeaponDisplayName(weapon);
  player.sendMessage(`§aWeapon placed: ${formattedName}`);
}
/**
 * Handles material placement on crafting altar
 */
function handleCraftingAltarMaterialPlacement(player, altar, material, type) {
  // Check if altar is fully assembled first
  const woodState = altar.getProperty("aft_soulhunters:woodtable");
  const stoneState = altar.getProperty("aft_soulhunters:stonetable");
  const centerState = altar.getProperty("aft_soulhunters:centertable");
  const gongState = altar.getProperty("aft_soulhunters:gong");

  if (woodState !== "on" || stoneState !== "on" || centerState !== "on" || gongState !== "on") {
    const missing = [];
    if (woodState !== "on") missing.push("woodtable");
    if (stoneState !== "on") missing.push("stonetable");
    if (centerState !== "on") missing.push("centertable");
    if (gongState !== "on") missing.push("gong");
    player.sendMessage(`§cThe crafting altar must be fully assembled before placing materials!`);
    player.sendMessage(`§eStill need: §7${missing.join(", ")}`);
    return;
  }

  // Check if weapon is placed and get requirements
  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  if (!weapon) {
    player.sendMessage("§cPlace a weapon first to determine material requirements!");
    return;
  }
  const weaponLevel = getWeaponLevel(weapon);
  const requirements = getUpgradeRequirements(weaponLevel);
  if (!requirements) {
    player.sendMessage("§cThis weapon cannot be upgraded further!");
    return;
  }

  const propName = type === "iron" ? ALTAR_IRON_PROP :
    type === "diamond" ? ALTAR_DIAMOND_PROP :
      ALTAR_NETHER_STAR_PROP;
  // Check current state of all materials
  const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP);
  const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP);
  const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP);
  const hasMaterial = altar.getDynamicProperty(propName);
  if (hasMaterial) {
    player.sendMessage(`§cAltar already has a ${type}!`);
    return;
  }
  altar.setDynamicProperty(propName, true);
  // Check state after setting
  const newHasIron = altar.getDynamicProperty(ALTAR_IRON_PROP);
  const newHasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP);
  const newHasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP);
  updateAltarVisuals(altar);
  // Consume item - create new ItemStack or undefined
  if (material.amount > 1) {
    const newMaterial = new ItemStack(material.typeId, material.amount - 1);
    setPlayerEquipment(player, EquipmentSlot.Mainhand, newMaterial);
  } else {
    setPlayerEquipment(player, EquipmentSlot.Mainhand, undefined);
  }
  player.sendMessage(`§a${type.charAt(0).toUpperCase() + type.slice(1)} placed!`);
}
/**
 * Handles gem placement on crafting altar
 */
function handleCraftingAltarGemPlacement(player, altar, gem) {
  // Check if altar is fully assembled first
  const woodState = altar.getProperty("aft_soulhunters:woodtable");
  const stoneState = altar.getProperty("aft_soulhunters:stonetable");
  const centerState = altar.getProperty("aft_soulhunters:centertable");
  const gongState = altar.getProperty("aft_soulhunters:gong");

  if (woodState !== "on" || stoneState !== "on" || centerState !== "on" || gongState !== "on") {
    const missing = [];
    if (woodState !== "on") missing.push("woodtable");
    if (stoneState !== "on") missing.push("stonetable");
    if (centerState !== "on") missing.push("centertable");
    if (gongState !== "on") missing.push("gong");
    player.sendMessage(`§cThe crafting altar must be fully assembled before placing gems!`);
    player.sendMessage(`§eStill need: §7${missing.join(", ")}`);
    return;
  }

  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);

  const weaponLevel = weapon ? getWeaponLevel(weapon) : 0;

  const requirements = getUpgradeRequirements(weaponLevel);
  if (!requirements) {
    player.sendMessage("§cPlace a weapon first to determine gem requirements!");
    return;
  }
  const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
  const gems = gemsStr ? JSON.parse(gemsStr) : [];
  if (gems.length >= requirements.gems) {
    player.sendMessage(`§cAltar already has ${requirements.gems} gems!`);
    return;
  }
  gems.push(gem.typeId);

  try {
    // Convert array to JSON string for storage
    altar.setDynamicProperty(ALTAR_GEMS_PROP, JSON.stringify(gems));
  } catch (error) {
    throw error;
  }
  try {
    updateAltarVisuals(altar);
  } catch (error) {
    throw error;
  }
  // Consume item - create new ItemStack or undefined
  if (gem.amount > 1) {
    try {
      const newGem = new ItemStack(gem.typeId, gem.amount - 1);

      setPlayerEquipment(player, EquipmentSlot.Mainhand, newGem);
    } catch (error) {
      throw error;
    }
  } else {
    try {
      setPlayerEquipment(player, EquipmentSlot.Mainhand, undefined);
    } catch (error) {
      throw error;
    }
  }
  const formattedGemName = formatGemDisplayName(gem.typeId);
  player.sendMessage(`§aGem placed (${gems.length}/${requirements.gems}): ${formattedGemName}`);
}

/**
 * Handles crafting altar component placement (woodtable, stonetable, centertable, gong)
 */
function handleCraftingAltarComponentPlacement(player, altar, item, componentType) {
  // Check current component state
  const propertyName = `aft_soulhunters:${componentType}`;
  const currentState = altar.getProperty(propertyName);

  if (currentState === "on") {
    player.sendMessage(`§c${componentType} is already placed on the altar!`);
    return;
  }

  // Set the property to "on"
  altar.setProperty(propertyName, "on");

  // Consume the item
  if (item.amount > 1) {
    const newItem = new ItemStack(item.typeId, item.amount - 1);
    setPlayerEquipment(player, EquipmentSlot.Mainhand, newItem);
  } else {
    setPlayerEquipment(player, EquipmentSlot.Mainhand, undefined);
  }

  player.sendMessage(`§a${componentType.charAt(0).toUpperCase() + componentType.slice(1)} placed on altar!`);

  // Use a short delay to ensure property is synced before checking
  system.runTimeout(() => {
    // Check if all components are now placed
    const woodState = altar.getProperty("aft_soulhunters:woodtable");
    const stoneState = altar.getProperty("aft_soulhunters:stonetable");
    const centerState = altar.getProperty("aft_soulhunters:centertable");
    const gongState = altar.getProperty("aft_soulhunters:gong");

    if (woodState === "on" && stoneState === "on" && centerState === "on" && gongState === "on") {
      player.sendMessage("§6§lCrafting Altar is now fully assembled! You can now craft and upgrade weapons.");
    } else {
      const missing = [];
      if (woodState !== "on") missing.push("woodtable");
      if (stoneState !== "on") missing.push("stonetable");
      if (centerState !== "on") missing.push("centertable");
      if (gongState !== "on") missing.push("gong");
      player.sendMessage(`§eStill need: §7${missing.join(", ")}`);
    }
  }, 1); // Very short delay to ensure property sync
}

/**
 * Check if altar has any items or state
 */
function hasAltarItems(altar) {
  const weapon = altar.getDynamicProperty(ALTAR_WEAPON_PROP);
  const hasIron = altar.getDynamicProperty(ALTAR_IRON_PROP);
  const hasDiamond = altar.getDynamicProperty(ALTAR_DIAMOND_PROP);
  const hasNetherStar = altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP);
  const gemsStr = altar.getDynamicProperty(ALTAR_GEMS_PROP);
  const gems = gemsStr ? JSON.parse(gemsStr) : [];
  
  return weapon || hasIron || hasDiamond || hasNetherStar || gems.length > 0;
}

/**
 * Save altar state to player's dynamic properties
 */
function saveAltarStateToPlayer(player, altar) {
  const playerId = player.id;
  
  // Create altar state object
  const altarState = {
    weapon: altar.getDynamicProperty(ALTAR_WEAPON_PROP),
    weaponData: altar.getDynamicProperty(ALTAR_WEAPON_DATA_PROP),
    iron: altar.getDynamicProperty(ALTAR_IRON_PROP),
    diamond: altar.getDynamicProperty(ALTAR_DIAMOND_PROP),
    netherStar: altar.getDynamicProperty(ALTAR_NETHER_STAR_PROP),
    gems: altar.getDynamicProperty(ALTAR_GEMS_PROP),
    componentStates: {
      woodtable: altar.getProperty("aft_soulhunters:woodtable"),
      stonetable: altar.getProperty("aft_soulhunters:stonetable"),
      centertable: altar.getProperty("aft_soulhunters:centertable"),
      gong: altar.getProperty("aft_soulhunters:gong")
    }
  };
  
  // Save to player's dynamic properties
  const altarStateKey = `aft_soulhunters:saved_altar_state`;
  player.setDynamicProperty(altarStateKey, JSON.stringify(altarState));
  
  player.sendMessage("§6§lAltar state saved! When you place it again, it will restore this state.");
}

/**
 * Remove crafting altar and spawn altar components as items
 */
function removeCraftingAltar(player, altar) {
  const location = altar.location;
  const dimension = altar.dimension;
  
  // Get altar component states
  const woodState = altar.getProperty("aft_soulhunters:woodtable");
  const stoneState = altar.getProperty("aft_soulhunters:stonetable");
  const centerState = altar.getProperty("aft_soulhunters:centertable");
  const gongState = altar.getProperty("aft_soulhunters:gong");
  
  // Spawn the altar components that are currently placed
  if (woodState === "on") {
    const woodtable = new ItemStack("aft_soulhunters:woodtable", 1);
    dimension.spawnItem(woodtable, location);
  }
  
  if (stoneState === "on") {
    const stonetable = new ItemStack("aft_soulhunters:stonetable", 1);
    dimension.spawnItem(stonetable, location);
  }
  
  if (centerState === "on") {
    const centertable = new ItemStack("aft_soulhunters:centertable", 1);
    dimension.spawnItem(centertable, location);
  }
  
  if (gongState === "on") {
    const gong = new ItemStack("aft_soulhunters:gong", 1);
    dimension.spawnItem(gong, location);
  }
  
  // Also spawn a crafting altar spawn egg so they can rebuild it elsewhere
  const altarSpawnEgg = new ItemStack("aft_soulhunters:crafting_altar_spawn_egg", 1);
  dimension.spawnItem(altarSpawnEgg, location);
  
  // Remove the altar entity
  altar.remove();
  
  player.sendMessage("§a§lCrafting Altar dismantled! Components and spawn egg dropped.");
  player.sendMessage("§7§oYour altar state is saved. Use the spawn egg to rebuild and restore state.");
}

// ================================================================================================
// COMPANION HANDLERS (Behavior Control & Soul Management)
// ================================================================================================
/**
 * Handles interactions with weapon companions
 * @param {Player} player - The player
 * @param {Entity} companion - The weapon companion entity
 * @param {ItemStack} itemStack - Item being used (if any)
 */
function handleWeaponCompanionInteraction(player, companion, itemStack) {
  // Soul feeding
  if (itemStack && (itemStack.typeId === SOUL_ITEM_ID || itemStack.typeId === SOUL_ITEM_ALT_ID)) {
    handleCompanionSoulFeeding(player, companion, itemStack);
    return;
  }
  // Behavior control (empty hand or other items)
  showCompanionControlUI(player, companion);
}
/**
 * Handles interactions with altar companions
 * @param {Player} player - The player
 * @param {Entity} companion - The altar companion entity
 * @param {ItemStack} itemStack - Item being used (if any)
 */
function handleAltarCompanionInteraction(player, companion, itemStack) {
  // Altar companions don't need soul feeding, just behavior control
  handleCompanionBehaviorControl(player, companion, true);
}
// NOTE: handleCompanionSoulFeeding function moved to companion_manager.js

/**
 * Handles companion behavior control UI
  // Get the stored weapon slot from the companion
  const storedWeaponSlot = companion.getDynamicProperty("weapon_slot");
  if (storedWeaponSlot === undefined) {
    return;
  }
  let weaponItem = null;
  let weaponInfo = null;
  // Get the specific weapon from the stored slot
  if (storedWeaponSlot === -1) {
    // Weapon should be in main hand
    const mainHandItem = getPlayerEquipment(player, EquipmentSlot.Mainhand);
    if (mainHandItem) {
      const mainHandInfo = getWeaponInfo(mainHandItem);
      if (mainHandInfo) {
        weaponItem = mainHandItem;
        weaponInfo = mainHandInfo;
      }
    }
  } else {
    // Weapon should be in specific inventory slot
    try {
      const inventory = player.getComponent("inventory");
      if (inventory && inventory.container) {
        const invItem = inventory.container.getItem(storedWeaponSlot);
        if (invItem) {
          const invInfo = getWeaponInfo(invItem);
          if (invInfo) {
            weaponItem = invItem;
            weaponInfo = invInfo;
          }
        }
      }
    } catch (error) {
    }
  }
  // If weapon not found in stored slot, search for it
  if (!weaponItem) {
    const companionType = companion.typeId.replace(MOD_PREFIX, "");
    // Check main hand first
    const mainHandItem = getPlayerEquipment(player, EquipmentSlot.Mainhand);
    if (mainHandItem) {
      const mainHandInfo = getWeaponInfo(mainHandItem);
      if (mainHandInfo && mainHandInfo.companion === companionType) {
        weaponItem = mainHandItem;
        weaponInfo = mainHandInfo;
        companion.setDynamicProperty("weapon_slot", -1);
      }
    }
    // Search inventory if not in main hand
    if (!weaponItem) {
      try {
        const inventory = player.getComponent("inventory");
        if (inventory && inventory.container) {
          for (let i = 0; i < inventory.container.size; i++) {
            const invItem = inventory.container.getItem(i);
            if (invItem) {
              const invInfo = getWeaponInfo(invItem);
              if (invInfo && invInfo.companion === companionType) {
                weaponItem = invItem;
                weaponInfo = invInfo;
                companion.setDynamicProperty("weapon_slot", i);
                break;
              }
            }
          }
        }
      } catch (error) {
      }
    }
  }
  if (!weaponItem || !weaponInfo) {
    player.sendMessage("§cCannot find the weapon associated with this companion. Make sure you have the infused weapon in your inventory.");
    return;
  }
  // Verify this is the correct companion type
  const companionType = companion.typeId.replace(MOD_PREFIX, "");
  if (weaponInfo.companion !== companionType) {
    return;
  }
  let souls = weaponInfo.souls ?? 0;
  if (souls >= MAX_SOULS) {
    player.sendMessage("§cThis weapon already has maximum souls (10/10).");
    return;
  }
  // Consume the soul item
  const mainHandItem = getPlayerEquipment(player, EquipmentSlot.Mainhand);
  if (mainHandItem && (mainHandItem.typeId === SOUL_ITEM_ID || mainHandItem.typeId === SOUL_ITEM_ALT_ID)) {
    if (mainHandItem.amount > 1) {
      mainHandItem.amount -= 1;
      setPlayerEquipment(player, EquipmentSlot.Mainhand, mainHandItem);
    } else {
      setPlayerEquipment(player, EquipmentSlot.Mainhand, undefined);
    }
  }
  // Update the weapon
  souls++;
  updateWeaponLore(weaponItem, weaponInfo.companion, souls);
  // Set the weapon back to its proper location
  const currentWeaponSlot = companion.getDynamicProperty("weapon_slot");
  if (currentWeaponSlot === -1) {
    setPlayerEquipment(player, EquipmentSlot.Mainhand, weaponItem);
  } else {
    try {
      const inventory = player.getComponent("inventory");
      if (inventory && inventory.container) {
        inventory.container.setItem(currentWeaponSlot, weaponItem);
      }
    } catch (error) {
    }
  }
  // Update companion visuals and play effects
  const scoreName = SCORE_TO_EVENT[souls];
  try {
    companion.runCommand(`event entity @s aft_soulhunters:souls_bar_${scoreName}`);
    companion.triggerEvent("aft_soulhunters:eat");
  } catch (error) {
  }

  player.sendMessage(`§aSoul added! Weapon now has ${souls}/${MAX_SOULS} souls.`);
}
/**
 * Handles companion behavior control UI
 * @param {Player} player - The player
 * @param {Entity} companion - The companion entity
 * @param {boolean} isAltarCompanion - Whether this is an altar companion
 */
function handleCompanionBehaviorControl(player, companion, isAltarCompanion) {
  // For weapon companions, check if activated and has souls
  const isActive = companion.getDynamicProperty(ACTIVE_PROP);

  if (!isAltarCompanion) {
    if (!isActive) {
      player.sendMessage("§cYour companion must be activated first.");
      return;
    }
    // Check if companion has souls
    const companionWeaponSlot = companion.getDynamicProperty("weapon_slot");
    if (companionWeaponSlot !== undefined) {
      let weaponItem = null;
      // Get the specific weapon that this companion belongs to
      if (companionWeaponSlot === -1) {
        weaponItem = getPlayerEquipment(player, EquipmentSlot.Mainhand);
      } else {
        try {
          const inventory = player.getComponent("inventory");
          if (inventory && inventory.container) {
            weaponItem = inventory.container.getItem(companionWeaponSlot);
          }
        } catch (error) {
        }
      }
      if (weaponItem) {
        const weaponInfo = getWeaponInfo(weaponItem);
        if (weaponInfo) {
          const currentSouls = weaponInfo.souls ?? 0;
          if (currentSouls <= 0) {
            player.sendMessage("§cYour companion has no souls left to fight.");
            try {
              companion.triggerEvent("aft_soulhunters:dont_attack");
              // Auto-dismount if player is riding when souls are depleted
              if (player.getComponent("riding")?.entityRidingOn?.id === companion.id) {
                const dismountCommand = `ride @s stop_riding`;
                player.runCommand(dismountCommand);
                player.sendMessage("§eYou have been automatically dismounted due to soul depletion.");
              }
            } catch (error) {
              // Silent catch - auto-dismount errors are not critical
            }
            return;
          }
        }
      }
    }
  }

  // Filter available behaviors based on companion state
  let availableBehaviors = [...COMPANION_BEHAVIORS];

  // Show behavior selection UI
  const form = new ActionFormData()
    .title(isAltarCompanion ? "Altar Companion Control" : "Companion Control")
    .body("Select an option for your companion:");

  availableBehaviors.forEach(option => {
    form.button(option.text, option.texture);
  });

  form.show(player).then(response => {
    if (response.canceled) return;
    const selectedOption = availableBehaviors[response.selection];
    if (!selectedOption) return;

    // Special handling for riding
    if (selectedOption.action === "start_ride") {
      if (!isActive) {
        player.sendMessage("§cCompanion must be activated to ride!");
        return;
      }

      // Validate companion is ready for riding
      if (!companion.isValid()) {
        player.sendMessage("§cCompanion is not available for riding.");
        return;
      }

      const rideCommand = `ride @s start_riding @e[type=${companion.typeId},c=1,r=5]`;
      player.runCommand(`ride @s start_riding @e[type=${companion.typeId},c=1,r=5]`);
    } else if (selectedOption.event) {
      // Apply behavior event for non-riding actions
      try {
        companion.triggerEvent(selectedOption.event);
        companion.setDynamicProperty(BEHAVIOR_PROP, selectedOption.event);
        player.sendMessage(`§aCompanion mode changed to: ${selectedOption.text}`);
      } catch (error) {
        player.sendMessage(`§cFailed to change companion behavior: ${error.message || error}`);
      }
    }
  });
}
// ================================================================================================
// TESTING UTILITIES
// ================================================================================================

/**
 * Testing utility to quickly add companion lore to weapons
 * Usage: /scriptevent soulhunters:test_companion <companion_type>
 * Example: /scriptevent soulhunters:test_companion dragon
 */
function addCompanionLoreToHeldWeapon(player, companionType) {
  const mainhand = player.getComponent("equippable").getEquipment(EquipmentSlot.Mainhand);
  
  if (!mainhand) {
    player.sendMessage("§cYou must be holding a weapon!");
    return;
  }

  // Check if it's a valid Soul Hunters weapon
  const weaponId = mainhand.typeId;
  if (!SOUL_ALTAR_WEAPONS.includes(weaponId)) {
    player.sendMessage("§cYou must be holding a valid Soul Hunters weapon (Tier 2, 3, or 4)!");
    return;
  }

  // Get companion data
  const companionData = Object.values(SOUL_ALTARS).find(altar => altar.id === companionType);
  if (!companionData) {
    player.sendMessage("§cInvalid companion type! Valid types: dragon, elephant, fox, leopard, manta_ray, panda, phoenix, red_panda, tiger, wolf");
    return;
  }

  // Add companion lore with full souls
  const newLore = [companionData.loreName, "10/10 Souls"];
  mainhand.setLore(newLore);
  
  // Update the item in inventory
  player.getComponent("equippable").setEquipment(EquipmentSlot.Mainhand, mainhand);
  
  player.sendMessage(`§a§lSuccess! Added ${companionData.loreName} lore to your ${weaponId.replace('aft_soulhunters:', '').replace('_', ' ')}!`);
  player.sendMessage("§eYou can now test companion summoning and behaviors!");
}

/**
 * Testing utility to show all available companion types
 */
function showCompanionTypes(player) {
  const companionList = Object.values(SOUL_ALTARS).map(altar => 
    `§6${altar.id}§f - ${altar.loreName}`
  ).join('\n');
  
  player.sendMessage("§e§lAvailable Companion Types:");
  player.sendMessage(companionList);
  player.sendMessage("\n§bUsage: §f/scriptevent soulhunters:test_companion <type>");
  player.sendMessage("§bExample: §f/scriptevent soulhunters:test_companion dragon");
}

// Register script event handlers for testing
system.afterEvents.scriptEventReceive.subscribe((event) => {
  const { id, message, sourceEntity } = event;
  
  // Only handle our mod's script events
  if (!id.startsWith("soulhunters:")) return;
  
  // Must be triggered by a player
  if (!sourceEntity || sourceEntity.typeId !== "minecraft:player") {
    return;
  }
  
  const player = sourceEntity;
  
  switch (id) {
    case "soulhunters:test_companion":
      if (!message || message.trim() === "") {
        showCompanionTypes(player);
      } else {
        addCompanionLoreToHeldWeapon(player, message.trim().toLowerCase());
      }
      break;
      
    case "soulhunters:companion_list":
      showCompanionTypes(player);
      break;
      
    case "soulhunters:test_all_companions":
      // Give player one weapon with each companion type for comprehensive testing
      const testWeapon = "aft_soulhunters:kunai_knife_2";
      let successCount = 0;
      
      // First, clean up any existing companions
      despawnPlayerCompanions(player);
      player.sendMessage("§7Cleaned up existing companions...");
      
      Object.values(SOUL_ALTARS).forEach((companionData, index) => {
        system.runTimeout(() => {
          try {
            const testItem = new ItemStack(testWeapon, 1);
            testItem.setLore([companionData.loreName, "10/10 Souls"]);
            
            // Try to give item to player
            if (player.getComponent("inventory").container.addItem(testItem)) {
              successCount++;
              player.sendMessage(`§a+ Added ${companionData.loreName} test weapon`);
            }
          } catch (error) {
            player.sendMessage(`§c! Failed to create ${companionData.loreName} test weapon`);
          }
          
          // Final message after all weapons processed
          if (index === Object.values(SOUL_ALTARS).length - 1) {
            system.runTimeout(() => {
              player.sendMessage(`§e§lTesting Setup Complete! Created ${successCount}/${Object.values(SOUL_ALTARS).length} companion weapons.`);
              player.sendMessage("§bSwitch between weapons to test automatic companion switching!");
              player.sendMessage("§7Note: Only hold one weapon at a time for proper testing.");
            }, 5);
          }
        }, index * 2); // Stagger creation to avoid issues
      });
      break;
      
    case "soulhunters:cleanup_companions":
      // Manual cleanup command
      despawnPlayerCompanions(player);
      player.sendMessage("§a§lAll companions have been despawned!");
      break;
  }
});

// ================================================================================================
// EXPORTS
// ================================================================================================
export {
  handleSoulAltarInteraction,
  handleCraftingAltarInteraction,
  handleWeaponCompanionInteraction,
  handleAltarCompanionInteraction,
  addCompanionLoreToHeldWeapon,
  showCompanionTypes
};


