-- =============================================================================
-- ETB v12.40.0 — TransmogUI/CategoryBar.lua
-- =============================================================================
-- Two-row category icon bar: Armor row (11 icons) + Weapons row (1H/2H/Rng-OH).
-- Extracted from the v12.39.0 monolithic TransmogUI.lua.
--
-- Owns CATEGORY_ICONS / CATEGORY_NAMES / CATEGORY_TO_INVSLOT constants since
-- nothing else outside CategoryBar consumes them as of v12.39.0.
--
-- Public API:
--   CategoryBar:Create(parent, owner)       — build the bar inside parent frame
--   CategoryBar:UpdateHighlight(owner)      — reflect owner.selectedCategoryID
--   CategoryBar:UpdateCurrentViewingLabel(owner, frame)
--     — refresh the "Head 182/1351 (13%)" label on the bar
--   CategoryBar.CATEGORY_TO_INVSLOT         — exposed for callers that still need it
--   CategoryBar.CATEGORY_NAMES              — same
--   CategoryBar.CATEGORY_ICONS              — same
--
-- The `owner` parameter is the TUI singleton. Passing it explicitly means the
-- submodule is not coupled to `NS.ETB.TransmogUI.TUI` directly, which leaves
-- room for alternative parents (tests, alternative UIs) later.
--
-- Owner contract — fields and methods used:
--   owner.selectedCategoryID (written on click, read for highlight)
--   owner.selectedSlot       (written on click)
--   owner.selectedTab        (written on click)
--   owner.categoryBarIcons   (populated during Create; map of catID -> button)
--   owner.frame.browserPanel — referenced to update tabs on click
--   owner:RefreshBrowser()   — called after category change
--   owner:UpdateCategoryBarHighlight()  (called after click for consistency)
--   owner:UpdateCurrentViewingLabel()   (called after click)
-- =============================================================================

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

NS.ETB.TransmogUI = NS.ETB.TransmogUI or {}
local CategoryBar = {}
NS.ETB.TransmogUI.CategoryBar = CategoryBar

-- Layout constants (hardcoded; matches v12.39.0 behavior)
local FRAME_WIDTH = 1050
local CB_SIZE = 20
local CB_SPACING = 24
local WEAPON_Y = -38

-- =============================================================================
-- Category metadata (moved out of TransmogUI.lua file-scope)
-- =============================================================================

CategoryBar.CATEGORY_TO_INVSLOT = {
    [1]=1, [2]=3, [3]=15, [4]=5, [5]=4, [6]=19, [7]=9, [8]=10, [9]=6, [10]=7, [11]=8,
    [12]=16, [13]=16, [14]=16, [15]=16, [16]=16, [17]=16,
    [18]=17, [19]=17,
    [20]=16, [21]=16, [22]=16, [23]=16, [24]=16,
    [25]=16, [26]=16, [27]=16,
}

CategoryBar.CATEGORY_ICONS = {
    [1]="Interface\\Icons\\INV_Helmet_44", [2]="Interface\\Icons\\INV_Shoulder_22", [3]="Interface\\Icons\\INV_Misc_Cape_18",
    [4]="Interface\\Icons\\INV_Chest_Chain_05", [5]="Interface\\Icons\\INV_Shirt_01", [6]="Interface\\Icons\\INV_Shirt_GuildTabard_01",
    [7]="Interface\\Icons\\INV_Bracer_07", [8]="Interface\\Icons\\INV_Gauntlets_24", [9]="Interface\\Icons\\INV_Belt_13",
    [10]="Interface\\Icons\\INV_Pants_06", [11]="Interface\\Icons\\INV_Boots_05",
    [12]="Interface\\Icons\\INV_Wand_01", [13]="Interface\\Icons\\INV_Axe_01", [14]="Interface\\Icons\\INV_Sword_04",
    [15]="Interface\\Icons\\INV_Mace_01", [16]="Interface\\Icons\\INV_Weapon_ShortBlade_05", [17]="Interface\\Icons\\INV_Gauntlets_04",
    [18]="Interface\\Icons\\INV_Shield_04", [19]="Interface\\Icons\\INV_Misc_Orb_01",
    [20]="Interface\\Icons\\INV_Axe_09", [21]="Interface\\Icons\\INV_Sword_27", [22]="Interface\\Icons\\INV_Mace_15",
    [23]="Interface\\Icons\\INV_Staff_08", [24]="Interface\\Icons\\INV_Spear_04",
    [25]="Interface\\Icons\\INV_Weapon_Bow_05", [26]="Interface\\Icons\\INV_Weapon_Rifle_01", [27]="Interface\\Icons\\INV_Weapon_Crossbow_01",
}

CategoryBar.CATEGORY_NAMES = {
    [1]="Head", [2]="Shoulder", [3]="Back", [4]="Chest", [5]="Shirt", [6]="Tabard", [7]="Wrist", [8]="Hands", [9]="Waist", [10]="Legs", [11]="Feet",
    [12]="Wands", [13]="1H Axes", [14]="1H Swords", [15]="1H Maces", [16]="Daggers", [17]="Fist Weapons",
    [18]="Shields", [19]="Off-Hands", [20]="2H Axes", [21]="2H Swords", [22]="2H Maces", [23]="Staves", [24]="Polearms",
    [25]="Bows", [26]="Guns", [27]="Crossbows",
}

-- =============================================================================
-- Metadata accessors (ETB.CATEGORY_INFO fallback to local tables)
-- =============================================================================

local function getIcon(catID)
    local E = ETB_ADDON
    if E and E.CATEGORY_INFO and E.CATEGORY_INFO[catID] then
        return E.CATEGORY_INFO[catID].icon
    end
    return CategoryBar.CATEGORY_ICONS[catID] or "Interface\\Icons\\INV_Misc_QuestionMark"
end

local function getName(catID)
    local E = ETB_ADDON
    if E and E.CATEGORY_INFO and E.CATEGORY_INFO[catID] then
        return E.CATEGORY_INFO[catID].name
    end
    return CategoryBar.CATEGORY_NAMES[catID] or ("Category " .. catID)
end

-- =============================================================================
-- Bar creation
-- =============================================================================

function CategoryBar:Create(parent, owner)
    if not parent then
        error("[ETB] CategoryBar:Create requires a parent frame", 2)
    end
    if not owner then
        error("[ETB] CategoryBar:Create requires an owner table", 2)
    end

    local bar = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    bar:SetSize(FRAME_WIDTH - 16, 60)
    bar:SetPoint("BOTTOM", parent, "BOTTOM", 0, 32)
    bar:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 10,
        insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    parent.categoryBar = bar

    bar.currentViewingLabel = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    bar.currentViewingLabel:SetPoint("TOPLEFT", 8, -5)
    bar.currentViewingLabel:SetText("|cff00cc66Head|r |cff444444182/1351 (13%)|r")

    owner.categoryBarIcons = owner.categoryBarIcons or {}
    local CAT_TO_INVSLOT = self.CATEGORY_TO_INVSLOT

    local function makeCategoryButton(catID, x, y)
        local btn = CreateFrame("Button", nil, bar)
        btn:SetSize(CB_SIZE, CB_SIZE)
        btn:SetPoint("TOPLEFT", bar, "TOPLEFT", x, y)

        btn.icon = btn:CreateTexture(nil, "ARTWORK")
        btn.icon:SetAllPoints()
        btn.icon:SetTexture(getIcon(catID))
        btn.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

        btn.selected = btn:CreateTexture(nil, "OVERLAY")
        btn.selected:SetAllPoints()
        btn.selected:SetColorTexture(0, 1, 0, 0.45)
        btn.selected:Hide()

        btn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")

        btn:SetScript("OnEnter", function(b)
            GameTooltip:SetOwner(b, "ANCHOR_TOP")
            GameTooltip:SetText(getName(catID))
            GameTooltip:Show()
        end)
        btn:SetScript("OnLeave", function() GameTooltip:Hide() end)

        btn:SetScript("OnClick", function()
            owner.selectedCategoryID = catID
            local invSlot = CAT_TO_INVSLOT[catID]
            if invSlot then
                owner.selectedSlot = invSlot
                owner.selectedTab = "appearances"
            end

            -- Reset tab visual state on the browser panel
            local bp = owner.frame and owner.frame.browserPanel
            if bp then
                if bp.title then
                    bp.title:SetText("|cffffd100" .. getName(catID) .. " Appearances|r")
                end
                if bp.appearancesTab then
                    bp.appearancesTab:SetText("|cff00ff00Appearances|r")
                    if bp.appearancesTab.underline then bp.appearancesTab.underline:Show() end
                end
                if bp.setsTab then
                    bp.setsTab:SetText("|cff888888Sets|r")
                    if bp.setsTab.underline then bp.setsTab.underline:Hide() end
                end
                if bp.incompleteTab then
                    bp.incompleteTab:SetText("|cff888888Incomplete|r")
                    if bp.incompleteTab.underline then bp.incompleteTab.underline:Hide() end
                end
            end

            -- Delegate back through the owner for the actual refresh work.
            if owner.UpdateCategoryBarHighlight then owner:UpdateCategoryBarHighlight() end
            if owner.UpdateCurrentViewingLabel then owner:UpdateCurrentViewingLabel() end
            if owner.RefreshBrowser then owner:RefreshBrowser() end
        end)

        btn.categoryID = catID
        owner.categoryBarIcons[catID] = btn
        return btn
    end

    -- Row 1: Armor (matches main addon layout)
    local armorLabel = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    armorLabel:SetPoint("TOPLEFT", 8, -20)
    armorLabel:SetText("|cffffd100Armor:|r")
    for i, catID in ipairs({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }) do
        makeCategoryButton(catID, 50 + (i - 1) * CB_SPACING, -18)
    end

    -- Row 2: Weapons (1H, 2H, Rng/OH with labels)
    local label1H = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    label1H:SetPoint("TOPLEFT", 8, WEAPON_Y - 2)
    label1H:SetText("|cffffd1001H:|r")
    for i, catID in ipairs({ 14, 13, 15, 16, 17, 12 }) do
        makeCategoryButton(catID, 28 + (i - 1) * CB_SPACING, WEAPON_Y)
    end

    local label2H = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    label2H:SetPoint("TOPLEFT", 180, WEAPON_Y - 2)
    label2H:SetText("|cffffd1002H:|r")
    for i, catID in ipairs({ 21, 20, 22, 23, 24 }) do
        makeCategoryButton(catID, 200 + (i - 1) * CB_SPACING, WEAPON_Y)
    end

    local labelRng = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    labelRng:SetPoint("TOPLEFT", 330, WEAPON_Y - 2)
    labelRng:SetText("|cffffd100Rng/OH:|r")
    for i, catID in ipairs({ 25, 26, 27, 18, 19 }) do
        makeCategoryButton(catID, 390 + (i - 1) * CB_SPACING, WEAPON_Y)
    end

    return bar
end

-- =============================================================================
-- State updates
-- =============================================================================

function CategoryBar:UpdateHighlight(owner)
    if not owner or not owner.categoryBarIcons then return end
    for catID, btn in pairs(owner.categoryBarIcons) do
        if btn.selected then
            btn.selected:SetShown(owner.selectedCategoryID == catID)
        end
    end
end

function CategoryBar:UpdateCurrentViewingLabel(owner)
    if not owner or not owner.frame or not owner.frame.categoryBar then return end
    local catID = owner.selectedCategoryID
    local name, collected, total, percent = "Select a category", 0, 0, 0

    local E = ETB_ADDON
    if catID then
        name = (E and E.CATEGORY_INFO and E.CATEGORY_INFO[catID] and E.CATEGORY_INFO[catID].name)
               or self.CATEGORY_NAMES[catID]
               or ("Category " .. catID)

        if E and E.BlizzardData and E.BlizzardData.GetCollectionStats then
            local stats = E.BlizzardData:GetCollectionStats(catID)
            if stats and stats.total then
                collected, total = stats.collected or 0, stats.total
                percent = total > 0 and (100 * collected / total) or 0
            end
        end

        if (not total or total == 0) and C_TransmogCollection and C_TransmogCollection.GetCategoryAppearances then
            local ok, appearances = pcall(C_TransmogCollection.GetCategoryAppearances, catID)
            if ok and appearances then
                total = #appearances
                for _, app in ipairs(appearances) do
                    if app and app.isCollected then collected = collected + 1 end
                end
                percent = total > 0 and (100 * collected / total) or 0
            end
        end
    end

    local statStr = (total and total > 0)
                    and string.format(" %d/%d (%.0f%%)", collected, total, percent)
                    or ""
    owner.frame.categoryBar.currentViewingLabel:SetText(
        "|cff00cc66" .. name .. "|r |cff333333" .. statStr .. "|r"
    )
end
