package items

import (
	"database/sql"
	"fmt"
	"log"
)

// loadItemTypeDetails loads type-specific details for an item based on its type
func (idb *ItemDatabase) loadItemTypeDetails(item *Item) error {
	switch item.GenericInfo.ItemType {
	case ItemTypeWeapon:
		return idb.loadWeaponDetails(item)
	case ItemTypeRanged:
		return idb.loadRangedWeaponDetails(item)
	case ItemTypeArmor:
		return idb.loadArmorDetails(item)
	case ItemTypeShield:
		return idb.loadShieldDetails(item)
	case ItemTypeBag:
		return idb.loadBagDetails(item)
	case ItemTypeSkill:
		return idb.loadSkillDetails(item)
	case ItemTypeRecipe:
		return idb.loadRecipeBookDetails(item)
	case ItemTypeFood:
		return idb.loadFoodDetails(item)
	case ItemTypeBauble:
		return idb.loadBaubleDetails(item)
	case ItemTypeHouse:
		return idb.loadHouseItemDetails(item)
	case ItemTypeThrown:
		return idb.loadThrownWeaponDetails(item)
	case ItemTypeHouseContainer:
		return idb.loadHouseContainerDetails(item)
	case ItemTypeBook:
		return idb.loadBookDetails(item)
	case ItemTypeAdornment:
		return idb.loadAdornmentDetails(item)
	}
	
	// No specific type details needed for this item type
	return nil
}

// loadWeaponDetails loads weapon-specific information
func (idb *ItemDatabase) loadWeaponDetails(item *Item) error {
	query := `
		SELECT wield_type, damage_low1, damage_high1, damage_low2, damage_high2,
			   damage_low3, damage_high3, delay_hundredths, rating
		FROM item_details_weapon
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	weapon := &WeaponInfo{}
	err := row.Scan(
		&weapon.WieldType,
		&weapon.DamageLow1,
		&weapon.DamageHigh1,
		&weapon.DamageLow2,
		&weapon.DamageHigh2,
		&weapon.DamageLow3,
		&weapon.DamageHigh3,
		&weapon.Delay,
		&weapon.Rating,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No weapon details found
		}
		return fmt.Errorf("failed to load weapon details: %v", err)
	}

	item.WeaponInfo = weapon
	return nil
}

// loadRangedWeaponDetails loads ranged weapon information
func (idb *ItemDatabase) loadRangedWeaponDetails(item *Item) error {
	// First load weapon info
	if err := idb.loadWeaponDetails(item); err != nil {
		return err
	}

	query := `
		SELECT range_low, range_high
		FROM item_details_range
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	ranged := &RangedInfo{
		WeaponInfo: *item.WeaponInfo, // Copy weapon info
	}

	err := row.Scan(&ranged.RangeLow, &ranged.RangeHigh)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No ranged details found
		}
		return fmt.Errorf("failed to load ranged weapon details: %v", err)
	}

	item.RangedInfo = ranged
	item.WeaponInfo = nil // Clear weapon info since we have ranged info
	return nil
}

// loadArmorDetails loads armor mitigation information
func (idb *ItemDatabase) loadArmorDetails(item *Item) error {
	query := `
		SELECT mitigation_low, mitigation_high
		FROM item_details_armor
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	armor := &ArmorInfo{}
	err := row.Scan(&armor.MitigationLow, &armor.MitigationHigh)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No armor details found
		}
		return fmt.Errorf("failed to load armor details: %v", err)
	}

	item.ArmorInfo = armor
	return nil
}

// loadShieldDetails loads shield information
func (idb *ItemDatabase) loadShieldDetails(item *Item) error {
	// Load armor details first
	if err := idb.loadArmorDetails(item); err != nil {
		return err
	}

	if item.ArmorInfo != nil {
		shield := &ShieldInfo{
			ArmorInfo: *item.ArmorInfo,
		}
		item.ArmorInfo = nil // Clear armor info
		// Note: In Go we don't have ShieldInfo, just use ArmorInfo
		item.ArmorInfo = &shield.ArmorInfo
	}

	return nil
}

// loadBagDetails loads bag information
func (idb *ItemDatabase) loadBagDetails(item *Item) error {
	query := `
		SELECT num_slots, weight_reduction
		FROM item_details_bag
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	bag := &BagInfo{}
	err := row.Scan(&bag.NumSlots, &bag.WeightReduction)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No bag details found
		}
		return fmt.Errorf("failed to load bag details: %v", err)
	}

	item.BagInfo = bag
	return nil
}

// loadSkillDetails loads skill book information
func (idb *ItemDatabase) loadSkillDetails(item *Item) error {
	query := `
		SELECT spell_id, spell_tier
		FROM item_details_skill
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	skill := &SkillInfo{}
	err := row.Scan(&skill.SpellID, &skill.SpellTier)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No skill details found
		}
		return fmt.Errorf("failed to load skill details: %v", err)
	}

	item.SkillInfo = skill
	item.SpellID = skill.SpellID
	item.SpellTier = int8(skill.SpellTier)
	return nil
}

// loadRecipeBookDetails loads recipe book information
func (idb *ItemDatabase) loadRecipeBookDetails(item *Item) error {
	query := `
		SELECT recipe_id, uses
		FROM item_details_recipe_book
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	recipe := &RecipeBookInfo{}
	var recipeID int32
	err := row.Scan(&recipeID, &recipe.Uses)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No recipe book details found
		}
		return fmt.Errorf("failed to load recipe book details: %v", err)
	}

	recipe.RecipeID = recipeID
	recipe.Recipes = []uint32{uint32(recipeID)} // Add the single recipe
	item.RecipeBookInfo = recipe
	return nil
}

// loadFoodDetails loads food/drink information
func (idb *ItemDatabase) loadFoodDetails(item *Item) error {
	query := `
		SELECT type, level, duration, satiation
		FROM item_details_food
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	food := &FoodInfo{}
	err := row.Scan(&food.Type, &food.Level, &food.Duration, &food.Satiation)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No food details found
		}
		return fmt.Errorf("failed to load food details: %v", err)
	}

	item.FoodInfo = food
	return nil
}

// loadBaubleDetails loads bauble information
func (idb *ItemDatabase) loadBaubleDetails(item *Item) error {
	query := `
		SELECT cast, recovery, duration, recast, display_slot_optional,
			   display_cast_time, display_bauble_type, effect_radius,
			   max_aoe_targets, display_until_cancelled
		FROM item_details_bauble
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	bauble := &BaubleInfo{}
	err := row.Scan(
		&bauble.Cast,
		&bauble.Recovery,
		&bauble.Duration,
		&bauble.Recast,
		&bauble.DisplaySlotOptional,
		&bauble.DisplayCastTime,
		&bauble.DisplayBaubleType,
		&bauble.EffectRadius,
		&bauble.MaxAOETargets,
		&bauble.DisplayUntilCancelled,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No bauble details found
		}
		return fmt.Errorf("failed to load bauble details: %v", err)
	}

	item.BaubleInfo = bauble
	return nil
}

// loadHouseItemDetails loads house item information
func (idb *ItemDatabase) loadHouseItemDetails(item *Item) error {
	query := `
		SELECT status_rent_reduction, coin_rent_reduction, house_only, house_location
		FROM item_details_house
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	house := &HouseItemInfo{}
	err := row.Scan(
		&house.StatusRentReduction,
		&house.CoinRentReduction,
		&house.HouseOnly,
		&house.HouseLocation,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No house item details found
		}
		return fmt.Errorf("failed to load house item details: %v", err)
	}

	item.HouseItemInfo = house
	return nil
}

// loadThrownWeaponDetails loads thrown weapon information
func (idb *ItemDatabase) loadThrownWeaponDetails(item *Item) error {
	query := `
		SELECT range_val, damage_modifier, hit_bonus, damage_type
		FROM item_details_thrown
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	thrown := &ThrownInfo{}
	err := row.Scan(
		&thrown.Range,
		&thrown.DamageModifier,
		&thrown.HitBonus,
		&thrown.DamageType,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No thrown weapon details found
		}
		return fmt.Errorf("failed to load thrown weapon details: %v", err)
	}

	item.ThrownInfo = thrown
	return nil
}

// loadHouseContainerDetails loads house container information
func (idb *ItemDatabase) loadHouseContainerDetails(item *Item) error {
	query := `
		SELECT allowed_types, num_slots, broker_commission, fence_commission
		FROM item_details_house_container
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	container := &HouseContainerInfo{}
	err := row.Scan(
		&container.AllowedTypes,
		&container.NumSlots,
		&container.BrokerCommission,
		&container.FenceCommission,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No house container details found
		}
		return fmt.Errorf("failed to load house container details: %v", err)
	}

	item.HouseContainerInfo = container
	return nil
}

// loadBookDetails loads book information
func (idb *ItemDatabase) loadBookDetails(item *Item) error {
	query := `
		SELECT language, author, title
		FROM item_details_book
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	book := &BookInfo{}
	err := row.Scan(&book.Language, &book.Author, &book.Title)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No book details found
		}
		return fmt.Errorf("failed to load book details: %v", err)
	}

	item.BookInfo = book
	item.BookLanguage = book.Language

	// Load book pages
	if err := idb.loadBookPages(item); err != nil {
		log.Printf("Error loading book pages for item %d: %v", item.Details.ItemID, err)
	}

	return nil
}

// loadBookPages loads book page content
func (idb *ItemDatabase) loadBookPages(item *Item) error {
	query := `
		SELECT page, page_text, page_text_valign, page_text_halign
		FROM item_details_book_pages
		WHERE item_id = ?
		ORDER BY page
	`

	rows, err := idb.db.Query(query, item.Details.ItemID)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var page BookPage
		err := rows.Scan(&page.Page, &page.PageText, &page.VAlign, &page.HAlign)
		if err != nil {
			return err
		}

		item.BookPages = append(item.BookPages, &page)
	}

	return rows.Err()
}

// loadAdornmentDetails loads adornment information
func (idb *ItemDatabase) loadAdornmentDetails(item *Item) error {
	query := `
		SELECT duration, item_types, slot_type
		FROM item_details_adornments
		WHERE item_id = ?
	`

	row := idb.db.QueryRow(query, item.Details.ItemID)

	adornment := &AdornmentInfo{}
	err := row.Scan(&adornment.Duration, &adornment.ItemTypes, &adornment.SlotType)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil // No adornment details found
		}
		return fmt.Errorf("failed to load adornment details: %v", err)
	}

	item.AdornmentInfo = adornment
	return nil
}

// LoadItemSets loads item set information
func (idb *ItemDatabase) LoadItemSets(masterList *MasterItemList) error {
	query := `
		SELECT item_id, item_crc, item_icon, item_stack_size, item_list_color
		FROM reward_crate_items
		ORDER BY item_id
	`

	rows, err := idb.db.Query(query)
	if err != nil {
		return fmt.Errorf("failed to query item sets: %v", err)
	}
	defer rows.Close()

	itemSets := make(map[int32][]*ItemSet)

	for rows.Next() {
		var itemSet ItemSet
		err := rows.Scan(
			&itemSet.ItemID,
			&itemSet.ItemCRC,
			&itemSet.ItemIcon,
			&itemSet.ItemStackSize,
			&itemSet.ItemListColor,
		)
		if err != nil {
			log.Printf("Error scanning item set row: %v", err)
			continue
		}

		// Add to item sets map
		itemSets[itemSet.ItemID] = append(itemSets[itemSet.ItemID], &itemSet)
	}

	if err = rows.Err(); err != nil {
		return fmt.Errorf("error iterating item set rows: %v", err)
	}

	// Associate item sets with items
	for itemID, sets := range itemSets {
		item := masterList.GetItem(itemID)
		if item != nil {
			item.ItemSets = sets
		}
	}

	log.Printf("Loaded item sets for %d items", len(itemSets))
	return nil
}

// LoadItemClassifications loads item classifications
func (idb *ItemDatabase) LoadItemClassifications(masterList *MasterItemList) error {
	query := `
		SELECT item_id, classification_id, classification_name
		FROM item_classifications
		ORDER BY item_id
	`

	rows, err := idb.db.Query(query)
	if err != nil {
		return fmt.Errorf("failed to query item classifications: %v", err)
	}
	defer rows.Close()

	classifications := make(map[int32][]*Classifications)

	for rows.Next() {
		var itemID int32
		var classification Classifications
		err := rows.Scan(&itemID, &classification.ClassificationID, &classification.ClassificationName)
		if err != nil {
			log.Printf("Error scanning classification row: %v", err)
			continue
		}

		classifications[itemID] = append(classifications[itemID], &classification)
	}

	if err = rows.Err(); err != nil {
		return fmt.Errorf("error iterating classification rows: %v", err)
	}

	// Associate classifications with items
	for itemID, classifs := range classifications {
		item := masterList.GetItem(itemID)
		if item != nil {
			item.Classifications = classifs
		}
	}

	log.Printf("Loaded classifications for %d items", len(classifications))
	return nil
}