--[[
    点数资源显示模块
    支持职业：盗贼、德鲁伊(猫)、圣骑士、术士、武僧、法师(奥术充能/冰刺)、唤魔师、死亡骑士、萨满(增强-漩涡武器)、猎人(生存-利矛之刃)
    拖动方式：按住 Ctrl + 左键拖动
]]

local moduleName = "ComboPoints"
local frame = nil
local text = nil
local hitText = nil
local animIn = nil
local animOut = nil
local lastPoints = 0
local isInitialized = false
local isDragging = false

-- 职业资源配置
local POWER_INDEX = nil
local RESOURCE_NAME = nil
local EVENT_NAME = nil
local POWER_TYPE = "none"

-- Buff ID 配置
local ICE_SHARD_BUFF_ID = 205473          -- 冰刺
local MAELSTROM_WEAPON_BUFF_ID = 344179   -- 漩涡武器
local OVERFLOWING_MAELSTROM_SPELL_ID = 384143  -- 溢流漩涡（使漩涡武器变为10层）
local TIP_OF_THE_SPEAR_BUFF_ID = 260286   -- 利矛之刃 (Tip of the Spear)

-- 固定字体路径
local FONT_PATH = "Interface\\Addons\\OrzUI\\Media\\Fonts\\Edo.ttf"

-- 配置保存
local defaults = {
    enabled = true,
    fontSize = 72,
    fontStyle = "OUTLINE",
    textX = 300,
    textY = 0,
    textOpacity = 1.0,
    animationDuration = 0.2,
    useShadow = true,
    showStar = true,
    useClassSuffix = false,
}

local function InitDB()
    if not ComboPointsDB then
        ComboPointsDB = {}
    end
    if not ComboPointsDB[moduleName] then
        ComboPointsDB[moduleName] = {}
    end
    
    local db = ComboPointsDB[moduleName]
    for k, v in pairs(defaults) do
        if db[k] == nil then
            db[k] = v
        end
    end
end

-- 根据职业设置资源索引和事件名称
local function SetupPowerType()
    local _, class = UnitClass("player")
    
    if class == "ROGUE" or class == "DRUID" then
        POWER_INDEX = 4
        EVENT_NAME = "COMBO_POINTS"
        RESOURCE_NAME = "连击点"
        POWER_TYPE = "normal"
    elseif class == "HUNTER" then
        -- 先检测利矛之刃 Buff 是否存在（兜底）
        local auraData = C_UnitAuras.GetPlayerAuraBySpellID(TIP_OF_THE_SPEAR_BUFF_ID)
        if auraData then
            POWER_INDEX = nil
            EVENT_NAME = "UNIT_AURA"
            RESOURCE_NAME = "利矛之刃"
            POWER_TYPE = "tip_of_the_spear"
        else
            -- 如果当前没有 Buff，再检测专精
            local spec = GetSpecialization()
            if spec then
                local specId, specName = GetSpecializationInfo(spec)
                if specName and string.find(specName, "生存") then
                    POWER_INDEX = nil
                    EVENT_NAME = "UNIT_AURA"
                    RESOURCE_NAME = "利矛之刃"
                    POWER_TYPE = "tip_of_the_spear"
                else
                    POWER_INDEX = nil
                    EVENT_NAME = nil
                    RESOURCE_NAME = nil
                    POWER_TYPE = "none"
                end
            else
                POWER_INDEX = nil
                EVENT_NAME = nil
                RESOURCE_NAME = nil
                POWER_TYPE = "none"
            end
        end
    elseif class == "PALADIN" then
        POWER_INDEX = 9
        EVENT_NAME = "HOLY_POWER"
        RESOURCE_NAME = "神圣能量"
        POWER_TYPE = "normal"
    elseif class == "WARLOCK" then
        POWER_INDEX = 7
        EVENT_NAME = "SOUL_SHARDS"
        RESOURCE_NAME = "灵魂碎片"
        POWER_TYPE = "normal"
    elseif class == "MONK" then
        POWER_INDEX = 12
        EVENT_NAME = "CHI"
        RESOURCE_NAME = "真气"
        POWER_TYPE = "normal"
    elseif class == "MAGE" then
        local spec = GetSpecialization()
        if spec then
            local specId, specName = GetSpecializationInfo(spec)
            if specName and string.find(specName, "冰霜") then
                POWER_INDEX = nil
                EVENT_NAME = "UNIT_AURA"
                RESOURCE_NAME = "冰刺"
                POWER_TYPE = "ice_shards"
            elseif specName and string.find(specName, "奥术") then
                POWER_INDEX = 16
                EVENT_NAME = "ARCANE_CHARGES"
                RESOURCE_NAME = "奥术充能"
                POWER_TYPE = "normal"
            else
                POWER_INDEX = nil
                EVENT_NAME = nil
                RESOURCE_NAME = nil
                POWER_TYPE = "none"
            end
        else
            POWER_INDEX = nil
            EVENT_NAME = nil
            RESOURCE_NAME = nil
            POWER_TYPE = "none"
        end
    elseif class == "SHAMAN" then
        -- 通过检测漩涡武器 Buff 是否存在来判断是否为增强萨满
        local auraData = C_UnitAuras.GetPlayerAuraBySpellID(MAELSTROM_WEAPON_BUFF_ID)
        if auraData then
            POWER_INDEX = nil
            EVENT_NAME = "UNIT_AURA"
            RESOURCE_NAME = "漩涡武器"
            POWER_TYPE = "maelstrom_weapon"
        else
            -- 如果当前没有漩涡武器 Buff，再检测专精
            local spec = GetSpecialization()
            if spec then
                local specId, specName = GetSpecializationInfo(spec)
                if specName and string.find(specName, "增强") then
                    POWER_INDEX = nil
                    EVENT_NAME = "UNIT_AURA"
                    RESOURCE_NAME = "漩涡武器"
                    POWER_TYPE = "maelstrom_weapon"
                else
                    POWER_INDEX = nil
                    EVENT_NAME = nil
                    RESOURCE_NAME = nil
                    POWER_TYPE = "none"
                end
            else
                POWER_INDEX = nil
                EVENT_NAME = nil
                RESOURCE_NAME = nil
                POWER_TYPE = "none"
            end
        end
    elseif class == "EVOKER" then
        POWER_INDEX = 19
        EVENT_NAME = "ESSENCE"
        RESOURCE_NAME = "精华"
        POWER_TYPE = "normal"
    elseif class == "DEATHKNIGHT" then
        POWER_INDEX = nil
        EVENT_NAME = nil
        RESOURCE_NAME = "符文"
        POWER_TYPE = "rune"
    else
        POWER_INDEX = nil
        EVENT_NAME = nil
        RESOURCE_NAME = nil
        POWER_TYPE = "none"
    end
end

-- ==================== 获取冰刺层数 ====================
local function GetIceShardStacks()
    local auraData = C_UnitAuras.GetPlayerAuraBySpellID(ICE_SHARD_BUFF_ID)
    if auraData then
        return auraData.applications or 0
    end
    return 0
end

-- ==================== 获取漩涡武器层数 ====================
local function GetMaelstromWeaponStacks()
    local auraData = C_UnitAuras.GetPlayerAuraBySpellID(MAELSTROM_WEAPON_BUFF_ID)
    if auraData then
        return auraData.applications or 0
    end
    return 0
end

-- ==================== 获取漩涡武器最大层数 ====================
local function GetMaelstromWeaponMaxStacks()
    -- 检测是否学习了"溢流漩涡"技能（使漩涡武器最大层数变为10层）
    if IsSpellKnown(OVERFLOWING_MAELSTROM_SPELL_ID) then
        return 10
    end
    return 5
end

-- ==================== 获取利矛之刃层数 ====================
local function GetTipOfTheSpearStacks()
    local auraData = C_UnitAuras.GetPlayerAuraBySpellID(TIP_OF_THE_SPEAR_BUFF_ID)
    if auraData then
        return auraData.applications or 0
    end
    return 0
end

-- ==================== 获取最大点数 ====================
local function GetMaxPoints()
    if POWER_TYPE == "rune" then
        return 6
    end
    
    -- Buff 类资源
    if POWER_TYPE == "ice_shards" then
        return 5
    end
    if POWER_TYPE == "maelstrom_weapon" then
        return GetMaelstromWeaponMaxStacks()
    end
    if POWER_TYPE == "tip_of_the_spear" then
        return 3
    end
    
    -- 普通资源类型
    if not POWER_INDEX then
        return 0
    end
    
    local maxPower = UnitPowerMax("player", POWER_INDEX)
    if maxPower and maxPower > 0 then
        if POWER_INDEX == 4 then
            return math.min(maxPower, 7)
        end
        return maxPower
    end
    return 0
end

-- ==================== 获取当前点数 ====================
local function GetCurrentPoints()
    if POWER_TYPE == "rune" then
        local count = 0
        for i = 1, 6 do
            local _, _, runeReady = GetRuneCooldown(i)
            if runeReady then
                count = count + 1
            end
        end
        return count
    elseif POWER_TYPE == "ice_shards" then
        return GetIceShardStacks()
    elseif POWER_TYPE == "maelstrom_weapon" then
        return GetMaelstromWeaponStacks()
    elseif POWER_TYPE == "tip_of_the_spear" then
        return GetTipOfTheSpearStacks()
    end
    
    if not POWER_INDEX then
        return 0
    end
    local current = UnitPower("player", POWER_INDEX)
    if current and current > 0 then
        return current
    end
    return 0
end

local function ShouldShow()
    -- 所有资源统一：需要目标或在战斗中才显示
    if not UnitAffectingCombat("player") and not UnitExists("target") then
        return false
    end
    
    -- Buff 类资源：有 Buff 才显示（由 GetCurrentPoints 判断层数 > 0）
    if POWER_TYPE == "ice_shards" or POWER_TYPE == "maelstrom_weapon" or POWER_TYPE == "tip_of_the_spear" then
        return true
    end
    
    -- 其他资源：直接显示
    return true
end

-- ==================== 字体设置 ====================
local function UpdateFontStyle()
    local db = ComboPointsDB[moduleName]
    if not text then return end
    
    text:SetFont(FONT_PATH, db.fontSize, db.fontStyle)
    
    if hitText then
        hitText:SetFont(FONT_PATH, db.fontSize * 0.35, db.fontStyle)
    end
    
    if db.useShadow then
        text:SetShadowOffset(2, -2)
        text:SetShadowColor(0, 0, 0, 0.8)
        if hitText then
            hitText:SetShadowOffset(2, -2)
            hitText:SetShadowColor(0, 0, 0, 0.8)
        end
    else
        text:SetShadowOffset(0, 0)
        if hitText then
            hitText:SetShadowOffset(0, 0)
        end
    end
end

-- ==================== 显示逻辑 ====================
local function UpdateDisplayLayout()
    if not frame or not text then return end
    
    local db = ComboPointsDB[moduleName]
    if not db.enabled or POWER_TYPE == "none" then
        if frame then frame:Hide() end
        return
    end
    
    UpdateFontStyle()
    
    frame:ClearAllPoints()
    frame:SetPoint("CENTER", UIParent, "CENTER", db.textX, db.textY)
    frame:SetSize(db.fontSize * 1, db.fontSize * 1)
end

local function ShowPoints(points, isInstant)
    local db = ComboPointsDB[moduleName]
    
    if not db.enabled or points <= 0 or POWER_TYPE == "none" then
        if frame then frame:Hide() end
        return
    end
    
    if not ShouldShow() then
        if frame then frame:Hide() end
        return
    end
    
    local maxPoints = GetMaxPoints()
    local r, g, b
    
    if points >= maxPoints then
        r, g, b = 1.0, 0.0, 0.0
    elseif points >= maxPoints - 1 then
        r, g, b = 1.0, 0.65, 0.0
    else
        r, g, b = 1.0, 0.82, 0.0
    end
    
    text:SetText(points)
    text:SetTextColor(r, g, b, db.textOpacity)
    text:SetAlpha(db.textOpacity)
    
    if db.showStar then
        local suffix = ""
        if db.useClassSuffix then
            if POWER_TYPE == "rune" then
                suffix = "Rune"
            elseif POWER_TYPE == "ice_shards" then
                suffix = "Ice"
            elseif POWER_TYPE == "maelstrom_weapon" then
                suffix = "MW"
            elseif POWER_TYPE == "tip_of_the_spear" then
                suffix = "TOTS"
            elseif POWER_INDEX == 4 then
                suffix = "CP"
            elseif POWER_INDEX == 9 then
                suffix = "HP"
            elseif POWER_INDEX == 7 then
                suffix = "SS"
            elseif POWER_INDEX == 12 then
                suffix = "Chi"
            elseif POWER_INDEX == 16 then
                suffix = "AC"
            elseif POWER_INDEX == 19 then
                suffix = "Ess"
            else
                suffix = "Hit"
            end
        else
            suffix = "Hit"
        end
        hitText:SetText(suffix)
        hitText:SetTextColor(r, g, b, db.textOpacity)
        hitText:Show()
    else
        hitText:Hide()
    end
    
    frame:Show()
    frame:SetAlpha(1)
    
    if isInstant then
        frame:SetAlpha(1)
        text:SetAlpha(db.textOpacity)
        hitText:SetAlpha(db.textOpacity)
    else
        if animOut and animOut:IsPlaying() then
            animOut:Stop()
        end
        if animIn then
            animIn:Stop()
            animIn:Play()
        else
            frame:SetAlpha(1)
            text:SetAlpha(db.textOpacity)
            hitText:SetAlpha(db.textOpacity)
        end
    end
end

local function HidePoints()
    if not frame then return end
    if animOut and not animOut:IsPlaying() then
        animOut:Play()
    end
end

-- ==================== 动画系统 ====================
local function CreateAnimations()
    local db = ComboPointsDB[moduleName]
    
    if animIn then
        animIn:Finish()
    end
    
    animIn = frame:CreateAnimationGroup()
    local fadeIn = animIn:CreateAnimation("Alpha")
    fadeIn:SetFromAlpha(0)
    fadeIn:SetToAlpha(1)
    fadeIn:SetDuration(db.animationDuration)
    
    local scaleIn = animIn:CreateAnimation("Scale")
    scaleIn:SetScale(0.8, 0.8)
    scaleIn:SetDuration(db.animationDuration * 0.8)
    scaleIn:SetOrder(0)
    
    local scaleIn2 = animIn:CreateAnimation("Scale")
    scaleIn2:SetScale(1.1, 1.1)
    scaleIn2:SetDuration(db.animationDuration * 0.2)
    scaleIn2:SetOrder(1)
    
    if animOut then
        animOut:Finish()
    end
    animOut = frame:CreateAnimationGroup()
    local fadeOut = animOut:CreateAnimation("Alpha")
    fadeOut:SetFromAlpha(1)
    fadeOut:SetToAlpha(0)
    fadeOut:SetDuration(db.animationDuration)
    
    animOut:SetScript("OnFinished", function()
        frame:Hide()
        frame:SetAlpha(0)
        text:SetAlpha(0)
        hitText:SetAlpha(0)
    end)
end

-- ==================== 更新点数 ====================
local function UpdatePoints()
    local db = ComboPointsDB[moduleName]
    if not db or not db.enabled or POWER_TYPE == "none" then
        if frame then frame:Hide() end
        return
    end
    
    if not ShouldShow() then
        if frame then 
            frame:Hide() 
            frame:SetAlpha(0)
            text:SetAlpha(0)
            hitText:SetAlpha(0)
        end
        return
    end
    
    local currentPoints = GetCurrentPoints()
    local maxPoints = GetMaxPoints()
    
    if currentPoints and currentPoints > 0 and maxPoints and maxPoints > 0 then
        ShowPoints(currentPoints, (currentPoints == lastPoints))
        if currentPoints > lastPoints and lastPoints > 0 then
            frame:SetScale(1.1)
            C_Timer.After(0.1, function()
                if frame then
                    frame:SetScale(1)
                end
            end)
        end
        lastPoints = currentPoints
    else
        if lastPoints > 0 then
            HidePoints()
        end
        lastPoints = 0
    end
end

-- ==================== 事件处理 ====================
local function OnUnitPowerUpdate(unit, powerType)
    if unit ~= "player" then return end
    if POWER_TYPE == "rune" then return end
    if POWER_TYPE == "ice_shards" or POWER_TYPE == "maelstrom_weapon" or POWER_TYPE == "tip_of_the_spear" then return end
    if powerType == POWER_INDEX or (EVENT_NAME and powerType == EVENT_NAME) then
        UpdatePoints()
    end
end

-- ==================== 初始化 ====================
local function Initialize()
    if isInitialized then return end
    
    SetupPowerType()
    
    if POWER_TYPE == "none" then
        return
    end
    
    InitDB()
    
    frame = CreateFrame("Frame", "ComboPoints_Frame", UIParent)
    frame:SetSize(200, 200)
    frame:SetFrameStrata("TOOLTIP")
    
    local db = ComboPointsDB[moduleName]
    if db then
        frame:SetPoint("CENTER", UIParent, "CENTER", db.textX, db.textY)
    else
        frame:SetPoint("CENTER")
    end
    
    -- 点击穿透 + Ctrl拖动
    frame:EnableMouse(false)
    frame:SetMovable(false)
    frame:RegisterForDrag("LeftButton")
    
    frame:SetScript("OnUpdate", function(self, elapsed)
        if IsControlKeyDown() then
            if not self:IsMouseEnabled() then
                self:EnableMouse(true)
                self:SetMovable(true)
            end
        else
            if self:IsMouseEnabled() then
                self:EnableMouse(false)
                self:SetMovable(false)
                if isDragging then
                    isDragging = false
                    self:StopMovingOrSizing()
                end
            end
        end
    end)
    
    frame:SetScript("OnMouseDown", function(self, button)
        if button == "LeftButton" and IsControlKeyDown() then
            isDragging = true
            self:StartMoving()
        end
    end)
    
    frame:SetScript("OnMouseUp", function(self, button)
        if button == "LeftButton" and isDragging then
            isDragging = false
            self:StopMovingOrSizing()
            local x, y = self:GetCenter()
            local cx, cy = UIParent:GetCenter()
            if ComboPointsDB and ComboPointsDB[moduleName] then
                ComboPointsDB[moduleName].textX = x - cx
                ComboPointsDB[moduleName].textY = y - cy
            end
            UpdateDisplayLayout()
            UpdatePoints()
        end
    end)
    
    frame:SetScript("OnDragStart", function(self)
        if not isDragging then
            self:StopMovingOrSizing()
        end
    end)
    
    -- 创建组合容器
    local textGroup = CreateFrame("Frame", nil, frame)
    textGroup:SetAllPoints(frame)
    
    -- 数字文字
    text = textGroup:CreateFontString(nil, "OVERLAY")
    text:SetJustifyH("CENTER")
    text:SetJustifyV("MIDDLE")
    text:SetPoint("CENTER", textGroup, "CENTER", -15, 0)
    
    -- 后缀文字
    hitText = textGroup:CreateFontString(nil, "OVERLAY")
    hitText:SetJustifyH("LEFT")
    hitText:SetJustifyV("MIDDLE")
    hitText:SetPoint("LEFT", text, "RIGHT", 1, -10)
    hitText:Hide()
    
    CreateAnimations()
    UpdateDisplayLayout()
    
    local eventFrame = CreateFrame("Frame")
    eventFrame:RegisterUnitEvent("UNIT_POWER_UPDATE", "player")
    eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
    eventFrame:RegisterEvent("PLAYER_TALENT_UPDATE")
    eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
    eventFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
    eventFrame:RegisterEvent("UNIT_TARGET")
    eventFrame:RegisterUnitEvent("UNIT_AURA", "player")
    
    eventFrame:RegisterEvent("RUNE_POWER_UPDATE")
    eventFrame:RegisterEvent("RUNE_TYPE_UPDATE")
    
   eventFrame:SetScript("OnEvent", function(self, event, ...)
    if event == "PLAYER_ENTERING_WORLD" then
        C_Timer.After(0.5, function()
            SetupPowerType()
            UpdatePoints()
        end)
    elseif event == "PLAYER_TALENT_UPDATE" then
        SetupPowerType()
        -- 更新外部引用
        ComboPoints.RESOURCE_NAME = RESOURCE_NAME
        if POWER_TYPE ~= "none" then
            UpdateDisplayLayout()
            UpdatePoints()
        else
            -- 隐藏数字显示框
            if frame then frame:Hide() end
        end
        -- 刷新设置面板信息（无论 POWER_TYPE 是什么）
        if ComboPointsOptionsPanel and ComboPointsOptionsPanel.UpdateInfoText then
            ComboPointsOptionsPanel.UpdateInfoText()
        end
    elseif event == "UNIT_POWER_UPDATE" then
        local unit, powerType = ...
        OnUnitPowerUpdate(unit, powerType)
    elseif event == "UNIT_AURA" then
        local unit = ...
        if unit == "player" and (POWER_TYPE == "ice_shards" or POWER_TYPE == "maelstrom_weapon" or POWER_TYPE == "tip_of_the_spear") then
            UpdatePoints()
        end
    elseif event == "PLAYER_REGEN_ENABLED" or event == "PLAYER_REGEN_DISABLED" or event == "UNIT_TARGET" then
        UpdatePoints()
    elseif event == "RUNE_POWER_UPDATE" or event == "RUNE_TYPE_UPDATE" then
        if POWER_TYPE == "rune" then
            UpdatePoints()
        end
    end
end)
    
    UpdatePoints()
    
    C_Timer.After(0.5, function()
        SetupPowerType()
        UpdatePoints()
    end)
    
    isInitialized = true
end

local loadFrame = CreateFrame("Frame")
loadFrame:RegisterEvent("ADDON_LOADED")
loadFrame:SetScript("OnEvent", function(_, _, addon)
    if addon == "OrzUI" then
        C_Timer.After(1.0, function()
            Initialize()
        end)
        loadFrame:UnregisterEvent("ADDON_LOADED")
    end
end)

if GetLocale() == "zhCN" then
  ComboPointsLocal = "|cff8000ff[职业]|r连击点数";
elseif GetLocale() == "zhTW" then
  ComboPointsLocal = "|cff8000ff[职业]|r连击点数";
else
  ComboPointsLocal = "Combo Points";
end

-- ==================== 聊天命令支持 ====================
SLASH_COMBOPOINTS1 = "/cp"
SLASH_COMBOPOINTS2 = "/combopoints"
SlashCmdList["COMBOPOINTS"] = function(msg)
    local db = ComboPointsDB["ComboPoints"]
    if not db then
        --print("|cffff0000插件未正确加载，请重新加载界面 (/reload)|r")
        return
    end
    
    -- 如果输入为空，打开设置面板
    if not msg or msg:trim() == "" then
        -- 战斗中禁止打开设置面板
        if InCombatLockdown() then
            print("|cffffcc00战斗中无法打开设置面板，请脱离战斗后再试|r")
            return
        end
        
        -- 尝试打开设置面板
        local opened = false
        
        -- 方法1：通过全局 CATEGORY_ID（由 UI 文件设置）
        if ComboPointsUI_CATEGORY_ID then
            if Settings and Settings.OpenToCategory then
                Settings.OpenToCategory(ComboPointsUI_CATEGORY_ID)
                opened = true
            end
        end
        
        -- 方法2：通过面板名称
        if not opened and Settings and Settings.OpenToCategory then
            -- 尝试通过名称查找
            local success, result = pcall(function()
                return Settings.OpenToCategory(ComboPointsLocal)
            end)
            if success and result then
                opened = true
            end
        end
        
        -- 方法3：传统 InterfaceOptions
        if not opened and InterfaceOptionsFrame and InterfaceOptionsFrame_Open then
            InterfaceOptionsFrame_Open()
            if InterfaceOptionsFrame_OpenToCategory then
                InterfaceOptionsFrame_OpenToCategory(ComboPointsLocal)
                opened = true
            end
        end
        
        if not opened then
            print("|cffffcc00无法打开设置面板，请输入 /cp help 查看可用命令|r")
        end
        return
    end
    
    -- 处理帮助命令
    if msg:trim() == "help" then
        print("|cffffd700===== ComboPoints 帮助 =====|r")
        print("  /cp                - 打开设置面板")
        print("  /cp font <20-200>  - 调整字体大小")
        print("  /cp opacity <0.1-1.0> - 调整透明度")
        print("  /cp suffix <on/off> - 切换后缀模式")
        print("  /cp help           - 显示此帮助")
        return
    end
    
    local cmd, val = msg:match("^(%S+)%s+(%S+)$")
    
    if not cmd or not val then
        print("|cffff0000无效命令，输入 /cp help 查看帮助|r")
        return
    end
    
    -- 处理开关类型的命令
    if cmd == "suffix" or cmd == "classsuffix" then
        local lowerVal = val:lower()
        if lowerVal == "on" or lowerVal == "true" or lowerVal == "1" then
            db.useClassSuffix = true
            UpdateDisplayLayout()
            UpdatePoints()
            print("|cff87ceeb后缀模式已设为: |cffffffff职业专属后缀|r")
        elseif lowerVal == "off" or lowerVal == "false" or lowerVal == "0" then
            db.useClassSuffix = false
            UpdateDisplayLayout()
            UpdatePoints()
            print("|cff87ceeb后缀模式已设为: |cffffffff统一 'Hit' 后缀|r")
        else
            print("|cffff0000无效值，请输入 on 或 off|r")
        end
        return
    end
    
    local numVal = tonumber(val)
    if not numVal then
        print("|cffff0000请输入有效的数字|r")
        return
    end
    
    if cmd == "font" or cmd == "size" then
        if numVal < 20 or numVal > 200 then
            print("|cffff0000字体大小范围: 20 ~ 200|r")
            return
        end
        db.fontSize = numVal
        UpdateFontStyle()
        UpdateDisplayLayout()
        UpdatePoints()
        print("|cff87ceeb字体大小已设为: |cffffffff" .. db.fontSize .. "|r")
        
    elseif cmd == "opacity" or cmd == "alpha" or cmd == "transparency" then
        if numVal < 0.1 or numVal > 1.0 then
            print("|cffff0000透明度范围: 0.1 ~ 1.0|r")
            return
        end
        db.textOpacity = numVal
        UpdatePoints()
        print("|cff87ceeb透明度已设为: |cffffffff" .. db.textOpacity .. "|r")
        
    else
        print("|cffff0000未知命令: " .. cmd .. "，输入 /cp help 查看帮助|r")
    end
end

-- ==================== 暴露给外部调用的函数 ====================
-- 让 UI 文件可以调用主文件的功能
ComboPoints = {
    RESOURCE_NAME = RESOURCE_NAME,
    UpdatePoints = UpdatePoints,
    UpdateDisplayLayout = UpdateDisplayLayout,
}

--[[
    ComboPointsUI.lua
    点数/次级资源显示插件 - 设置面板
]]

local function GetDB()
    if not ComboPointsDB then
        ComboPointsDB = {}
    end
    if not ComboPointsDB[moduleName] then
        ComboPointsDB[moduleName] = {}
    end
    return ComboPointsDB[moduleName]
end

-- ==================== 刷新显示的通用函数 ====================
local function RefreshDisplay()
    if ComboPoints and ComboPoints.UpdateDisplayLayout then
        ComboPoints.UpdateDisplayLayout()
    end
    if ComboPoints and ComboPoints.UpdatePoints then
        ComboPoints.UpdatePoints()
    end
end

-- ==================== 设置面板 ====================
local function BuildOptionsUI(panel)
    local db = GetDB()
    
    -- ===== 标题 =====
    local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 16, -16)
    title:SetText("点数/次级资源显示")
    
    -- ===== 当前职业和专精信息 =====
    local infoText = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    infoText:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -36)
    
    local function UpdateInfoText()
        local _, class = UnitClass("player")
        local classNames = {
            ["WARRIOR"] = "战士",
            ["PALADIN"] = "圣骑士",
            ["HUNTER"] = "猎人",
            ["ROGUE"] = "盗贼",
            ["PRIEST"] = "牧师",
            ["DEATHKNIGHT"] = "死亡骑士",
            ["SHAMAN"] = "萨满",
            ["MAGE"] = "法师",
            ["WARLOCK"] = "术士",
            ["MONK"] = "武僧",
            ["DRUID"] = "德鲁伊",
            ["DEMONHUNTER"] = "恶魔猎手",
            ["EVOKER"] = "唤魔师"
        }
        local className = classNames[class] or class or "未知"
        
        -- 获取职业颜色（仅用于职业名称）
        local color = RAID_CLASS_COLORS[class]
        local colorHex = color and string.format("|cff%02x%02x%02x", color.r*255, color.g*255, color.b*255) or "|cffffffff"
        local coloredClassName = colorHex .. className .. "|r"
        
        local spec = GetSpecialization()
        local specName = ""
        if spec then
            local _, name = GetSpecializationInfo(spec)
            specName = name or ""
        end
        -- 专精名称用白色
        local whiteSpecName = "|cffffffff" .. specName .. "|r"
        
        -- 直接用兜底逻辑判断资源名称（不依赖 ComboPoints.RESOURCE_NAME）
        local resourceName = "无"
        if class == "ROGUE" or class == "DRUID" then
            resourceName = "连击点"
        elseif class == "PALADIN" then
            resourceName = "神圣能量"
        elseif class == "WARLOCK" then
            resourceName = "灵魂碎片"
        elseif class == "MONK" then
            resourceName = "真气"
        elseif class == "MAGE" then
            if specName and string.find(specName, "冰霜") then
                resourceName = "冰刺"
            elseif specName and string.find(specName, "奥术") then
                resourceName = "奥术充能"
            else
                resourceName = "无"
            end
        elseif class == "HUNTER" then
            if specName and string.find(specName, "生存") then
                resourceName = "利矛之刃"
            else
                resourceName = "无"
            end
        elseif class == "SHAMAN" then
            if specName and string.find(specName, "增强") then
                resourceName = "漩涡武器"
            else
                resourceName = "无"
            end
        elseif class == "EVOKER" then
            resourceName = "精华"
        elseif class == "DEATHKNIGHT" then
            resourceName = "符文"
        end
        local whiteResourceName = "|cffffffff" .. resourceName .. "|r"
        
        infoText:SetText(string.format("职业: %s | 专精: %s | 资源: %s", coloredClassName, whiteSpecName, whiteResourceName))
    end
    
    UpdateInfoText()
    
    -- 锚点
    local anchor = infoText
    
    -- ===== 字体大小 =====
    local fontLabel = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    fontLabel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -24)
    fontLabel:SetText("字体大小:")
    
    local fontSlider = CreateFrame("Slider", nil, panel, "OptionsSliderTemplate")
    fontSlider:SetPoint("LEFT", fontLabel, "RIGHT", 10, 0)
    fontSlider:SetSize(200, 16)
    fontSlider:SetMinMaxValues(20, 150)
    fontSlider:SetValueStep(1)
    fontSlider:SetValue(db.fontSize or 72)
    fontSlider:SetScript("OnValueChanged", function(self, value)
        value = math.floor(value + 0.5)
        db.fontSize = value
        panel.fontValue:SetText(tostring(value))
        -- 立即刷新显示
        RefreshDisplay()
    end)
    
    panel.fontValue = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    panel.fontValue:SetPoint("LEFT", fontSlider, "RIGHT", 8, 0)
    panel.fontValue:SetText(tostring(db.fontSize or 72))
    panel.fontValue:SetWidth(40)
    
    -- ===== 透明度 =====
    local opacityLabel = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    opacityLabel:SetPoint("TOPLEFT", fontLabel, "BOTTOMLEFT", 0, -24)
    opacityLabel:SetText("透明度:")
    
    local opacitySlider = CreateFrame("Slider", nil, panel, "OptionsSliderTemplate")
    opacitySlider:SetPoint("LEFT", opacityLabel, "RIGHT", 10, 0)
    opacitySlider:SetSize(200, 16)
    opacitySlider:SetMinMaxValues(10, 100)
    opacitySlider:SetValueStep(1)
    opacitySlider:SetValue((db.textOpacity or 1.0) * 100)
    opacitySlider:SetScript("OnValueChanged", function(self, value)
        value = math.floor(value + 0.5)
        db.textOpacity = value / 100
        panel.opacityValue:SetText(tostring(value) .. "%")
        -- 立即刷新显示
        RefreshDisplay()
    end)
    
    panel.opacityValue = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    panel.opacityValue:SetPoint("LEFT", opacitySlider, "RIGHT", 8, 0)
    panel.opacityValue:SetText(tostring((db.textOpacity or 1.0) * 100) .. "%")
    panel.opacityValue:SetWidth(50)
    
    -- ===== 后缀模式切换 =====
    local suffixLabel = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    suffixLabel:SetPoint("TOPLEFT", opacityLabel, "BOTTOMLEFT", 0, -36)
    suffixLabel:SetText("当前后缀模式:")
    
    -- 创建状态文本（冒号后面的内容用白色）
    local suffixStatus = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    suffixStatus:SetPoint("LEFT", suffixLabel, "RIGHT", 10, 0)
    
    local function UpdateSuffixStatus()
        local statusText = db.useClassSuffix and "职业专属" or "统一 Hit"
        suffixStatus:SetText("|cffffffff" .. statusText .. "|r")
    end
    UpdateSuffixStatus()
    
    local suffixOnButton = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    suffixOnButton:SetPoint("LEFT", suffixStatus, "RIGHT", 10, 0)
    suffixOnButton:SetSize(60, 24)
    suffixOnButton:SetText("职业")
    suffixOnButton:SetScript("OnClick", function()
        db.useClassSuffix = true
        UpdateSuffixStatus()
        -- 立即刷新显示
        RefreshDisplay()
    end)
    
    local suffixOffButton = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    suffixOffButton:SetPoint("LEFT", suffixOnButton, "RIGHT", 4, 0)
    suffixOffButton:SetSize(60, 24)
    suffixOffButton:SetText("统一")
    suffixOffButton:SetScript("OnClick", function()
        db.useClassSuffix = false
        UpdateSuffixStatus()
        -- 立即刷新显示
        RefreshDisplay()
    end)
    
    -- ===== 职业专属后缀列表 =====
    local suffixListLabel = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    suffixListLabel:SetPoint("TOPLEFT", suffixLabel, "BOTTOMLEFT", 0, -30)
    suffixListLabel:SetText("职业专属后缀列表:")
    
    -- 根据你提供的代码定义职业和对应的后缀
    local classSuffixMap = {
        ["DEATHKNIGHT"] = {name = "死亡骑士", suffix = "Rune"},
        ["SHAMAN"] = {name = "萨满（增强）", suffix = "MW"},
        ["ROGUE"] = {name = "盗贼", suffix = "CP"},
        ["DRUID"] = {name = "德鲁伊（猫）", suffix = "CP"},
        ["PALADIN"] = {name = "圣骑士", suffix = "HP"},
        ["WARLOCK"] = {name = "术士", suffix = "SS"},
        ["MONK"] = {name = "武僧", suffix = "Chi"},
        ["EVOKER"] = {name = "唤魔师", suffix = "ESS"},
        ["MAGE_ARCANE"] = {name = "法师（奥术）", suffix = "AC"},
        ["MAGE_FROST"] = {name = "法师（冰霜）", suffix = "Ice"},
        ["HUNTER_SURVIVAL"] = {name = "猎人（生存）", suffix = "TOTS"},
    }
    
    -- 创建显示文本
    local suffixListText = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    suffixListText:SetPoint("TOPLEFT", suffixListLabel, "BOTTOMLEFT", 20, -8)
    suffixListText:SetJustifyH("LEFT")
    suffixListText:SetWidth(300)
    
    local function UpdateSuffixList()
        local lines = {}
        for classToken, data in pairs(classSuffixMap) do
            -- 处理特殊情况：映射到对应的职业颜色
            local colorKey = classToken
            if classToken == "MAGE_ARCANE" or classToken == "MAGE_FROST" then
                colorKey = "MAGE"
            elseif classToken == "HUNTER_SURVIVAL" then
                colorKey = "HUNTER"
            end
            local color = RAID_CLASS_COLORS[colorKey]
            local colorHex = color and string.format("|cff%02x%02x%02x", color.r*255, color.g*255, color.b*255) or "|cffffffff"
            local coloredClassName = colorHex .. data.name .. "|r"
            -- 后缀使用游戏默认黄色
            local suffixText = "|cffffd700" .. data.suffix .. "|r"
            table.insert(lines, coloredClassName .. "：" .. suffixText)
        end
        -- 排序
        table.sort(lines)
        -- 每个职业一行
        local displayText = table.concat(lines, "\n")
        suffixListText:SetText(displayText)
        suffixListText:SetSpacing(8)  -- 设置行间距
    end
    UpdateSuffixList()
    
    -- ===== 重置默认按钮 =====
    local resetButton = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    resetButton:SetPoint("BOTTOMLEFT", 16, 16)
    resetButton:SetSize(120, 28)
    resetButton:SetText("重置默认")
    resetButton:SetScript("OnClick", function()
        -- 重置所有设置到默认值
        db.fontSize = 72
        db.textOpacity = 1.0
        db.useClassSuffix = true
        db.textX = 300   -- 重置 X 位置到默认
        db.textY = 0     -- 重置 Y 位置到默认
        
        -- 更新UI控件
        fontSlider:SetValue(72)
        panel.fontValue:SetText("72")
        opacitySlider:SetValue(100)
        panel.opacityValue:SetText("100%")
        UpdateSuffixStatus()
        
        UpdateInfoText()
        
        -- 刷新显示（包括位置）
        if ComboPoints and ComboPoints.UpdateDisplayLayout then
            ComboPoints.UpdateDisplayLayout()
        end
        if ComboPoints and ComboPoints.UpdatePoints then
            ComboPoints.UpdatePoints()
        end
        
        -- 额外提示
        -- print("|cffffd700已重置所有设置为默认值|r")
    end)
    
    -- ===== 底部提示 =====
    local tipText = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
    tipText:SetPoint("BOTTOMRIGHT", -16, 16)
    tipText:SetText("|cffffd700提示: 按住 Ctrl + 左键拖动点数显示框调整位置|r")
    
    panel.UpdateInfoText = UpdateInfoText
end

-- ==================== 注册设置面板 ====================
ComboPointsUI_CATEGORY_ID = nil  -- 全局变量

local function RegisterSettings()
    local panel = CreateFrame("Frame", "ComboPointsOptionsPanel")
    panel.name = ComboPointsLocal
    panel.parent = "AddOns"
    
    panel.isLoaded = false
    panel:SetScript("OnShow", function(self)
        if not self.isLoaded then
            BuildOptionsUI(self)
            self.isLoaded = true
        end
    end)
    
    -- 使用 Settings API (11.0+)
    if Settings and Settings.RegisterCanvasLayoutCategory and Settings.RegisterAddOnCategory then
        local category = Settings.RegisterCanvasLayoutCategory(panel, ComboPointsLocal)
        Settings.RegisterAddOnCategory(category)
        ComboPointsUI_CATEGORY_ID = category.ID  -- 导出为全局
        return true
    end
    
    -- 使用 InterfaceOptions (传统方式)
    if InterfaceOptionsFrame_AddCategory then
        InterfaceOptionsFrame_AddCategory(panel)
        return true
    end
    
    return false
end

-- ==================== 斜杠命令 ====================
local function SetupSlashCommand()
    -- 检查主文件的命令是否已存在
    if SlashCmdList["COMBOPOINTS"] then
        print("|cff87ceebComboPoints|r 设置面板已加载")
    else
        -- 如果主文件未加载（极少情况），注册一个备用命令
        SlashCmdList["COMBOPOINTS"] = function()
            if CATEGORY_ID then
                Settings.OpenToCategory(CATEGORY_ID)
            elseif InterfaceOptionsFrame and InterfaceOptionsFrame_Open then
                InterfaceOptionsFrame_Open()
                if InterfaceOptionsFrame_OpenToCategory then
                    InterfaceOptionsFrame_OpenToCategory("ComboPoints")
                end
            else
                print("|cffffcc00ComboPoints|r 设置面板未加载，请使用 /reload")
            end
        end
        _G["SLASH_COMBOPOINTS1"] = "/combopoints"
        _G["SLASH_COMBOPOINTS2"] = "/cp"
    end
end

-- ==================== 初始化 ====================
local isInitialized = false

local function InitializeUI()
    if isInitialized then return end
    
    RegisterSettings()
    --SetupSlashCommand()
    isInitialized = true
    
end

-- ==================== 加载事件 ====================
local loadFrame = CreateFrame("Frame")
loadFrame:RegisterEvent("ADDON_LOADED")
loadFrame:SetScript("OnEvent", function(self, event, addon)
    if addon == "OrzUI" then
        GetDB() -- 确保数据库存在
        C_Timer.After(0.5, InitializeUI)
        self:UnregisterAllEvents()
        self:Hide()
    end
end)

-- 兜底：玩家进入世界后初始化
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:SetScript("OnEvent", function()
    C_Timer.After(0.5, InitializeUI)
    eventFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
end)