-- 衷心感谢，在 独处。 @ NGA 发的基础上进行二创，https://bbs.nga.cn/read.php?tid=46366498
-- 衷心感谢，在雪白的黑牛@的二创基础上优化了布局，修复了部分图标
-- ==========================================
-- 布局常量定义
-- ==========================================
local ICON_SIZE = 36                         -- 图标尺寸
local HORIZONTAL_GAP = 6                      -- 图标水平间距
local VERTICAL_GAP = 12                       -- 图标垂直间距（增大以避免文字重叠）
local CATEGORY_SPACING = 8                    -- 类别间距
local TITLE_TO_ICONS = 24                      -- 标题到第一个图标行的距离
local ROW_ICONS = 9                           -- 每行显示9个图标
local TEXT_GAP = 0                             -- 图标下方文字与图标的间距（调整为4）

-- 列宽计算：左边距10 + 6个图标 + 5个间距 + 右边距8
local COLUMN_WIDTH = 10 + ICON_SIZE * ROW_ICONS + HORIZONTAL_GAP * (ROW_ICONS - 1) + 8
local WINDOW_WIDTH = COLUMN_WIDTH + 30          -- 窗口宽度增加（左右边距各30）

-- ==========================================
-- 工具函数
-- ==========================================
local function GetItemCountSafe(itemID)
    if C_Item and C_Item.GetItemCount then
        return C_Item.GetItemCount(itemID, false, false, false) or 0
    elseif GetItemCount then
        return GetItemCount(itemID) or 0
    end
    return 0
end

-- 物品名在客户端未缓存时 GetItemInfo 第一返回值会为 nil；先显示占位并 RequestLoadItemDataByID，见 frame 创建后的实现。
local qabPendingTrackItemIDs = {}
local qabProfItemRefreshTimer
local GetItemNameSafe
-- 供 RefreshHomeProfessionsSection 在 CreateIconButton 定义之前引用
local RefreshHomeProfessionsSection
local CreateIconButton

local function GetItemIconSafe(itemID)
    if not itemID then return nil end
    if C_Item and C_Item.GetItemIconByID then
        return C_Item.GetItemIconByID(itemID)
    end
    if GetItemIcon then
        return GetItemIcon(itemID)
    end
    return nil
end

-- 品质、物品等级（用于 Tooltip 里多 ID 数量颜色区分）
local function GetItemQualitySafe(itemID)
    if C_Item and C_Item.GetItemQualityByID then
        local q = C_Item.GetItemQualityByID(itemID)
        if q ~= nil then return q end
    end
    if GetItemInfo then
        return select(3, GetItemInfo(itemID)) or 0
    end
    return 0
end

local function GetItemLevelSafe(itemID)
    if GetItemInfo then
        return select(4, GetItemInfo(itemID)) or 0
    end
    return 0
end

-- Tooltip 右侧数量：高品质暗金、低品质灰白
local COLOR_TIP_COUNT_HIGH = {0.72, 0.54, 0.18}
local COLOR_TIP_COUNT_LOW  = {0.78, 0.78, 0.82}

local QAB_ITEM_NAME_LOADING = (type(RETRIEVING_ITEM_INFO) == "string" and RETRIEVING_ITEM_INFO ~= "")
    and RETRIEVING_ITEM_INFO or "读取中…"

local function QAB_GetItemNameCached(itemID)
    if not itemID then
        return nil
    end
    if C_Item and C_Item.GetItemInfo then
        local nm = select(1, C_Item.GetItemInfo(itemID))
        if type(nm) == "string" and nm ~= "" then
            return nm
        end
    end
    return nil
end

local function QAB_RequestLoadItemNameForTrack(itemID)
    if not itemID or not C_Item or not C_Item.RequestLoadItemDataByID then
        return
    end
    if QAB_GetItemNameCached(itemID) then
        qabPendingTrackItemIDs[itemID] = nil
        return
    end
    qabPendingTrackItemIDs[itemID] = true
    pcall(C_Item.RequestLoadItemDataByID, itemID)
end

-- requestAsync：为 true 时请求服务器/客户端加载物品数据，收到 ITEM_DATA_LOAD_RESULT 后刷新首页追踪区以显示真名。
GetItemNameSafe = function(itemID, requestAsync)
    local nm = QAB_GetItemNameCached(itemID)
    if nm then
        return nm
    end
    if requestAsync then
        QAB_RequestLoadItemNameForTrack(itemID)
    end
    return QAB_ITEM_NAME_LOADING
end

-- ==========================================
-- 主框架创建与基础设置
-- ==========================================
local frame = CreateFrame("Frame", "QuickAuctionBuyerFrame", UIParent, "BackdropTemplate")
frame:SetSize(WINDOW_WIDTH, 580)                -- 初始高度580，后续自适应
frame:SetPoint("CENTER", 0, 0)
frame:SetFrameStrata("HIGH")
frame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 32, edgeSize = 16,
    insets = {left=4, right=4, top=4, bottom=4}
})
frame:SetBackdropColor(0.1, 0.1, 0.1, 0.95)
frame:SetBackdropBorderColor(1, 1, 1, 1)
frame:Hide()

local manuallyClosed = false                 -- 标记用户是否手动关闭（手动关闭后不再自动弹出）

-- ==========================================
-- 最小化图标按钮
-- ==========================================
local minimizeIcon = CreateFrame("Button", nil, UIParent)
minimizeIcon:SetSize(32, 32)
minimizeIcon:SetPoint("TOPLEFT", frame, "TOPRIGHT", 5, 0)
minimizeIcon:SetNormalTexture("Interface\\Icons\\INV_Misc_Note_01")
minimizeIcon:SetPushedTexture("Interface\\Icons\\INV_Misc_Note_01")
minimizeIcon:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
minimizeIcon:Hide()

local isMinimized = false

-- ==========================================
-- 标题与按钮行
-- ==========================================
local title = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
title:SetPoint("TOP", 0, -6)
title:SetText("购物助手")
title:SetTextColor(1, 0.82, 0, 1)

-- 关闭按钮（最小化）
local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
close:SetPoint("TOPRIGHT", -5, -5)
close:SetScript("OnClick", function()
    frame:Hide()
    minimizeIcon:Show()
    isMinimized = true
    manuallyClosed = true                    -- 记录手动关闭状态
end)

minimizeIcon:SetScript("OnClick", function()
    minimizeIcon:Hide()
    frame:Show()
    isMinimized = false
end)

-- ==========================================
-- 四列布局与标签页按钮
-- ==========================================
local columns = {}
local columnTitles = {"消耗品", "装备附魔", "公函与宝石", "配方材料"}
local activeColumn = 1

for i = 1, 4 do
    local col = CreateFrame("Frame", nil, frame)
    col:SetSize(COLUMN_WIDTH, 480)               -- 高度调整为480
    col:SetPoint("TOPLEFT", 10, -50)             -- 顶部偏移从-50改为-38，更贴近标签栏
    col.yOffset = -5
    col:Hide()
    columns[i] = col
end
columns[1]:Show()

-- 创建四个标签页切换按钮（宽度自适应）
local tabButtons = {}
local tabWidth = (WINDOW_WIDTH - 20) / 4 - 4
for i = 1, 4 do
    local btn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    btn:SetSize(tabWidth, 22)
    if i == 1 then
        btn:SetPoint("TOPLEFT", 10, -28)
    else
        btn:SetPoint("LEFT", tabButtons[i-1], "RIGHT", 2, 0)
    end
    btn:SetText(columnTitles[i])
    
    btn:SetScript("OnClick", function()
        for j = 1, 4 do
            columns[j]:Hide()
            tabButtons[j]:SetAlpha(0.6)
        end
        columns[i]:Show()
        btn:SetAlpha(1.0)
        activeColumn = i
        
        -- 点击配方材料标签时刷新材料列表
        if i == 4 then
            RefreshRecipeMaterials()
        end
    end)
    
    tabButtons[i] = btn
end
tabButtons[1]:SetAlpha(1.0)
for i = 2, 4 do
    tabButtons[i]:SetAlpha(0.6)
end

-- ==========================================
-- 拍卖行搜索功能（提前定义供后续使用）
-- ==========================================
local SearchItem
local function DoSearchItem(itemName)
    local ah = AuctionHouseFrame or AuctionFrame
    if not ah or not ah:IsShown() then
        return
    end
    if ah.SearchBar and ah.SearchBar.SearchBox then
        ah.SearchBar.SearchBox:SetText(itemName)
    else
        return
    end
    if ah.SearchBar and ah.SearchBar.Search then
        pcall(function() ah.SearchBar:Search() end)
    elseif ah.SearchBar and ah.SearchBar.SearchButton then
        pcall(function() ah.SearchBar.SearchButton:Click() end)
    elseif ah.SearchBar and ah.SearchBar.SearchBox then
        local onEnter = ah.SearchBar.SearchBox:GetScript("OnEnter")
        if onEnter then pcall(function() onEnter(ah.SearchBar.SearchBox) end) end
    end
end

-- ==========================================
-- 滚动区域设置（每列独立滚动）
-- ==========================================
local scrollFrames = {}
for i = 1, 4 do
    local sf = CreateFrame("ScrollFrame", nil, columns[i], "UIPanelScrollFrameTemplate")
    sf:SetPoint("TOPLEFT", 0, 0)
    sf:SetPoint("BOTTOMRIGHT", 0, 0)
    
    local content = CreateFrame("Frame", nil, sf)
    sf:SetScrollChild(content)
    content:SetSize(COLUMN_WIDTH, 10)
    
    sf.ScrollBar:Hide()
    sf.ScrollBar:SetAlpha(0)
    
    sf:SetScript("OnMouseWheel", function(self, delta)
        local scrollStep = 30
        local current = self:GetVerticalScroll()
        local maxScroll = self:GetVerticalScrollRange()
        local newScroll = current - (delta * scrollStep)
        if newScroll < 0 then newScroll = 0 end
        if newScroll > maxScroll then newScroll = maxScroll end
        self:SetVerticalScroll(newScroll)
    end)
    
    sf:EnableMouse(true)
    content:EnableMouse(true)
    content:SetScript("OnMouseWheel", function(self, delta)
        sf:GetScript("OnMouseWheel")(sf, delta)
    end)
    
    columns[i].scrollFrame = sf
    columns[i].content = content
    scrollFrames[i] = sf
end

-- ==========================================
-- 配方材料追踪功能
-- ==========================================
local recipeMaterialButtons = {}
local trackedRecipes = {} -- 存储追踪的配方

-- 获取追踪的配方列表
local function GetTrackedRecipes()
    local recipes = {}
    
    if not C_TradeSkillUI then
        return recipes
    end
    
    -- 同时获取普通配方和再造配方
    -- C_TradeSkillUI.GetRecipesTracked(isRecraft) 返回服务器保存的追踪列表
    -- 这个列表在玩家下线后仍然保留，重新登录后可以直接获取
    
    -- 获取普通配方 (isRecraft = false)
    local normalRecipes = C_TradeSkillUI.GetRecipesTracked(false) or {}
    for _, recipeID in ipairs(normalRecipes) do
        table.insert(recipes, {id = recipeID, isRecraft = false})
    end
    
    -- 获取再造配方 (isRecraft = true)
    local recraftRecipes = C_TradeSkillUI.GetRecipesTracked(true) or {}
    for _, recipeID in ipairs(recraftRecipes) do
        table.insert(recipes, {id = recipeID, isRecraft = true})
    end
    
    return recipes
end

-- 成品材料显示开关（默认不显示）
local showOptionalReagents = false
-- 显示齐备材料开关（默认勾选）
local showCompleteMaterials = true

-- 设置成品材料显示状态
local function SetShowOptionalReagents(show)
    showOptionalReagents = show
end

-- 获取成品材料显示状态
local function GetShowOptionalReagents()
    return showOptionalReagents
end

-- 设置显示齐备材料状态
local function SetShowCompleteMaterials(show)
    showCompleteMaterials = show
end

-- 获取显示齐备材料状态
local function GetShowCompleteMaterials()
    return showCompleteMaterials
end

-- 获取配方所需材料
local function GetRecipeMaterials(recipeID, isRecraft)
    local materials = {}
    if not recipeID then return materials end
    
    -- 默认不是再造
    isRecraft = isRecraft or false
    
    -- 使用表来按名称去重
    local materialMap = {}
    
    -- 使用新的配方结构API (10.0+ 版本)
    if C_TradeSkillUI and C_TradeSkillUI.GetRecipeSchematic then
        local schematic = C_TradeSkillUI.GetRecipeSchematic(recipeID, isRecraft)
        if schematic and schematic.reagentSlotSchematics then
            for _, slotSchematic in ipairs(schematic.reagentSlotSchematics) do
                -- 检查是否是可选材料（成品材料）
                -- 判断标准：reagentType == 2 表示可选材料，1 表示基础材料
                local reagentType = slotSchematic.reagentType
                local isOptional = reagentType == 2
                
                -- 如果不显示成品材料，跳过可选槽位
                if isOptional and not showOptionalReagents then
                    -- 跳过可选材料
                else
                    if slotSchematic.reagents then
                        for _, reagent in ipairs(slotSchematic.reagents) do
                            local itemID = reagent.itemID
                            if itemID then
                                local name, itemLink, _, _, _, _, _, _, _, icon = C_Item.GetItemInfo(itemID)
                                if name then
                                    -- 按名称去重，只保留第一个
                                    if not materialMap[name] then
                                        local needed = slotSchematic.quantityRequired or 1
                                        -- 使用 true 参数包含银行和材料银行，更准确地统计材料数量
                                        local have = C_Item.GetItemCount(itemID, true, true, true) or 0
                                        local materialData = {
                                            name = name,
                                            itemID = itemID,
                                            icon = icon,
                                            needed = needed,
                                            have = have,
                                            itemLink = itemLink,
                                            isOptional = isOptional
                                        }
                                        materialMap[name] = materialData
                                        table.insert(materials, materialData)
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    
    return materials
end

-- 创建材料图标按钮
local function CreateMaterialButton(parent, material, x, y)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(ICON_SIZE, ICON_SIZE)
    btn:SetPoint("TOPLEFT", x, y)
    
    btn.itemID = material.itemID
    btn.itemName = material.name
    btn.itemLink = material.itemLink
    
    -- 图标
    local tex = btn:CreateTexture(nil, "ARTWORK")
    tex:SetAllPoints()
    tex:SetTexture(material.icon or "Interface\\Icons\\INV_Misc_QuestionMark")
    tex:SetTexCoord(0.07, 0.93, 0.07, 0.93)
    btn.icon = tex
    
    -- 材料名称
    local label = btn:CreateFontString(nil, "OVERLAY")
    local fontFile, _, fontFlags = GameFontNormal:GetFont()
    label:SetFont(fontFile, 11, fontFlags)
    label:SetPoint("TOP", btn, "BOTTOM", 0, TEXT_GAP)
    label:SetText(material.name)
    label:SetWidth(ICON_SIZE + 10)
    label:SetHeight(30)
    label:SetWordWrap(true)
    label:SetTextColor(1, 1, 1, 1)
    
    -- 数量显示（需求/拥有）
    local countText = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    countText:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -2, 2)
    countText:SetTextColor(1, 1, 0, 1)
    countText:SetFont(fontFile, 10, "OUTLINE")
    countText:SetText(material.have .. "/" .. material.needed)
    
    -- 根据是否足够显示不同颜色
    if material.have < material.needed then
        countText:SetTextColor(1, 0, 0, 1) -- 红色：不足
        btn.icon:SetVertexColor(1, 1, 1, 1)
    else
        countText:SetTextColor(0, 1, 0, 1) -- 绿色：足够
        btn.icon:SetVertexColor(0.5, 0.5, 0.5, 1) -- 变灰表示不需要购买
    end
    
    btn:SetScript("OnClick", function()
        if material.have < material.needed then
            DoSearchItem(material.name)
        end
    end)
    
    btn:SetScript("OnEnter", function()
        GameTooltip:SetOwner(btn, "ANCHOR_RIGHT")
        if material.itemLink then
            GameTooltip:SetHyperlink(material.itemLink)
        else
            GameTooltip:SetText(material.name)
        end
        GameTooltip:AddLine(" ")
        GameTooltip:AddLine("拥有: " .. material.have, 1, 1, 0)
        GameTooltip:AddLine("需要: " .. material.needed, 1, 0.82, 0)
        if material.have < material.needed then
            GameTooltip:AddLine("点击搜索购买", 0, 1, 0)
        else
            GameTooltip:AddLine("材料充足", 0, 1, 0)
        end
        GameTooltip:Show()
    end)
    
    btn:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)
    
    table.insert(recipeMaterialButtons, btn)
    return btn
end

-- 成品材料复选框（全局变量，用于刷新时保持状态）
local optionalReagentsCheckbox = nil
local onlyMissingCheckbox = nil

-- 创建成品材料复选框
local function CreateOptionalReagentsCheckbox(parent)
    local checkbox = CreateFrame("CheckButton", nil, parent, "UICheckButtonTemplate")
    checkbox:SetSize(20, 20)
    checkbox:SetPoint("TOPLEFT", 8, -5)
    
    -- 设置初始状态
    checkbox:SetChecked(showOptionalReagents)
    
    -- 标签文字
    local label = checkbox:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    label:SetPoint("LEFT", checkbox, "RIGHT", 4, 0)
    label:SetText("显示成品材料")
    label:SetTextColor(1, 0.82, 0, 1)
    
    checkbox:SetScript("OnClick", function(self)
        local isChecked = self:GetChecked()
        SetShowOptionalReagents(isChecked)
        -- 刷新材料列表
        RefreshRecipeMaterials()
    end)
    
    checkbox:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText("显示成品材料")
        GameTooltip:AddLine("勾选后显示用于提升品质的成品材料", 0.8, 0.8, 0.8)
        GameTooltip:Show()
    end)
    
    checkbox:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)
    
    return checkbox
end

-- 创建显示齐备材料复选框
local function CreateShowCompleteCheckbox(parent)
    local checkbox = CreateFrame("CheckButton", nil, parent, "UICheckButtonTemplate")
    checkbox:SetSize(20, 20)
    checkbox:SetPoint("TOPLEFT", 140, -5)
    
    -- 设置初始状态
    checkbox:SetChecked(showCompleteMaterials)
    
    -- 标签文字
    local label = checkbox:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    label:SetPoint("LEFT", checkbox, "RIGHT", 4, 0)
    label:SetText("显示齐备材料")
    label:SetTextColor(1, 0.82, 0, 1)
    
    checkbox:SetScript("OnClick", function(self)
        local isChecked = self:GetChecked()
        SetShowCompleteMaterials(isChecked)
        -- 刷新材料列表
        RefreshRecipeMaterials()
    end)
    
    checkbox:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText("显示齐备材料")
        GameTooltip:AddLine("勾选后显示数量已满足的材料", 0.8, 0.8, 0.8)
        GameTooltip:Show()
    end)
    
    checkbox:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)
    
    return checkbox
end

-- 刷新配方材料显示
function RefreshRecipeMaterials()
    local col = columns[4]
    local content = col.content
    
    -- 清除旧按钮
    for _, btn in ipairs(recipeMaterialButtons) do
        btn:Hide()
        btn:SetParent(nil)
    end
    wipe(recipeMaterialButtons)
    
    -- 清除内容框架的所有子元素
    for _, child in pairs({content:GetChildren()}) do
        child:Hide()
        child:SetParent(nil)
    end
    
    -- 清除所有文字元素（FontString）
    local regions = {content:GetRegions()}
    for _, region in ipairs(regions) do
        if region:GetObjectType() == "FontString" then
            region:Hide()
            region:SetParent(nil)
        end
    end
    
    col.yOffset = -5
    local y = col.yOffset
    
    -- 创建成品材料复选框
    if not optionalReagentsCheckbox then
        optionalReagentsCheckbox = CreateOptionalReagentsCheckbox(content)
    else
        optionalReagentsCheckbox:SetParent(content)
        optionalReagentsCheckbox:Show()
        optionalReagentsCheckbox:SetChecked(showOptionalReagents)
    end
    
    -- 创建显示齐备材料复选框
    if not onlyMissingCheckbox then
        onlyMissingCheckbox = CreateShowCompleteCheckbox(content)
    else
        onlyMissingCheckbox:SetParent(content)
        onlyMissingCheckbox:Show()
        onlyMissingCheckbox:SetChecked(showCompleteMaterials)
    end
    
    y = y - 30 -- 为复选框留出空间
    
    -- 获取追踪的配方
    local trackedRecipes = GetTrackedRecipes()
    
    if #trackedRecipes == 0 then
        -- 显示提示信息
        local tipText = content:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        tipText:SetPoint("TOP", content, "TOP", 0, -50)
        tipText:SetText("暂无追踪的配方\n请在专业界面点击追踪图标")
        tipText:SetTextColor(0.7, 0.7, 0.7, 1)
        col.yOffset = -100
    else
        for _, recipeData in ipairs(trackedRecipes) do
            local recipeID = recipeData.id
            local isRecraft = recipeData.isRecraft
            local recipeInfo = C_TradeSkillUI and C_TradeSkillUI.GetRecipeInfo(recipeID)
            if recipeInfo then
                -- 创建配方标题栏
                local bar = CreateFrame("Frame", nil, content)
                bar:SetSize(COLUMN_WIDTH - 10, 24)
                bar:SetPoint("TOPLEFT", 8, y)
                
                local barBg = bar:CreateTexture(nil, "BACKGROUND")
                barBg:SetAllPoints()
                barBg:SetColorTexture(0.3, 0.5, 0.7, 0.5)
                
                local titleText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
                titleText:SetPoint("CENTER", bar, "CENTER")
                -- 如果是再造配方，在标题后标注
                local displayName = recipeInfo.name or "未知配方"
                if isRecraft then
                    displayName = displayName .. " (再造)"
                end
                titleText:SetText(displayName)
                titleText:SetTextColor(1, 1, 1, 1)
                
                y = y - TITLE_TO_ICONS
                
                -- 获取材料并创建按钮
                local materials = GetRecipeMaterials(recipeID, isRecraft)
                local row = {}
                for i, material in ipairs(materials) do
                    -- 如果没有勾选"显示齐备材料"，则跳过数量满足的材料
                    if not showCompleteMaterials and material.have >= material.needed then
                        -- 跳过数量满足的材料
                    else
                        table.insert(row, material)
                        if #row == ROW_ICONS then
                            for j, m in ipairs(row) do
                                local bx = 8 + (j-1) * (ICON_SIZE + HORIZONTAL_GAP)
                                CreateMaterialButton(content, m, bx, y)
                            end
                            y = y - (ICON_SIZE + VERTICAL_GAP)
                            row = {}
                        end
                    end
                end
                -- 处理剩余的材料
                if #row > 0 then
                    for j, m in ipairs(row) do
                        local bx = 8 + (j-1) * (ICON_SIZE + HORIZONTAL_GAP)
                        CreateMaterialButton(content, m, bx, y)
                    end
                    y = y - (ICON_SIZE + VERTICAL_GAP)
                end
                
                y = y - CATEGORY_SPACING
            end
        end
    end
    
    col.yOffset = y
    local height = math.abs(y) + 30
    content:SetHeight(height)
end

-- ==========================================
-- 拍卖行搜索功能
-- ==========================================
SearchItem = DoSearchItem

-- ==========================================
-- 创建类别标题栏（宽度与按钮区域对齐）
-- ==========================================
local function CreateCategoryBar(parent, title, x, y)
    local bar = CreateFrame("Frame", nil, parent)
    bar:SetSize(COLUMN_WIDTH - 10, 24)          -- 宽度为按钮区域宽度
    bar:SetPoint("TOPLEFT", x, y)
    
    -- 背景色：半透明灰色
    local barBg = bar:CreateTexture(nil, "BACKGROUND")
    barBg:SetAllPoints()
    barBg:SetColorTexture(0.5, 0.5, 0.5, 0.5)
    
    -- 标题文字：加粗，白色
    local titleText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    titleText:SetPoint("CENTER", bar, "CENTER")
    titleText:SetText(title)
    titleText:SetTextColor(1, 1, 1, 1)
    
    return bar
end

-- ==========================================
-- 存储所有按钮的表
-- ==========================================
local allButtons = {}

-- ==========================================
-- 更新按钮状态函数
-- ==========================================
local function UpdateButtonState(btn)
    if not btn or not btn.itemIDs then return end
    
    local totalCount = 0
    local hasAny = false
    
    for _, itemID in ipairs(btn.itemIDs) do
        local count = 0
        if C_Item and C_Item.GetItemCount then
            count = C_Item.GetItemCount(itemID, false, false, false)
        elseif GetItemCount then
            count = GetItemCount(itemID)
        end
        
        if count > 0 then
            hasAny = true
            totalCount = totalCount + count
        end
    end
    
    if hasAny then
        btn.icon:SetVertexColor(1, 1, 1, 1)
        btn.countText:SetText(totalCount)
        btn.countText:Show()
    else
        btn.icon:SetVertexColor(0.5, 0.5, 0.5, 1)
        btn.countText:Hide()
    end
end

local function RefreshAllButtons()
    for _, btn in ipairs(allButtons) do
        UpdateButtonState(btn)
    end
end

-- ==========================================
-- 创建单个图标按钮（文字间距为4）
-- ==========================================
local function CreateIconButton(parent, btnData, x, y)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(ICON_SIZE, ICON_SIZE)
    btn:SetPoint("TOPLEFT", x, y)
    
    if type(btnData.id) == "table" then
        btn.itemIDs = btnData.id
    elseif btnData.id then
        btn.itemIDs = {btnData.id}
    else
        btn.itemIDs = {}
    end
    
    btn.searchName = btnData.search

    local iconPath = "Interface\\Icons\\INV_Misc_QuestionMark"
    for _, id in ipairs(btn.itemIDs) do
        if id then
            local path = GetItemIcon(id)
            if path then
                iconPath = path
                break
            end
        end
    end

    local tex = btn:CreateTexture(nil, "ARTWORK")
    tex:SetAllPoints()
    tex:SetTexture(iconPath)
    tex:SetTexCoord(0.07, 0.93, 0.07, 0.93)
    btn.icon = tex

    -- 图标下方文字标签，间距 TEXT_GAP = 4
    local label = btn:CreateFontString(nil, "OVERLAY")
    local fontFile, _, fontFlags = GameFontNormal:GetFont()
    label:SetFont(fontFile, 13, fontFlags)
    label:SetPoint("TOP", btn, "BOTTOM", 0, TEXT_GAP)
    label:SetText(btnData.label)
    label:SetTextColor(1, 1, 1, 1)

    -- 右下角数量显示（字号11）
    local countText = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    countText:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -2, 2)
    countText:SetTextColor(1, 1, 0, 1)
    countText:SetFont(fontFile, 11, "OUTLINE")
    countText:Hide()
    btn.countText = countText

    btn:SetScript("OnClick", function() SearchItem(btnData.search) end)
    
    btn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(btnData.search)

        --[[if #btn.itemIDs > 1 then
            local itemsWithCount = {}
            for _, id in ipairs(btn.itemIDs) do
                local count = 0
                if C_Item and C_Item.GetItemCount then
                    count = C_Item.GetItemCount(id, false, false, false)
                elseif GetItemCount then
                    count = GetItemCount(id)
                end

                if count > 0 then
                    local itemName = C_Item and C_Item.GetItemInfo and select(1, C_Item.GetItemInfo(id)) or ("物品"..id)
                    table.insert(itemsWithCount, {name=itemName, count=count})
                end
            end

            if #itemsWithCount > 0 then
                GameTooltip:AddLine(" ")
                for _, item in ipairs(itemsWithCount) do
                    GameTooltip:AddDoubleLine(item.name, item.count, 0.8, 0.8, 0.8, 1, 1, 0)
                end
            end
        end]]
                    if #self.itemIDs > 1 then
                local rows = {}
                for _, id in ipairs(self.itemIDs) do
                    local c = GetItemCountSafe(id)
                    if c > 0 then
                        table.insert(rows, {
                            name    = GetItemNameSafe(id, true),
                            count   = c,
                            quality = GetItemQualitySafe(id),
                            ilvl    = GetItemLevelSafe(id),
                        })
                    end
                end
                if #rows > 0 then
                    GameTooltip:AddLine(" ")
                    local bestIdx = 1
                    if #rows > 1 then
                        for i = 2, #rows do
                            if rows[i].quality > rows[bestIdx].quality then
                                bestIdx = i
                            elseif rows[i].quality == rows[bestIdx].quality
                                and rows[i].ilvl > rows[bestIdx].ilvl then
                                bestIdx = i
                            end
                        end
                    end
                    for i, r in ipairs(rows) do
                        local cr, cg, cb
                        if #rows == 1 then
                            if r.quality >= 3 then
                                cr, cg, cb = unpack(COLOR_TIP_COUNT_HIGH)
                            else
                                cr, cg, cb = unpack(COLOR_TIP_COUNT_LOW)
                            end
                        else
                            if i == bestIdx then
                                cr, cg, cb = unpack(COLOR_TIP_COUNT_HIGH)
                            else
                                cr, cg, cb = unpack(COLOR_TIP_COUNT_LOW)
                            end
                        end
                        GameTooltip:AddDoubleLine(r.name, tostring(r.count), cr, cg, cb, cr, cg, cb)
                    end
                end
            end
        GameTooltip:Show()
    end)
    btn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    table.insert(allButtons, btn)
    UpdateButtonState(btn)

    return btn
end

-- ==========================================
-- 添加一个完整类别（标题栏起始X为8）
-- ==========================================
local function AddCategory(columnIdx, title, buttons)
    local col = columns[columnIdx]
    local content = col.content
    local x = 8                                    -- 标题栏起始X与按钮区域对齐
    local y = col.yOffset
    
    -- 创建标题栏
    local cat = CreateCategoryBar(content, title, x, y)
    y = y - TITLE_TO_ICONS
    
    -- 按钮区域起始X与标题栏相同
    local buttonStartX = x
    local row = {}
    for i, btnData in ipairs(buttons) do
        table.insert(row, btnData)
        if #row == ROW_ICONS or i == #buttons then
            for j, b in ipairs(row) do
                local bx = buttonStartX + (j-1) * (ICON_SIZE + HORIZONTAL_GAP)
                CreateIconButton(content, b, bx, y)
            end
            y = y - (ICON_SIZE + VERTICAL_GAP)
            row = {}
        end
    end
    
    y = y - CATEGORY_SPACING
    col.yOffset = y
    
    local height = math.abs(y) + 30
    content:SetHeight(height)
end

-- ==========================================
-- 第一列：消耗与附魔
-- ==========================================
AddCategory(1, "药水", {
    {label="红药", search="银月城生命药水", id={241304, 241305}},
    {label="蓝药", search="光注法力药水", id={241300, 241301}},
    {label="双回", search="复苏血清", id={241306, 241307}},
    {label="护盾", search="圣光之护", id={241286, 241287}},
    {label="隐身", search="虚空遮蔽酊剂", id={241302, 241303}},
    {label="主属性", search="圣光潜力", id={241308, 241309}},
    {label="主狂", search="狂放恣意饮剂", id={241292, 241293}},
    {label="绿字", search="鲁莽药水", id={241288, 241289}},
    {label="单体", search="狂热药水", id={241296, 241297}},
    {label="生命", search="阿曼尼提取物", id=241299},
    {label="法力", search="吞噬之梦药水", id={241294, 241295}},
    {label="缓落", search="启迪药水", id={241338, 241339}},
})

AddCategory(1, "合剂", {
    {label="暴击", search="破碎残阳合剂", id={241326, 241327}},
    {label="急速", search="血骑士合剂", id={241324, 241325}},
    {label="全能", search="萨拉斯抗性合剂", id={241320, 241321}},
    {label="精通", search="魔导师合剂", id={241322, 241323}},
})

AddCategory(1, "武器加强", {
    {label="平衡石", search="辉耀平衡石", id={237367, 237369}},
    {label="磨刀石", search="辉耀磨刀石", id={237370, 237371}},
    {label="绿字", search="萨拉斯凤凰之油", id={243734, 243733}},
    {label="治疗", search="黎明之油", id={243735, 243736}},
    {label="奥术", search="私运者的附魔之锋", id={243737, 243738}},
})

AddCategory(1, "食物/符文", {
    {label="主属性", search="异乎寻常的皇家烤肉", id=255847},
    {label="副属性", search="勇士便当", id=242274},
    {label="符文", search="虚触强化符文", id=259085},
    {label="主大餐", search="银月城浮华大餐", id={255845, 255846}},
    {label="副大餐", search="盛放筵席", id={242272, 242273}},
    {label="团本", search="凡图斯符文：光耀", id={245879, 245880}},
    {label="气泡酒", search="逐春者气泡酒", id=260260},
    --{label="蓟茶", search="血艳蓟茶", id=242299},
    {label="主属", search="皇家烤肉", id=242275},
    {label="副属", search="植物狂宴", id=255848},
    {label="急速", search="赤红炸鱿鱼", id=242277},
    {label="急速", search="邪吻肉柳", id=242286},
    {label="爆击", search="美味熏脂鲤", id=242278},
    {label="爆击", search="阳灼光鳍鱼", id=242283},
    {label="爆击", search="奥能肉饼", id=242287},
    {label="全能", search="红烧鲜血猎手", id=242276},
    {label="全能", search="黄油根须蟹", id=242280},
    {label="全能", search="虚吻鱼肉卷", id=242284},
    {label="精通", search="闪光烤串", id=242281},
    {label="精通", search="迁跃睿心鱼翅", id=242285},
    --{label="精全", search="油炸绽尾鱼", id=242291},
    {label="副属性", search="太阳之井特餐", id=242293},
    {label="加速", search="血艳蓟茶", id=242299},
    {label="加速", search="白银叶茶", id=242298},
    {label="肉柳", search="魔焰肉柳", id=242289},
})

AddCategory(1, "其他", {
    {label="嗜血", search="掣雷之鼓", id={219905}},
    {label="战复", search="应急灵魂链接", id={248486, 269586}},
    {label="修理", search="自动铁锤", id=132514},
    {label="开锁", search="萨拉斯万能钥匙", id=260232},
    {label="银月", search="合约：银月宫廷", id={245799, 245800}},
    {label="奇点", search="合约：奇点特勤", id={245793, 245794}},
    {label="哈籁提", search="合约：哈籁提", id={245795, 245796}},
    {label="阿曼尼", search="合约：阿曼尼部族", id={245797, 245798}},
})

-- ==========================================
-- 第二列：装备附魔
-- ==========================================
AddCategory(2, "附魔:武器", {
    {label="主属性", search="附魔武器 - 朗多雷之锐", id={244028, 244029}},
    {label="暴击", search="附魔武器 - 加亚莱的精准", id={243970, 243971}},
    {label="急速", search="附魔武器 - 狂战士之怒", id={243972, 243973}},
    {label="精通", search="附魔武器 - 奥术精通", id={244030, 244031}},
    {label="全能", search="附魔武器 - 世界之魂的坚韧", id={244000, 244001}},
    {label="护盾", search="附魔武器 - 世界之魂的庇护", id={243998, 243999}},
    {label="治疗", search="附魔武器 - 世界之魂的摇篮", id={243996, 243997}},
    {label="流血", search="附魔武器 - 哈尔拉兹之力", id={243968, 243969}},
    {label="AOE", search="附魔武器 - 辛多雷之焰", id={244026, 244027}},
    {label="火焰", search="附魔武器 - 辛多雷之焰", id={244026, 244027}},
    {label="鹰眼", search="附魔武器 - 辛多雷之焰", id={257745, 257746}},
    {label="猫眼", search="附魔武器 - 辛多雷之焰", id={257747, 257748}},
    {label="毒弹", search="附魔武器 - 辛多雷之焰", id={257749, 257750}},
    {label="轰弹", search="附魔武器 - 辛多雷之焰", id={257751, 257752}},
})

AddCategory(2, "附魔:头盔", {
    {label="吸血", search="附魔头盔 - 强化吸血妖术", id={243950, 243951}},
    {label="闪避", search="附魔头盔 - 强化闪避符文", id={244006, 244007}},
    {label="加速", search="附魔头盔 - 强化加速祝福", id={243980, 243981}},
    {label="加速", search="附魔头盔 - 加速祝福", id={243978, 243979}},
    {label="吸血", search="附魔头盔 - 吸血妖术", id={243948, 243949}},
    {label="闪避", search="附魔头盔 - 闪避符文", id={244004, 244005}},
})

AddCategory(2, "附魔:胸甲", {
    {label="主属性", search="附魔胸甲 - 世界之魂印记", id={243976, 243977}},
    {label="敏捷", search="附魔胸甲 - 护根者印记", id={243974, 243975}},
    {label="力耐", search="附魔胸甲 - 纳洛拉克印记", id={243946, 243947}},
    {label="智法", search="附魔胸甲 - 魔导师印记", id={244002, 244003}},
})

AddCategory(2, "附魔:护肩", {
    {label="吸血", search="附魔护肩 - 银月城治愈", id={244020, 244021}},
    {label="闪避", search="附魔护肩 - 阿梅达希尔之赐", id={243990, 243991}},
    {label="加速", search="附魔护肩 - 埃基尔松的迅捷", id={243962, 243963}},
    {label="加速", search="附魔护肩 - 鹰翔长空", id={243960, 243961}},
    {label="吸血", search="附魔护肩 - 萨拉斯复原", id={244018, 244019}},
    {label="闪避", search="附魔护肩 - 自然的优雅", id={243988, 243989}},
})

AddCategory(2, "附魔:腿部", {
    {label="力敏耐", search="森林猎手的护甲片", id={244640, 244641}},
    {label="力敏甲", search="血骑士的护甲片", id={244642, 244643}},
    {label="智法", search="奥纹魔线", id={240154, 240155}},
    {label="护甲片", search="萨拉斯斥候护甲片", id={244644, 244645}},
    {label="智力", search="阳炎丝绸魔线", id={240094, 240095}},
    {label="智力", search="光明亚麻魔线", id={240156, 240157}},
})

AddCategory(2, "附魔:鞋子", {
    {label="加速", search="附魔靴子 - 远行者的狩猎", id={244008, 244009}},
    {label="吸血", search="附魔靴子 - 莎拉达希尔之根", id={243982, 243983}},
    {label="闪避", search="附魔靴子 - 山猫之敏", id={243952, 243953}},
})

AddCategory(2, "附魔:戒指", {
    {label="暴击", search="附魔戒指 - 自然之怒", id={243986, 243987}},
    {label="急速", search="附魔戒指 - 银月城之捷", id={244014, 244015}},
    {label="精通", search="附魔戒指 - 祖尔金的精通", id={243958, 243959}},
    {label="全能", search="附魔戒指 - 银月城之韧", id={244016, 244017}},
    {label="暴伤", search="附魔戒指 - 鹰眼神视", id={243956, 243957}},
    {label="爆击", search="附魔戒指 - 自然之愤", id={243984, 243985}},
    {label="精通", search="附魔戒指 - 阿曼尼精通", id={243954, 243955}},
    {label="急速", search="附魔戒指 - 萨拉斯急速", id={244010, 244011}},
    {label="全能", search="附魔戒指 - 萨拉斯全能", id={244012, 244013}},
})

AddCategory(2, "附魔-工具", {
    {label="奇思", search="附魔工具 - 朗多雷奇思", id={244024, 244025}},
    {label="充裕", search="附魔工具 - 阿曼尼充裕", id={243966, 243967}},
    {label="产能", search="附魔工具 - 哈籁尼尔产能", id={243994, 243995}},
    {label="感知", search="附魔工具 - 阿曼尼感知", id={243964, 243965}},
    {label="熟练", search="附魔工具 - 辛多雷熟练", id={244022, 244023}},
    {label="精细", search="附魔工具 - 哈籁尼尔精细", id={243992, 243993}},
})

-- ==========================================
-- 第三列：公函与宝石
-- ==========================================
AddCategory(3, "萨拉斯公函", {
    {label="全 急", search="曙光之萨拉斯公函", id={245781, 245782}},
    {label="急 精", search="灼光之萨拉斯公函", id={245783, 245784}},
    {label="急 暴", search="燎火之萨拉斯公函", id={245785, 245786}},
    {label="暴 精", search="无双之萨拉斯公函", id={245789, 245790}},
    {label="暴 全", search="快刀之萨拉斯公函", id={245791, 245792}},
    {label="全 精", search="谐律之萨拉斯公函", id={245787, 245788}},
})

AddCategory(3, "公函-专业工具", {
    {label="速度", search="制作速度之萨拉斯公函", id={245820, 245821}},
    {label="产能", search="产能之萨拉斯公函", id={245818, 245819}},
    {label="奇思", search="奇思之萨拉斯公函", id={245814, 245815}},
    {label="熟练", search="熟练之萨拉斯公函", id={245826, 245827}},
    {label="充裕", search="充裕之萨拉斯公函", id={245816, 245817}},
    {label="感知", search="感知之萨拉斯公函", id={245824, 245825}},
    {label="精细", search="精细之萨拉斯公函", id={245822, 245823}},
})

AddCategory(3, "美化材料", {
    {label="穿山甲", search="圣佑穿山甲护符", id={244603, 244604}},
    {label="孢子", search="原始孢子缚带", id={244607, 244608}},
    {label="吞噬", search="吞噬绑带", id={244674, 244675}},
    {label="奥纹", search="奥纹内衬", id={240166, 240167}},
    {label="阳炎", search="阳炎丝绸内衬", id={240164, 240165}},
    {label="鲜血", search="暗月徽记：鲜血", id={245871, 245872}},
    {label="狩猎", search="暗月徽记：狩猎", id={245875, 245876}},
    {label="腐烂", search="暗月徽记：腐烂", id={245877, 245878}},
    {label="虚空", search="暗月徽记：虚空", id={245873, 245874}},
    {label="幸运", search="幸运钥匙串", id=248130},
})

AddCategory(3, "永歌钻石", {
    {label="主属性", search="费解之永歌钻石", id={240982, 240983}},
    {label="暴伤", search="强能之永歌钻石", id={240966, 240967}},
    {label="法力", search="御土之永歌钻石", id={240968, 240969}},
    {label="护甲", search="坚韧之永歌钻石", id={240970, 240971}},
})

AddCategory(3, "血石", {
    {label="决心", search="决心鸡血石", id=241142},
    {label="感知", search="感知鸡血石", id=241143},
    {label="坚韧", search="坚韧鸡血石", id=241144},
})
                
AddCategory(3, "急速/全能宝石", {
    {label="全能", search="无瑕万能榄石", id={240893, 240894}},
    {label="精通", search="无瑕精湛榄石", id={240891, 240892}},
    {label="暴击", search="无瑕致命榄石", id={240889, 240890}},
    {label="急速", search="无瑕迅捷青金石", id={240915, 240916}},
    {label="暴击", search="无瑕致命青金石", id={240913, 240914}},
    {label="精通", search="无瑕精湛青金石", id={240917, 240918}},
})

AddCategory(3, "暴击/精通宝石", {
    {label="急速", search="无瑕迅捷榴石", id={240905, 240906}},
    {label="全能", search="无瑕万能榴石", id={240909, 240910}},
    {label="精通", search="无瑕精湛榴石", id={240907, 240908}},
    {label="急速", search="无瑕迅捷紫晶", id={240899, 240900}},
    {label="暴击", search="无瑕致命紫晶", id={240897, 240898}},
    {label="全能", search="无瑕万能紫晶", id={240901, 240902}},
})

AddCategory(3, "宝石", {
    {label="爆击", search="无瑕致命榴石", id={240903,240904}},
    {label="精通", search="无瑕精湛紫晶", id={240895,240896}},
    {label="急速", search="无瑕迅捷榄石", id={240887,240888}},
    {label="全能", search="无瑕万能青金石", id={240911,240912}},
--})
--AddCategory(3, "初级宝石", {
    {label="爆击", search="致命榴石", id={240871,240872}},
    {label="爆精", search="精湛榴石", id={240875,240876}},
    {label="爆急", search="迅捷榴石", id={240873,240874}},
    {label="爆全", search="万能榴石", id={240877,240878}},
    {label="精通", search="精湛紫晶", id={240863,240864}},
    {label="精爆", search="致命紫晶", id={240865,240866}},
    {label="精急", search="迅捷紫晶", id={240867,240868}},
    {label="精全", search="万能紫晶", id={240869,240870}},
    {label="急速", search="迅捷榄石", id={240855,240856}},
    {label="急爆", search="致命榄石", id={240857,240858}},
    {label="急精", search="精湛榄石", id={240859,240860}},
    {label="急全", search="万能榄石", id={240861,240862}},
    {label="全能", search="万能青金石", id={240879,240880}},
    {label="全爆", search="致命青金石", id={240881,240882}},
    {label="全精", search="精湛青金石", id={240885,240886}},
    {label="全急", search="迅捷青金石", id={240883,240884}},
})

AddCategory(3, "工程齿轮", {
    {label="暴击", search="通量齿轮", id={244697, 244698}},
    {label="急速", search="滑油齿轮", id={244699, 244700}},
    {label="全能", search="吻合齿轮", id={244703, 244704}},
    {label="精通", search="完美齿轮", id={244701, 244702}},
})
-- ==========================================
-- 事件监听
-- ==========================================
frame:RegisterEvent("AUCTION_HOUSE_SHOW")
frame:RegisterEvent("AUCTION_HOUSE_CLOSED")
frame:RegisterEvent("BAG_UPDATE")
frame:RegisterEvent("PLAYER_LOGIN")

frame:SetScript("OnEvent", function(self, event, ...)
    if event == "AUCTION_HOUSE_SHOW" then
        local ah = AuctionHouseFrame or AuctionFrame
        if ah then
            self:ClearAllPoints()
            self:SetPoint("TOPLEFT", ah, "TOPRIGHT", 5, 0)
            minimizeIcon:ClearAllPoints()
            minimizeIcon:SetPoint("TOPLEFT", ah, "TOPRIGHT", 5, 0)
            
            if isMinimized then
                minimizeIcon:Show()
                self:Hide()
            else
                self:Show()
                minimizeIcon:Hide()
            end
            
            -- 高度完全跟随拍卖行，限制最大高度为屏幕高度的90%
            local ahHeight = ah:GetHeight()
            if ahHeight and ahHeight > 100 then
                local maxHeight = GetScreenHeight() * 0.9
                self:SetHeight(math.min(ahHeight, maxHeight))
            else
                self:SetHeight(580)
            end
            
            RefreshAllButtons()
            -- 刷新配方材料列表
            RefreshRecipeMaterials()
        end
    elseif event == "AUCTION_HOUSE_CLOSED" then
        self:Hide()
        minimizeIcon:Hide()
    elseif event == "BAG_UPDATE" then
        RefreshAllButtons()
    elseif event == "PLAYER_LOGIN" then
        RefreshAllButtons()
    end
end)

-- ==========================================
-- 实时更新器（无打印）
-- ==========================================
local updater = CreateFrame("Frame")
updater:SetScript("OnUpdate", function(self, elapsed)
    self.elapsed = (self.elapsed or 0) + elapsed
    if self.elapsed > 1.0 then
        self.elapsed = 0
        local ah = AuctionHouseFrame or AuctionFrame
        if ah and ah:IsShown() then
            if not frame:IsShown() and not minimizeIcon:IsShown() then
                if isMinimized then
                    minimizeIcon:Show()
                else
                    frame:Show()
                end
                frame:ClearAllPoints()
                frame:SetPoint("TOPLEFT", ah, "TOPRIGHT", 5, 0)
                minimizeIcon:ClearAllPoints()
                minimizeIcon:SetPoint("TOPLEFT", ah, "TOPRIGHT", 5, 0)
            end
        else
            if frame:IsShown() then
                frame:Hide()
            end
            if minimizeIcon:IsShown() then
                minimizeIcon:Hide()
            end
        end
    end
end)

-- ==========================================
-- 手动命令（仅保留 debug 输出）
-- ==========================================
SLASH_QUICKAUCTION1 = "/qa"
SlashCmdList["QUICKAUCTION"] = function(msg)
    if msg == "show" then
        isMinimized = false
        minimizeIcon:Hide()
        frame:Show()
    elseif msg == "hide" then
        frame:Hide()
    elseif msg == "debug" then
        local ah = AuctionHouseFrame or AuctionFrame
        print("|cffffff00[购物助手调试信息]|r")
        print("窗口宽度: " .. WINDOW_WIDTH)
        print("列宽: " .. COLUMN_WIDTH)
        print("图标大小: " .. ICON_SIZE)
        print("拍卖行可见: " .. tostring(ah and ah:IsShown()))
        print("窗口可见: " .. tostring(frame:IsShown()))
        print("最小化图标可见: " .. tostring(minimizeIcon:IsShown()))
    else
        print("购物助手 - 命令列表")
        print("  /qa show          - 显示窗口")
        print("  /qa hide          - 隐藏窗口")
        print("  /qa debug         - 显示调试信息")
    end
end