package items

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"
)

// NewItem creates a new item instance
func NewItem() *Item {
	return &Item{
		Details: ItemCore{
			UniqueID: NextUniqueID(),
			Count:    1,
		},
		GenericInfo: GenericInfo{
			Condition: DefaultItemCondition,
		},
		GroupedCharIDs: make(map[int32]bool),
		Created:        time.Now(),
	}
}

// NewItemFromTemplate creates a new item from an existing item template
func NewItemFromTemplate(template *Item) *Item {
	if template == nil {
		return NewItem()
	}

	item := &Item{
		// Copy basic information
		LowerName:    template.LowerName,
		Name:         template.Name,
		Description:  template.Description,
		StackCount:   template.StackCount,
		SellPrice:    template.SellPrice,
		SellStatus:   template.SellStatus,
		MaxSellValue: template.MaxSellValue,

		// Copy metadata
		WeaponType:   template.WeaponType,
		SpellID:      template.SpellID,
		SpellTier:    template.SpellTier,
		ItemScript:   template.ItemScript,
		BookLanguage: template.BookLanguage,
		EffectType:   template.EffectType,

		// Initialize new instance data
		Details: ItemCore{
			ItemID:           template.Details.ItemID,
			UniqueID:         NextUniqueID(),
			Count:            1,
			Icon:             template.Details.Icon,
			ClassicIcon:      template.Details.ClassicIcon,
			Tier:             template.Details.Tier,
			RecommendedLevel: template.Details.RecommendedLevel,
		},
		GenericInfo:    template.GenericInfo,
		GroupedCharIDs: make(map[int32]bool),
		Created:        time.Now(),
	}

	// Copy type-specific information
	if template.WeaponInfo != nil {
		weaponInfo := *template.WeaponInfo
		item.WeaponInfo = &weaponInfo
	}
	if template.RangedInfo != nil {
		rangedInfo := *template.RangedInfo
		item.RangedInfo = &rangedInfo
	}
	if template.ArmorInfo != nil {
		armorInfo := *template.ArmorInfo
		item.ArmorInfo = &armorInfo
	}
	if template.AdornmentInfo != nil {
		adornmentInfo := *template.AdornmentInfo
		item.AdornmentInfo = &adornmentInfo
	}
	if template.BagInfo != nil {
		bagInfo := *template.BagInfo
		item.BagInfo = &bagInfo
	}
	if template.FoodInfo != nil {
		foodInfo := *template.FoodInfo
		item.FoodInfo = &foodInfo
	}
	if template.BaubleInfo != nil {
		baubleInfo := *template.BaubleInfo
		item.BaubleInfo = &baubleInfo
	}
	if template.BookInfo != nil {
		bookInfo := *template.BookInfo
		item.BookInfo = &bookInfo
	}
	if template.HouseItemInfo != nil {
		houseItemInfo := *template.HouseItemInfo
		item.HouseItemInfo = &houseItemInfo
	}
	if template.HouseContainerInfo != nil {
		houseContainerInfo := *template.HouseContainerInfo
		item.HouseContainerInfo = &houseContainerInfo
	}
	if template.SkillInfo != nil {
		skillInfo := *template.SkillInfo
		item.SkillInfo = &skillInfo
	}
	if template.RecipeBookInfo != nil {
		recipeBookInfo := *template.RecipeBookInfo
		item.RecipeBookInfo = &recipeBookInfo
	}
	if template.ItemSetInfo != nil {
		itemSetInfo := *template.ItemSetInfo
		item.ItemSetInfo = &itemSetInfo
	}
	if template.ThrownInfo != nil {
		thrownInfo := *template.ThrownInfo
		item.ThrownInfo = &thrownInfo
	}

	// Copy collections (deep copy)
	if len(template.Classifications) > 0 {
		item.Classifications = make([]*Classifications, len(template.Classifications))
		for i, c := range template.Classifications {
			classification := *c
			item.Classifications[i] = &classification
		}
	}

	if len(template.ItemStats) > 0 {
		item.ItemStats = make([]*ItemStat, len(template.ItemStats))
		for i, s := range template.ItemStats {
			stat := *s
			item.ItemStats[i] = &stat
		}
	}

	if len(template.ItemSets) > 0 {
		item.ItemSets = make([]*ItemSet, len(template.ItemSets))
		for i, s := range template.ItemSets {
			set := *s
			item.ItemSets[i] = &set
		}
	}

	if len(template.ItemStringStats) > 0 {
		item.ItemStringStats = make([]*ItemStatString, len(template.ItemStringStats))
		for i, s := range template.ItemStringStats {
			stat := *s
			item.ItemStringStats[i] = &stat
		}
	}

	if len(template.ItemLevelOverrides) > 0 {
		item.ItemLevelOverrides = make([]*ItemLevelOverride, len(template.ItemLevelOverrides))
		for i, o := range template.ItemLevelOverrides {
			override := *o
			item.ItemLevelOverrides[i] = &override
		}
	}

	if len(template.ItemEffects) > 0 {
		item.ItemEffects = make([]*ItemEffect, len(template.ItemEffects))
		for i, e := range template.ItemEffects {
			effect := *e
			item.ItemEffects[i] = &effect
		}
	}

	if len(template.BookPages) > 0 {
		item.BookPages = make([]*BookPage, len(template.BookPages))
		for i, p := range template.BookPages {
			page := *p
			item.BookPages[i] = &page
		}
	}

	if len(template.SlotData) > 0 {
		item.SlotData = make([]int8, len(template.SlotData))
		copy(item.SlotData, template.SlotData)
	}

	return item
}

// Copy creates a deep copy of the item
func (i *Item) Copy() *Item {
	if i == nil {
		return nil
	}

	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return NewItemFromTemplate(i)
}

// AddEffect adds an effect to the item
func (i *Item) AddEffect(effect string, percentage int8, subBulletFlag int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	itemEffect := &ItemEffect{
		Effect:        effect,
		Percentage:    percentage,
		SubBulletFlag: subBulletFlag,
	}

	i.ItemEffects = append(i.ItemEffects, itemEffect)
}

// AddBookPage adds a page to the book item
func (i *Item) AddBookPage(page int8, pageText string, vAlign int8, hAlign int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	bookPage := &BookPage{
		Page:     page,
		PageText: pageText,
		VAlign:   vAlign,
		HAlign:   hAlign,
	}

	i.BookPages = append(i.BookPages, bookPage)
}

// GetMaxSellValue returns the maximum sell value for the item
func (i *Item) GetMaxSellValue() int32 {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.MaxSellValue
}

// SetMaxSellValue sets the maximum sell value for the item
func (i *Item) SetMaxSellValue(val int32) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.MaxSellValue = val
}

// GetOverrideLevel gets the level override for specific classes
func (i *Item) GetOverrideLevel(adventureClass int8, tradeskillClass int8) int16 {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	for _, override := range i.ItemLevelOverrides {
		if override.AdventureClass == adventureClass && override.TradeskillClass == tradeskillClass {
			return override.Level
		}
	}

	return 0
}

// AddLevelOverride adds a level override for specific classes
func (i *Item) AddLevelOverride(adventureClass int8, tradeskillClass int8, level int16) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	override := &ItemLevelOverride{
		AdventureClass:  adventureClass,
		TradeskillClass: tradeskillClass,
		Level:           level,
	}

	i.ItemLevelOverrides = append(i.ItemLevelOverrides, override)
}

// CheckClassLevel checks if the item meets class and level requirements
func (i *Item) CheckClassLevel(adventureClass int8, tradeskillClass int8, level int16) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	// Check for specific level override
	overrideLevel := i.GetOverrideLevel(adventureClass, tradeskillClass)
	if overrideLevel > 0 {
		return level >= overrideLevel
	}

	// Check general requirements
	if adventureClass > 0 && i.GenericInfo.AdventureDefaultLevel > 0 {
		return level >= i.GenericInfo.AdventureDefaultLevel
	}

	if tradeskillClass > 0 && i.GenericInfo.TradeskillDefaultLevel > 0 {
		return level >= i.GenericInfo.TradeskillDefaultLevel
	}

	return true
}

// CheckClass checks if the item can be used by the specified classes
func (i *Item) CheckClass(adventureClass int8, tradeskillClass int8) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	// Check adventure class requirements
	if adventureClass > 0 && i.GenericInfo.AdventureClasses > 0 {
		classBit := int64(1 << uint(adventureClass))
		if (i.GenericInfo.AdventureClasses & classBit) == 0 {
			return false
		}
	}

	// Check tradeskill class requirements
	if tradeskillClass > 0 && i.GenericInfo.TradeskillClasses > 0 {
		classBit := int64(1 << uint(tradeskillClass))
		if (i.GenericInfo.TradeskillClasses & classBit) == 0 {
			return false
		}
	}

	return true
}

// SetAppearance sets the appearance information for the item
func (i *Item) SetAppearance(appearanceType int16, red int8, green int8, blue int8, highlightRed int8, highlightGreen int8, highlightBlue int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.GenericInfo.AppearanceID = appearanceType
	i.GenericInfo.AppearanceRed = red
	i.GenericInfo.AppearanceGreen = green
	i.GenericInfo.AppearanceBlue = blue
	i.GenericInfo.AppearanceHighlightRed = highlightRed
	i.GenericInfo.AppearanceHighlightGreen = highlightGreen
	i.GenericInfo.AppearanceHighlightBlue = highlightBlue
}

// AddStat adds a stat to the item
func (i *Item) AddStat(stat *ItemStat) {
	if stat == nil {
		return
	}

	i.mutex.Lock()
	defer i.mutex.Unlock()

	statCopy := *stat
	i.ItemStats = append(i.ItemStats, &statCopy)
}

// AddStatByValues adds a stat using individual values
func (i *Item) AddStatByValues(statType int32, subType int16, value float32, level int8, name string) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	stat := &ItemStat{
		StatName:         name,
		StatType:         statType,
		StatSubtype:      subType,
		StatTypeCombined: (int16(statType) << 8) | subType,
		Value:            value,
		Level:            level,
	}

	i.ItemStats = append(i.ItemStats, stat)
}

// HasStat checks if the item has a specific stat
func (i *Item) HasStat(statID uint32, statName string) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	for _, stat := range i.ItemStats {
		if statName != "" && strings.EqualFold(stat.StatName, statName) {
			return true
		}
		if statID > 0 && uint32(stat.StatTypeCombined) == statID {
			return true
		}
	}

	return false
}

// AddSet adds an item set to the item
func (i *Item) AddSet(set *ItemSet) {
	if set == nil {
		return
	}

	i.mutex.Lock()
	defer i.mutex.Unlock()

	setCopy := *set
	i.ItemSets = append(i.ItemSets, &setCopy)
}

// AddSetByValues adds an item set using individual values
func (i *Item) AddSetByValues(itemID int32, itemCRC int32, itemIcon int16, itemStackSize int32, itemListColor int32, name string, language int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	set := &ItemSet{
		ItemID:        itemID,
		ItemCRC:       itemCRC,
		ItemIcon:      itemIcon,
		ItemStackSize: int16(itemStackSize),
		ItemListColor: itemListColor,
		Name:          name,
		Language:      language,
	}

	i.ItemSets = append(i.ItemSets, set)
}

// DeleteItemSets removes all item sets from the item
func (i *Item) DeleteItemSets() {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.ItemSets = nil
}

// AddStatString adds a string stat to the item
func (i *Item) AddStatString(statString *ItemStatString) {
	if statString == nil {
		return
	}

	i.mutex.Lock()
	defer i.mutex.Unlock()

	statCopy := *statString
	i.ItemStringStats = append(i.ItemStringStats, &statCopy)
}

// SetWeaponType sets the weapon type
func (i *Item) SetWeaponType(weaponType int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.WeaponType = weaponType
}

// GetWeaponType gets the weapon type
func (i *Item) GetWeaponType() int8 {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.WeaponType
}

// HasSlot checks if the item can be equipped in specific slots
func (i *Item) HasSlot(slot int8, slot2 int8) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	for _, slotData := range i.SlotData {
		if slotData == slot || (slot2 != -1 && slotData == slot2) {
			return true
		}
	}

	return false
}

// HasAdorn0 checks if the item has an adornment in slot 0
func (i *Item) HasAdorn0() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.Adorn0 > 0
}

// HasAdorn1 checks if the item has an adornment in slot 1
func (i *Item) HasAdorn1() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.Adorn1 > 0
}

// HasAdorn2 checks if the item has an adornment in slot 2
func (i *Item) HasAdorn2() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.Adorn2 > 0
}

// SetItemType sets the item type
func (i *Item) SetItemType(itemType int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.GenericInfo.ItemType = itemType
}

// CheckFlag checks if the item has a specific flag set
func (i *Item) CheckFlag(flag int32) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return (int32(i.GenericInfo.ItemFlags) & flag) != 0
}

// CheckFlag2 checks if the item has a specific flag2 set
func (i *Item) CheckFlag2(flag int32) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return (int32(i.GenericInfo.ItemFlags2) & flag) != 0
}

// AddSlot adds a slot to the item's slot data
func (i *Item) AddSlot(slotID int8) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	// Check if slot already exists
	for _, slot := range i.SlotData {
		if slot == slotID {
			return
		}
	}

	i.SlotData = append(i.SlotData, slotID)
}

// SetSlots sets the slots using a bitmask
func (i *Item) SetSlots(slots int32) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.SlotData = nil

	// Convert bitmask to slot array
	for slotID := int8(0); slotID < 32; slotID++ {
		if (slots & (1 << uint(slotID))) != 0 {
			i.SlotData = append(i.SlotData, slotID)
		}
	}
}

// GetIcon returns the appropriate icon for the given client version
func (i *Item) GetIcon(version int16) int16 {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	// Use classic icon for older clients
	if version < 1000 && i.Details.ClassicIcon > 0 {
		return i.Details.ClassicIcon
	}

	return i.Details.Icon
}

// TryLockItem attempts to lock the item for a specific reason
func (i *Item) TryLockItem(reason LockReason) bool {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	if i.Details.ItemLocked {
		// Check if already locked for this reason
		if (LockReason(i.Details.LockFlags) & reason) != 0 {
			return true // Already locked for this reason
		}
		return false // Locked for different reason
	}

	i.Details.ItemLocked = true
	i.Details.LockFlags = int32(reason)
	return true
}

// TryUnlockItem attempts to unlock the item for a specific reason
func (i *Item) TryUnlockItem(reason LockReason) bool {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	if !i.Details.ItemLocked {
		return true // Already unlocked
	}

	// Remove the specific lock reason
	currentFlags := LockReason(i.Details.LockFlags)
	newFlags := currentFlags & ^reason

	if newFlags == 0 {
		// No more lock reasons, unlock the item
		i.Details.ItemLocked = false
		i.Details.LockFlags = 0
	} else {
		// Still have other lock reasons
		i.Details.LockFlags = int32(newFlags)
	}

	return true
}

// IsItemLocked checks if the item is locked
func (i *Item) IsItemLocked() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.Details.ItemLocked
}

// IsItemLockedFor checks if the item is locked for a specific reason
func (i *Item) IsItemLockedFor(reason LockReason) bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	if !i.Details.ItemLocked {
		return false
	}

	return (LockReason(i.Details.LockFlags) & reason) != 0
}

// SetItemScript sets the item script
func (i *Item) SetItemScript(script string) {
	i.mutex.Lock()
	defer i.mutex.Unlock()

	i.ItemScript = script
}

// GetItemScript returns the item script
func (i *Item) GetItemScript() string {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return i.ItemScript
}

// CalculateRepairCost calculates the repair cost for the item
func (i *Item) CalculateRepairCost() int32 {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	// Basic repair cost calculation based on item level and condition
	baseRepairCost := int32(i.Details.RecommendedLevel * 10)

	// Adjust based on condition (lower condition = higher repair cost)
	conditionMultiplier := float32(100-i.GenericInfo.Condition) / 100.0

	return int32(float32(baseRepairCost) * conditionMultiplier)
}

// CreateItemLink creates an item link for chat/display
func (i *Item) CreateItemLink(clientVersion int16, useUniqueID bool) string {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	var builder strings.Builder

	builder.WriteString("[item:")

	if useUniqueID {
		builder.WriteString(strconv.FormatInt(i.Details.UniqueID, 10))
	} else {
		builder.WriteString(strconv.FormatInt(int64(i.Details.ItemID), 10))
	}

	builder.WriteString(":")
	builder.WriteString(strconv.FormatInt(int64(i.Details.Count), 10))
	builder.WriteString(":")
	builder.WriteString(strconv.FormatInt(int64(i.Details.Tier), 10))
	builder.WriteString("]")
	builder.WriteString(i.Name)
	builder.WriteString("[/item]")

	return builder.String()
}

// Validate validates the item data
func (i *Item) Validate() *ItemValidationResult {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	result := &ItemValidationResult{Valid: true}

	// Check required fields
	if i.Name == "" {
		result.Valid = false
		result.Errors = append(result.Errors, "item name is required")
	}

	if len(i.Name) > MaxItemNameLength {
		result.Valid = false
		result.Errors = append(result.Errors, fmt.Sprintf("item name exceeds maximum length of %d", MaxItemNameLength))
	}

	if len(i.Description) > MaxItemDescLength {
		result.Valid = false
		result.Errors = append(result.Errors, fmt.Sprintf("item description exceeds maximum length of %d", MaxItemDescLength))
	}

	if i.Details.ItemID <= 0 {
		result.Valid = false
		result.Errors = append(result.Errors, "item ID must be positive")
	}

	if i.Details.Count <= 0 {
		result.Valid = false
		result.Errors = append(result.Errors, "item count must be positive")
	}

	if i.GenericInfo.Condition < 0 || i.GenericInfo.Condition > 100 {
		result.Valid = false
		result.Errors = append(result.Errors, "item condition must be between 0 and 100")
	}

	// Validate item type-specific data
	switch i.GenericInfo.ItemType {
	case ItemTypeWeapon:
		if i.WeaponInfo == nil {
			result.Valid = false
			result.Errors = append(result.Errors, "weapon items must have weapon info")
		}
	case ItemTypeArmor:
		if i.ArmorInfo == nil {
			result.Valid = false
			result.Errors = append(result.Errors, "armor items must have armor info")
		}
	case ItemTypeBag:
		if i.BagInfo == nil {
			result.Valid = false
			result.Errors = append(result.Errors, "bag items must have bag info")
		}
	}

	return result
}

// String returns a string representation of the item
func (i *Item) String() string {
	i.mutex.RLock()
	defer i.mutex.RUnlock()

	return fmt.Sprintf("Item{ID: %d, Name: %s, Type: %d, Count: %d}",
		i.Details.ItemID, i.Name, i.GenericInfo.ItemType, i.Details.Count)
}

// Global unique ID counter
var (
	uniqueIDCounter int64 = 1
	uniqueIDMutex   sync.Mutex
)

// NextUniqueID generates the next unique ID for items
func NextUniqueID() int64 {
	uniqueIDMutex.Lock()
	defer uniqueIDMutex.Unlock()

	id := uniqueIDCounter
	uniqueIDCounter++
	return id
}

// Item type checking methods

// IsNormal checks if the item is a normal item
func (i *Item) IsNormal() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeNormal
}

// IsWeapon checks if the item is a weapon
func (i *Item) IsWeapon() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeWeapon
}

// IsArmor checks if the item is armor
func (i *Item) IsArmor() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeArmor
}

// IsRanged checks if the item is a ranged weapon
func (i *Item) IsRanged() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeRanged
}

// IsBag checks if the item is a bag
func (i *Item) IsBag() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeBag
}

// IsFood checks if the item is food
func (i *Item) IsFood() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeFood
}

// IsBauble checks if the item is a bauble
func (i *Item) IsBauble() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeBauble
}

// IsSkill checks if the item is a skill item
func (i *Item) IsSkill() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeSkill
}

// IsHouseItem checks if the item is a house item
func (i *Item) IsHouseItem() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeHouse
}

// IsHouseContainer checks if the item is a house container
func (i *Item) IsHouseContainer() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeHouseContainer
}

// IsShield checks if the item is a shield
func (i *Item) IsShield() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeShield
}

// IsAdornment checks if the item is an adornment
func (i *Item) IsAdornment() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeAdornment
}

// IsBook checks if the item is a book
func (i *Item) IsBook() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeBook
}

// IsThrown checks if the item is a thrown weapon
func (i *Item) IsThrown() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeThrown
}

// IsHarvest checks if the item is harvestable
func (i *Item) IsHarvest() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.Harvest > 0
}

// IsBodyDrop checks if the item drops on death
func (i *Item) IsBodyDrop() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.BodyDrop > 0
}

// IsCollectable checks if the item is collectable
func (i *Item) IsCollectable() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.Collectable > 0
}

// Additional broker-specific type checks

// IsAmmo checks if the item is ammunition
func (i *Item) IsAmmo() bool {
	// TODO: Implement ammo detection logic based on item properties
	return false
}

// IsChainArmor checks if the item is chain armor
func (i *Item) IsChainArmor() bool {
	// TODO: Implement chain armor detection logic
	return false
}

// IsCloak checks if the item is a cloak
func (i *Item) IsCloak() bool {
	// TODO: Implement cloak detection logic
	return false
}

// IsClothArmor checks if the item is cloth armor
func (i *Item) IsClothArmor() bool {
	// TODO: Implement cloth armor detection logic
	return false
}

// IsCrushWeapon checks if the item is a crush weapon
func (i *Item) IsCrushWeapon() bool {
	// TODO: Implement crush weapon detection logic
	return false
}

// IsFoodFood checks if the item is food (not drink)
func (i *Item) IsFoodFood() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.IsFood() && i.FoodInfo != nil && i.FoodInfo.Type == 1
}

// IsFoodDrink checks if the item is a drink
func (i *Item) IsFoodDrink() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.IsFood() && i.FoodInfo != nil && i.FoodInfo.Type == 0
}

// IsJewelry checks if the item is jewelry
func (i *Item) IsJewelry() bool {
	// TODO: Implement jewelry detection logic
	return false
}

// IsLeatherArmor checks if the item is leather armor
func (i *Item) IsLeatherArmor() bool {
	// TODO: Implement leather armor detection logic
	return false
}

// IsMisc checks if the item is miscellaneous
func (i *Item) IsMisc() bool {
	// TODO: Implement misc item detection logic
	return false
}

// IsPierceWeapon checks if the item is a pierce weapon
func (i *Item) IsPierceWeapon() bool {
	// TODO: Implement pierce weapon detection logic
	return false
}

// IsPlateArmor checks if the item is plate armor
func (i *Item) IsPlateArmor() bool {
	// TODO: Implement plate armor detection logic
	return false
}

// IsPoison checks if the item is poison
func (i *Item) IsPoison() bool {
	// TODO: Implement poison detection logic
	return false
}

// IsPotion checks if the item is a potion
func (i *Item) IsPotion() bool {
	// TODO: Implement potion detection logic
	return false
}

// IsRecipeBook checks if the item is a recipe book
func (i *Item) IsRecipeBook() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.GenericInfo.ItemType == ItemTypeRecipe
}

// IsSalesDisplay checks if the item is a sales display
func (i *Item) IsSalesDisplay() bool {
	// TODO: Implement sales display detection logic
	return false
}

// IsSlashWeapon checks if the item is a slash weapon
func (i *Item) IsSlashWeapon() bool {
	// TODO: Implement slash weapon detection logic
	return false
}

// IsSpellScroll checks if the item is a spell scroll
func (i *Item) IsSpellScroll() bool {
	// TODO: Implement spell scroll detection logic
	return false
}

// IsTinkered checks if the item is tinkered
func (i *Item) IsTinkered() bool {
	i.mutex.RLock()
	defer i.mutex.RUnlock()
	return i.Tinkered
}

// IsTradeskill checks if the item is a tradeskill item
func (i *Item) IsTradeskill() bool {
	// TODO: Implement tradeskill item detection logic
	return false
}

// Log a message when the item system is initialized
func init() {
	log.Printf("Items system initialized")
}
