--[[
============================================================================
Core/BlizzardData/Player.lua  (added in v15.2.0 — Audit Batch 4 Part 2)
============================================================================

Player-class capability queries + item classification for the BlizzardData
orchestrator. Owner-pattern: each method takes `owner` (the BD orchestrator)
as first argument.

Methods owned here (12):
  -- Categories / Appearances API
  GetCategoryAppearances    — wraps C_TransmogCollection.GetCategoryAppearances
  GetAppearanceSources      — wraps C_TransmogCollection.GetAppearanceSources
  GetItemIcon               — sync GetItemIcon with cache + Loading fallback
  -- Player profile queries
  GetPlayerArmorTypes       — set of all armor types the player can wear
  GetPlayerPrimaryArmor     — recommended armor type for the player class
  CanPlayerWearArmorType    — does player class get any benefit from this type
  CanPlayerEquipArmorType   — alias used by some callers
  GetPlayerWeaponTypes      — set of usable weapon types
  CanPlayerUseWeaponType    — single-type weapon proficiency check
  GetActiveClassName        — current class, respecting ProfileManager
  -- Item-by-item classifiers
  GetArmorType              — classify an itemID as PLATE/MAIL/LEATHER/CLOTH/SHIELD
  GetWeaponType             — classify an itemID's weapon type + isTwoHanded

External dependencies pulled from owner (BD):
  owner.CLASS_ARMOR              — what armor each class can WEAR (4-type tables)
  owner.CLASS_PRIMARY_ARMOR      — what each class TRANSMOGS to (single token)
  owner.CLASS_WEAPONS            — weapon proficiency sets per class
  owner._armorCache              — itemID -> armor type cache
  owner._weaponCache             — itemID -> (weapon type, isTwoHanded) cache

Closure / shadowing notes: All synchronous methods, no closures, no async.
============================================================================
]]--
local ADDON_NAME, NS = ...
local ETB = NS.ETB
NS.ETB.BlizzardData = NS.ETB.BlizzardData or {}
NS.ETB.BlizzardData.Player = NS.ETB.BlizzardData.Player or {}
local Player = NS.ETB.BlizzardData.Player

-- =============================================================================
-- METHODS (extracted from Core/BlizzardData.lua in v15.2.0)
-- =============================================================================

function Player:GetCategoryAppearances(owner, categoryID)
    if not categoryID then return {} end
    
    if owner.cache.categories[categoryID] then
        owner.stats.cacheHits = owner.stats.cacheHits + 1
        return owner.cache.categories[categoryID]
    end
    
    owner.stats.cacheMisses = owner.stats.cacheMisses + 1
    owner.stats.categoryQueries = owner.stats.categoryQueries + 1
    
    local success, appearances = pcall(C_TransmogCollection.GetCategoryAppearances, categoryID)
    if not success then
        ETB:Debug("BlizzardData", string.format("GetCategoryAppearances failed for category %d: %s", categoryID, tostring(appearances)))
        return {}
    end
    
    if not appearances then
        ETB:Debug("BlizzardData", string.format("GetCategoryAppearances returned nil for category %d", categoryID))
        return {}
    end
    
    -- Debug for weapons (categories 12+)
    if owner:IsWeaponCategory(categoryID) and #appearances == 0 then
        ETB:Debug("BlizzardData", string.format("Warning: No appearances returned for weapon category %d", categoryID))
    end
    
    owner.cache.categories[categoryID] = appearances
    return appearances
end

function Player:GetAppearanceSources(owner, visualID)
    if not visualID then return {} end
    
    if owner.cache.sources[visualID] then
        owner.stats.cacheHits = owner.stats.cacheHits + 1
        return owner.cache.sources[visualID]
    end
    
    owner.stats.cacheMisses = owner.stats.cacheMisses + 1
    owner.stats.sourceQueries = owner.stats.sourceQueries + 1
    
    local success, sources = pcall(C_TransmogCollection.GetAppearanceSources, visualID)
    if not success or not sources then return {} end
    
    owner.cache.sources[visualID] = sources
    return sources
end

function Player:GetItemIcon(owner, itemID)
    if not itemID then return nil end
    
    local cached = owner.iconCache:Get(itemID)
    if cached then return cached end
    
    local icon
    if GetItemInfoInstant then
        local _, _, _, _, tex = GetItemInfoInstant(itemID)
        icon = tex
    end
    
    if not icon then
        local _, _, _, _, _, _, _, _, _, tex = GetItemInfo(itemID)
        icon = tex
    end
    
    if icon then
        owner.iconCache:Set(itemID, icon)
    end
    
    return icon
end


function Player:GetPlayerArmorTypes(owner)
    -- If ProfileManager is active and viewing different character, use that class
    if ETB.ProfileManager then
        local activeClass = ETB.ProfileManager:GetActiveClassID()
        if activeClass then
            return owner.CLASS_ARMOR[activeClass] or {}
        end
    end
    local _, playerClass = UnitClass("player")
    return owner.CLASS_ARMOR[playerClass] or {}
end

function Player:GetPlayerPrimaryArmor(owner)
    -- If ProfileManager is active and viewing different character, use that class
    if ETB.ProfileManager then
        local activeClass = ETB.ProfileManager:GetActiveClassID()
        if activeClass then
            return owner.CLASS_PRIMARY_ARMOR[activeClass] or "CLOTH"
        end
    end
    local _, playerClass = UnitClass("player")
    return owner.CLASS_PRIMARY_ARMOR[playerClass] or "CLOTH"
end

function Player:CanPlayerWearArmorType(owner, armorType)
    if not armorType then return true end  -- Unknown armor type, allow it
    
    -- For transmog filtering, we want to match the PRIMARY armor type
    -- (what the class SHOULD transmog, not what they CAN equip)
    local primaryArmor = owner:GetPlayerPrimaryArmor()
    return armorType == primaryArmor
end

-- Check if player can equip any armor type (for general use)
function Player:CanPlayerEquipArmorType(owner, armorType)
    if not armorType then return true end
    local validTypes = owner:GetPlayerArmorTypes()
    return validTypes[armorType] == true
end

function Player:GetPlayerWeaponTypes(owner)
    -- If ProfileManager is active and viewing different character, use that class
    if ETB.ProfileManager then
        local activeClass = ETB.ProfileManager:GetActiveClassID()
        if activeClass then
            return owner.CLASS_WEAPONS[activeClass] or {}
        end
    end
    local _, playerClass = UnitClass("player")
    return owner.CLASS_WEAPONS[playerClass] or {}
end

function Player:CanPlayerUseWeaponType(owner, weaponType)
    if not weaponType then return true end  -- Unknown weapon type, allow it
    local validTypes = owner:GetPlayerWeaponTypes()
    return validTypes[weaponType] == true
end

-- Get the class name being used for filtering (for UI display)
function Player:GetActiveClassName(owner)
    if ETB.ProfileManager then
        local profile = ETB.ProfileManager:GetActiveProfile()
        if profile then
            return profile.classID, profile.name
        end
    end
    local _, playerClass = UnitClass("player")
    local playerName = UnitName("player")
    return playerClass, playerName
end


function Player:GetArmorType(owner, itemID)
    if not itemID then return nil end
    
    -- Try GetItemInfoInstant first (faster, synchronous)
    if GetItemInfoInstant then
        local _, _, _, _, _, classID, subclassID = GetItemInfoInstant(itemID)
        -- classID 4 = Armor
        if classID == 4 then
            -- subclassID: 1=Cloth, 2=Leather, 3=Mail, 4=Plate, 6=Shield
            if subclassID == 1 then return "CLOTH"
            elseif subclassID == 2 then return "LEATHER"
            elseif subclassID == 3 then return "MAIL"
            elseif subclassID == 4 then return "PLATE"
            elseif subclassID == 6 then return "SHIELD"
            end
        end
    end
    
    -- Fallback to GetItemInfo (works in Classic, but may return nil if not cached)
    -- This is critical for MoP Classic where GetItemInfoInstant may not have data for uncached items
    local name, link, quality, itemLevel, minLevel, itemType, itemSubType = GetItemInfo(itemID)
    if itemType == "Armor" and itemSubType then
        -- Map itemSubType string to armor type
        if itemSubType == "Cloth" then return "CLOTH"
        elseif itemSubType == "Leather" then return "LEATHER"
        elseif itemSubType == "Mail" then return "MAIL"
        elseif itemSubType == "Plate" then return "PLATE"
        elseif itemSubType == "Shields" or itemSubType == "Shield" then return "SHIELD"
        end
    end
    
    return nil
end

-- Weapon type detection from itemID
-- Uses GetItemInfoInstant first (if available), then falls back to GetItemInfo (works in Classic)
function Player:GetWeaponType(owner, itemID)
    if not itemID then return nil, nil end
    
    -- Try GetItemInfoInstant first (faster, synchronous) - may not be available in Classic
    -- GetItemInfoInstant returns: itemID, itemType, itemSubType, equipLoc, icon, classID, subclassID (7 values)
    if GetItemInfoInstant then
        local _, itemType, itemSubType, equipLoc, icon, classID, subclassID = GetItemInfoInstant(itemID)
        -- classID 2 = Weapon
        if classID == 2 and subclassID then
            -- subclassID: 0=One-Handed Axes, 1=Two-Handed Axes, 2=Bows, 3=Guns, 4=One-Handed Maces, 
            -- 5=Two-Handed Maces, 6=Polearms, 7=One-Handed Swords, 8=Two-Handed Swords, 
            -- 9=Warglaives, 10=Staves, 13=Fist Weapons, 15=Daggers, 16=Thrown, 18=Crossbows, 19=Wands
            if subclassID == 0 then return "AXE", false
            elseif subclassID == 1 then return "AXE", true
            elseif subclassID == 2 then return "BOW", true
            elseif subclassID == 3 then return "GUN", false
            elseif subclassID == 4 then return "MACE", false
            elseif subclassID == 5 then return "MACE", true
            elseif subclassID == 6 then return "POLEARM", true
            elseif subclassID == 7 then return "SWORD", false
            elseif subclassID == 8 then return "SWORD", true
            elseif subclassID == 9 then return "WARGLAIVE", false
            elseif subclassID == 10 then return "STAFF", true
            elseif subclassID == 13 then return "FIST", false
            elseif subclassID == 15 then return "DAGGER", false
            elseif subclassID == 16 then return "THROWN", false
            elseif subclassID == 18 then return "CROSSBOW", true
            elseif subclassID == 19 then return "WAND", false
            end
        end
    end
    
    -- Fallback to GetItemInfo (works in Classic, but may return nil if not cached)
    local name, link, quality, itemLevel, minLevel, itemType, itemSubType = GetItemInfo(itemID)
    if itemType == "Weapon" and itemSubType then
        -- Map itemSubType string to weapon type
        if itemSubType == "One-Handed Axes" then return "AXE", false
        elseif itemSubType == "Two-Handed Axes" then return "AXE", true
        elseif itemSubType == "Bows" then return "BOW", true
        elseif itemSubType == "Guns" then return "GUN", false
        elseif itemSubType == "One-Handed Maces" then return "MACE", false
        elseif itemSubType == "Two-Handed Maces" then return "MACE", true
        elseif itemSubType == "Polearms" then return "POLEARM", true
        elseif itemSubType == "One-Handed Swords" then return "SWORD", false
        elseif itemSubType == "Two-Handed Swords" then return "SWORD", true
        elseif itemSubType == "Staves" then return "STAFF", true
        elseif itemSubType == "Fist Weapons" then return "FIST", false
        elseif itemSubType == "Daggers" then return "DAGGER", false
        elseif itemSubType == "Thrown" then return "THROWN", false
        elseif itemSubType == "Crossbows" then return "CROSSBOW", true
        elseif itemSubType == "Wands" then return "WAND", false
        end
    end
    
    return nil, nil
end

