--[[
============================================================================
ETB v10.0 - FilterBar.lua
============================================================================
Advanced filter and search controls.
============================================================================
]]--

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

ETB.FilterBar = {}
local FilterBar = ETB.FilterBar

-- =============================================================================
-- CREATE
-- =============================================================================

function FilterBar:Create(parent)
    local f = CreateFrame("Frame", nil, parent)
    f:SetSize(parent:GetWidth() - 20, 105)  -- 3 rows: category/collection, source/quality, sort/search
    f:SetPoint("TOPLEFT", 10, -30)
    
    f.bg = f:CreateTexture(nil, "BACKGROUND")
    f.bg:SetAllPoints()
    f.bg:SetColorTexture(0, 0, 0, 0.3)
    
    -- Row 1: Category and Collection
    f.categoryLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.categoryLabel:SetPoint("TOPLEFT", 5, -8)
    f.categoryLabel:SetText("Slot:")
    
    f.categoryDropdown = ETBDropdown:Create("ETBCategoryDD", f)
    f.categoryDropdown:SetPoint("LEFT", f.categoryLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.categoryDropdown, 100)
    ETBDropdown:Initialize(f.categoryDropdown, function(dd, _items_)
        for catID, info in pairs(ETB.CATEGORY_INFO) do
            -- Skip weapon categories (12+) - handled by icon buttons at top
            if not info.isWeapon then
            local item = ETBDropdown:CreateInfo()
            item.text = info.name
            item.value = catID
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, catID)
                ETBDropdown:SetText(dd, info.name)
                ETB.Filtering:SetCategory(catID)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
            end
        end
    end)
    ETBDropdown:SetSelectedValue(f.categoryDropdown, 1)
    ETBDropdown:SetText(f.categoryDropdown, "Head")
    
    f.collectedLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.collectedLabel:SetPoint("LEFT", f.categoryDropdown, "RIGHT", 10, 2)
    f.collectedLabel:SetText("Show:")
    
    f.collectedDropdown = ETBDropdown:Create("ETBCollectedDD", f)
    f.collectedDropdown:SetPoint("LEFT", f.collectedLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.collectedDropdown, 90)
    
    local collOpts = {{ value = "all", text = "All" }, { value = "collected", text = "Collected" }, { value = "uncollected", text = "Missing" }}
    ETBDropdown:Initialize(f.collectedDropdown, function(dd, _items_)
        for _, opt in ipairs(collOpts) do
            local item = ETBDropdown:CreateInfo()
            item.text = opt.text
            item.value = opt.value
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, opt.value)
                ETBDropdown:SetText(dd, opt.text)
                ETB.Filtering:SetCollectedFilter(opt.value)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    ETBDropdown:SetSelectedValue(f.collectedDropdown, "all")
    ETBDropdown:SetText(f.collectedDropdown, "All")
    
    -- Row 2: Source type and Quality/Weapon Type
    f.sourceLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.sourceLabel:SetPoint("TOPLEFT", 5, -35)
    f.sourceLabel:SetText("Source:")
    
    f.sourceDropdown = ETBDropdown:Create("ETBSourceDD", f)
    f.sourceDropdown:SetPoint("LEFT", f.sourceLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.sourceDropdown, 90)
    ETBDropdown:Initialize(f.sourceDropdown, function(dd, _items_)
        for _, src in ipairs(ETB.SOURCE_TYPES) do
            local item = ETBDropdown:CreateInfo()
            item.text = src.name
            item.value = src.id
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, src.id)
                ETBDropdown:SetText(dd, src.name)
                ETB.Filtering:SetSourceType(src.id)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    ETBDropdown:SetSelectedValue(f.sourceDropdown, "all")
    ETBDropdown:SetText(f.sourceDropdown, "All Sources")
    
    f.qualityLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.qualityLabel:SetPoint("LEFT", f.sourceDropdown, "RIGHT", 10, 2)
    f.qualityLabel:SetText("Quality:")
    
    f.qualityDropdown = ETBDropdown:Create("ETBQualityDD", f)
    f.qualityDropdown:SetPoint("LEFT", f.qualityLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.qualityDropdown, 80)
    ETBDropdown:Initialize(f.qualityDropdown, function(dd, _items_)
        local item = ETBDropdown:CreateInfo()
        item.text = "All"
        item.value = "all"
        item.func = function()
            ETBDropdown:SetSelectedValue(dd, "all")
            ETBDropdown:SetText(dd, "All")
            ETB.Filtering:SetQuality("all")
            if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
        end
        ETBDropdown:AddButton(_items_, item)
        
        for q = 1, 5 do
            local qInfo = ETB.QUALITY_COLORS[q]
            item = ETBDropdown:CreateInfo()
            item.text = qInfo.hex .. qInfo.name .. "|r"
            item.value = q
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, q)
                ETBDropdown:SetText(dd, qInfo.name)
                ETB.Filtering:SetQuality(q)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    ETBDropdown:SetSelectedValue(f.qualityDropdown, "all")
    ETBDropdown:SetText(f.qualityDropdown, "All")
    
    -- Weapons Only checkbox
    f.weaponsOnlyCheck = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    f.weaponsOnlyCheck:SetSize(24, 24)
    f.weaponsOnlyCheck:SetPoint("LEFT", f.qualityDropdown, "RIGHT", 20, 0)
    f.weaponsOnlyCheck:SetChecked(false)
    f.weaponsOnlyCheck:SetScript("OnClick", function(self)
        ETB.Filtering:SetShowWeaponsOnly(self:GetChecked())
        -- Update sort dropdown to show weapon sorts when "Weapons Only" is enabled
        if self:GetChecked() then
            ETBDropdown:Initialize(f.sortDropdown, function(dd, _items_)
                local sortOptions = {
                    { value = "name", text = "Name" },
                    { value = "quality", text = "Quality" },
                    { value = "collected", text = "Collection" },
                    { value = "source", text = "Source" },
                    { value = "weaponType", text = "Weapon Type" },
                    { value = "weaponHand", text = "One/Two-Handed" },
                    { value = "weaponTypeHand", text = "Type + Hand" },
                }
                
                for _, opt in ipairs(sortOptions) do
                    local item = ETBDropdown:CreateInfo()
                    item.text = opt.text
                    item.value = opt.value
                    item.func = function()
                        ETBDropdown:SetSelectedValue(dd, opt.value)
                        ETBDropdown:SetText(dd, opt.text)
                        ETB.Filtering:SetSort(opt.value, true)
                        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
                    end
                    ETBDropdown:AddButton(_items_, item)
                end
            end)
        end
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)
    
    f.weaponsOnlyLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.weaponsOnlyLabel:SetPoint("LEFT", f.weaponsOnlyCheck, "RIGHT", 0, 0)
    f.weaponsOnlyLabel:SetText("Weapons Only")
    
    -- Class filter dropdown (replaces old "My Class Only" checkbox)
    f.classLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.classLabel:SetPoint("LEFT", f.weaponsOnlyCheck, "RIGHT", 80, 0)
    f.classLabel:SetText("Class:")
    
    f.classDropdown = ETBDropdown:Create("ETBClassDD", f)
    f.classDropdown:SetPoint("LEFT", f.classLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.classDropdown, 120)
    
    local CLASS_OPTIONS = {
        { id = nil,  name = "All Classes" },
        { id = 1,    name = "Warrior" },
        { id = 2,    name = "Paladin" },
        { id = 3,    name = "Hunter" },
        { id = 4,    name = "Rogue" },
        { id = 5,    name = "Priest" },
        { id = 6,    name = "Death Knight" },
        { id = 7,    name = "Shaman" },
        { id = 8,    name = "Mage" },
        { id = 9,    name = "Warlock" },
        { id = 10,   name = "Monk" },
        { id = 11,   name = "Druid" },
    }
    
    ETBDropdown:Initialize(f.classDropdown, function(dd, _items_)
        -- Get player's classID for highlighting
        local _, _, playerClassID = UnitClass("player")
        
        for _, cls in ipairs(CLASS_OPTIONS) do
            local item = ETBDropdown:CreateInfo()
            item.text = cls.name
            item.value = cls.id
            -- Highlight current player class
            if cls.id and cls.id == playerClassID then
                item.text = "|cff00ff00" .. cls.name .. " (You)|r"
            end
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, cls.id)
                ETBDropdown:SetText(dd, cls.name)
                ETB.Filtering:SetClassFilter(cls.id)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    
    -- Default to player's class
    local _, playerClassName, playerClassID = UnitClass("player")
    ETBDropdown:SetSelectedValue(f.classDropdown, playerClassID)
    ETBDropdown:SetText(f.classDropdown, playerClassName or "My Class")

    -- Feature 2.3: explain that "All Classes" is browse-only on 5.4.8 since
    -- you can't actually transmog cross-armor-type. Tooltip on hover.
    f.classDropdown:HookScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_LEFT")
        GameTooltip:SetText("Class Filter")
        GameTooltip:AddLine("Filter the item list by class.", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine(" ")
        GameTooltip:AddLine("Selecting |cffffd100All Classes|r is browse-only:", 1, 0.82, 0)
        GameTooltip:AddLine("you can preview items from other classes,", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine("but transmog requires the same armor type", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine("(Cloth/Leather/Mail/Plate) and equippable slot.", 0.8, 0.8, 0.8, true)
        GameTooltip:Show()
    end)
    f.classDropdown:HookScript("OnLeave", function() GameTooltip:Hide() end)
    
    -- Row 3: Sort and Search
    f.sortLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.sortLabel:SetPoint("TOPLEFT", 5, -60)
    f.sortLabel:SetText("Sort:")
    
    f.sortDropdown = ETBDropdown:Create("ETBSortDD", f)
    f.sortDropdown:SetPoint("LEFT", f.sortLabel, "RIGHT", -5, -2)
    ETBDropdown:SetWidth(f.sortDropdown, 120)
    ETBDropdown:Initialize(f.sortDropdown, function(dd, _items_)
        local sortOptions = {
            { value = "name", text = "Name" },
            { value = "quality", text = "Quality" },
            { value = "collected", text = "Collection" },
            { value = "source", text = "Source" },
            -- v14.1.0 wardrobe-grade sorts (Feature 1.4)
            { value = "expansion", text = "Expansion" },
            { value = "itemLevel", text = "Item Level" },
            { value = "recent", text = "Recently Collected" },
        }
        
        -- Add weapon-specific sorts when viewing weapons (categories 12+)
        local categoryID = ETB.Filtering.filters.category
        local catInfo = ETB.CATEGORY_INFO and ETB.CATEGORY_INFO[categoryID]
        local isWeaponCat = (catInfo and catInfo.isWeapon) or categoryID >= 12
        if isWeaponCat or ETB.Filtering.filters.showWeaponsOnly then
            table.insert(sortOptions, { value = "weaponType", text = "Weapon Type" })
            table.insert(sortOptions, { value = "weaponHand", text = "One/Two-Handed" })
            table.insert(sortOptions, { value = "weaponTypeHand", text = "Type + Hand" })
        end
        
        for _, opt in ipairs(sortOptions) do
            local item = ETBDropdown:CreateInfo()
            item.text = opt.text
            item.value = opt.value
            item.func = function()
                ETBDropdown:SetSelectedValue(dd, opt.value)
                ETBDropdown:SetText(dd, opt.text)
                ETB.Filtering:SetSort(opt.value, true)
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    ETBDropdown:SetSelectedValue(f.sortDropdown, "name")
    ETBDropdown:SetText(f.sortDropdown, "Name")
    
    -- Sort direction button
    f.sortDirBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    f.sortDirBtn:SetSize(25, 20)
    f.sortDirBtn:SetPoint("LEFT", f.sortDropdown, "RIGHT", 5, 0)
    f.sortDirBtn:SetText("↑")
    f.sortDirBtn:SetScript("OnClick", function(self)
        local ascending = not ETB.Filtering.sortAscending
        ETB.Filtering:SetSort(ETB.Filtering.sortBy, ascending)
        FilterBar:UpdateSortDirection()
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)
    
    -- Initialize sort direction button
    FilterBar:UpdateSortDirection()
    
    f.searchLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.searchLabel:SetPoint("LEFT", f.sortDirBtn, "RIGHT", 10, 0)
    f.searchLabel:SetText("Search:")
    
    f.searchBox = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
    f.searchBox:SetSize(200, 20)
    f.searchBox:SetPoint("LEFT", f.searchLabel, "RIGHT", 5, 0)
    f.searchBox:SetAutoFocus(false)
    f.searchBox:SetScript("OnEnterPressed", function(self)
        ETB.Filtering:SetSearchText(self:GetText())
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
        self:ClearFocus()
    end)
    f.searchBox:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    
    f.searchBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    f.searchBtn:SetSize(60, 20)
    f.searchBtn:SetPoint("LEFT", f.searchBox, "RIGHT", 5, 0)
    f.searchBtn:SetText("Search")
    f.searchBtn:SetScript("OnClick", function()
        ETB.Filtering:SetSearchText(f.searchBox:GetText())
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)
    
    f.clearBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    f.clearBtn:SetSize(50, 20)
    f.clearBtn:SetPoint("LEFT", f.searchBtn, "RIGHT", 5, 0)
    f.clearBtn:SetText("Clear")
    f.clearBtn:SetScript("OnClick", function()
        f.searchBox:SetText("")
        ETB.Filtering:ClearFilters()
        ETBDropdown:SetSelectedValue(f.collectedDropdown, "all")
        ETBDropdown:SetText(f.collectedDropdown, "All")
        ETBDropdown:SetSelectedValue(f.sourceDropdown, "all")
        ETBDropdown:SetText(f.sourceDropdown, "All Sources")
        ETBDropdown:SetSelectedValue(f.qualityDropdown, "all")
        ETBDropdown:SetText(f.qualityDropdown, "All")
        f.weaponsOnlyCheck:SetChecked(false)
        -- v14.6.0: also reset the new toggles
        if f.favOnlyBtn then f.favOnlyBtn:SetChecked(false); ETB.Filtering:SetFavoritesOnly(false) end
        if f.showHiddenBtn then f.showHiddenBtn:SetChecked(false); ETB.Filtering:SetShowHidden(false) end
        -- Reset class filter to player's class
        local _, playerClassName, playerClassID = UnitClass("player")
        ETBDropdown:SetSelectedValue(f.classDropdown, playerClassID)
        ETBDropdown:SetText(f.classDropdown, playerClassName or "My Class")
        ETB.Filtering:SetClassFilter(playerClassID)
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)

    -- v14.6.0 Feature 1.3: Favorites-only toggle
    f.favOnlyBtn = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    f.favOnlyBtn:SetSize(22, 22)
    f.favOnlyBtn:SetPoint("LEFT", f.clearBtn, "RIGHT", 8, 0)
    f.favOnlyBtn:SetChecked(false)
    f.favOnlyBtn:SetScript("OnClick", function(self)
        ETB.Filtering:SetFavoritesOnly(self:GetChecked() and true or false)
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)
    f.favOnlyBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
        GameTooltip:SetText("Favorites only")
        GameTooltip:AddLine("Show only items you've marked as favorites.", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine("|cffaaaaaaAlt+Left-Click an item to favorite/unfavorite it.|r", 0.7, 0.7, 0.7, true)
        GameTooltip:Show()
    end)
    f.favOnlyBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    f.favOnlyLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.favOnlyLabel:SetPoint("LEFT", f.favOnlyBtn, "RIGHT", 1, 1)
    f.favOnlyLabel:SetText("|cffffd100★|r")

    -- v14.6.0 Feature 1.3: Show-hidden toggle
    f.showHiddenBtn = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    f.showHiddenBtn:SetSize(22, 22)
    f.showHiddenBtn:SetPoint("LEFT", f.favOnlyLabel, "RIGHT", 8, 0)
    f.showHiddenBtn:SetChecked(false)
    f.showHiddenBtn:SetScript("OnClick", function(self)
        ETB.Filtering:SetShowHidden(self:GetChecked() and true or false)
        if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
    end)
    f.showHiddenBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
        GameTooltip:SetText("Show hidden")
        GameTooltip:AddLine("Include appearances you've hidden.", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine("|cffaaaaaaShift+Right-Click an item to hide/unhide it.|r", 0.7, 0.7, 0.7, true)
        if ETB.HiddenAppearances then
            local n = ETB.HiddenAppearances:GetCount()
            GameTooltip:AddLine(string.format("Currently %d hidden.", n), 0.6, 0.6, 0.6, true)
        end
        GameTooltip:Show()
    end)
    f.showHiddenBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    f.showHiddenLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.showHiddenLabel:SetPoint("LEFT", f.showHiddenBtn, "RIGHT", 1, 1)
    f.showHiddenLabel:SetText("|cffaaaaaahidden|r")

    -- v14.6.0 Feature 2.2: Saved Searches dropdown + Save button
    f.savedSearchSaveBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    f.savedSearchSaveBtn:SetSize(80, 20)
    f.savedSearchSaveBtn:SetPoint("LEFT", f.showHiddenLabel, "RIGHT", 12, 0)
    f.savedSearchSaveBtn:SetText("Save Search")
    f.savedSearchSaveBtn:SetScript("OnClick", function()
        StaticPopup_Show("ETB_SAVE_SEARCH")
    end)
    f.savedSearchSaveBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
        GameTooltip:SetText("Save current search")
        GameTooltip:AddLine("Saves the current filter + search settings.", 0.8, 0.8, 0.8, true)
        GameTooltip:AddLine("Doesn't save category or collected/uncollected toggle.", 0.7, 0.7, 0.7, true)
        GameTooltip:Show()
    end)
    f.savedSearchSaveBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    f.savedSearchLoadBtn = ETBDropdown:Create("ETBSavedSearchLoadDD", f)
    f.savedSearchLoadBtn:SetPoint("LEFT", f.savedSearchSaveBtn, "RIGHT", 4, 0)
    ETBDropdown:SetWidth(f.savedSearchLoadBtn, 100)
    ETBDropdown:SetText(f.savedSearchLoadBtn, "Load Search")
    ETBDropdown:Initialize(f.savedSearchLoadBtn, function(dd, _items_)
        if not ETB.SavedSearches then return end
        local list = ETB.SavedSearches:GetAll()
        if #list == 0 then
            local emptyItem = ETBDropdown:CreateInfo()
            emptyItem.text = "|cffaaaaaa(no saved searches)|r"
            emptyItem.disabled = true
            ETBDropdown:AddButton(_items_, emptyItem)
            return
        end
        for _, entry in ipairs(list) do
            local item = ETBDropdown:CreateInfo()
            item.text = entry.name
            item.func = function()
                ETB.SavedSearches:Restore(entry.name)
                if FilterBar.frame and FilterBar.frame.searchBox then
                    FilterBar.frame.searchBox:SetText(
                        ETB.Filtering.filters.searchText or "")
                end
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
                if ETB.Print then ETB:Print("Loaded search: " .. entry.name) end
            end
            ETBDropdown:AddButton(_items_, item)
        end
        -- Separator + delete entries
        local sep = ETBDropdown:CreateInfo()
        sep.text = "|cff666666— delete —|r"
        sep.disabled = true
        ETBDropdown:AddButton(_items_, sep)
        for _, entry in ipairs(list) do
            local item = ETBDropdown:CreateInfo()
            item.text = "|cffff5555×|r " .. entry.name
            item.func = function() ETB.SavedSearches:Delete(entry.name) end
            ETBDropdown:AddButton(_items_, item)
        end
    end)
    
    -- v15.8.0: Color filter dropdown. ColorSearch + Filtering already
    -- support filters.colorFilter end-to-end (Filtering.lua line 108 setter,
    -- line 284 filter loop, line 410 stats). Previously the dropdown was
    -- removed; restoring it here so the user-facing surface is complete.
    --
    -- The 12 color categories come from ColorSearch.Categories. Each entry
    -- gets a colored swatch in the dropdown text using |cAARRGGBB|r color
    -- codes so the player can pick visually without inspecting hex values.
    f.colorFilterBtn = ETBDropdown:Create("ETBColorFilterDD", f)
    f.colorFilterBtn:SetPoint("LEFT", f.savedSearchLoadBtn, "RIGHT", 4, 0)
    ETBDropdown:SetWidth(f.colorFilterBtn, 100)
    ETBDropdown:SetText(f.colorFilterBtn, "Color: All")

    local function rgbToHex(rgb)
        local r = math.floor((rgb[1] or 1) * 255)
        local g = math.floor((rgb[2] or 1) * 255)
        local b = math.floor((rgb[3] or 1) * 255)
        return string.format("ff%02x%02x%02x", r, g, b)
    end

    local function refreshColorFilterLabel()
        local cur = ETB.Filtering and ETB.Filtering.filters and ETB.Filtering.filters.colorFilter
        if not cur then
            ETBDropdown:SetText(f.colorFilterBtn, "Color: All")
        elseif ETB.ColorSearch and ETB.ColorSearch.CategoryByID and ETB.ColorSearch.CategoryByID[cur] then
            local cat = ETB.ColorSearch.CategoryByID[cur]
            ETBDropdown:SetText(f.colorFilterBtn,
                string.format("|c%s■|r %s", rgbToHex(cat.swatch), cat.name))
        else
            ETBDropdown:SetText(f.colorFilterBtn, "Color: " .. cur)
        end
    end

    ETBDropdown:Initialize(f.colorFilterBtn, function(dd, _items_)
        if not ETB.ColorSearch or not ETB.Filtering then
            local none = ETBDropdown:CreateInfo()
            none.text = "|cffaaaaaa(ColorSearch not loaded)|r"
            none.disabled = true
            ETBDropdown:AddButton(_items_, none)
            return
        end

        -- "All" option clears the filter
        local allItem = ETBDropdown:CreateInfo()
        allItem.text = "All"
        allItem.func = function()
            ETB.Filtering:SetColorFilter(nil)
            refreshColorFilterLabel()
            if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
        end
        ETBDropdown:AddButton(_items_, allItem)

        -- One entry per color category, with a colored swatch glyph
        for _, cat in ipairs(ETB.ColorSearch.Categories) do
            local item = ETBDropdown:CreateInfo()
            item.text = string.format("|c%s■■|r %s", rgbToHex(cat.swatch), cat.name)
            item.func = function()
                ETB.Filtering:SetColorFilter(cat.id)
                refreshColorFilterLabel()
                if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
            end
            ETBDropdown:AddButton(_items_, item)
        end
    end)

    -- Restore label if the user saved their filter state across a /reload
    refreshColorFilterLabel()
    f.refreshColorFilterLabel = refreshColorFilterLabel  -- expose for external Filtering changes

    self.frame = f
    return f
end

function FilterBar:UpdateSortDirection()
    if self.frame and self.frame.sortDirBtn then
        self.frame.sortDirBtn:SetText(ETB.Filtering.sortAscending and "↑" or "↓")
    end
end

function FilterBar:SetCategory(categoryID)
    if self.frame and self.frame.categoryDropdown then
        local info = ETB.CATEGORY_INFO[categoryID]
        if info then
            ETBDropdown:SetSelectedValue(self.frame.categoryDropdown, categoryID)
            ETBDropdown:SetText(self.frame.categoryDropdown, info.name)
            
            -- Update sort dropdown to show weapon sorts when viewing weapons (categories 12+)
            local isWeaponCat = (info and info.isWeapon) or categoryID >= 12
            if isWeaponCat then
                -- Reinitialize sort dropdown to include weapon sorts
                ETBDropdown:Initialize(self.frame.sortDropdown, function(dd, _items_)
                    local sortOptions = {
                        { value = "name", text = "Name" },
                        { value = "quality", text = "Quality" },
                        { value = "collected", text = "Collection" },
                        { value = "source", text = "Source" },
                        { value = "weaponType", text = "Weapon Type" },
                        { value = "weaponHand", text = "One/Two-Handed" },
                        { value = "weaponTypeHand", text = "Type + Hand" },
                    }
                    
                    for _, opt in ipairs(sortOptions) do
                        local item = ETBDropdown:CreateInfo()
                        item.text = opt.text
                        item.value = opt.value
                        item.func = function()
                            ETBDropdown:SetSelectedValue(dd, opt.value)
                            ETBDropdown:SetText(dd, opt.text)
                            ETB.Filtering:SetSort(opt.value, ETB.Filtering.sortAscending)
                            FilterBar:UpdateSortDirection()
                            if ETB.MainFrame then ETB.MainFrame:RefreshItems() end
                        end
                        ETBDropdown:AddButton(_items_, item)
                    end
                end)
            end
        end
    end
end

-- StaticPopup for naming a new saved search (defined at file scope to avoid taint)
StaticPopupDialogs["ETB_SAVE_SEARCH"] = {
    text = "Name this search:",
    button1 = "Save", button2 = "Cancel",
    hasEditBox = true, maxLetters = 32,
    OnAccept = function(self)
        local eb = self.editBox or self.EditBox
        local name = eb and eb:GetText() or ""
        if name ~= "" and ETB.SavedSearches then
            ETB.SavedSearches:SaveAs(name)
        end
    end,
    EditBoxOnEnterPressed = function(self)
        local parent = self:GetParent()
        if parent and parent.button1 then parent.button1:Click() end
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout = 0, whileDead = true, hideOnEscape = true,
}

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