-- Housing Decor Guide - Acquisition Row Factories & Pooling
-- Row/cell creation for item list, vendor headers, and 3D gallery.

local addonName, addon = ...

HDG_AcqRows = HDG_AcqRows or {}

-- Theme helpers (delegating to ThemeEngine canonical helpers)
local HDG = _G.HousingDecorGuide
local function GetScheme() return HDG.Theme.GetCurrentScheme() end
local function RegisterWidget(w, t) HDG.Theme.RegisterWidget(w, t) end
local ApplyFont = function(fs, s, ft) HDG.Theme.ApplyFont(fs, s, ft) end

-- ============================================================================
-- CACHED SCHEME (avoids per-row GetScheme/ApplyFont overhead)
-- ============================================================================

local cachedScheme = nil

function HDG_AcqRows.InvalidateSchemeCache()
    cachedScheme = nil
end

local function EnsureCachedScheme()
    if not cachedScheme then cachedScheme = GetScheme() end
    return cachedScheme
end

-- ============================================================================
-- CACHED DYE ICON (avoids per-row C_Item.GetItemIconByID + string.format)
-- ============================================================================

local cachedDyeIconStr -- lazily populated
local function GetDyeIconStr()
    if not cachedDyeIconStr then
        local icon = C_Item.GetItemIconByID(259113)
        if icon then cachedDyeIconStr = string.format("|T%s:12:12|t", icon) end
    end
    return cachedDyeIconStr
end

-- ============================================================================
-- SHARED ROW HANDLERS (avoids per-row closure allocation)
-- ============================================================================

local function ItemRow_OnClick(self)
    if IsShiftKeyDown() and HDG.Store then
        local npcIDs = HDG_VendorByItem and HDG_VendorByItem[self.itemID]
        local npcID = nil
        if npcIDs and #npcIDs > 0 then
            npcID = self.parentNpcID or npcIDs[1]
        end
        if HDG.Store:AddToVendorShoppingList(self.itemID, npcID) then
            local iName = HDG_Data and HDG_Data.GetCachedItemName(self.itemID) or ("Item " .. self.itemID)
            local dest = npcID and "shopping list" or "wish list"
            print(HDG.Theme.C_Success() .. "[HDG]|r Added " .. "|cFF14b8a6" .. iName .. "|r to " .. dest)
            if HDG_VendorShoppingList and HDG_VendorShoppingList.IsShown and HDG_VendorShoppingList.IsShown() then
                HDG_VendorShoppingList.Refresh()
            end
            HDG_AcqRows.UpdateShopListBadge()
        end
        return
    end
    if self._onSelect then self._onSelect(self.itemID) end
end

local function ItemRow_OnEnter(self)
    if self._selectedID ~= self.itemID then
        local c = GetScheme()
        if c then self:SetBackdropColor(c.button_hover.r, c.button_hover.g, c.button_hover.b, 0.5) end
    end
    GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
    if self.itemID then
        local item = Item:CreateFromItemID(self.itemID)
        item:ContinueOnItemLoad(function()
            if GameTooltip:IsOwned(self) then
                GameTooltip:SetItemByID(self.itemID)
                GameTooltip:AddLine(" ")
                GameTooltip:AddLine("Shift-Click to add to Shopping List", 0.78, 0.78, 0.78)
                GameTooltip:Show()
            end
        end)
    end
end

local function ItemRow_OnLeave(self)
    if self._selectedID ~= self.itemID then
        local c = GetScheme()
        if c then
            self:SetBackdropColor(c.panel.r, c.panel.g, c.panel.b, c.panel.a)
        end
    end
    GameTooltip:Hide()
end

local function VendorRow_OnClick(self)
    if IsShiftKeyDown() then
        local ve = HDG_VendorDB and HDG_VendorDB[self.npcID]
        if ve and ve.items and HDG.Store then
            local addCount = 0
            for iID, _ in pairs(ve.items) do
                if HDG.Store:AddToVendorShoppingList(iID, self.npcID) then
                    addCount = addCount + 1
                end
            end
            if addCount > 0 then
                local vname = HDG_VendorResolver.GetVendorNameByID(self.npcID)
                print(HDG.Theme.C_Success() .. "[HDG]|r Added " .. "|cFF14b8a6" .. addCount .. "|r items from " .. vname .. " to shopping list")
                if HDG_VendorShoppingList and HDG_VendorShoppingList.IsShown and HDG_VendorShoppingList.IsShown() then
                    HDG_VendorShoppingList.Refresh()
                end
                HDG_AcqRows.UpdateShopListBadge()
            end
        end
        return
    end
    if self._onToggle then self._onToggle(self.npcID) end
end

local function VendorRow_OnEnter(self)
    local c = GetScheme()
    if c then self:SetBackdropColor(c.button_hover.r, c.button_hover.g, c.button_hover.b, 0.3) end
    GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
    GameTooltip:SetText(self._displayName or "", 1, 1, 1)
    GameTooltip:AddLine("Shift-Click to add all items to Shopping List", 0.78, 0.78, 0.78)
    GameTooltip:Show()
end

local function VendorRow_OnLeave(self)
    local c = GetScheme()
    if c then self:SetBackdropColor(c.bg.r, c.bg.g, c.bg.b, 0.8) end
    GameTooltip:Hide()
end

-- ============================================================================
-- ROW POOL STATE
-- ============================================================================

local itemRowPool
local vendorRowPool
local galleryCellPool = { all = {}, active = {}, free = {}, timers = {} }

function HDG_AcqRows.ReleaseAllRows()
    cachedScheme = nil
    if itemRowPool then itemRowPool:ReleaseAll() end
    if vendorRowPool then vendorRowPool:ReleaseAll() end
end

function HDG_AcqRows.ReleaseAllCells()
    HDG_UIHelpers.ReleaseAllGalleryCells(galleryCellPool)
end

-- Update the shopping list badge on the main title bar
function HDG_AcqRows.UpdateShopListBadge()
    if HDG_UI and HDG_UI.UpdateShopListBadge then HDG_UI.UpdateShopListBadge() end
end

-- ============================================================================
-- CREATE ITEM ROW
-- ============================================================================

function HDG_AcqRows.CreateItemRow(parent, itemID, yOffset, listWidth, indent, selectedID, onSelect, CONFIG)
    local scheme = EnsureCachedScheme()
    indent = indent or 0

    if not itemRowPool then
        itemRowPool = HDG_UIHelpers.CreateRowPool(function(parent)
            local row = CreateFrame("Button", nil, parent, "BackdropTemplate")
            row:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8x8",
                edgeFile = "Interface\\Buttons\\WHITE8x8",
                edgeSize = 1,
                insets = { left = 0, right = 0, top = 0, bottom = 0 },
            })

            row.nameText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            row.nameText:SetJustifyH("LEFT")
            row.nameText:SetWordWrap(false)

            return row
        end)
    end

    local row = itemRowPool:Acquire(parent)
    row.parentNpcID = nil

    -- Ensure icons exist (pooled row may be recycled group header)
    if not row.collectedIcon then
        row.collectedIcon = row:CreateTexture(nil, "OVERLAY")
        row.collectedIcon:SetSize(CONFIG.ACQUISITION_TAB.STATUS_ICON_SIZE, CONFIG.ACQUISITION_TAB.STATUS_ICON_SIZE)
        row.collectedIcon:SetPoint("RIGHT", -6, 0)
        row.collectedIcon:SetTexture(CONFIG.TEXTURES.CHECKMARK)
    end
    if not row.repIcon then
        row.repIcon = row:CreateTexture(nil, "OVERLAY")
        row.repIcon:SetSize(CONFIG.ACQUISITION_TAB.STATUS_ICON_SIZE, CONFIG.ACQUISITION_TAB.STATUS_ICON_SIZE)
        row.repIcon:SetPoint("RIGHT", row.collectedIcon, "LEFT", -2, 0)
    end
    if not row.statusText then
        row.statusText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
        row.statusText:SetPoint("RIGHT", row.repIcon, "LEFT", -2, 0)
        row.statusText:SetJustifyH("RIGHT")
    end

    row:SetSize(listWidth, CONFIG.ACQUISITION_TAB.ITEM_ROW_HEIGHT)
    row:SetPoint("TOPLEFT", indent, yOffset)

    row.nameText:ClearAllPoints()
    row.nameText:SetPoint("LEFT", 6, 0)

    local isCollected = HDG_Data.IsItemCollected(itemID)
    -- Promotion items false-positive on firstAcquisitionBonus==0; use strict quantity/placed check
    local si0 = HDG_AcqData.GetSourceInfo(itemID)
    if isCollected and si0 and si0[2] == CONFIG.SOURCE_TYPE.PROMOTION then
        if C_HousingCatalog and C_HousingCatalog.GetCatalogEntryInfoByItem then
            local catInfo = C_HousingCatalog.GetCatalogEntryInfoByItem(itemID, true)
            isCollected = catInfo and ((catInfo.quantity or 0) > 0 or (catInfo.numPlaced or 0) > 0)
        end
    end
    local name = HDG_Data.GetCachedItemName(itemID) or ("Item #" .. itemID)

    local npcIDs = HDG_VendorByItem and HDG_VendorByItem[itemID]
    local hasGate, meetsGate = false, true
    if npcIDs then
        for _, npcID in ipairs(npcIDs) do
            local ie = HDG_VendorDB[npcID] and HDG_VendorDB[npcID].items and HDG_VendorDB[npcID].items[itemID]
            if ie then
                if (ie[2] or 0) ~= 0 then
                    hasGate = true
                    if not HDG_VendorResolver.MeetsRepRequirement({ factionID = ie[2], minRep = ie[3] or 0 }) then meetsGate = false end
                end
                if (ie[6] or 0) ~= 0 then
                    hasGate = true
                    if not C_QuestLog.IsQuestFlaggedCompleted(ie[6]) then meetsGate = false end
                end
                if (ie[7] or 0) ~= 0 then
                    hasGate = true
                    local _, _, _, completed = GetAchievementInfo(ie[7])
                    if not completed then meetsGate = false end
                end
                if hasGate then break end
            end
        end
    end

    -- Apply colors
    if scheme then
        if selectedID == itemID then
            row:SetBackdropColor(scheme.accent.r, scheme.accent.g, scheme.accent.b, 0.3)
            row:SetBackdropBorderColor(scheme.accent.r, scheme.accent.g, scheme.accent.b, 0.8)
        else
            row:SetBackdropColor(scheme.panel.r, scheme.panel.g, scheme.panel.b, scheme.panel.a)
            row:SetBackdropBorderColor(scheme.border.r, scheme.border.g, scheme.border.b, scheme.border.a)
        end
        ApplyFont(row.nameText, scheme, "small")
    end

    -- Source icon prefix
    local displayName = name
    local si = si0
    local siType = si and si[2] or 0
    local isCraftable = HDG_AcqData.craftableByItem[itemID] ~= nil
    if si and HDG_AcqData.IsAcquirableType(siType) then
        local iconRef = HDG_AcqData.GetSourceTypeAtlas(siType, CONFIG)
        if iconRef then
            if iconRef:find("^TEXTURE:") then
                displayName = string.format("|T%s:14:14|t", iconRef:sub(9)) .. " " .. name
            else
                displayName = CreateAtlasMarkup(iconRef, 14, 14) .. " " .. name
            end
        end
    elseif isCraftable then
        displayName = string.format("|T%s:14:14|t", CONFIG.TEXTURES.CRAFTED_ICON) .. " " .. name
    end

    -- Dyeable indicator (dye icon after name — uses cached icon string)
    if HDG_DyeData and HDG_DyeData.IsDecorDyeable(itemID) then
        local dyeStr = GetDyeIconStr()
        if dyeStr then displayName = displayName .. " " .. dyeStr end
    end

    -- User note indicator
    if HDG and HDG.Store and HDG.Store:GetUserNote(itemID) then
        displayName = displayName .. " " .. HDG.Theme.C_Dim() .. "[N]|r"
    end

    -- Name text width constraint
    local ST = CONFIG.SOURCE_TYPE
    local hasStatus = (si and HDG_AcqData.IsAcquirableType(siType) and (siType == ST.ACHIEVEMENT or siType == ST.QUEST or siType == ST.WORLD_QUEST or siType == ST.DROP or siType == ST.CRAFTED or siType == ST.TREASURE or siType == ST.PROMOTION)) or (isCraftable and not (si and HDG_AcqData.IsAcquirableType(siType)))
    row.nameText:SetWidth(listWidth - indent - (hasStatus and 90 or 30))
    row.nameText:SetText(displayName)
    if scheme then
        if isCollected then
            row.nameText:SetTextColor(scheme.text.r, scheme.text.g, scheme.text.b, scheme.text.a)
        else
            row.nameText:SetTextColor(scheme.text_dim.r, scheme.text_dim.g, scheme.text_dim.b, scheme.text_dim.a)
        end
    end

    -- Collected icon
    if isCollected then
        row.collectedIcon:SetVertexColor(0.2, 0.9, 0.2)
        row.collectedIcon:Show()
    else
        row.collectedIcon:Hide()
    end

    -- Gate icon (rep/quest/achieve — atlas based on whether player meets requirement)
    if hasGate then
        local atlas = meetsGate and "gficon-chest-evergreen-greatvault-collect" or "gficon-chest-evergreen-greatvault-incomplete"
        row.repIcon:SetAtlas(atlas)
        row.repIcon:Show()
    else
        row.repIcon:Hide()
    end

    -- Completion status for acquirable source types and craftable items
    if hasStatus then
        if scheme then ApplyFont(row.statusText, scheme, "xsmall") end
        if isCollected then
            row.statusText:SetText("Done")
            row.statusText:SetTextColor(0.2, 0.9, 0.2)
        else
            row.statusText:SetText("Incomplete")
            row.statusText:SetTextColor(0.9, 0.4, 0.2)
        end
        row.statusText:Show()
    else
        row.statusText:Hide()
    end

    row.itemID = itemID
    row._onSelect = onSelect
    row._selectedID = selectedID

    -- Shared handlers (set once, reused across pool)
    if not row._handlersSet then
        row:SetScript("OnClick", ItemRow_OnClick)
        row:SetScript("OnEnter", ItemRow_OnEnter)
        row:SetScript("OnLeave", ItemRow_OnLeave)
        row._handlersSet = true
    end

    row:Show()
    return row
end

-- ============================================================================
-- CREATE VENDOR HEADER ROW
-- ============================================================================

function HDG_AcqRows.CreateVendorHeaderRow(parent, npcID, yOffset, listWidth, isExpanded, onToggle, CONFIG)
    local scheme = EnsureCachedScheme()
    local ACQ = CONFIG.ACQUISITION_TAB
    local ve = HDG_VendorDB and HDG_VendorDB[npcID]
    if not ve then return nil, yOffset end

    if not vendorRowPool then
        vendorRowPool = HDG_UIHelpers.CreateRowPool(function(parent)
            local row = CreateFrame("Button", nil, parent, "BackdropTemplate")
            row:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8x8",
                edgeFile = "Interface\\Buttons\\WHITE8x8",
                edgeSize = 1,
                insets = { left = 0, right = 0, top = 0, bottom = 0 },
            })

            row.collapseText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            row.collapseText:SetPoint("LEFT", 6, 0)
            row.collapseText:SetWidth(12)
            row.collapseText:SetJustifyH("LEFT")

            row.nameText = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            row.nameText:SetPoint("LEFT", row.collapseText, "RIGHT", 4, 0)
            row.nameText:SetJustifyH("LEFT")
            row.nameText:SetWordWrap(false)

            row.countText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            row.countText:SetPoint("RIGHT", -6, 0)
            row.countText:SetJustifyH("RIGHT")
            row.countText:SetWordWrap(false)

            row.zoneText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            row.zoneText:SetPoint("RIGHT", row.countText, "LEFT", -4, 0)
            row.zoneText:SetJustifyH("RIGHT")
            row.zoneText:SetWordWrap(false)

            return row
        end)
    end

    local row = vendorRowPool:Acquire(parent)

    row:SetSize(listWidth, ACQ.VENDOR_ROW_HEIGHT)
    row:SetPoint("TOPLEFT", 0, yOffset)

    if scheme then
        row:SetBackdropColor(scheme.bg.r, scheme.bg.g, scheme.bg.b, 0.8)
        row:SetBackdropBorderColor(scheme.border.r, scheme.border.g, scheme.border.b, scheme.border.a)

        ApplyFont(row.collapseText, scheme, "xsmall")
        row.collapseText:SetTextColor(scheme.text_dim.r, scheme.text_dim.g, scheme.text_dim.b, scheme.text_dim.a)

        ApplyFont(row.nameText, scheme, "small")
        row.nameText:SetTextColor(scheme.text_header.r, scheme.text_header.g, scheme.text_header.b, scheme.text_header.a)
        row.nameText:SetWidth(listWidth * 0.55)

        ApplyFont(row.countText, scheme, "small")
        row.countText:SetTextColor(scheme.text_dim.r, scheme.text_dim.g, scheme.text_dim.b, scheme.text_dim.a)

        ApplyFont(row.zoneText, scheme, "xsmall")
        row.zoneText:SetTextColor(scheme.text_dim.r, scheme.text_dim.g, scheme.text_dim.b, scheme.text_dim.a)
        row.zoneText:SetWidth(listWidth * 0.30)
    end

    row.collapseText:SetText(isExpanded and "-" or "+")
    row.zoneText:SetText(ve[2] or "")

    -- Faction icon inline
    local vendorFaction = ve[6] or "N"
    local factionPrefix = ""
    if vendorFaction == "A" then
        factionPrefix = CreateAtlasMarkup("communities-create-button-wow-alliance", 14, 14) .. " "
    elseif vendorFaction == "H" then
        factionPrefix = CreateAtlasMarkup("communities-create-button-wow-horde", 14, 14) .. " "
    end
    local vendorDisplayName = factionPrefix .. HDG_VendorResolver.GetVendorNameByID(npcID)
    if HDG and HDG.Store and HDG.Store:GetVendorNote(npcID) then
        vendorDisplayName = vendorDisplayName .. " " .. HDG.Theme.C_Dim() .. "[N]|r"
    end
    row.nameText:SetText(vendorDisplayName)

    -- Use cached counts from RebuildFilteredVendors
    local counts = HDG_AcqData.vendorCounts[npcID]
    local total = counts and counts.total or 0
    local collected = counts and counts.collected or 0
    row.countText:SetText(string.format("(%d/%d)", collected, total))

    row.npcID = npcID
    row._onToggle = onToggle
    row._displayName = vendorDisplayName

    -- Shared handlers (set once, reused across pool)
    if not row._handlersSet then
        row:SetScript("OnClick", VendorRow_OnClick)
        row:SetScript("OnEnter", VendorRow_OnEnter)
        row:SetScript("OnLeave", VendorRow_OnLeave)
        row._handlersSet = true
    end

    row:Show()
    return row
end

-- ============================================================================
-- CREATE GALLERY CELL (3D model)
-- ============================================================================

function HDG_AcqRows.CreateGalleryCell(parent, itemID, x, y, cellSize, selectedID, onSelect, CONFIG, npcID)
    local ACQ = CONFIG.ACQUISITION_TAB

    local cell = HDG_UIHelpers.CreateGalleryCell(galleryCellPool, parent, cellSize, {
        statusIconSize = ACQ.STATUS_ICON_SIZE,
        checkmarkTexture = CONFIG.TEXTURES.CHECKMARK,
    })
    cell:SetPoint("TOPLEFT", x, y)

    local isCollected = HDG_Data.IsItemCollected(itemID)
    local isSelected = (selectedID == itemID)
    HDG_UIHelpers.UpdateGalleryCellBackground(cell, isSelected)
    cell.checkmark:SetShown(isCollected)
    cell.redX:SetShown(not isCollected)

    cell.itemID = itemID
    cell.parentNpcID = npcID

    -- Lazy-load visuals via staggered timer
    local cellRef = cell
    local loadDelay = #galleryCellPool.timers * 0.05
    local timer = C_Timer.NewTimer(loadDelay, function()
        if not cellRef.inUse or cellRef.itemID ~= itemID then return end
        if not C_HousingCatalog or not C_HousingCatalog.GetCatalogEntryInfoByItem then return end
        local decorInfo = C_HousingCatalog.GetCatalogEntryInfoByItem(itemID, true)
        local sceneID = (decorInfo and decorInfo.uiModelSceneID) or ACQ.DEFAULT_SCENE_ID
        HDG_UIHelpers.UpdateGalleryCellVisuals(cellRef, decorInfo, isCollected, sceneID)
        if decorInfo and decorInfo.recordID then
            HDG_UIHelpers.UpdateGalleryCellQuantity(cellRef, decorInfo.recordID)
        end
    end)
    table.insert(galleryCellPool.timers, timer)

    -- Click handler with shift-click shopping list support
    cell:SetScript("OnClick", function(self)
        if IsShiftKeyDown() and HDG.Store then
            local nIDs = HDG_VendorByItem and HDG_VendorByItem[self.itemID]
            local nID = nil
            if nIDs and #nIDs > 0 then
                nID = self.parentNpcID or nIDs[1]
            end
            if HDG.Store:AddToVendorShoppingList(self.itemID, nID) then
                local iName = HDG_Data and HDG_Data.GetCachedItemName(self.itemID) or ("Item " .. self.itemID)
                local dest = nID and "shopping list" or "wish list"
                print(HDG.Theme.C_Success() .. "[HDG]|r Added " .. "|cFF14b8a6" .. iName .. "|r to " .. dest)
                if HDG_VendorShoppingList and HDG_VendorShoppingList.IsShown and HDG_VendorShoppingList.IsShown() then
                    HDG_VendorShoppingList.Refresh()
                end
                HDG_AcqRows.UpdateShopListBadge()
            end
            return
        end
        if onSelect then onSelect(self.itemID) end
    end)

    -- Tooltip
    cell:SetScript("OnEnter", function(self)
        self.hoverBg:Show()
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        local tipName = HDG_Data.GetCachedItemName(self.itemID) or ("Item #" .. self.itemID)
        local tipCollected = HDG_Data.IsItemCollected(self.itemID)
        local tipNpcIDs = HDG_VendorByItem and HDG_VendorByItem[self.itemID]
        local tipPrice = 0
        if tipNpcIDs and tipNpcIDs[1] and HDG_VendorDB then
            local ve = HDG_VendorDB[tipNpcIDs[1]]
            local ie = ve and ve.items and ve.items[self.itemID]
            tipPrice = ie and ie[1] or 0
        end
        local priceStr = HDG_VendorResolver.FormatGoldCost(tipPrice)

        GameTooltip:AddLine(tipName, 1, 1, 1)
        if tipCollected then
            GameTooltip:AddLine(HDG.Theme.C_Success() .. "Collected|r", 0.2, 0.9, 0.2)
        else
            GameTooltip:AddLine(HDG.Theme.C_Dim() .. "Not collected|r", 0.78, 0.78, 0.78)
        end
        if priceStr then
            GameTooltip:AddLine("Price: " .. priceStr, 0.8, 0.8, 0.8)
        else
            local currencies = HDG_VendorResolver.GetCurrencyCost(self.itemID)
            if currencies then
                local iconSize = CONFIG.ACQUISITION_TAB.CURRENCY_ICON_SIZE
                for _, cc in ipairs(currencies) do
                    local iconStr = cc.icon and cc.icon ~= 0 and string.format("|T%s:%d:%d|t ", cc.icon, iconSize, iconSize) or ""
                    GameTooltip:AddDoubleLine(iconStr .. (cc.name or "Currency"), tostring(cc.amount), 0.8, 0.8, 0.8, 1, 1, 1)
                end
            else
                GameTooltip:AddLine("|cFFAAAA00Visit vendor to see cost|r", 0.7, 0.7, 0.5)
            end
        end
        GameTooltip:AddLine(" ")
        GameTooltip:AddLine("Shift-Click to add to Shopping List", 0.78, 0.78, 0.78)
        GameTooltip:Show()
    end)
    cell:SetScript("OnLeave", function(self)
        self.hoverBg:Hide()
        GameTooltip:Hide()
    end)

    cell:Show()
    return cell
end

-- ============================================================================
-- HIGHLIGHT-ONLY UPDATES (no rebuild)
-- ============================================================================

function HDG_AcqRows.UpdateGalleryHighlights(selectedItemID)
    for _, cell in ipairs(galleryCellPool.active) do
        if not cell.inUse then break end
        HDG_UIHelpers.UpdateGalleryCellBackground(cell, cell.itemID == selectedItemID)
    end
end

function HDG_AcqRows.UpdateRowHighlights(selectedItemID)
    local scheme = GetScheme()
    if not scheme or not itemRowPool then return end
    for _, row in ipairs(itemRowPool:GetActive()) do
        if not row.inUse then break end
        if row.itemID == selectedItemID then
            row:SetBackdropColor(scheme.accent.r, scheme.accent.g, scheme.accent.b, 0.3)
            row:SetBackdropBorderColor(scheme.accent.r, scheme.accent.g, scheme.accent.b, 0.8)
        elseif row.itemID then
            row:SetBackdropColor(scheme.panel.r, scheme.panel.g, scheme.panel.b, scheme.panel.a)
            row:SetBackdropBorderColor(scheme.border.r, scheme.border.g, scheme.border.b, scheme.border.a)
        end
    end
end
