-- Portal Authority — core/keystone.lua
-- Keystone utility runtime, release-gate logic, and tooltip customization.
--
-- Depends on: PortalAuthority; PortalAuthority.CoreInternal helpers; PortalAuthority.SpellMap
-- Exposes:    KeystoneUtility_* methods, InitializeKeystoneUtility, InitializeKeystoneTooltip, ApplyKeystoneUtilitySettings
-- DB keys:    keystone*, releaseGate*
-- Events:     none
-- Search key: none

local ADDON_NAME = ...

PortalAuthority = PortalAuthority or {}
PortalAuthority.CoreInternal = PortalAuthority.CoreInternal or {}
local CoreInternal = PortalAuthority.CoreInternal
local L = PortalAuthority.L

local PA_IsUiSurfaceGateEnabled = CoreInternal.PA_IsUiSurfaceGateEnabled
local PA_IsStaticBaselineGateEnabled = CoreInternal.PA_IsStaticBaselineGateEnabled
local PA_IsSettingsBaselineGateEnabled = CoreInternal.PA_IsSettingsBaselineGateEnabled
local PA_IsSettingsEagerBuildGateEnabled = CoreInternal.PA_IsSettingsEagerBuildGateEnabled
local PA_IsSettingsDirectBuildGateEnabled = CoreInternal.PA_IsSettingsDirectBuildGateEnabled
local PA_IsSettingsWindowHostEnabled = CoreInternal.PA_IsSettingsWindowHostEnabled
local PA_IsSettingsWindowDevGateEnabled = CoreInternal.PA_IsSettingsWindowDevGateEnabled
local PA_IsSettingsWindowPublicGateEnabled = CoreInternal.PA_IsSettingsWindowPublicGateEnabled
local PA_IsOnboardingD1DevGateEnabled = CoreInternal.PA_IsOnboardingD1DevGateEnabled
local PA_IsOnboardingD3DevGateEnabled = CoreInternal.PA_IsOnboardingD3DevGateEnabled
local PA_IsOnboardingD4DevGateEnabled = CoreInternal.PA_IsOnboardingD4DevGateEnabled
local PA_IsOnboardingD3PublicGateEnabled = CoreInternal.PA_IsOnboardingD3PublicGateEnabled
local PA_IsOnboardingD4PublicGateEnabled = CoreInternal.PA_IsOnboardingD4PublicGateEnabled
local PA_IsOnboardingQualifyingUpgradePublicGateEnabled = CoreInternal.PA_IsOnboardingQualifyingUpgradePublicGateEnabled
local PA_IsOnboardingD3Enabled = CoreInternal.PA_IsOnboardingD3Enabled
local PA_IsOnboardingD4Enabled = CoreInternal.PA_IsOnboardingD4Enabled
local trim = CoreInternal.trim
local clampNumber = CoreInternal.clampNumber
local PA_Clamp = CoreInternal.PA_Clamp
local PA_ToNumber = CoreInternal.PA_ToNumber
local PA_SafeBool = CoreInternal.PA_SafeBool
local PA_CompareSemver = CoreInternal.PA_CompareSemver
local PA_IsSemverStringValid = CoreInternal.PA_IsSemverStringValid
local PA_GetCurrentAddonVersionState = CoreInternal.PA_GetCurrentAddonVersionState
local VALID_OUTLINES = CoreInternal.VALID_OUTLINES
local VALID_SOUND_CHANNELS = CoreInternal.VALID_SOUND_CHANNELS
local BUILTIN_FONT_FALLBACK = CoreInternal.BUILTIN_FONT_FALLBACK
local PLAYER_LOGIN_MESSAGE = CoreInternal.PLAYER_LOGIN_MESSAGE
local DOCK_ENABLE_DEFAULTS_VERSION = CoreInternal.DOCK_ENABLE_DEFAULTS_VERSION
local PA_PrintPortalAuthorityMessage = CoreInternal.PA_PrintPortalAuthorityMessage
local PA_MaybeShowMPlusNotice = CoreInternal.PA_MaybeShowMPlusNotice
local ResetMPlusNoticeShown = CoreInternal.ResetMPlusNoticeShown
local PA_IsSecretValue = CoreInternal.PA_IsSecretValue
local PA_NormalizeSafeString = CoreInternal.PA_NormalizeSafeString
local PA_SafeStringsEqual = CoreInternal.PA_SafeStringsEqual
local PA_SafeUnitGUID = CoreInternal.PA_SafeUnitGUID

local function PA_LeaderOrAssist()
    return PA_SafeBool(UnitIsGroupLeader and UnitIsGroupLeader("player"))
        or PA_SafeBool(UnitIsGroupAssistant and UnitIsGroupAssistant("player"))
end

local function PA_ApplyExternalButtonSkin(btn)
    if not btn then
        return
    end
    local elv = _G.ElvUI
    local E = nil
    if type(elv) == "table" then
        E = elv[1] or elv
    end
    if E and E.GetModule then
        local okS, S = pcall(E.GetModule, E, "Skins")
        if okS and S and S.HandleButton then
            pcall(S.HandleButton, S, btn)
        end
    end
end
function PortalAuthority:KeystoneUtility_GetPullSeconds(short)
    local defaults = self.defaults or {}
    local fallback = short and (defaults.pullShortSeconds or 5) or (defaults.pullLongSeconds or 10)
    if not PortalAuthorityDB then
        return fallback
    end
    local value = short and PortalAuthorityDB.pullShortSeconds or PortalAuthorityDB.pullLongSeconds
    return math.floor(PA_Clamp(value, fallback, 1, 60))
end

function PortalAuthority:KeystoneUtility_UpdateButtons()
    local util = self.KeystoneUtility
    if not util then return end
    local kf = _G.ChallengesKeystoneFrame
    local container = util.container or (kf and kf.PA_KeystoneUtilContainer)
    if not container then return end

    local enabled = PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneHelperEnabled)
    local shown = kf and kf.IsShown and kf:IsShown()
    container:SetShown(enabled and shown)
    if not (enabled and shown) then
        return
    end

    if util.pullButton and util.pullButton.SetText then
        util.pullButton:SetText(L["COMMON_COUNTDOWN"])
    end
    if util.readyButton and util.readyButton.SetText then
        util.readyButton:SetText(L["COMMON_READY_CHECK"])
    end

    local hasKeystone = PA_KeystoneIsSlotted and PA_KeystoneIsSlotted() or false
    local leaderOk = PA_LeaderOrAssist()
    local inCombat = PA_SafeBool(InCombatLockdown and InCombatLockdown())

    if util.readyButton then
        PA_ApplyExternalButtonSkin(util.readyButton)
        if (not inCombat) and hasKeystone and leaderOk then
            util.readyButton:Enable()
        else
            util.readyButton:Disable()
        end
    end

    if util.pullButton then
        PA_ApplyExternalButtonSkin(util.pullButton)
        if (not inCombat) and hasKeystone then
            util.pullButton:Enable()
        else
            util.pullButton:Disable()
        end
    end
end

function PortalAuthority:KeystoneUtility_EnsureKeystoneButtons()
    local kf = _G.ChallengesKeystoneFrame
    if not kf then return end

    local util = self.KeystoneUtility
    if not util.container then
        local container = CreateFrame("Frame", nil, kf)
        container:SetPoint("BOTTOMLEFT", kf, "BOTTOMLEFT", 0, 0)
        container:SetSize(110, 50)
        kf.PA_KeystoneUtilContainer = container
        util.container = container

        local function makeButton(parent, text)
            local btn = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
            btn:SetSize(100, 22)
            btn:SetText(text)
            PA_ApplyExternalButtonSkin(btn)
            return btn
        end

        util.readyButton = makeButton(container, L["COMMON_READY_CHECK"])
        util.readyButton:SetPoint("TOPLEFT", container, "TOPLEFT", 0, 0)
        util.readyButton:SetScript("OnClick", function()
            if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
            if not (PA_KeystoneIsSlotted and PA_KeystoneIsSlotted()) then return end
            if not PA_LeaderOrAssist() then return end
            if type(DoReadyCheck) == "function" then
                pcall(DoReadyCheck)
            end
        end)

        util.pullButton = makeButton(container, L["COMMON_COUNTDOWN"])
        util.pullButton:SetPoint("TOPLEFT", util.readyButton, "BOTTOMLEFT", 0, -4)
        util.pullButton:SetScript("OnClick", function()
            if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
            if not (PA_KeystoneIsSlotted and PA_KeystoneIsSlotted()) then return end
            self:KeystoneUtility_DoPull10()
        end)

        local function startPolling()
            if PortalAuthority.KeystoneUtility and PortalAuthority.KeystoneUtility.container then
                local utilNow = PortalAuthority.KeystoneUtility
                utilNow._pollElapsed = 0
                PortalAuthority.KeystoneUtility.container:SetScript("OnUpdate", function(_, elapsed)
                    local perfStart, perfState = PortalAuthority:PerfBegin("keystone_buttons_poll")
                    PortalAuthority:CpuDiagCount("keystone_buttons_poll")
                    utilNow._pollElapsed = (utilNow._pollElapsed or 0) + (tonumber(elapsed) or 0)
                    if utilNow._pollElapsed >= 0.25 then
                        utilNow._pollElapsed = 0
                        PortalAuthority:KeystoneUtility_UpdateButtons()
                    end
                    PortalAuthority:PerfEnd("keystone_buttons_poll", perfStart, perfState)
                end)
            end
        end

        if not util.frameHooksSet then
            util.frameHooksSet = true
            kf:HookScript("OnShow", function()
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_frame_onshow")
                startPolling()
                PortalAuthority:KeystoneUtility_UpdateButtons()
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
            kf:HookScript("OnHide", function()
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_frame_onhide")
                if PortalAuthority.KeystoneUtility and PortalAuthority.KeystoneUtility.container then
                    PortalAuthority.KeystoneUtility.container:SetScript("OnUpdate", nil)
                    PortalAuthority.KeystoneUtility.container:Hide()
                end
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
        end

        if not util.keystoneSlotHooksSet and kf.KeystoneSlot then
            util.keystoneSlotHooksSet = true
            local function queueRefresh()
                if C_Timer and C_Timer.After then
                    C_Timer.After(0, function()
                        PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_buttons_refresh")
                        PortalAuthority:KeystoneUtility_UpdateButtons()
                    end)
                else
                    PortalAuthority:KeystoneUtility_UpdateButtons()
                end
            end
            kf.KeystoneSlot:HookScript("OnClick", function()
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_slot_onclick")
                queueRefresh()
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
            kf.KeystoneSlot:HookScript("OnReceiveDrag", function()
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_slot_onreceivedrag")
                queueRefresh()
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
            kf.KeystoneSlot:HookScript("OnMouseUp", function()
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_slot_onmouseup")
                queueRefresh()
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
        end

        if kf.IsShown and kf:IsShown() then
            startPolling()
            PortalAuthority:KeystoneUtility_UpdateButtons()
        end
    end

    self:KeystoneUtility_UpdateButtons()
end

PA_SafeNumber = function(v)
    if v == nil then return 0 end
    local ok, s = pcall(tostring, v)
    if not ok or s == nil then return 0 end
    local n = tonumber(s)
    return n or 0
end

local function PA_GetOwnedKeystoneMapID()
    if C_MythicPlus and type(C_MythicPlus.GetOwnedKeystoneMapID) == "function" then
        local ok, mapID = pcall(C_MythicPlus.GetOwnedKeystoneMapID)
        if ok then
            local n = PA_SafeNumber(mapID)
            if n > 0 then return n end
        end
    end
    if C_MythicPlus and type(C_MythicPlus.GetOwnedKeystoneChallengeMapID) == "function" then
        local ok, mapID = pcall(C_MythicPlus.GetOwnedKeystoneChallengeMapID)
        if ok then
            local n = PA_SafeNumber(mapID)
            if n > 0 then return n end
        end
    end
    return 0
end

local function PA_GetCurrentChallengeMapID()
    if C_ChallengeMode and type(C_ChallengeMode.GetActiveChallengeMapID) == "function" then
        local ok, mapID = pcall(C_ChallengeMode.GetActiveChallengeMapID)
        if ok then
            return PA_SafeNumber(mapID)
        end
    end
    return 0
end

local function PA_GetCurrentInstanceID()
    local _, _, _, _, _, _, _, instanceID = GetInstanceInfo()
    return PA_SafeNumber(instanceID)
end

local function PA_HasSlottedKeystone()
    if C_ChallengeMode and type(C_ChallengeMode.GetSlottedKeystoneInfo) == "function" then
        local ok, mapID = pcall(C_ChallengeMode.GetSlottedKeystoneInfo)
        if ok and PA_SafeNumber(mapID) > 0 then
            return true
        end
    end
    return false
end
PA_KeystoneIsSlotted = function()
    if C_ChallengeMode and type(C_ChallengeMode.GetSlottedKeystoneInfo) == "function" then
        local ok, mapID = pcall(C_ChallengeMode.GetSlottedKeystoneInfo)
        if ok and PA_SafeNumber(mapID) > 0 then
            return true
        end
    end
    return false
end

local function PA_IsAddOnLoaded(name)
    if trim(name) == "" then return false end
    if C_AddOns and type(C_AddOns.IsAddOnLoaded) == "function" then
        local ok, loaded = pcall(C_AddOns.IsAddOnLoaded, name)
        return ok and loaded and true or false
    end
    if type(IsAddOnLoaded) == "function" then
        local ok, loaded = pcall(IsAddOnLoaded, name)
        return ok and loaded and true or false
    end
    return false
end

local PA_KEYSTONE_ITEM_IDS = {
    [180653] = true,
    [151086] = true,
    [158923] = true,
    [138019] = true,
}

function PortalAuthority:KeystoneUtility_TryAutoSlot()
    if not PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneAutoSlotEnabled) then return end
    if InCombatLockdown and InCombatLockdown() then return end
    local kf = _G.ChallengesKeystoneFrame
    if not (kf and kf.IsShown and kf:IsShown()) then return end
    self.KeystoneUtility = self.KeystoneUtility or {}
    local util = self.KeystoneUtility
    local now = GetTime()
    if (now - PA_SafeNumber(util.autoSlotLastAttempt)) < 0.5 then return end
    util.autoSlotLastAttempt = now
    local owned = PA_GetOwnedKeystoneMapID()
    if owned <= 0 then return end
    local _, _, _, _, _, _, _, inst = GetInstanceInfo()
    inst = PA_SafeNumber(inst)
    if owned > 0 and inst > 0 and owned ~= inst then return end

    if PA_KeystoneIsSlotted() then return end

    if C_ChallengeMode and type(C_ChallengeMode.SlotKeystone) == "function" then
        pcall(C_ChallengeMode.SlotKeystone)
        if PA_KeystoneIsSlotted() then
            if C_Timer and C_Timer.After then
                C_Timer.After(0, function()
                    PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_buttons_refresh")
                    PortalAuthority:KeystoneUtility_UpdateButtons()
                end)
            else
                self:KeystoneUtility_UpdateButtons()
            end
            return
        end
    end

    if C_Container and type(C_Container.GetContainerNumSlots) == "function" and type(C_Container.GetContainerItemID) == "function" and type(C_Container.UseContainerItem) == "function" then
        local maxBag = NUM_TOTAL_EQUIPPED_BAG_SLOTS or 4
        for bag = BACKPACK_CONTAINER or 0, maxBag do
            local okSlots, slots = pcall(C_Container.GetContainerNumSlots, bag)
            slots = okSlots and tonumber(slots) or 0
            if slots and slots > 0 then
                for slot = 1, slots do
                    local okItem, itemID = pcall(C_Container.GetContainerItemID, bag, slot)
                    local isKeystone = false
                    if okItem and PA_KEYSTONE_ITEM_IDS[PA_SafeNumber(itemID)] then
                        isKeystone = true
                    elseif C_Container.GetContainerItemLink then
                        local okLink, link = pcall(C_Container.GetContainerItemLink, bag, slot)
                        if okLink and link ~= nil then
                            local okFind, found = pcall(string.find, tostring(link), "|Hkeystone:", 1, true)
                            if okFind and found ~= nil then
                                isKeystone = true
                            end
                        end
                    end
                    if isKeystone then
                        pcall(C_Container.UseContainerItem, bag, slot)
                        if C_Timer and C_Timer.After then
                            C_Timer.After(0, function()
                                PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_buttons_refresh")
                                PortalAuthority:KeystoneUtility_UpdateButtons()
                            end)
                        else
                            self:KeystoneUtility_UpdateButtons()
                        end
                        if C_Timer and C_Timer.After then
                            local function retrySlot()
                                PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_slot_retry")
                                if PA_KeystoneIsSlotted() then return end
                                if C_ChallengeMode and type(C_ChallengeMode.SlotKeystone) == "function" then
                                    pcall(C_ChallengeMode.SlotKeystone)
                                end
                            end
                            C_Timer.After(0, retrySlot)
                            C_Timer.After(0.1, retrySlot)
                        end
                        return
                    end
                end
            end
        end
    end
end

function PortalAuthority:KeystoneUtility_TryStartKey(fromFallback)
    if not PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneAutoStartEnabled) then return end
    if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
    if not (C_ChallengeMode and type(C_ChallengeMode.StartChallengeMode) == "function") then return end
    if not PA_LeaderOrAssist() then return end

    if not PA_KeystoneIsSlotted() then return end

    local okStart = pcall(C_ChallengeMode.StartChallengeMode)
    if okStart then
        if _G.ChallengesKeystoneFrame and _G.ChallengesKeystoneFrame.Hide then
            _G.ChallengesKeystoneFrame:Hide()
        end
        self:KeystoneUtility_UpdateButtons()
    end

    self.KeystoneUtility = self.KeystoneUtility or {}
    self.KeystoneUtility.pendingAutoStartWaiting = false
    self.KeystoneUtility.pendingAutoStartConsumed = true
end

function PortalAuthority:KeystoneUtility_StartPull(seconds)
    if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
    if not (PA_KeystoneIsSlotted and PA_KeystoneIsSlotted()) then return end

    local sec = math.floor(PA_Clamp(seconds, 10, 1, 60))
    local leaderOk = PA_LeaderOrAssist()
    local autoStartEnabled = PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneAutoStartEnabled)
    self.KeystoneUtility = self.KeystoneUtility or {}
    local util = self.KeystoneUtility
    util.pendingAutoStartAt = GetTime()
    util.pendingAutoStartSec = sec
    util.pendingAutoStartSawStartTimer = false
    util.pendingAutoStartWaiting = false
    util.pendingAutoStartConsumed = false

    if RunMacroText then
        pcall(RunMacroText, string.format("/cd %d", sec))
    end

    if C_PartyInfo and type(C_PartyInfo.DoCountdown) == "function" then
        pcall(C_PartyInfo.DoCountdown, sec)
    end

    if autoStartEnabled and leaderOk then
        util.pendingAutoStartWaiting = true
        if C_Timer and C_Timer.After then
            C_Timer.After(0.5, function()
                PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_autostart_arm_clear")
                local utilNow = PortalAuthority.KeystoneUtility
                if not utilNow then return end
                if utilNow.pendingAutoStartWaiting and not utilNow.pendingAutoStartSawStartTimer then
                    utilNow.pendingAutoStartWaiting = false
                end
            end)
        end
    else
        util.pendingAutoStartWaiting = false
    end
end

function PortalAuthority:KeystoneUtility_DoPull10()
    if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
    if not (PA_KeystoneIsSlotted and PA_KeystoneIsSlotted()) then return end
    self.KeystoneUtility = self.KeystoneUtility or {}
    local util = self.KeystoneUtility
    local autoStartEnabled = PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneAutoStartEnabled)
    local leaderOk = PA_LeaderOrAssist()

    util.pendingAutoStartAt = GetTime()
    util.pendingAutoStartSec = 10
    util.pendingAutoStartSawStartTimer = false
    util.pendingAutoStartWaiting = false
    util.pendingAutoStartConsumed = false

    local macroOk = false
    if RunMacroText then
        macroOk = pcall(RunMacroText, "/cd 10") and true or false
    end

    local blizzOk = false
    if (not macroOk) and C_PartyInfo and type(C_PartyInfo.DoCountdown) == "function" then
        blizzOk = pcall(C_PartyInfo.DoCountdown, 10) and true or false
    end

    local countdownStarted = macroOk or blizzOk

    if countdownStarted and autoStartEnabled and leaderOk then
        util.pendingAutoStartWaiting = true
        if C_Timer and C_Timer.After then
            C_Timer.After(10, function()
                PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_autostart_fallback")
                local utilNow = PortalAuthority.KeystoneUtility
                if not utilNow then return end
                if utilNow.pendingAutoStartWaiting and (not utilNow.pendingAutoStartConsumed) and (not utilNow.pendingAutoStartSawStartTimer) then
                    PortalAuthority:KeystoneUtility_TryStartKey(true)
                end
            end)
        end
    else
        util.pendingAutoStartWaiting = false
    end
end

function PortalAuthority:KeystoneUtility_OnEvent(event, ...)
    if event == "CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN" then
        if PortalAuthorityDB and PortalAuthorityDB.keystoneHelperEnabled then
            self:KeystoneUtility_EnsureKeystoneButtons()
        end
        if InCombatLockdown and InCombatLockdown() then return end
        self:KeystoneUtility_TryAutoSlot()
        return
    end

    if event == "START_TIMER" then
        if not PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.keystoneAutoStartEnabled) then return end
        if PA_SafeBool(InCombatLockdown and InCombatLockdown()) then return end
        self.KeystoneUtility = self.KeystoneUtility or {}
        local util = self.KeystoneUtility
        if not util.pendingAutoStartWaiting then return end
        local timerType, timeSeconds, totalTime = ...
        local dur = tonumber(totalTime) or tonumber(timeSeconds)
        if not dur or dur < 1 or dur > 60 then return end
        if util.pendingAutoStartSec and math.abs(dur - util.pendingAutoStartSec) > 0.5 then return end
        if not PA_LeaderOrAssist() then return end
        if not (PA_KeystoneIsSlotted and PA_KeystoneIsSlotted()) then return end
        if not (C_Timer and C_Timer.After) then return end
        util.pendingAutoStartSawStartTimer = true
        util.pendingAutoStartConsumed = true
        util.pendingAutoStartWaiting = false
        C_Timer.After(dur, function()
            PortalAuthority:CpuDiagCount("callback_class_delayed_timer", "keystone_autostart_startkey")
            PortalAuthority:KeystoneUtility_TryStartKey()
        end)
        return
    end
end

function PortalAuthority:KeystoneUtility_SetupReleaseGate()
    if PA_IsUiSurfaceGateEnabled() then
        return
    end
    local util = self.KeystoneUtility
    if util.releaseGateSetup then return end
    util.releaseGateSetup = true

    local function getModifierDown(modifier)
        if modifier == "CTRL" then
            return IsControlKeyDown and IsControlKeyDown()
        end
        return IsShiftKeyDown and IsShiftKeyDown()
    end

    local function ensureHint(popup)
        if popup.PAReleaseGateHint then
            local hint = popup.PAReleaseGateHint
            hint:ClearAllPoints()
            hint:SetPoint("TOP", popup, "BOTTOM", 0, 20)
            hint:SetTextColor(1, 0.2, 0.2, 1)
            return hint
        end
        local hint = popup:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
        hint:ClearAllPoints()
        hint:SetPoint("TOP", popup, "BOTTOM", 0, 10)
        hint:SetTextColor(1, 0.2, 0.2, 1)
        popup.PAReleaseGateHint = hint
        return hint
    end

    local function ensureBlocker(popup, releaseButton)
        if popup.PAReleaseGateBlocker then
            return popup.PAReleaseGateBlocker
        end
        local blocker = CreateFrame("Button", nil, popup)
        blocker:SetAllPoints(releaseButton)
        blocker:SetFrameLevel((releaseButton:GetFrameLevel() or 1) + 5)
        blocker:EnableMouse(true)
        blocker:RegisterForClicks("LeftButtonUp", "RightButtonUp")
        blocker:SetScript("OnClick", function() end)
        blocker:Hide()
        popup.PAReleaseGateBlocker = blocker
        return blocker
    end

    local function updatePopup(popup, elapsed)
        if not popup or not popup:IsShown() then return end
        local okW, which = pcall(tostring, popup.which)
        if not okW then return end
        local releaseButton = popup.GetButton and popup:GetButton(1) or nil
        if not releaseButton then return end
        local blocker = ensureBlocker(popup, releaseButton)

        if which == "RECOVER_CORPSE" then
            blocker:Hide()
            releaseButton:Show()
            releaseButton:Enable()
            releaseButton:SetAlpha(1)
            if popup.PAReleaseGateHint then popup.PAReleaseGateHint:Hide() end
            popup.PAReleaseGateHeld = 0
            popup.PAReleaseGateClicked = false
            return
        end
        if which ~= "DEATH" then
            blocker:Hide()
            releaseButton:SetAlpha(1)
            return
        end

        if not PA_SafeBool(PortalAuthorityDB and PortalAuthorityDB.releaseGateEnabled) then
            blocker:Hide()
            releaseButton:Show()
            releaseButton:Enable()
            releaseButton:SetAlpha(1)
            if popup.PAReleaseGateHint then popup.PAReleaseGateHint:Hide() end
            popup.PAReleaseGateHeld = 0
            popup.PAReleaseGateClicked = false
            return
        end

        local modifier = PortalAuthorityDB.releaseGateModifier == "CTRL" and "CTRL" or "SHIFT"
        local holdSeconds = PA_Clamp(PortalAuthorityDB.releaseGateHoldSeconds, 1.0, 0.0, 5.0)
        local hint = ensureHint(popup)
        hint:SetText(string.format(L["RUNTIME_KEYSTONE_HOLD_TO_RELEASE_FORMAT"], modifier))
        hint:Show()

        local down = getModifierDown(modifier)
        if not down then
            popup.PAReleaseGateHeld = 0
            popup.PAReleaseGateClicked = false
            blocker:Show()
            releaseButton:Show()
            releaseButton:Enable()
            releaseButton:SetAlpha(0.35)
            return
        end

        blocker:Hide()
        releaseButton:Show()
        releaseButton:Enable()
        releaseButton:SetAlpha(1)
        if popup.PAReleaseGateClicked then
            return
        end

        popup.PAReleaseGateHeld = (popup.PAReleaseGateHeld or 0) + (tonumber(elapsed) or 0)
        if popup.PAReleaseGateHeld >= holdSeconds then
            popup.PAReleaseGateClicked = true
            pcall(function() releaseButton:Click() end)
        end
    end

    local function hookPopup(popup)
        if not popup then return end
        if not popup.PAReleaseGateHooked then
            popup.PAReleaseGateHooked = true
            popup:HookScript("OnUpdate", function(selfPopup, elapsed)
                local perfStart, perfState = PortalAuthority:PerfBegin("release_gate_popup_onupdate")
                PortalAuthority:CpuDiagCount("release_gate_popup_onupdate")
                updatePopup(selfPopup, elapsed)
                PortalAuthority:PerfEnd("release_gate_popup_onupdate", perfStart, perfState)
            end)
            popup:HookScript("OnHide", function(selfPopup)
                selfPopup.PAReleaseGateHeld = 0
                selfPopup.PAReleaseGateClicked = false
                local releaseButton = selfPopup.GetButton and selfPopup:GetButton(1) or nil
                local blocker = selfPopup.PAReleaseGateBlocker
                if blocker then
                    blocker:Hide()
                end
                if releaseButton then
                    releaseButton:Show()
                    releaseButton:Enable()
                    releaseButton:SetAlpha(1)
                end
                if selfPopup.PAReleaseGateHint then
                    selfPopup.PAReleaseGateHint:Hide()
                end
            end)
        end
        hooksecurefunc(popup, "Show", function(selfPopup)
            local okW, which = pcall(tostring, selfPopup.which)
            if not okW then return end
            if which == "RECOVER_CORPSE" then
                local releaseButton = selfPopup.GetButton and selfPopup:GetButton(1) or nil
                local blocker = selfPopup.PAReleaseGateBlocker
                if blocker then
                    blocker:Hide()
                end
                if releaseButton then
                    releaseButton:Show()
                    releaseButton:Enable()
                    releaseButton:SetAlpha(1)
                end
                if selfPopup.PAReleaseGateHint then
                    selfPopup.PAReleaseGateHint:Hide()
                end
                return
            end
            if which ~= "DEATH" then return end
            selfPopup.PAReleaseGateHeld = 0
            selfPopup.PAReleaseGateClicked = false
            updatePopup(selfPopup, 0)
        end)
    end

    hookPopup(_G.StaticPopup1)
    hookPopup(_G.StaticPopup2)
    hookPopup(_G.StaticPopup3)
    hookPopup(_G.StaticPopup4)
end

function PortalAuthority:InitializeKeystoneUtility()
    if PA_IsUiSurfaceGateEnabled() then
        return
    end
    self.KeystoneUtility = self.KeystoneUtility or {}
    if self.KeystoneUtility.initialized then return end
    self.KeystoneUtility.initialized = true

    local frame = CreateFrame("Frame")
    self.KeystoneUtility.frame = frame
    frame:RegisterEvent("CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN")
    frame:RegisterEvent("START_TIMER")
    frame:SetScript("OnEvent", function(_, event, ...)
        PortalAuthority:CpuDiagRecordDispatcherEvent("keystone", event)
        local perfStart, perfState = PortalAuthority:PerfBegin("keystone_event_dispatch")
        PortalAuthority:KeystoneUtility_OnEvent(event, ...)
        PortalAuthority:PerfEnd("keystone_event_dispatch", perfStart, perfState)
    end)

    self:KeystoneUtility_SetupReleaseGate()
end

local PA_KEYSTONE_TOOLTIP_STOPWORDS = {
    ["the"] = true,
    ["of"] = true,
    ["and"] = true,
}

local function PA_ContainsNoCase(haystack, needle)
    local h = trim(haystack)
    local n = trim(needle)
    if h == "" or n == "" then
        return false
    end
    return string.find(string.lower(h), string.lower(n), 1, true) ~= nil
end

local function PA_BuildAcronym(text, maxLen)
    local out = {}
    for word in string.gmatch(trim(text), "%S+") do
        local lowerWord = string.lower(word)
        if not PA_KEYSTONE_TOOLTIP_STOPWORDS[lowerWord] then
            local first = string.sub(word, 1, 1)
            if first ~= "" then
                table.insert(out, string.upper(first))
                if #out >= (maxLen or 4) then
                    break
                end
            end
        end
    end
    if #out == 0 then
        return ""
    end
    return table.concat(out, "")
end

local function PA_GetKeystoneLink(tooltip, tooltipData)
    if tooltipData and type(tooltipData.hyperlink) == "string" then
        return tooltipData.hyperlink
    end
    if tooltip and tooltip.GetItem then
        local _, link = tooltip:GetItem()
        if type(link) == "string" then
            return link
        end
    end
    return nil
end

local function PA_ParseKeystoneLink(link)
    if type(link) ~= "string" then
        return nil
    end
    if not string.find(link, "|Hkeystone:", 1, true) then
        return nil
    end
    local itemString = link:match("|H(keystone:[^|]+)|")
    if not itemString then
        return nil
    end
    local fields = { strsplit(":", itemString) }
    local mapID = PA_ToNumber(fields[3], 0)
    local level = PA_ToNumber(fields[4], 0)
    local affixes = {}
    for i = 5, #fields do
        local id = PA_ToNumber(fields[i], 0)
        if id > 0 then
            table.insert(affixes, id)
        end
    end
    return {
        mapID = mapID,
        level = level,
        affixes = affixes,
    }
end

local function PA_GetKeystoneNameVariants(mapID)
    local fullName = nil
    if C_ChallengeMode and C_ChallengeMode.GetMapUIInfo and mapID and mapID > 0 then
        local ok, name = pcall(C_ChallengeMode.GetMapUIInfo, mapID)
        if ok and type(name) == "string" then
            fullName = trim(name)
        end
    end

    local nickname = nil
    local short = nil
    if fullName and fullName ~= "" then
        nickname = trim((fullName:match("^([^,]+),") or ""))
        if nickname == "" then
            nickname = nil
        end
    end

    if PortalAuthority and PortalAuthority.SpellMap then
        for _, dungeon in pairs(PortalAuthority.SpellMap) do
            if dungeon and dungeon.category == "mplus" then
                local dest = type(dungeon.dest) == "string" and trim(dungeon.dest) or ""
                local shortName = type(dungeon.short) == "string" and trim(dungeon.short) or ""
                if dest ~= "" and fullName and PA_ContainsNoCase(fullName, dest) then
                    nickname = dest
                    if shortName ~= "" then
                        short = shortName
                    end
                    break
                end
            end
        end
    end

    if (not short or short == "") and fullName and fullName ~= "" then
        short = PA_BuildAcronym(fullName, 4)
    end

    return fullName, nickname, short
end

local function PA_ReadTooltipLines(tooltip)
    local lines = {}
    if not tooltip or not tooltip.GetName or not tooltip.NumLines then
        return lines
    end
    local baseName = tooltip:GetName()
    if type(baseName) ~= "string" or baseName == "" then
        return lines
    end
    local numLines = tooltip:NumLines() or 0
    for i = 1, numLines do
        local leftFS = _G[baseName .. "TextLeft" .. i]
        local rightFS = _G[baseName .. "TextRight" .. i]
        local leftText = leftFS and leftFS.GetText and leftFS:GetText() or nil
        local rightText = rightFS and rightFS.GetText and rightFS:GetText() or nil
        local lr, lg, lb = 1, 1, 1
        local rr, rg, rb = 1, 1, 1
        if leftFS and leftFS.GetTextColor then
            lr, lg, lb = leftFS:GetTextColor()
        end
        if rightFS and rightFS.GetTextColor then
            rr, rg, rb = rightFS:GetTextColor()
        end
        table.insert(lines, {
            leftText = leftText or "",
            rightText = rightText or "",
            lr = lr or 1,
            lg = lg or 1,
            lb = lb or 1,
            rr = rr or 1,
            rg = rg or 1,
            rb = rb or 1,
        })
    end
    return lines
end

local function PA_GetTooltipLinePrimaryText(line)
    if not line then
        return ""
    end
    local left = trim(line.leftText or "")
    if left ~= "" then
        return left
    end
    return trim(line.rightText or "")
end

local function PA_GetKeystoneTooltipLineRole(index, line, dungeonLineIndex, mythicLineIndex, affixNames)
    local text = PA_GetTooltipLinePrimaryText(line)
    if text == "" then
        return "blank"
    end

    local lowerText = string.lower(text)
    if index == dungeonLineIndex or PA_ContainsNoCase(text, "Keystone:") then
        return "dungeon"
    end
    if index == mythicLineIndex or PA_ContainsNoCase(text, "Mythic Level") then
        return "mythicLevel"
    end
    if index == 1 and PA_ContainsNoCase(text, "Mythic Keystone") then
        return "itemHeader"
    end
    if string.find(lowerText, "resilient", 1, true) then
        return "resilient"
    end
    if string.find(lowerText, "soulbound", 1, true)
        or string.find(lowerText, "binds when picked up", 1, true)
        or string.find(lowerText, "binds when equipped", 1, true)
    then
        return "soulbound"
    end
    if string.find(lowerText, "unique", 1, true) == 1 then
        return "unique"
    end
    if string.find(lowerText, "duration", 1, true) then
        return "duration"
    end
    if string.find(lowerText, "dungeon modifiers", 1, true)
        or string.find(lowerText, "affixes", 1, true)
    then
        return "affixHeader"
    end
    for affixNameLower in pairs(affixNames or {}) do
        if string.find(lowerText, affixNameLower, 1, true) then
            return "affixLine"
        end
    end
    return "other"
end

local function PA_RemoveTrailingKeystoneFlavorLines(lines)
    local removed = false
    local sawTrailingFlavor = false

    for i = #lines, 2, -1 do
        local line = lines[i]
        local text = PA_GetTooltipLinePrimaryText(line)
        if text == "" then
            if sawTrailingFlavor then
                table.remove(lines, i)
                removed = true
            end
        else
            local role = line._paKeystoneTooltipRole or "other"
            if role == "other" then
                table.remove(lines, i)
                removed = true
                sawTrailingFlavor = true
            else
                break
            end
        end
    end

    return removed
end

local function PA_WriteTooltipLines(tooltip, lines)
    if not tooltip then
        return
    end
    tooltip:ClearLines()
    for _, line in ipairs(lines) do
        local left = line.leftText or ""
        local right = line.rightText or ""
        if right ~= "" then
            tooltip:AddDoubleLine(left, right, line.lr or 1, line.lg or 1, line.lb or 1, line.rr or 1, line.rg or 1, line.rb or 1)
        else
            tooltip:AddLine(left, line.lr or 1, line.lg or 1, line.lb or 1)
        end
    end
    tooltip:Show()
end

function PortalAuthority:KeystoneTooltip_OnItemTooltip(tooltip, tooltipData)
    if not PortalAuthorityDB or not tooltip then
        return false
    end
    local link = PA_GetKeystoneLink(tooltip, tooltipData)
    if type(link) ~= "string" then
        return false
    end
    if not string.find(link, "|Hkeystone:", 1, true) then
        return false
    end
    if tooltip.__PAKeystoneBusy then
        return false
    end

    tooltip.__PAKeystoneBusy = true
    local ok = pcall(function()
        local parsed = PA_ParseKeystoneLink(link)
        if not parsed then
            return
        end

        local mapID = parsed.mapID or 0
        local level = parsed.level or 0
        local affixIDs = parsed.affixes or {}
        local fullName, nickname, short = PA_GetKeystoneNameVariants(mapID)
        local lines = PA_ReadTooltipLines(tooltip)
        if #lines == 0 then
            return
        end

        local changed = false
        local db = PortalAuthorityDB

        local dungeonLineIndex = nil
        local dungeonExisting = nil
        local mythicLineIndex = nil
        for i, line in ipairs(lines) do
            local lt = line.leftText or ""
            if not dungeonLineIndex and PA_ContainsNoCase(lt, "Keystone:") then
                dungeonLineIndex = i
                dungeonExisting = trim((lt:gsub("^[%s]*Keystone:%s*", "")))
            end
            if not mythicLineIndex and PA_ContainsNoCase(lt, "Mythic Level") then
                mythicLineIndex = i
            end
        end

        if dungeonLineIndex then
            local mode = db.keystoneTooltipDungeonNameMode
            local removePrefix = PA_SafeBool(db.keystoneTooltipRemoveKeystonePrefix)
            local displayName = nil
            if mode == "FULL" then
                displayName = fullName or dungeonExisting
            elseif mode == "SHORT" then
                displayName = nickname or fullName or dungeonExisting
            elseif mode == "NICKNAME" then
                displayName = short or fullName or dungeonExisting
            elseif mode == "NICKNAME_FULL" then
                local correctedNickname = short or nickname
                if correctedNickname and fullName and correctedNickname ~= fullName then
                    displayName = correctedNickname .. " - " .. fullName
                else
                    displayName = correctedNickname or fullName or dungeonExisting
                end
            end
            if displayName and trim(displayName) ~= "" then
                local newText = removePrefix and trim(displayName) or ("Keystone: " .. trim(displayName))
                if lines[dungeonLineIndex].leftText ~= newText then
                    lines[dungeonLineIndex].leftText = newText
                    changed = true
                end
            elseif removePrefix then
                local newText = trim((lines[dungeonLineIndex].leftText or ""):gsub("^[%s]*Keystone:%s*", ""))
                if lines[dungeonLineIndex].leftText ~= newText then
                    lines[dungeonLineIndex].leftText = newText
                    changed = true
                end
            end
        end

        local tooltipLevel = level
        if tooltipLevel <= 0 then
            for _, line in ipairs(lines) do
                local n = tonumber((line.leftText or ""):match("(%d+)"))
                if n and PA_ContainsNoCase(line.leftText or "", "Mythic Level") then
                    tooltipLevel = n
                    break
                end
            end
        end
        local removeMythicLevelLine = false
        if db.keystoneTooltipLevelMode == "HIDE" then
            removeMythicLevelLine = true
        elseif tooltipLevel > 0 and db.keystoneTooltipLevelMode ~= "NO_CHANGES" then
            local formatted = nil
            if db.keystoneTooltipLevelMode == "PLUS_N" then
                formatted = "+" .. tostring(math.floor(tooltipLevel))
            elseif db.keystoneTooltipLevelMode == "N" then
                formatted = tostring(math.floor(tooltipLevel))
            elseif db.keystoneTooltipLevelMode == "M_N_PLUS" then
                formatted = "m" .. tostring(math.floor(tooltipLevel)) .. "+"
            end
            if formatted then
                if PA_SafeBool(db.keystoneTooltipLevelAddToName) and dungeonLineIndex then
                    local dungeonText = trim(lines[dungeonLineIndex].leftText or "")
                    dungeonText = trim((dungeonText:gsub("%(Level%s*[%+mM]?%d+%+?%)", "")))
                    local newDungeonText = trim(dungeonText .. " " .. formatted)
                    if newDungeonText ~= dungeonText then
                        lines[dungeonLineIndex].leftText = newDungeonText
                        changed = true
                    end
                    removeMythicLevelLine = true
                elseif mythicLineIndex then
                    if lines[mythicLineIndex].leftText ~= formatted then
                        lines[mythicLineIndex].leftText = formatted
                        changed = true
                    end
                elseif dungeonLineIndex then
                    local old = lines[dungeonLineIndex].leftText or ""
                    local new = old:gsub("%(Level%s*%d+%)", formatted)
                    if new ~= old then
                        lines[dungeonLineIndex].leftText = new
                        changed = true
                    end
                end
            end
        end

        local affixNames = {}
        if #affixIDs > 0 and C_ChallengeMode and C_ChallengeMode.GetAffixInfo then
            for _, affixID in ipairs(affixIDs) do
                local okAffix, affixName = pcall(C_ChallengeMode.GetAffixInfo, affixID)
                if okAffix and type(affixName) == "string" and trim(affixName) ~= "" then
                    affixNames[string.lower(trim(affixName))] = true
                end
            end
        end

        local filtered = {}
        for i, line in ipairs(lines) do
            local left = line.leftText or ""
            local lowerLeft = string.lower(left)
            local role = PA_GetKeystoneTooltipLineRole(i, line, dungeonLineIndex, mythicLineIndex, affixNames)
            local drop = false

            if (not drop) and removeMythicLevelLine and mythicLineIndex and i == mythicLineIndex then
                drop = true
            end
            if db.keystoneTooltipResilientMode == "HIDE" and string.find(lowerLeft, "resilient", 1, true) then
                drop = true
            end
            if (not drop) and db.keystoneTooltipSoulboundMode == "HIDE" and (
                string.find(lowerLeft, "soulbound", 1, true)
                or string.find(lowerLeft, "binds when picked up", 1, true)
                or string.find(lowerLeft, "binds when equipped", 1, true)
            ) then
                drop = true
            end
            if (not drop) and db.keystoneTooltipUniqueMode == "HIDE" and string.find(lowerLeft, "unique", 1, true) == 1 then
                drop = true
            end
            if (not drop) and db.keystoneTooltipDurationMode == "HIDE" and string.find(lowerLeft, "duration", 1, true) then
                drop = true
            end

            local isAffixHeader = (role == "affixHeader")
            if (not drop) and db.keystoneTooltipAffixesMode == "HIDE" then
                if isAffixHeader then
                    drop = true
                elseif role == "affixLine" then
                    drop = true
                else
                    for affixNameLower in pairs(affixNames) do
                        if string.find(lowerLeft, affixNameLower, 1, true) then
                            drop = true
                            break
                        end
                    end
                end
            end

            if not drop then
                if db.keystoneTooltipAffixesMode == "RENAME_AFFIXES" and isAffixHeader then
                    local newText = left:gsub("[Dd]ungeon [Mm]odifiers", "Affixes")
                    if newText ~= left then
                        line.leftText = newText
                        changed = true
                    end
                    local c = db.keystoneTooltipAffixesColor or { r = 1, g = 0.82, b = 0 }
                    line.lr = c.r or 1
                    line.lg = c.g or 0.82
                    line.lb = c.b or 0
                    changed = true
                end
                line._paKeystoneTooltipRole = role
                table.insert(filtered, line)
            else
                changed = true
            end

            if i == #lines then
                -- no-op
            end
        end

        if db.keystoneTooltipRPQuoteMode == "HIDE" and #filtered > 1 then
            if PA_RemoveTrailingKeystoneFlavorLines(filtered) then
                changed = true
            end
        end

        if changed then
            PA_WriteTooltipLines(tooltip, filtered)
        end
    end)
    tooltip.__PAKeystoneBusy = nil
    if not ok then
        return true
    end
    return true
end

function PortalAuthority:InitializeKeystoneTooltip()
    if PA_IsStaticBaselineGateEnabled() then
        return false
    end
    if self._keystoneTooltipHooked then
        return true
    end
    self._keystoneTooltipHooked = true

    if TooltipDataProcessor and TooltipDataProcessor.AddTooltipPostCall and Enum and Enum.TooltipDataType and Enum.TooltipDataType.Item then
        TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, function(tooltip, tooltipData)
            local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
            local handled = PortalAuthority:KeystoneTooltip_OnItemTooltip(tooltip, tooltipData)
            if handled then
                PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_tooltip_postcall")
            end
            PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
        end)
    else
        if GameTooltip and GameTooltip.HookScript then
            GameTooltip:HookScript("OnTooltipSetItem", function(tooltip)
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                local handled = PortalAuthority:KeystoneTooltip_OnItemTooltip(tooltip, nil)
                if handled then
                    PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_tooltip_gametooltip")
                end
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
        end
        if ItemRefTooltip and ItemRefTooltip.HookScript then
            ItemRefTooltip:HookScript("OnTooltipSetItem", function(tooltip)
                local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                local handled = PortalAuthority:KeystoneTooltip_OnItemTooltip(tooltip, nil)
                if handled then
                    PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_tooltip_itemref")
                end
                PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
            end)
        end
    end

    if SetItemRef and C_Timer and C_Timer.After then
        hooksecurefunc("SetItemRef", function()
            C_Timer.After(0, function()
                if ItemRefTooltip and ItemRefTooltip:IsShown() then
                    local perfStart, perfState = PortalAuthority:PerfBegin("callback_class_ui_hook")
                    local handled = PortalAuthority:KeystoneTooltip_OnItemTooltip(ItemRefTooltip, nil)
                    if handled then
                        PortalAuthority:CpuDiagCount("callback_class_ui_hook", "keystone_setitemref_after")
                    end
                    PortalAuthority:PerfEnd("callback_class_ui_hook", perfStart, perfState)
                end
            end)
        end)
    end
    return true
end

function PortalAuthority:ApplyKeystoneUtilitySettings()
    if not PortalAuthorityDB then return end
    if PA_SafeBool(PortalAuthorityDB.keystoneHelperEnabled) then
        self:KeystoneUtility_EnsureKeystoneButtons()
    elseif self.KeystoneUtility and self.KeystoneUtility.container then
        self.KeystoneUtility.container:Hide()
    end
    self:KeystoneUtility_UpdateButtons()
end
