--[[
============================================================================
ETB - ProfileManager.lua
============================================================================
Character Profile Switching System

Features:
- Store multiple character profiles (name, realm, class, level)
- Switch "viewing as" to any character on account
- Auto-detect current character on login
- Filter items based on SELECTED profile's class (not current character)
- Account-wide favorites with class compatibility
- Account-wide outfits with class compatibility checking

Similar to Altaholic's character switching but focused on transmog planning.
============================================================================
]]--

local ADDON_NAME, NS = ...
local ETB = NS.ETB

ETB.ProfileManager = {
    -- All known characters on this account
    profiles = {},
    
    -- Currently selected profile (for viewing/filtering)
    activeProfileKey = nil,
    
    -- Current logged-in character
    currentCharacterKey = nil,
    
    -- Saved outfits (account-wide)
    savedOutfits = {},
    
    -- Account-wide favorites (itemID -> true)
    accountFavorites = {},
}

local PM = ETB.ProfileManager

-- =============================================================================
-- CLASS DATA (for filtering)
-- =============================================================================
-- v14.8.0: tables consolidated to Data/Categories/ClassData.lua. We keep
-- locals so the rest of this file's code (which reads them by direct name)
-- doesn't need to be rewritten — locals just point at the canonical tables.

local _CD = ETB.ClassData
local CLASS_PRIMARY_ARMOR = _CD and _CD.PRIMARY_ARMOR or {
    WARRIOR     = "PLATE",
    PALADIN     = "PLATE",
    DEATHKNIGHT = "PLATE",
    HUNTER      = "MAIL",
    SHAMAN      = "MAIL",
    ROGUE       = "LEATHER",
    DRUID       = "LEATHER",
    MONK        = "LEATHER",
    MAGE        = "CLOTH",
    WARLOCK     = "CLOTH",
    PRIEST      = "CLOTH",
}

-- What weapon types each class can use (MoP Classic)
-- Note: Thrown weapons removed in MoP, ranged/relic slot gone, wands are main-hand
local CLASS_WEAPONS = _CD and _CD.WEAPONS or {
    WARRIOR     = { AXE = true, SWORD = true, MACE = true, POLEARM = true, STAFF = true, DAGGER = true, FIST = true, SHIELD = true },
    PALADIN     = { AXE = true, SWORD = true, MACE = true, POLEARM = true, SHIELD = true },
    DEATHKNIGHT = { AXE = true, SWORD = true, MACE = true, POLEARM = true },
    HUNTER      = { AXE = true, SWORD = true, POLEARM = true, STAFF = true, DAGGER = true, FIST = true, BOW = true, GUN = true, CROSSBOW = true },
    SHAMAN      = { AXE = true, MACE = true, STAFF = true, DAGGER = true, FIST = true, SHIELD = true },
    ROGUE       = { AXE = true, SWORD = true, MACE = true, DAGGER = true, FIST = true },
    DRUID       = { MACE = true, POLEARM = true, STAFF = true, DAGGER = true, FIST = true },
    MONK        = { AXE = true, SWORD = true, MACE = true, POLEARM = true, STAFF = true, FIST = true },
    MAGE        = { SWORD = true, STAFF = true, DAGGER = true, WAND = true },
    WARLOCK     = { SWORD = true, STAFF = true, DAGGER = true, WAND = true },
    PRIEST      = { MACE = true, STAFF = true, DAGGER = true, WAND = true },
}

-- Classes grouped by armor type (for outfit compatibility)
local ARMOR_TYPE_CLASSES = {
    PLATE   = { "WARRIOR", "PALADIN", "DEATHKNIGHT" },
    MAIL    = { "HUNTER", "SHAMAN" },
    LEATHER = { "ROGUE", "DRUID", "MONK" },
    CLOTH   = { "MAGE", "WARLOCK", "PRIEST" },
}

-- =============================================================================
-- PROFILE KEY GENERATION
-- =============================================================================

function PM:GetProfileKey(name, realm)
    return string.format("%s-%s", name or "Unknown", realm or "Unknown")
end

function PM:GetCurrentCharacterKey()
    local name = UnitName("player")
    local realm = GetRealmName()
    return self:GetProfileKey(name, realm)
end

-- =============================================================================
-- PROFILE MANAGEMENT
-- =============================================================================

function PM:Initialize()
    -- Load saved data
    if ETB_ProfileData then
        self.profiles = ETB_ProfileData.profiles or {}
        self.savedOutfits = ETB_ProfileData.outfits or {}
        self.accountFavorites = ETB_ProfileData.favorites or {}
    end
    
    -- Register current character
    self:RegisterCurrentCharacter()
    
    -- Set active profile to current character by default
    self.currentCharacterKey = self:GetCurrentCharacterKey()
    self.activeProfileKey = self.currentCharacterKey
    
    ETB:Debug("ProfileManager", "Initialized with " .. self:GetProfileCount() .. " profiles")
end

function PM:RegisterCurrentCharacter()
    local name = UnitName("player")
    local realm = GetRealmName()
    local _, classID = UnitClass("player")
    local level = UnitLevel("player")
    local _, _, raceID = UnitRace("player")
    local faction = UnitFactionGroup("player")
    
    local key = self:GetProfileKey(name, realm)
    
    self.profiles[key] = {
        name = name,
        realm = realm,
        classID = classID,
        level = level,
        raceID = raceID,
        faction = faction,
        lastSeen = time(),
    }
    
    self:SaveData()
end

function PM:GetProfile(key)
    return self.profiles[key]
end

function PM:GetActiveProfile()
    return self.profiles[self.activeProfileKey]
end

function PM:GetCurrentProfile()
    return self.profiles[self.currentCharacterKey]
end

function PM:SetActiveProfile(key)
    if self.profiles[key] then
        self.activeProfileKey = key
        ETB.EventBus:Fire("ETB_PROFILE_CHANGED", key, self.profiles[key])
        ETB:Debug("ProfileManager", "Switched to profile: " .. key)
        return true
    end
    return false
end

function PM:GetProfileCount()
    local count = 0
    for _ in pairs(self.profiles) do
        count = count + 1
    end
    return count
end

function PM:GetAllProfiles()
    local list = {}
    for key, profile in pairs(self.profiles) do
        list[#list + 1] = {
            key = key,
            name = profile.name,
            realm = profile.realm,
            classID = profile.classID,
            level = profile.level,
            isCurrent = (key == self.currentCharacterKey),
            isActive = (key == self.activeProfileKey),
        }
    end
    -- Sort by realm, then name
    table.sort(list, function(a, b)
        if a.realm ~= b.realm then return a.realm < b.realm end
        return a.name < b.name
    end)
    return list
end

function PM:DeleteProfile(key)
    if key == self.currentCharacterKey then
        ETB:Print("Cannot delete current character's profile!")
        return false
    end
    if self.profiles[key] then
        self.profiles[key] = nil
        if self.activeProfileKey == key then
            self.activeProfileKey = self.currentCharacterKey
        end
        self:SaveData()
        ETB.EventBus:Fire("ETB_PROFILE_DELETED", key)
        return true
    end
    return false
end

-- =============================================================================
-- CLASS FILTERING (Based on ACTIVE profile, not current character)
-- =============================================================================

function PM:GetActiveClassID()
    local profile = self:GetActiveProfile()
    return profile and profile.classID or select(2, UnitClass("player"))
end

function PM:GetActivePrimaryArmor()
    local classID = self:GetActiveClassID()
    return CLASS_PRIMARY_ARMOR[classID] or "CLOTH"
end

function PM:CanActiveProfileUseWeapon(weaponType)
    if not weaponType then return true end
    local classID = self:GetActiveClassID()
    local weapons = CLASS_WEAPONS[classID]
    return weapons and weapons[weaponType] or false
end

function PM:CanActiveProfileUseItem(item)
    if not item then return false end
    
    local classID = self:GetActiveClassID()
    local primaryArmor = CLASS_PRIMARY_ARMOR[classID]
    
    -- Check armor type
    if item.armorType then
        if item.armorType ~= primaryArmor then
            return false
        end
    end
    
    -- Check weapon type
    if item.weaponType then
        if not self:CanActiveProfileUseWeapon(item.weaponType) then
            return false
        end
    end
    
    return true
end

-- =============================================================================
-- ACCOUNT-WIDE FAVORITES
-- =============================================================================

function PM:AddFavorite(itemID, item)
    if not itemID then return end
    
    self.accountFavorites[itemID] = {
        addedBy = self.currentCharacterKey,
        addedAt = time(),
        name = item and item.name,
        armorType = item and item.armorType,
        weaponType = item and item.weaponType,
    }
    
    self:SaveData()
    ETB.EventBus:Fire("ETB_FAVORITE_ADDED", itemID)
end

function PM:RemoveFavorite(itemID)
    if self.accountFavorites[itemID] then
        self.accountFavorites[itemID] = nil
        self:SaveData()
        ETB.EventBus:Fire("ETB_FAVORITE_REMOVED", itemID)
        return true
    end
    return false
end

function PM:IsFavorite(itemID)
    return self.accountFavorites[itemID] ~= nil
end

function PM:GetFavorites()
    return self.accountFavorites
end

function PM:GetFavoriteCount()
    local count = 0
    for _ in pairs(self.accountFavorites) do
        count = count + 1
    end
    return count
end

-- Get favorites usable by a specific class
function PM:GetFavoritesForClass(classID)
    local primaryArmor = CLASS_PRIMARY_ARMOR[classID]
    local weapons = CLASS_WEAPONS[classID]
    local usable = {}
    
    for itemID, data in pairs(self.accountFavorites) do
        local canUse = true
        
        if data.armorType and data.armorType ~= primaryArmor then
            canUse = false
        end
        
        if data.weaponType and not (weapons and weapons[data.weaponType]) then
            canUse = false
        end
        
        if canUse then
            usable[itemID] = data
        end
    end
    
    return usable
end

-- =============================================================================
-- ACCOUNT-WIDE OUTFITS
-- =============================================================================

function PM:CreateOutfit(name, items)
    -- items = { Head = itemData, Chest = itemData, ... }
    local outfit = {
        name = name,
        createdBy = self.currentCharacterKey,
        createdAt = time(),
        items = {},
        compatibleClasses = {},
    }
    
    -- Store item data and determine compatibility
    local armorTypes = {}
    local weaponTypes = {}
    
    for slot, item in pairs(items) do
        outfit.items[slot] = {
            itemID = item.itemID,
            name = item.name,
            armorType = item.armorType,
            weaponType = item.weaponType,
        }
        
        if item.armorType then
            armorTypes[item.armorType] = true
        end
        if item.weaponType then
            weaponTypes[item.weaponType] = true
        end
    end
    
    -- Determine which classes can use this outfit
    outfit.compatibleClasses = self:CalculateOutfitCompatibility(armorTypes, weaponTypes)
    
    -- Generate unique ID
    local outfitID = string.format("%s_%d", name:gsub("%s+", "_"), time())
    self.savedOutfits[outfitID] = outfit
    
    self:SaveData()
    ETB.EventBus:Fire("ETB_OUTFIT_CREATED", outfitID, outfit)
    
    return outfitID
end

function PM:CalculateOutfitCompatibility(armorTypes, weaponTypes)
    local compatible = {}
    
    -- Check each class
    for classID, primaryArmor in pairs(CLASS_PRIMARY_ARMOR) do
        local canUse = true
        
        -- Check armor types
        for armorType in pairs(armorTypes) do
            if armorType ~= primaryArmor then
                canUse = false
                break
            end
        end
        
        -- Check weapon types
        if canUse then
            local classWeapons = CLASS_WEAPONS[classID]
            for weaponType in pairs(weaponTypes) do
                if not classWeapons[weaponType] then
                    canUse = false
                    break
                end
            end
        end
        
        if canUse then
            compatible[#compatible + 1] = classID
        end
    end
    
    return compatible
end

function PM:GetOutfit(outfitID)
    return self.savedOutfits[outfitID]
end

function PM:DeleteOutfit(outfitID)
    if self.savedOutfits[outfitID] then
        self.savedOutfits[outfitID] = nil
        self:SaveData()
        ETB.EventBus:Fire("ETB_OUTFIT_DELETED", outfitID)
        return true
    end
    return false
end

function PM:GetAllOutfits()
    return self.savedOutfits
end

function PM:GetOutfitsForClass(classID)
    local usable = {}
    for outfitID, outfit in pairs(self.savedOutfits) do
        for _, compatClass in ipairs(outfit.compatibleClasses) do
            if compatClass == classID then
                usable[outfitID] = outfit
                break
            end
        end
    end
    return usable
end

function PM:GetOutfitCount()
    local count = 0
    for _ in pairs(self.savedOutfits) do
        count = count + 1
    end
    return count
end

function PM:IsOutfitCompatibleWithActiveProfile(outfitID)
    local outfit = self.savedOutfits[outfitID]
    if not outfit then return false end
    
    local activeClass = self:GetActiveClassID()
    for _, compatClass in ipairs(outfit.compatibleClasses) do
        if compatClass == activeClass then
            return true
        end
    end
    return false
end

-- =============================================================================
-- DATA PERSISTENCE
-- =============================================================================

function PM:SaveData()
    ETB_ProfileData = {
        profiles = self.profiles,
        outfits = self.savedOutfits,
        favorites = self.accountFavorites,
        version = 1,
    }
end

function PM:GetStats()
    local activeClass = self:GetActiveClassID()
    return {
        totalProfiles = self:GetProfileCount(),
        totalFavorites = self:GetFavoriteCount(),
        totalOutfits = self:GetOutfitCount(),
        favoritesForActiveClass = self:CountTable(self:GetFavoritesForClass(activeClass)),
        outfitsForActiveClass = self:CountTable(self:GetOutfitsForClass(activeClass)),
        activeProfile = self.activeProfileKey,
        currentProfile = self.currentCharacterKey,
    }
end

function PM:CountTable(t)
    local count = 0
    for _ in pairs(t) do count = count + 1 end
    return count
end

-- =============================================================================
-- DEBUG / PRINT
-- =============================================================================

function PM:PrintStats()
    local stats = self:GetStats()
    local activeProfile = self:GetActiveProfile()
    
    ETB:Print("=== PROFILE MANAGER ===")
    ETB:Print(string.format("Profiles: %d characters", stats.totalProfiles))
    ETB:Print(string.format("Active: %s (%s)", 
        activeProfile and activeProfile.name or "?", 
        activeProfile and activeProfile.classID or "?"))
    ETB:Print(string.format("Favorites: %d total, %d usable by active", 
        stats.totalFavorites, stats.favoritesForActiveClass))
    ETB:Print(string.format("Outfits: %d total, %d usable by active", 
        stats.totalOutfits, stats.outfitsForActiveClass))
end

-- =============================================================================
-- INITIALIZATION HOOK
-- =============================================================================

ETB.EventBus:Register("ETB_INITIALIZED", function()
    PM:Initialize()
end, ETB.EventBus.Priority.EARLY)

ETB:Debug("ProfileManager", "ProfileManager.lua loaded")
