--## Author: Kaineoa ## SavedVariables: InstanceHelperDB

-- 默认配置
local Config = {
    FrameWidth = 320, -- 框架宽度
    FrameHeight = 146, -- 主框架高度
    FrameHeightInstance = 86, -- 主框架副本内高度
    FrameBgHeightInstance = 80, -- 主框架副本内背景高度
    FrameRowHeight = 22, -- 框架行高
    BtnY = -15, -- 按钮垂直定位
    BtnGapI = 10, -- 按钮内边距
    BtnGapX = 10, -- 按钮水平间距
    BtnGapY = 10, -- 按钮垂直间距
    clrActive = {1, 0.8196, 0}, -- 激活颜色 (#FFD100)
    clrActiveS = {0, 1, 1}, -- 激活颜色-专精
    clrActiveO = {1, 0.960, 0.410}, -- 激活颜色-老本
    clrActiveN = {0, 1, 0}, -- 激活颜色-普通
    clrActiveH = {0, 0.7, 1}, -- 激活颜色--英雄
    clrActiveM = {0.85, 0.45, 1}, -- 激活颜色-史诗
    clrInactive = {0.900, 0.150, 0.180}, -- 未激活颜色
    clrDisabled = {0.5, 0.5, 0.5} -- 置灰颜色
}

-- 副本难度ID表
local diffData = {
    ["N"] = 14,  -- 普通团本
    ["H"] = 15,  -- 英雄团本
    ["M"] = 16,  -- 史诗团本
    ["5N"] = 1,  -- 5人普通
    ["5H"] = 2,  -- 5人英雄
    ["5M"] = 23, -- 5人史诗
    ["10N"] = 3, -- 10人普通
    ["10H"] = 5, -- 10人英雄
    ["25N"] = 4, -- 25人普通
    ["25H"] = 6 -- 25人英雄
}

-- 创建标题框架
local titleFrame = CreateFrame("Frame", nil, GameMenuFrame, "BackdropTemplate")
titleFrame:SetSize(Config.FrameWidth, Config.FrameRowHeight + 3)
titleFrame:SetPoint("BOTTOM", GameMenuFrame, "TOP", 0, 8)
titleFrame:SetMovable(true) -- 允许框架被鼠标拖动移动位置
titleFrame:EnableMouse(true) -- 启用框架的鼠标交互功能，使其能够响应鼠标事件
titleFrame:RegisterForDrag("LeftButton") -- 注册左键为拖动按钮
titleFrame:SetClampedToScreen(true) -- 限制框架在屏幕内

-- 创建标题按钮
local titleText = "副本助手"
local title = CreateFrame("Button", nil, titleFrame)
title:SetAllPoints(titleFrame)
title:EnableMouse(true)
title:RegisterForClicks("AnyUp")
title:RegisterForDrag("LeftButton")
title:SetNormalFontObject("GameFontNormalLarge")
title:SetHighlightFontObject("GameFontNormalLarge")
title:SetText(titleText)

-- 创建主框架
local frame = CreateFrame("Frame", nil, GameMenuFrame, "BackdropTemplate")
frame:SetSize(Config.FrameWidth, Config.FrameHeight)
frame:SetPoint("BOTTOM", titleFrame, "TOP", 0, -3)
frame:SetClampedToScreen(true)

-- 创建材质的辅助函数
local function CreateTexture(parent, atlasName, width, height, point, relativeTo, relativePoint, xOffset, yOffset, layer)
    local texture = parent:CreateTexture(nil, layer or "OVERLAY")
    texture:SetSize(width, height)
    texture:SetPoint(point, relativeTo, relativePoint, xOffset, yOffset)
    texture:SetAtlas(atlasName, false)
    return texture
end
-- 创建材质：顶部、背景、底部。
local textureTitleBg = CreateTexture(titleFrame, "timerunning-TopHUD-button-glow", 228, 35.5, "BOTTOM", titleFrame, "BOTTOM", 0, -3, "BACKGROUND")
textureTitleBg:SetAlpha(0.8)
local textureTop = CreateTexture(frame, "evergreen-scenario-line-top", 350, 5, "TOP", frame, "TOP", 0, 0)
local textureBottom = CreateTexture(frame, "evergreen-scenario-line-bottom", 350, 5, "BOTTOM", frame, "BOTTOM", 0, 0)
local textureBg = CreateTexture(frame, "BossBanner-BgBanner-Mid", 430, 140, "CENTER", frame, "CENTER", 0, 0, "BACKGROUND")
textureBg:SetAlpha(0.6)

local rowBtn = {}
-- 统一按钮创建函数，使用内置文本系统
local function CreateTextBtn(row, col, text, color, extraProps)
    local btn = CreateFrame("Button", nil, frame)
    btn:EnableMouse(true)
    btn:RegisterForClicks("AnyUp")
    btn:SetNormalFontObject("GameFontNormal")
    btn:SetHighlightFontObject("GameFontNormal")
    btn:SetText(text)
    local fontString = btn:GetFontString()
    if fontString then
        fontString:SetTextColor(color[1], color[2], color[3])
        fontString:SetJustifyH("CENTER")
    end
    btn.originalText = text
    if extraProps then
        for k, v in pairs(extraProps) do
            btn[k] = v
        end
    end
    if not rowBtn[row] then
        rowBtn[row] = {}
    end
    rowBtn[row][#rowBtn[row]+1] = btn
    return btn
end

-- 自动布局每行按钮，实现自动适应宽度并平均分配空间
local function LayoutRowBtn()
    local frameWidth = frame:GetWidth() - Config.BtnGapI * 2
    for row, buttons in pairs(rowBtn) do
        if #buttons > 0 then
            local totalGapWidth = Config.BtnGapX * (#buttons - 1)
            local buttonWidth = (frameWidth - totalGapWidth) / #buttons
            for i, btn in ipairs(buttons) do
                btn:SetWidth(buttonWidth)
                local x = Config.BtnGapI + (i - 1) * (buttonWidth + Config.BtnGapX)
                local y = Config.BtnY - (row - 1) * (Config.FrameRowHeight + Config.BtnGapY)
                btn:ClearAllPoints()
                btn:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y)
                btn:SetHeight(Config.FrameRowHeight)
            end
        end
    end
end


-- 按钮配置集中管理
local dungeonBtn = {}
local raidBtn = {}
local raidNumBtn = {}
local specLootBtn = {}

-- 第2行：副本功能按钮
local leaveGroupBtn = CreateTextBtn(2, 1, "退出", Config.clrActive)
local teleportBtn = CreateTextBtn(2, 2, "传送", Config.clrActive)
local readyCheckBtn = CreateTextBtn(2, 3, "就位", Config.clrActive)
local resetBtn = CreateTextBtn(2, 4, "重置", Config.clrActive); resetBtn.inInstanceText = "倒数"

-- 第3行：10人按钮，地下城难度按钮
raidNumBtn[1] = CreateTextBtn(3, 1, "10人", Config.clrInactive, {isRaidNum = true, raidNum = 10, colorType = "O"})
dungeonBtn[1] = CreateTextBtn(3, 2, "普通", Config.clrInactive, {diffID = diffData["5N"], isDungeon = true, colorType = "N"})
dungeonBtn[2] = CreateTextBtn(3, 3, "英雄", Config.clrInactive, {diffID = diffData["5H"], isDungeon = true, colorType = "H"})
dungeonBtn[3] = CreateTextBtn(3, 4, "史诗", Config.clrInactive, {diffID = diffData["5M"], isDungeon = true, colorType = "M"})
-- 第4行：25人按钮，团本难度按钮
raidNumBtn[2] = CreateTextBtn(4, 1, "25人", Config.clrInactive, {isRaidNum = true, raidNum = 25, colorType = "O"})
raidBtn[1] = CreateTextBtn(4, 2, "普通团", Config.clrInactive, {diff10 = diffData["10N"], diff25 = diffData["25N"], isRaidDiff = true, colorType = "N"})
raidBtn[2] = CreateTextBtn(4, 3, "英雄团", Config.clrInactive, {diff10 = diffData["10H"], diff25 = diffData["25H"], isRaidDiff = true, colorType = "H"})
raidBtn[3] = CreateTextBtn(4, 4, "史诗团", Config.clrInactive, {diff10 = diffData["M"], diff25 = diffData["M"], isRaidDiff = true, colorType = "M"})

-- 随机副本传送按钮点击事件 - 正确判断传送状态
teleportBtn:SetScript("OnClick", function() 
    -- 检查是否在随机副本队伍中
    local inLFGGroup = IsInGroup(LE_PARTY_CATEGORY_INSTANCE)
    local inLFGDungeon = IsInLFGDungeon()
    
    if inLFGGroup or inLFGDungeon then 
        LFGTeleport(inLFGDungeon) 
    else
        print("|cFFFF0000错误：只有在随机副本队伍中才能使用传送功能|r")
    end
end)

-- 就位确认按钮点击事件
readyCheckBtn:SetScript("OnClick", function() 
    local inGroup = IsInGroup() or IsInRaid()
    local isLeader = UnitIsGroupLeader("player")
    
    if inGroup and isLeader then 
        DoReadyCheck() 
    else
        if inGroup and not isLeader then
            print("|cFFFF0000错误：只有队长/团长才能发起就位检查|r")
        else
            print("|cFFFF0000错误：只有组队状态下才能使用就位检查|r")
        end
    end
end)

-- 重置按钮点击事件 - 在副本内只有队长/团长可以倒数，在副本外只有队长/团长可以重置
resetBtn:SetScript("OnClick", function()
    local inInstance = IsInInstance()
    local inGroup = IsInGroup() or IsInRaid()
    local isLeader = UnitIsGroupLeader("player")
    
    if inInstance then
        -- 在副本内，执行开怪倒数，只有队长/团长才能使用
        if inGroup then
            if isLeader then
                C_PartyInfo.DoCountdown(8)
            else
                print("|cFFFF0000错误：只有队长/团长才能发起倒数|r")
            end
        else
            -- 单人状态下，也可以倒数
            C_PartyInfo.DoCountdown(8)
        end
    else
        -- 在副本外，执行重置副本
        if not inGroup or (inGroup and isLeader) then
            ResetInstances()
            local message = "副本已重置"
            if IsInRaid() then SendChatMessage(message, "RAID")
            elseif IsInGroup() then SendChatMessage(message, "PARTY")
            else print(message)
            end
        else
            print("|cFFFF0000错误：只有队长/团长才能重置副本|r")
        end
    end
end)

-- 通用离开队伍函数，处理不同类型实例和队伍状态。
local function LeaveGroup()
    local inInstance, instanceType = IsInInstance()
    local inGroup = IsInGroup() or IsInRaid()
    -- 特殊类型处理，战场&竞技场，地下堡&场景战役。
    if inInstance then
        if instanceType == "arena" or instanceType == "pvp" then
            LeaveBattlefield()
            return
        elseif instanceType == "scenario" then
            if C_PartyInfo and C_PartyInfo.DelveTeleportOut then
                C_PartyInfo.DelveTeleportOut()
                return
            end
        end
    end
    if inGroup then
        C_PartyInfo.LeaveParty() -- 通用离开逻辑，有队伍直接离开。
    else
        local numGroupMembers = GetNumGroupMembers()-- 没有队伍，检查是否真的是单人状态
        if numGroupMembers <= 1 then -- 确实是单人，先邀请123创建队伍并离开，触发60秒传送。
            C_PartyInfo.InviteUnit("123")
            C_Timer.After(1, function()
                C_PartyInfo.LeaveParty()
            end)
        else
            C_PartyInfo.LeaveParty() -- 实际有队友直接离开
        end
    end
end
-- 离开队伍按钮点击事件
leaveGroupBtn:SetScript("OnClick", function() LeaveGroup() end)

local wasInInstance = false
-- 进入副本内时，隐藏难度按钮，并替换标题文字为副本难度信息，离开副本时，显示难度按钮，并恢复标题文字。
local function SetCollapsedMode(collapsed)
    -- 处理标题文本，在副本内显示当前副本难度信息
    if not collapsed then
        title:SetText(titleText)
        -- 离开副本时恢复默认颜色
        title:GetFontString():SetTextColor(1, 0.82, 0)
    else
        local name, instanceType, difficultyID, difficultyName, maxPlayers = GetInstanceInfo()
        if name then
            local displayDifficulty = difficultyName or ""
            title:SetText(name .. (displayDifficulty and "-" .. displayDifficulty or ""))
            -- 根据难度设置标题颜色
            local fontString = title:GetFontString()
            if fontString then
                if difficultyName and string.find(difficultyName, "普通") then
                    fontString:SetTextColor(unpack(Config.clrActiveN))
                elseif difficultyName and string.find(difficultyName, "英雄") then
                    fontString:SetTextColor(unpack(Config.clrActiveH))
                elseif difficultyName and string.find(difficultyName, "史诗") then
                    fontString:SetTextColor(unpack(Config.clrActiveM))
                else
                    -- 如果没有难度名称，尝试从difficultyID获取难度信息
                    local diffColor = Config.clrActive
                    if difficultyID == 1 then -- 5人普通
                        diffColor = Config.clrActiveN
                    elseif difficultyID == 2 then -- 5人英雄
                        diffColor = Config.clrActiveH
                    elseif difficultyID == 23 then -- 5人史诗
                        diffColor = Config.clrActiveM
                    elseif difficultyID == 14 then -- 团本普通
                        diffColor = Config.clrActiveN
                    elseif difficultyID == 15 then -- 团本英雄
                        diffColor = Config.clrActiveH
                    elseif difficultyID == 16 then -- 团本史诗
                        diffColor = Config.clrActiveM
                    end
                    fontString:SetTextColor(unpack(diffColor))
                end
            end
        else
            title:SetText(titleText)
            title:GetFontString():SetTextColor(1, 0.82, 0)
        end
    end
    -- 处理重置按钮文本
    local inInstance = IsInInstance() and collapsed
    resetBtn:SetText(inInstance and resetBtn.inInstanceText or resetBtn.originalText)
    -- 处理框架高度
    frame:SetHeight(collapsed and Config.FrameHeightInstance or Config.FrameHeight)
    -- 处理背景材质高度
    if textureBg then
        textureBg:SetHeight(collapsed and Config.FrameBgHeightInstance or 140)
    end
    -- 处理难度按钮的显示/隐藏
    for _, btnList in ipairs({dungeonBtn, raidNumBtn, raidBtn}) do 
        for _, btn in ipairs(btnList) do 
            btn:SetShown(not collapsed) 
        end 
    end
    -- 处理功能按钮的显示/隐藏（始终显示）
    leaveGroupBtn:SetShown(true)
    teleportBtn:SetShown(true)
    readyCheckBtn:SetShown(true)
    resetBtn:SetShown(true)
    -- 处理专精拾取按钮的显示/隐藏（始终显示）
    for _, btn in ipairs(specLootBtn) do
        btn:SetShown(true)
    end
end

-- 统一的按钮状态更新函数，按钮类型、激活/禁用状态设定颜色
local function UpdateBtnState(btn, isActive, isEnabled, isOptionBtn)
    if not isEnabled then
        btn:Disable()
        local fontString = btn:GetFontString()
        if fontString then
            fontString:SetTextColor(unpack(Config.clrDisabled))
        end
        btn.isHighlighted = false
        return
    end
    btn:Enable()
    btn.isHighlighted = isOptionBtn or isActive
    local color
    if isOptionBtn then 
        color = Config.clrActive
    elseif isActive then
        if btn.specID then 
            color = Config.clrActiveS
        else
            local colorMap = {
                ["O"] = Config.clrActiveO,
                ["N"] = Config.clrActiveN,
                ["H"] = Config.clrActiveH,
                ["M"] = Config.clrActiveM
            }
            color = colorMap[btn.colorType] or Config.clrActive
        end
    else
        color = Config.clrInactive
    end
    local fontString = btn:GetFontString()
    if fontString then
        fontString:SetTextColor(unpack(color))
    end
end

-- 更新专精拾取按钮高亮状态
local function UpdateSpecLootBtn()
    local currentLootSpec = GetLootSpecialization()
    local activeSpec = GetSpecialization()
    local activeSpecID = activeSpec and GetSpecializationInfo(activeSpec) or 0
    for _, btn in ipairs(specLootBtn) do
        local isActive = (btn.specID == currentLootSpec) or (currentLootSpec == 0 and btn.specID == activeSpecID)
        UpdateBtnState(btn, isActive, true, false)
    end
end

-- 创建专精拾取按钮
local function CreateSpecLootBtn()
    if #specLootBtn == 0 then
        rowBtn[1] = {}
        local numSpecs = GetNumSpecializations()
        for i = 1, numSpecs do
            local specID, specName = GetSpecializationInfo(i)
            if specID then
                local btn = CreateTextBtn(1, i, specName, Config.clrInactive, {specID = specID})
                specLootBtn[i] = btn
                btn:SetScript("OnClick", function(self)
                    SetLootSpecialization(self.specID)
                    UpdateSpecLootBtn()
                end)
            end
        end
        LayoutRowBtn()
    end
    UpdateSpecLootBtn()
end

-- 统一权限检查函数
local function GetPermissionState()
    local inInstance = IsInInstance()
    local inGroup = IsInGroup() or IsInRaid()
    local isLeader = UnitIsGroupLeader("player")
    local isRaid = IsInRaid()
    local isAlone = not inGroup and not isRaid
    
    -- 检查是否在实例队伍中（随机副本队伍）
    local isInInstanceGroup = IsInGroup(LE_PARTY_CATEGORY_INSTANCE)
    
    -- 如果正在随机副本队伍中，即使被传送到副本外，也应视为在副本内处理难度按钮
    local shouldTreatDiffBtnsAsInInstance = inInstance or isInInstanceGroup
    
    -- 检查是否需要禁用一键退出按钮，如果是单人并在野外则禁用。
    local function ShouldDisableLeaveGroupBtn()
        return not IsInInstance() and not IsInGroup() and not IsInRaid()
    end
    
    -- 检查是否可以使用传送功能 - 只要在随机副本队伍中就可以使用
    local function CanUseLFGTeleport()
        -- 检查是否在随机副本队伍中（实例队伍）
        return isInInstanceGroup
    end
    
    -- 就位功能权限：只有在队伍中且是队长/团长才能使用
    local function CanUseReadyCheck()
        return inGroup and isLeader
    end
    
    -- 重置功能权限：在副本内只有队长/团长可以倒数，在副本外只有队长/团长可以重置
    local function CanUseReset()
        if inInstance then
            -- 在副本内，只有队长/团长才能倒数
            return not inGroup or isLeader
        else
            -- 在副本外，只有队长/团长可以重置
            return not inGroup or isLeader
        end
    end
    
    -- 检查难度设置权限：不在副本内，并且（单人或者队长/团长）
    -- 如果在随机副本队伍中，即使不在副本内，也不能改变难度
    local function CanChangeDifficulty()
        return not shouldTreatDiffBtnsAsInInstance and (not inGroup or isLeader)
    end
    
    return {
        canChangeDiff = CanChangeDifficulty(),
        canUseTeleport = CanUseLFGTeleport(),
        canUseLeaveGroup = not ShouldDisableLeaveGroupBtn(),
        canUseReadyCheck = CanUseReadyCheck(),
        canUseReset = CanUseReset(),
        isAlone = isAlone,
        isLeader = isLeader,
        isRaid = isRaid,
        inGroup = inGroup,
        inInstance = inInstance,
        isInInstanceGroup = isInInstanceGroup,
        shouldTreatDiffBtnsAsInInstance = shouldTreatDiffBtnsAsInInstance
    }
end

-- 集中难度检测函数
local function GetCurrentDiffInfo()
    local dungeonDiff = GetDungeonDifficultyID and GetDungeonDifficultyID() or 0
    local raidDiff = GetRaidDifficultyID and GetRaidDifficultyID() or 0
    local legacyDiff = GetLegacyRaidDifficultyID and GetLegacyRaidDifficultyID() or 0
    local currentDiff = raidDiff > 0 and raidDiff or legacyDiff
    local raidNum = 25
    if legacyDiff == diffData["10N"] or legacyDiff == diffData["10H"] then raidNum = 10
    elseif legacyDiff == diffData["25N"] or legacyDiff == diffData["25H"] then raidNum = 25
    end
    return {
        dungeon = dungeonDiff,
        raid = currentDiff,
        legacy = legacyDiff,
        raidNum = raidNum,
        isMythic = currentDiff == diffData["M"],
        isHeroic = currentDiff == diffData["H"] or currentDiff == diffData["10H"] or currentDiff == diffData["25H"],
        isNormal = currentDiff == diffData["N"] or currentDiff == diffData["10N"] or currentDiff == diffData["25N"]
    }
end

-- 合并状态更新函数
local function UpdateAllBtnStates()
    local permState = GetPermissionState()
    local diffInfo = GetCurrentDiffInfo()
    -- 更新地下城难度按钮
    for _, btn in ipairs(dungeonBtn) do
        local isActive = btn.diffID == diffInfo.dungeon
        UpdateBtnState(btn, isActive, permState.canChangeDiff, false)
    end
    -- 更新团本难度按钮
    for _, btn in ipairs(raidBtn) do
        local isActive = false
        if diffInfo.isMythic and btn.diff10 == diffData["M"] then isActive = true
        elseif diffInfo.isHeroic and btn.diff10 == diffData["10H"] then isActive = true
        elseif diffInfo.isNormal and btn.diff10 == diffData["10N"] then isActive = true
        end
        UpdateBtnState(btn, isActive, permState.canChangeDiff, false)
    end
    -- 更新团本人数按钮
    for _, btn in ipairs(raidNumBtn) do
        local isActive = btn.raidNum == diffInfo.raidNum
        local isEnabled = permState.canChangeDiff and not diffInfo.isMythic
        UpdateBtnState(btn, isActive, isEnabled, false)
    end
    -- 更新功能按钮
    UpdateBtnState(resetBtn, true, permState.canUseReset, true)
    UpdateBtnState(teleportBtn, true, permState.canUseTeleport, true) -- 只要在随机副本队伍中就可以传送
    UpdateBtnState(readyCheckBtn, true, permState.canUseReadyCheck, true)
    UpdateBtnState(leaveGroupBtn, true, permState.canUseLeaveGroup, true)
end

-- 团本人数切换函数
local function SetRaidNum(targetRaidNum)
    local permState = GetPermissionState()
    -- 检查是否有权限
    if not permState.canChangeDiff then 
        if permState.inGroup and not permState.isLeader then
            print("|cFFFF0000错误：只有队长/团长才能设置团本人数|r")
        end
        return 
    end
    local diffInfo = GetCurrentDiffInfo()
    local newLegacyId, newModernId
    if diffInfo.isMythic then
        newLegacyId = diffData["M"]
        newModernId = diffData["M"]
    elseif diffInfo.isHeroic then
        newLegacyId = targetRaidNum == 10 and diffData["10H"] or diffData["25H"]
        newModernId = diffData["H"]
    else
        newLegacyId = targetRaidNum == 10 and diffData["10N"] or diffData["25N"]
        newModernId = diffData["N"]
    end
    if SetRaidDifficultyID then SetRaidDifficultyID(newModernId) end
    if SetLegacyRaidDifficultyID then SetLegacyRaidDifficultyID(newLegacyId) end
    UpdateAllBtnStates()
end

-- 统一的按钮点击事件处理函数
local function CreateBtnClickHandler(actionType, actionData)
    return function(self)
        local permState = GetPermissionState()
        
        -- 检查权限
        if not permState.canChangeDiff then
            if permState.inGroup and not permState.isLeader then
                print("|cFFFF0000错误：只有队长/团长才能设置难度|r")
            end
            return
        end
        
        if actionType == "raidNum" then
            SetRaidNum(actionData)
        elseif actionType == "dungeon" then
            SetDungeonDifficultyID(actionData)
            UpdateAllBtnStates()
        elseif actionType == "raid" then
            local diffInfo = GetCurrentDiffInfo()
            local legacyDiffID = diffInfo.raidNum == 10 and actionData.diff10 or actionData.diff25
            local modernDiffID = actionData.diff10 == diffData["10N"] and diffData["N"] or (actionData.diff10 == diffData["10H"] and diffData["H"] or diffData["M"])
            if SetRaidDifficultyID then
                SetRaidDifficultyID(modernDiffID)
            end
            if SetLegacyRaidDifficultyID then
                SetLegacyRaidDifficultyID(legacyDiffID)
            end
            UpdateAllBtnStates()
        end
    end
end
-- 地下城按钮点击事件
for i, btn in ipairs(dungeonBtn) do
    btn:SetScript("OnClick", CreateBtnClickHandler("dungeon", btn.diffID))
end
-- 10人按钮点击事件
raidNumBtn[1]:SetScript("OnClick", CreateBtnClickHandler("raidNum", 10))
-- 25人按钮点击事件
raidNumBtn[2]:SetScript("OnClick", CreateBtnClickHandler("raidNum", 25))
-- 团本难度按钮点击事件
for i, btn in ipairs(raidBtn) do
    btn:SetScript("OnClick", CreateBtnClickHandler("raid", {
        diff10 = btn.diff10,
        diff25 = btn.diff25
    }))
end

-- 定期检查难度状态变化的定时器，发生变化则更新按钮状态。
local lastKnownDiffInfo = nil
local function CheckDiffChanges()
    local currentDiffInfo = GetCurrentDiffInfo()
    local hasChanged = false
    if not lastKnownDiffInfo or
       lastKnownDiffInfo.dungeon ~= currentDiffInfo.dungeon or
       lastKnownDiffInfo.raid ~= currentDiffInfo.raid or
       lastKnownDiffInfo.legacy ~= currentDiffInfo.legacy then
        hasChanged = true
        lastKnownDiffInfo = currentDiffInfo
    end
    if hasChanged then UpdateAllBtnStates()
    end
end

-- 处理副本状态变化，进入副本收缩界面，离开副本展开界面
local function HandleInstanceStateChange()
    local permState = GetPermissionState()
    local inInstance = permState.inInstance
    
    if wasInInstance and not inInstance then
        -- 离开副本状态
        SetCollapsedMode(false)
    elseif inInstance then
        -- 进入副本状态
        SetCollapsedMode(true)
    end
    wasInInstance = inInstance
end

-- 初始化函数
local function InitializeAddon()
    UpdateAllBtnStates() -- 更新按钮难度设置状态
    CreateSpecLootBtn() -- 创建专精拾取按钮
    LayoutRowBtn() -- 布局所有按钮
    HandleInstanceStateChange() -- 检查是否在副本内
end

-- 事件处理函数，并延迟处理一些事件。
frame:SetScript("OnEvent", function(self, event, ...)
    if event == "ZONE_CHANGED_NEW_AREA" then
        HandleInstanceStateChange()
    elseif event == "GUILD_PARTY_STATE_UPDATED" or event == "UPDATE_INSTANCE_INFO" or event == "RAID_INSTANCE_WELCOME" then
        UpdateAllBtnStates()
    elseif event == "PLAYER_DIFFICULTY_CHANGED" or event == "PLAYER_ENTERING_WORLD" or event == "GROUP_FORMED" or event == "GROUP_LEFT" or event == "GROUP_ROSTER_UPDATE" then
        C_Timer.After(0.1, UpdateAllBtnStates)
    elseif event == "PARTY_LEADER_CHANGED" then
        C_Timer.After(0.2, UpdateAllBtnStates)
    elseif event == "GROUP_JOINED" then
        C_Timer.After(0.5, UpdateAllBtnStates)
    elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
        CreateSpecLootBtn()
    elseif event == "PLAYER_LOOT_SPEC_UPDATED" then
        UpdateSpecLootBtn()
    end
end)

-- 注册事件
frame:RegisterEvent("PLAYER_DIFFICULTY_CHANGED")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
frame:RegisterEvent("GROUP_FORMED")
frame:RegisterEvent("GROUP_LEFT")
frame:RegisterEvent("GROUP_ROSTER_UPDATE")
frame:RegisterEvent("GUILD_PARTY_STATE_UPDATED")
frame:RegisterEvent("UPDATE_INSTANCE_INFO")
frame:RegisterEvent("PARTY_LEADER_CHANGED")
frame:RegisterEvent("GROUP_JOINED")
frame:RegisterEvent("RAID_INSTANCE_WELCOME")
frame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
frame:RegisterEvent("PLAYER_LOOT_SPEC_UPDATED")

-- 初始化
local initFrame = CreateFrame("Frame")
initFrame:RegisterEvent("PLAYER_LOGIN")
initFrame:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_LOGIN" then
        C_Timer.After(0.1, InitializeAddon) -- 读取当前游戏状态
        frame:Show() -- 默认显示界面
        C_Timer.NewTicker(0.5, CheckDiffChanges) -- 启动定时器检查难度变化
        self:UnregisterEvent("PLAYER_LOGIN")
        self:SetScript("OnEvent", nil)
    end
end)