-- SaveVariables helper for settings persistence  ## Author: Ckraigfriend ## Version: 3.1 ## SavedVariables: ClassPetWatcherDB, SoulstoneTrackerDB
local LSM = LibStub and LibStub("LibSharedMedia-3.0", true)
local function SaveVariables()
end
local function GetSelectedFont()
    if not ClassPetWatcherDB or not ClassPetWatcherDB.fontName or not LSM then
        return "Fonts\\FRIZQT__.TTF"
    end
    local font = LSM:Fetch("font", ClassPetWatcherDB.fontName)
    return font or "Fonts\\FRIZQT__.TTF"
end

local function GetSelectedFontFlags()
    if not ClassPetWatcherDB or not ClassPetWatcherDB.fontFlags then
        return "OUTLINE"
    end
    if ClassPetWatcherDB.fontFlags == "NONE" then
        return ""
    end
    return ClassPetWatcherDB.fontFlags
end

local grimoireText

local function IsSpellKnownSafe(spellID)
    if not spellID then return false end
    if C_SpellBook and C_SpellBook.IsSpellKnown then
        return C_SpellBook.IsSpellKnown(spellID) and true or false
    end
    return false
end

-- Spell name lookup (works on both old and modern WoW API)
local function SafeGetSpellName(spellID)
    if not spellID then return nil end
    if C_Spell and C_Spell.GetSpellName then
        return C_Spell.GetSpellName(spellID)
    end
    if GetSpellInfo then
        return GetSpellInfo(spellID)
    end
    return nil
end

-- Felguard-specific spell IDs (global scope for reuse)
local FELGUARD_ABILITY_IDS = {
    [89751] = true,  -- Felstorm (EN/Global)
    [30213] = true,  -- Legion Strike (EN/Global)
    [89766] = true,  -- Axe Toss (EN/Global)
    [30146] = true,  -- Felguard ability (Korean client)
    [30151] = true,  -- Felguard ability (Korean client, found in error log)
}

-- Felguard NPC IDs (global scope for reuse)
local FELGUARD_NPC_IDS = {
    [17252] = true,
}
-- Localization helper
local function L(key)
    local locale = GetLocale and GetLocale() or "enUS"
    local t = {
        HUNTER_PET_MISSING = {
            deDE = "Jägerbegleiter fehlt!", koKR = "사냥꾼 소환수 없음!", ruRU = "Питомец охотника отсутствует!",
            esES = "¡Falta mascota de cazador!", esMX = "¡Falta mascota de cazador!", frFR = "Familier du chasseur manquant!",
            zhCN = "猎人宠物缺失!", zhTW = "獵人寵物缺失!", itIT = "Famiglio del cacciatore mancante!",
            ptBR = "Mascote do caçador ausente!", enUS = "Hunter Pet Missing!"
        },
        WARLOCK_PET_MISSING = {
            deDE = "Teufelswache fehlt!", koKR = "지옥수호병 없음!", ruRU = "Страж ужаса отсутствует!",
            esES = "¡Falta guardia vil!", esMX = "¡Falta guardia vil!", frFR = "Garde funeste manquant!",
            zhCN = "恶魔卫士缺失!", zhTW = "惡魔守衛缺失!", itIT = "Vilguardia mancante!",
            ptBR = "Guarda Vil ausente!", enUS = "Warlock Pet Missing!"
        },
        DK_PET_MISSING = {
            deDE = "Unheiliges Ghoul fehlt!", koKR = "부정한 구울 없음!", ruRU = "Нечестивый вурдалак отсутствует!",
            esES = "¡Falta necrófago profano!", esMX = "¡Falta necrófago profano!", frFR = "Goule impie manquante!",
            zhCN = "邪恶食尸鬼缺失!", zhTW = "邪惡食屍鬼缺失!", itIT = "Ghoul Empio mancante!",
            ptBR = "Carniçal profano ausente!", enUS = "Unholy Ghoul Missing!"
        },
        MAGE_PET_MISSING = {
            deDE = "Wasserelementar fehlt!", koKR = "물의 정령 없음!", ruRU = "Водный элементаль отсутствует!",
            esES = "¡Falta elemental de agua!", esMX = "¡Falta elemental de agua!", frFR = "Élémentaire d'eau manquant!",
            zhCN = "水元素缺失!", zhTW = "水元素缺失!", itIT = "Elementale d'acqua mancante!",
            ptBR = "Elemental da água ausente!", enUS = "Water Elemental Missing!"
        },
        PET_PASSIVE = {
            deDE = "Begleiter ist auf PASSIV!", koKR = "소환수가 수동 상태입니다!", ruRU = "Питомец в режиме ПАССИВ!",
            esES = "¡Mascota en PASIVO!", esMX = "¡Mascota en PASIVO!", frFR = "Familier en mode PASSIF!",
            zhCN = "宠物处于被动状态!", zhTW = "寵物處於被動狀態!", itIT = "Famiglio impostato su PASSIVO!",
            ptBR = "Mascote está em PASSIVO!", enUS = "Pet is set to PASSIVE!"
        },
        WRONG_PET_FELGUARD = {
            deDE = "FALCHES PET, TEUFELSWACHE BESCHWÖREN!", koKR = "잘못된 소환수, 지옥수호병 소환!",
            ruRU = "НЕВЕРНЫЙ ПИТОМЕЦ, ПРИЗОВИТЕ СТРАЖА УЖАСА!", esES = "MASCOTA INCORRECTA, ¡INVOCA GUARDIA VIL!",
            esMX = "MASCOTA INCORRECTA, ¡INVOCA GUARDIA VIL!", frFR = "MAUVAIS FAMILIER, INVOQUEZ GARDE FUNESTE!",
            zhCN = "错误的宠物，请召唤恶魔卫士!", zhTW = "錯誤的寵物，請召喚惡魔守衛!",
            itIT = "FAMIGLIO ERRATO, EVOCA VILGUARDIA!", ptBR = "MASCOTE ERRADO, EVOQUE O GUARDA VIL!",
            enUS = "WRONG PET SUMM FELGUARD"
        },
    }
    return t[key] and (t[key][locale] or t[key]["enUS"]) or key
end

local function GetNPCID(unit)
    if not issecure() then return nil end
    return UnitCreatureID(unit)
end

local function HasGrimoireOfSacrifice()
    if IsSpellKnownSafe(108503) then return true end
    if C_ClassTalents and C_ClassTalents.GetActiveConfigID and C_Traits and C_Traits.GetNodeIDs then
        local configID = C_ClassTalents.GetActiveConfigID()
        if configID then
            local nodes = C_Traits.GetNodeIDs(configID)
            if nodes then
                for _, nodeID in ipairs(nodes) do
                    local nodeInfo = C_Traits.GetNodeInfo(configID, nodeID)
                    if nodeInfo and nodeInfo.activeEntry and nodeInfo.activeEntry.entryID then
                        local entryInfo = C_Traits.GetEntryInfo(configID, nodeInfo.activeEntry.entryID)
                        if entryInfo and entryInfo.definitionID then
                            if entryInfo.definitionID == 231410 then return true end
                        end
                    end
                end
            end
        end
    end
    return false
end

--local ADDON_NAME = "ClassPetWatcher"

local showIcon
local onlyInInstance
local SyncSummonBtnPosition

------------------------------------------------------------
-- Frame (original — NO secure children, no taint)
------------------------------------------------------------
local frame = CreateFrame("Frame", "ClassPetWarningFrame", UIParent)
frame:SetSize(45, 145)
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 300)
frame:Hide()

frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetClampedToScreen(true)
frame.isLocked = true

frame:SetScript("OnDragStart", function(self)
    if not self.isLocked or IsShiftKeyDown() then self:StartMoving() end
end)
frame:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    SyncSummonBtnPosition()
end)

------------------------------------------------------------
-- Clickable Summon Overlay (separate from frame — no taint)
-- Parented to UIParent so it never taints the warning frame.
------------------------------------------------------------
local summonBtn = CreateFrame("Button", "ClassPetWatcherSummonBtn", UIParent, "SecureActionButtonTemplate")
summonBtn:SetSize(54, 54)
-- NO anchor to frame or icon — that would taint frame:Hide() in combat.
-- We position it using screen coords, synced out of combat.
summonBtn:SetPoint("CENTER", UIParent, "CENTER", 0, 320)
summonBtn:RegisterForClicks("AnyUp", "AnyDown")
summonBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
summonBtn:SetFrameStrata("HIGH")
summonBtn:Hide()

-- Sync summonBtn position to the icon's screen position (only call out of combat)
SyncSummonBtnPosition = function()
    if InCombatLockdown() then return end
    local cx, cy = icon:GetCenter()
    if cx and cy then
        summonBtn:ClearAllPoints()
        summonBtn:SetPoint("CENTER", UIParent, "BOTTOMLEFT", cx, cy)
    end
    local sz = (ClassPetWatcherDB and ClassPetWatcherDB.iconSize) or 54
    summonBtn:SetSize(sz, sz)
end

-- Tooltip
summonBtn:SetScript("OnEnter", function(self)
    if self.tooltipSpell then
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(self.tooltipSpell, 1, 1, 1)
        GameTooltip:AddLine("Left-click to cast", 0.5, 0.5, 0.5)
        local _, class = UnitClass("player")
        if class == "WARLOCK" then
            GameTooltip:AddLine("Right-click to choose demon", 0.8, 0.6, 1)
        elseif class == "HUNTER" then
            GameTooltip:AddLine("Right-click to choose pet slot", 0.8, 0.6, 1)
        end
        GameTooltip:Show()
    end
end)
summonBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

------------------------------------------------------------
-- Warlock Demon Flyout
------------------------------------------------------------
local WARLOCK_DEMONS = {
    { spellID = 688,   name = "Summon Imp",         iconID = 136218 },
    { spellID = 697,   name = "Summon Voidwalker",  iconID = 136221 },
    { spellID = 712,   name = "Summon Succubus",    iconID = 136220 },
    { spellID = 713,   name = "Summon Incubus",     iconID = 4352494 },
    { spellID = 691,   name = "Summon Felhunter",   iconID = 136217 },
    { spellID = 30146, name = "Summon Felguard",    iconID = 136216 },
}

local HUNTER_CALL_PETS = {
    { spellID = 883,   name = "Call Pet 1", iconID = 132161 },
    { spellID = 83242, name = "Call Pet 2", iconID = 132161 },
    { spellID = 83243, name = "Call Pet 3", iconID = 132161 },
    { spellID = 83244, name = "Call Pet 4", iconID = 132161 },
    { spellID = 83245, name = "Call Pet 5", iconID = 132161 },
}

local function GetSpellTextureSafe(spellID)
    if not spellID then return nil end
    if C_Spell and C_Spell.GetSpellTexture then
        return C_Spell.GetSpellTexture(spellID)
    end
    if GetSpellTexture then
        return GetSpellTexture(spellID)
    end
    return nil
end

local function GetHunterSlotFromSpellID(spellID)
    for slot, pet in ipairs(HUNTER_CALL_PETS) do
        if pet.spellID == spellID then
            return slot
        end
    end
    return nil
end

local function GetStablePetInfoSafe(slotIndex)
    if not slotIndex then return nil end
    if not C_StableInfo or not C_StableInfo.GetStablePetInfo then return nil end
    if not issecure() then return nil end
    return C_StableInfo.GetStablePetInfo(slotIndex)
end

local function GetHunterSlotVisualData(spellID)
    local slotIndex = GetHunterSlotFromSpellID(spellID)
    local petInfo = GetStablePetInfoSafe(slotIndex)
    local iconID = (petInfo and petInfo.icon) or GetSpellTextureSafe(spellID) or 132161
    local petName = petInfo and petInfo.name or nil
    return iconID, petName
end

local demonFlyout = CreateFrame("Frame", "ClassPetWatcherDemonFlyout", UIParent, "BackdropTemplate")
demonFlyout:SetFrameStrata("DIALOG")
demonFlyout:SetBackdrop({
    bgFile   = "Interface/Tooltips/UI-Tooltip-Background",
    edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 12,
    insets = { left = 3, right = 3, top = 3, bottom = 3 },
})
demonFlyout:SetBackdropColor(0.1, 0.0, 0.15, 0.92)
demonFlyout:SetBackdropBorderColor(0.6, 0.2, 0.8, 1)
demonFlyout:EnableMouse(true)
demonFlyout:Hide()

local flyoutTitle = demonFlyout:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
flyoutTitle:SetPoint("TOP", demonFlyout, "TOP", 0, -6)
flyoutTitle:SetText("Choose Summon")
flyoutTitle:SetTextColor(0.8, 0.6, 1)

local demonButtons = {}
local function BuildSummonFlyoutButtons(class)
    local btnSize = 36
    local padding = 4
    local topOffset = -22
    local count = 0
    local summonList
    local selectedSpellID
    local selectedLabel

    if class == "WARLOCK" then
        summonList = WARLOCK_DEMONS
        selectedSpellID = ClassPetWatcherDB and ClassPetWatcherDB.warlockDemonSpellID
        selectedLabel = "Choose Demon"
    elseif class == "HUNTER" then
        summonList = HUNTER_CALL_PETS
        selectedSpellID = ClassPetWatcherDB and ClassPetWatcherDB.hunterCallPetSpellID
        selectedLabel = "Choose Pet Slot"
    else
        demonFlyout:Hide()
        return
    end

    flyoutTitle:SetText(selectedLabel)

    for _, btn in pairs(demonButtons) do
        btn:Hide()
    end

    for i, demon in ipairs(summonList) do
        if IsSpellKnownSafe(demon.spellID) then
            count = count + 1
            local btn = demonButtons[i]
            if not btn then
                btn = CreateFrame("Button", "CPW_Demon" .. i, demonFlyout)
                btn:SetSize(btnSize, btnSize)
                btn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")

                btn.tex = btn:CreateTexture(nil, "ARTWORK")
                btn.tex:SetAllPoints(btn)

                btn.border = btn:CreateTexture(nil, "OVERLAY")
                btn.border:SetAllPoints(btn)
                btn.border:SetColorTexture(0.6, 0.2, 0.8, 0.3)
                btn.border:Hide()

                btn:SetScript("OnEnter", function(self)
                    GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
                    local sName = SafeGetSpellName(self.demonSpellID) or self.demonLabel
                    GameTooltip:SetText(sName, 1, 1, 1)
                    if class == "HUNTER" and self.hunterPetName and self.hunterPetName ~= "" then
                        GameTooltip:AddLine(self.hunterPetName, 0.8, 0.9, 1)
                    end
                    local isSelected = selectedSpellID == self.demonSpellID
                    if isSelected then
                        GameTooltip:AddLine("Currently selected", 0.5, 1, 0.5)
                    else
                        GameTooltip:AddLine("Click to select", 0.5, 0.5, 0.5)
                    end
                    GameTooltip:Show()
                end)
                btn:SetScript("OnLeave", function() GameTooltip:Hide() end)

                demonButtons[i] = btn
            end

            local iconID = demon.iconID
            local hunterPetName
            if class == "HUNTER" then
                iconID, hunterPetName = GetHunterSlotVisualData(demon.spellID)
            end

            btn.demonSpellID = demon.spellID
            btn.demonLabel = demon.name
            btn.hunterPetName = hunterPetName
            btn.tex:SetTexture(iconID)
            btn:SetPoint("TOPLEFT", demonFlyout, "TOPLEFT", padding + (count - 1) * (btnSize + padding), topOffset)

            btn:SetScript("OnClick", function(self)
                if not ClassPetWatcherDB then return end
                if class == "WARLOCK" then
                    ClassPetWatcherDB.warlockDemonSpellID = self.demonSpellID
                elseif class == "HUNTER" then
                    ClassPetWatcherDB.hunterCallPetSpellID = self.demonSpellID
                end
                local spellName = SafeGetSpellName(self.demonSpellID)
                print("ClassPetWatcher: Selected " .. (spellName or self.demonLabel) .. " as your summon.")
                demonFlyout:Hide()
                UpdatePetStatus()
            end)
            btn:Show()
        else
            if demonButtons[i] then demonButtons[i]:Hide() end
        end
    end

    local width = math.max(100, padding + count * (btnSize + padding))
    demonFlyout:SetSize(width, 64)
    demonFlyout:ClearAllPoints()
    demonFlyout:SetPoint("TOP", summonBtn, "BOTTOM", 0, -4)

    for _, btn in pairs(demonButtons) do
        if btn:IsShown() and btn.border then
            btn.border:SetShown(selectedSpellID == btn.demonSpellID)
        end
    end
end

-- Get the warlock's chosen demon spell
local function GetWarlockSelectedSpellID()
    if ClassPetWatcherDB and ClassPetWatcherDB.warlockDemonSpellID then
        if IsSpellKnownSafe(ClassPetWatcherDB.warlockDemonSpellID) then
            return ClassPetWatcherDB.warlockDemonSpellID
        end
    end
    local specIndex = GetSpecialization()
    local specID = specIndex and select(1, GetSpecializationInfo(specIndex))
    if specID == 266 and IsSpellKnownSafe(30146) then return 30146 end
    return 688
end

local function GetHunterSelectedSpellID()
    if ClassPetWatcherDB and ClassPetWatcherDB.hunterCallPetSpellID then
        if IsSpellKnownSafe(ClassPetWatcherDB.hunterCallPetSpellID) then
            return ClassPetWatcherDB.hunterCallPetSpellID
        end
    end
    for _, pet in ipairs(HUNTER_CALL_PETS) do
        if IsSpellKnownSafe(pet.spellID) then
            return pet.spellID
        end
    end
    return 883
end

-- Right-click toggles summon flyout (warlock/hunter)
summonBtn:HookScript("PostClick", function(self, button)
    if button == "RightButton" then
        local _, class = UnitClass("player")
        if (class == "WARLOCK" or class == "HUNTER") and not InCombatLockdown() then
            if demonFlyout:IsShown() then
                demonFlyout:Hide()
            else
                BuildSummonFlyoutButtons(class)
                demonFlyout:Show()
            end
        end
    else
        if demonFlyout:IsShown() then demonFlyout:Hide() end
    end
end)

-- Helper: configure the summon button spell (only outside combat)
local function SetSummonSpell(spellName)
    if InCombatLockdown() then return end
    if not ClassPetWatcherDB or ClassPetWatcherDB.clickableIcon == false then
        summonBtn:Hide()
        return
    end
    if spellName then
        summonBtn:SetAttribute("type1", "spell")
        summonBtn:SetAttribute("spell", spellName)
        summonBtn:SetAttribute("type2", nil)
        summonBtn.tooltipSpell = spellName
        SyncSummonBtnPosition()
        summonBtn:Show()
    else
        summonBtn:SetAttribute("type1", nil)
        summonBtn:SetAttribute("spell", nil)
        summonBtn.tooltipSpell = nil
        summonBtn:Hide()
        demonFlyout:Hide()
    end
end

------------------------------------------------------------
-- Event Frame for Loading
------------------------------------------------------------
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", function(self, event, arg1)
    if arg1 == "ClassPetWatcher" then
        ClassPetWatcherDB = ClassPetWatcherDB or {}
        showIcon = ClassPetWatcherDB.showIcon
        if showIcon == nil then showIcon = true end
        onlyInInstance = ClassPetWatcherDB.onlyInInstance or false
        if not ClassPetWatcherDB.iconSize then ClassPetWatcherDB.iconSize = 54 end
        icon:SetSize(ClassPetWatcherDB.iconSize, ClassPetWatcherDB.iconSize)
        if not ClassPetWatcherDB.textSize then ClassPetWatcherDB.textSize = 32 end
        if ClassPetWatcherDB.fontFlags == nil then ClassPetWatcherDB.fontFlags = "OUTLINE" end
        text:SetFont(GetSelectedFont(), ClassPetWatcherDB.textSize, GetSelectedFontFlags())
        if ClassPetWatcherDB.motionText == nil then ClassPetWatcherDB.motionText = true end
        if ClassPetWatcherDB.showPassiveAlert == nil then ClassPetWatcherDB.showPassiveAlert = true end
        if ClassPetWatcherDB.showPassiveAlertPvP == nil then ClassPetWatcherDB.showPassiveAlertPvP = true end
        if ClassPetWatcherDB.hideInNeighborhood == nil then ClassPetWatcherDB.hideInNeighborhood = false end
        if ClassPetWatcherDB.clickableIcon == nil then ClassPetWatcherDB.clickableIcon = true end
        print("ClassPetWatcher loaded: showIcon =", showIcon, "onlyInInstance =", onlyInInstance,
              "iconSize =", ClassPetWatcherDB.iconSize, "textSize =", ClassPetWatcherDB.textSize,
              "motionText =", ClassPetWatcherDB.motionText)
        UpdatePetStatus()
    end
end)

------------------------------------------------------------
-- Slash Commands
------------------------------------------------------------
SLASH_CLASSPETLOCK1 = "/petlock"
SlashCmdList.CLASSPETLOCK = function()
    frame.isLocked = not frame.isLocked
    print(frame.isLocked and "ClassPetWatcher locked (hold SHIFT to move)." or "ClassPetWatcher unlocked.")
end

SLASH_CLASSPETINSTANCE1 = "/petinstance"
SlashCmdList.CLASSPETINSTANCE = function()
    onlyInInstance = not onlyInInstance
    ClassPetWatcherDB.onlyInInstance = onlyInInstance
    print(onlyInInstance and "ClassPetWatcher: Alerts only in instances." or "ClassPetWatcher: Alerts everywhere.")
    UpdatePetStatus()
end

SLASH_CLASSPETHIDEICON1 = "/hideicon"
SlashCmdList.CLASSPETHIDEICON = function()
    showIcon = not showIcon
    ClassPetWatcherDB.showIcon = showIcon
    print("Saved showIcon =", ClassPetWatcherDB.showIcon)
    print(showIcon and "ClassPetWatcher: Icon shown." or "ClassPetWatcher: Icon hidden.")
    UpdatePetStatus()
end

SLASH_CLASSPETNEIGHBORHOOD1 = "/pethood"
SlashCmdList.CLASSPETNEIGHBORHOOD = function()
    if not ClassPetWatcherDB then return end
    ClassPetWatcherDB.hideInNeighborhood = not ClassPetWatcherDB.hideInNeighborhood
    print("ClassPetWatcher: Pet warnings " ..
          (ClassPetWatcherDB.hideInNeighborhood and "HIDDEN" or "SHOWN") ..
          " while in a housing neighborhood.")
    UpdatePetStatus()
end

SLASH_CLASSPETOPTIONS1 = "/PETOP"
SlashCmdList.CLASSPETOPTIONS = function()
     ClassPetWatcher_ShowPetOptionsMenu()
end

-- Popup menu for /PETOP
if not EasyMenu then
    if C_AddOns and C_AddOns.IsAddOnLoaded and C_AddOns.LoadAddOn then
        if not C_AddOns.IsAddOnLoaded("Blizzard_UIDropDownMenu") then
            C_AddOns.LoadAddOn("Blizzard_UIDropDownMenu")
        end
    end
end

ClassPetWatcher_ShowPetOptionsMenu = function()
    if not ClassPetWatcherOptionsFrame then
        local f = CreateFrame("Frame", "ClassPetWatcherOptionsFrame", UIParent, "BackdropTemplate")
        f:SetSize(300, 530)
        f:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
        f:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background", edgeFile = "Interface/Tooltips/UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 16, insets = {left = 4, right = 4, top = 4, bottom = 4}})
        f:SetBackdropColor(0, 0, 0, 0.8)
        f:SetBackdropBorderColor(RAID_CLASS_COLORS[select(2, UnitClass("player"))].r, RAID_CLASS_COLORS[select(2, UnitClass("player"))].g, RAID_CLASS_COLORS[select(2, UnitClass("player"))].b) 
        f:EnableMouse(true)
        f:SetMovable(true)
        f:RegisterForDrag("LeftButton")
        f:SetScript("OnDragStart", function(self) self:StartMoving() end)
        f:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
        
        local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        title:SetPoint("TOP", f, "TOP", 0, -10)
        title:SetText("ClassPetWatcher Options")
        local function makeButton(text, y, func)
            local b = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
            b:SetSize(160, 24)
            b:SetPoint("TOP", f, "TOP", 0, y)
            b:SetText(text)
            b:SetScript("OnClick", func)
            return b
        end
        f.btn1 = makeButton("Toggle Icon", -40, function()
            showIcon = not showIcon
            ClassPetWatcherDB.showIcon = showIcon
            print("ClassPetWatcher: Icon " .. (showIcon and "shown" or "hidden"))
            UpdatePetStatus()
        end)
        f.btn2 = makeButton("Toggle Instance Only", -70, function()
            onlyInInstance = not onlyInInstance
            ClassPetWatcherDB.onlyInInstance = onlyInInstance
            print("ClassPetWatcher: Alerts " .. (onlyInInstance and "only in instances" or "everywhere"))
            UpdatePetStatus()
        end)
        f.btn3 = makeButton("Lock/Unlock Frame", -100, function()
            frame.isLocked = not frame.isLocked
            print(frame.isLocked and "ClassPetWatcher locked (hold SHIFT to move)." or "ClassPetWatcher unlocked.")
        end)
        f.btn4 = makeButton("Static Text", -130, function()
            ClassPetWatcherDB.motionText = false
            print("ClassPetWatcher: Static text enabled.")
            UpdatePetStatus()
        end)
        f.btn5 = makeButton("Motion Text", -160, function()
            ClassPetWatcherDB.motionText = true
            print("ClassPetWatcher: Motion text enabled.")
            UpdatePetStatus()
        end)
        f.btn6 = makeButton("Turn On/Off Passive Alert", -190, function()
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.showPassiveAlert = not ClassPetWatcherDB.showPassiveAlert
            print("ClassPetWatcher: Passive alert " .. (ClassPetWatcherDB.showPassiveAlert and "enabled" or "disabled") .. ".")
            UpdatePetStatus()
        end)
        f.btn7 = makeButton("Passive Alert in PvP", -220, function()
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.showPassiveAlertPvP = not ClassPetWatcherDB.showPassiveAlertPvP
            print("ClassPetWatcher: Passive alert in PvP " .. (ClassPetWatcherDB.showPassiveAlertPvP and "enabled" or "disabled") .. ".")
            UpdatePetStatus()
        end)
        f.btn8 = makeButton("Hide in Neighborhood", -250, function()
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.hideInNeighborhood = not ClassPetWatcherDB.hideInNeighborhood
            local state = ClassPetWatcherDB.hideInNeighborhood and "HIDDEN in neighborhoods" or "SHOWN in neighborhoods"
            print("ClassPetWatcher: Pet warnings now " .. state .. ".")
            f.btn8:SetText(ClassPetWatcherDB.hideInNeighborhood and "Show in Neighborhood" or "Hide in Neighborhood")
            UpdatePetStatus()
        end)
        f.btn9 = makeButton("Clickable Icon: ON", -280, function()
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.clickableIcon = not ClassPetWatcherDB.clickableIcon
            local state = ClassPetWatcherDB.clickableIcon and "ENABLED" or "DISABLED"
            print("ClassPetWatcher: Clickable icon " .. state .. ".")
            f.btn9:SetText("Clickable Icon: " .. (ClassPetWatcherDB.clickableIcon and "ON" or "OFF"))
            UpdatePetStatus()
        end)

        f.closeBtn = CreateFrame("Button", nil, f, "UIPanelCloseButton")
        f.closeBtn:SetSize(24, 24)
        f.closeBtn:SetPoint("TOPRIGHT", f, "TOPRIGHT", -4, -4)
        f.closeBtn:SetScript("OnClick", function() f:Hide() end)
        
        f.textSizeSlider = CreateFrame("Slider", nil, f, "MinimalSliderTemplate")
        f.textSizeSlider:SetOrientation("HORIZONTAL")
        f.textSizeSlider:SetSize(160, 16)
        f.textSizeSlider:SetPoint("TOP", f, "TOP", 0, -325)
        f.textSizeSlider:SetMinMaxValues(16, 48)
        f.textSizeSlider:SetValueStep(1)
        f.textSizeSlider:SetValue(ClassPetWatcherDB and ClassPetWatcherDB.textSize or 32)
        f.textSizeSlider:SetObeyStepOnDrag(true)
        f.textSizeSlider:SetScript("OnValueChanged", function(self, value)
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.textSize = value
            text:SetFont(GetSelectedFont(), value, GetSelectedFontFlags())
            UpdatePetStatus()
            print("ClassPetWatcher: Text size set to " .. math.floor(value))
            if not InCombatLockdown() then SaveVariables() end
        end)
        f.textSizeSlider.Text = f.textSizeSlider:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        f.textSizeSlider.Text:SetPoint("BOTTOM", f.textSizeSlider, "TOP", 0, 2)
        f.textSizeSlider.Text:SetText("Text Size")
        
        f.iconSizeSlider = CreateFrame("Slider", nil, f, "MinimalSliderTemplate") 
        f.iconSizeSlider:SetOrientation("HORIZONTAL")
        f.iconSizeSlider:SetSize(160, 16)
        f.iconSizeSlider:SetPoint("TOP", f, "TOP", 0, -350)
        f.iconSizeSlider:SetMinMaxValues(24, 96)
        f.iconSizeSlider:SetValueStep(1)
        f.iconSizeSlider:SetValue(ClassPetWatcherDB and ClassPetWatcherDB.iconSize or 54)
        f.iconSizeSlider:SetObeyStepOnDrag(true)
        f.iconSizeSlider:SetScript("OnValueChanged", function(self, value)
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.iconSize = value
            icon:SetSize(value, value)
            UpdatePetStatus()
            print("ClassPetWatcher: Icon size set to " .. math.floor(value))
            if not InCombatLockdown() then SaveVariables() end
        end)
        f.iconSizeSlider.Text = f.iconSizeSlider:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        f.iconSizeSlider.Text:SetPoint("BOTTOM", f.iconSizeSlider, "TOP", 0, 2)
        f.iconSizeSlider.Text:SetText("Icon Size")
        
        f.fontDropdownLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        f.fontDropdownLabel:SetPoint("TOP", f, "TOP", 0, -380)
        f.fontDropdownLabel:SetText("Font")
        f.fontDropdown = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
        f.fontDropdown:SetSize(170, 22)
        f.fontDropdown:SetPoint("TOP", f, "TOP", 0, -390)
        f.fontDropdown:SetText((ClassPetWatcherDB and ClassPetWatcherDB.fontName) or "Default")

        f.fontListFrame = CreateFrame("Frame", nil, f, "BackdropTemplate")
        f.fontListFrame:SetPoint("TOP", f.fontDropdown, "BOTTOM", 0, -2)
        f.fontListFrame:SetSize(190, 130)
        f.fontListFrame:SetBackdrop({
            bgFile = "Interface/Tooltips/UI-Tooltip-Background",
            edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
            tile = true, tileSize = 16, edgeSize = 16,
            insets = {left = 4, right = 4, top = 4, bottom = 4}
        })
        f.fontListFrame:SetBackdropColor(0, 0, 0, 0.9)
        f.fontListFrame:SetFrameStrata("TOOLTIP")
        f.fontListFrame:Hide()

        f.fontListScroll = CreateFrame("ScrollFrame", nil, f.fontListFrame, "UIPanelScrollFrameTemplate")
        f.fontListScroll:SetPoint("TOPLEFT", 8, -8)
        f.fontListScroll:SetPoint("BOTTOMRIGHT", -28, 8)
        f.fontListContent = CreateFrame("Frame", nil, f.fontListScroll)
        f.fontListContent:SetSize(1, 1)
        f.fontListScroll:SetScrollChild(f.fontListContent)
        f.fontButtons = {}

        local function SelectFont(fontName)
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.fontName = fontName
            local font = GetSelectedFont()
            text:SetFont(font, ClassPetWatcherDB.textSize or 32, GetSelectedFontFlags())
            local gText = grimoireText or (ClassPetWatcherOptionsFrame and ClassPetWatcherOptionsFrame._grimoireText)
            if gText and gText.SetFont then gText:SetFont(font, 28, GetSelectedFontFlags()) end
            f.fontDropdown:SetText(fontName)
            f.fontListFrame:Hide()
            UpdatePetStatus()
        end

        local function RebuildFontList()
            if not LSM then return end
            local fonts = LSM:List("font") or {}
            table.sort(fonts)
            for i = 1, #f.fontButtons do f.fontButtons[i]:Hide() end
            for i, fontName in ipairs(fonts) do
                local button = f.fontButtons[i]
                if not button then
                    button = CreateFrame("Button", nil, f.fontListContent)
                    button:SetSize(150, 18)
                    button:SetNormalFontObject("GameFontHighlightSmall")
                    button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
                    button:GetHighlightTexture():SetBlendMode("ADD")
                    f.fontButtons[i] = button
                end
                button:SetPoint("TOPLEFT", f.fontListContent, "TOPLEFT", 0, -((i - 1) * 18))
                button:SetText(fontName)
                button:SetScript("OnClick", function() SelectFont(fontName) end)
                button:Show()
            end
            f.fontListContent:SetSize(150, math.max(1, #fonts * 18))
        end

        f.fontDropdown:SetScript("OnClick", function()
            if f.fontListFrame:IsShown() then
                f.fontListFrame:Hide()
            else
                f.fontStyleListFrame:Hide()
                RebuildFontList()
                f.fontListFrame:Show()
            end
        end)

        f.fontListFrame:EnableMouseWheel(true)
        f.fontListFrame:SetScript("OnMouseWheel", function(_, delta)
            local current = f.fontListScroll:GetVerticalScroll()
            local maxScroll = math.max(0, f.fontListContent:GetHeight() - f.fontListScroll:GetHeight())
            local nextScroll = math.min(math.max(0, current - (delta * 18)), maxScroll)
            f.fontListScroll:SetVerticalScroll(nextScroll)
        end)

        f.fontStyleLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        f.fontStyleLabel:SetPoint("TOP", f, "TOP", 0, -425)
        f.fontStyleLabel:SetText("Font Style")
        f.fontStyleDropdown = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
        f.fontStyleDropdown:SetSize(170, 22)
        f.fontStyleDropdown:SetPoint("TOP", f, "TOP", 0, -435)
        f.fontStyleDropdown:SetText((ClassPetWatcherDB and ClassPetWatcherDB.fontFlags) or "OUTLINE")

        f.fontStyleListFrame = CreateFrame("Frame", nil, f, "BackdropTemplate")
        f.fontStyleListFrame:SetPoint("TOP", f.fontStyleDropdown, "BOTTOM", 0, -2)
        f.fontStyleListFrame:SetSize(190, 130)
        f.fontStyleListFrame:SetBackdrop({
            bgFile = "Interface/Tooltips/UI-Tooltip-Background",
            edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
            tile = true, tileSize = 16, edgeSize = 16,
            insets = {left = 4, right = 4, top = 4, bottom = 4}
        })
        f.fontStyleListFrame:SetBackdropColor(0, 0, 0, 0.9)
        f.fontStyleListFrame:SetFrameStrata("DIALOG")
        f.fontStyleListFrame:Hide()

        f.fontStyleListScroll = CreateFrame("ScrollFrame", nil, f.fontStyleListFrame, "UIPanelScrollFrameTemplate")
        f.fontStyleListScroll:SetPoint("TOPLEFT", 8, -8)
        f.fontStyleListScroll:SetPoint("BOTTOMRIGHT", -28, 8)
        f.fontStyleListContent = CreateFrame("Frame", nil, f.fontStyleListScroll)
        f.fontStyleListContent:SetSize(1, 1)
        f.fontStyleListScroll:SetScrollChild(f.fontStyleListContent)
        f.fontStyleButtons = {}

        local styleOptions = {
            "NONE", "OUTLINE", "MONOCHROME", "OUTLINE, MONOCHROME",
            "THICKOUTLINE", "THICKOUTLINE, MONOCHROME",
        }

        local function SelectFontStyle(styleName)
            if not ClassPetWatcherDB then return end
            ClassPetWatcherDB.fontFlags = styleName
            local font = GetSelectedFont()
            local flags = GetSelectedFontFlags()
            text:SetFont(font, ClassPetWatcherDB.textSize or 32, flags)
            local gText = grimoireText or (ClassPetWatcherOptionsFrame and ClassPetWatcherOptionsFrame._grimoireText)
            if gText and gText.SetFont then gText:SetFont(font, 28, flags) end
            f.fontStyleDropdown:SetText(styleName)
            f.fontStyleListFrame:Hide()
            UpdatePetStatus()
        end

        local function RebuildFontStyleList()
            for i = 1, #f.fontStyleButtons do f.fontStyleButtons[i]:Hide() end
            for i, styleName in ipairs(styleOptions) do
                local button = f.fontStyleButtons[i]
                if not button then
                    button = CreateFrame("Button", nil, f.fontStyleListContent)
                    button:SetSize(150, 18)
                    button:SetNormalFontObject("GameFontHighlightSmall")
                    button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
                    button:GetHighlightTexture():SetBlendMode("ADD")
                    f.fontStyleButtons[i] = button
                end
                button:SetPoint("TOPLEFT", f.fontStyleListContent, "TOPLEFT", 0, -((i - 1) * 18))
                button:SetText(styleName)
                button:SetScript("OnClick", function() SelectFontStyle(styleName) end)
                button:Show()
            end
            f.fontStyleListContent:SetSize(150, math.max(1, #styleOptions * 18))
        end

        f.fontStyleDropdown:SetScript("OnClick", function()
            if f.fontStyleListFrame:IsShown() then
                f.fontStyleListFrame:Hide()
            else
                f.fontListFrame:Hide()
                RebuildFontStyleList()
                f.fontStyleListFrame:Show()
            end
        end)

        f.fontStyleListFrame:EnableMouseWheel(true)
        f.fontStyleListFrame:SetScript("OnMouseWheel", function(_, delta)
            local current = f.fontStyleListScroll:GetVerticalScroll()
            local maxScroll = math.max(0, f.fontStyleListContent:GetHeight() - f.fontStyleListScroll:GetHeight())
            local nextScroll = math.min(math.max(0, current - (delta * 18)), maxScroll)
            f.fontStyleListScroll:SetVerticalScroll(nextScroll)
        end)

        ClassPetWatcherOptionsFrame = f
    end

    if ClassPetWatcherOptionsFrame.fontDropdown then
        ClassPetWatcherOptionsFrame.fontDropdown:SetText((ClassPetWatcherDB and ClassPetWatcherDB.fontName) or "Default")
    end
    if ClassPetWatcherOptionsFrame.fontListFrame then
        ClassPetWatcherOptionsFrame.fontListFrame:Hide()
    end
    if ClassPetWatcherOptionsFrame.fontStyleDropdown then
        ClassPetWatcherOptionsFrame.fontStyleDropdown:SetText((ClassPetWatcherDB and ClassPetWatcherDB.fontFlags) or "OUTLINE")
    end
    if ClassPetWatcherOptionsFrame.fontStyleListFrame then
        ClassPetWatcherOptionsFrame.fontStyleListFrame:Hide()
    end
    if ClassPetWatcherOptionsFrame.btn8 then
        local hiding = ClassPetWatcherDB and ClassPetWatcherDB.hideInNeighborhood
        ClassPetWatcherOptionsFrame.btn8:SetText(hiding and "Show in Neighborhood" or "Hide in Neighborhood")
    end
    if ClassPetWatcherOptionsFrame.btn9 then
        local clickable = ClassPetWatcherDB and ClassPetWatcherDB.clickableIcon ~= false
        ClassPetWatcherOptionsFrame.btn9:SetText("Clickable Icon: " .. (clickable and "ON" or "OFF"))
    end
    ClassPetWatcherOptionsFrame:Show()
end

------------------------------------------------------------
-- Icon + Text (original — plain texture, no secure frame)
------------------------------------------------------------
icon = frame:CreateTexture(nil, "OVERLAY")
icon:SetSize(54, 54)
icon:SetPoint("CENTER", frame, "CENTER", 0, 20)

local blackSquare = frame:CreateTexture(nil, "BACKGROUND")
blackSquare:SetPoint("TOP", icon, "BOTTOM", 0, 35)
blackSquare:SetSize(40, 40)
blackSquare:SetColorTexture(0, 0, 0, 0)

grimoireText = frame:CreateFontString(nil, "OVERLAY")
grimoireText:SetPoint("TOP", icon, "BOTTOM", 0, -40)
grimoireText:SetFont(GetSelectedFont(), 28, GetSelectedFontFlags())
grimoireText:SetTextColor(0.8, 0.2, 1)
grimoireText:SetShadowOffset(1, -1)
grimoireText:SetShadowColor(0, 0, 0, 1)
grimoireText:Hide()
if ClassPetWatcherOptionsFrame then
    ClassPetWatcherOptionsFrame._grimoireText = grimoireText
end

text = frame:CreateFontString(nil, "OVERLAY")
text:SetPoint("CENTER", frame, "CENTER", 0, -40)
local _, classFilename = UnitClass("player")
local classColor = C_ClassColor.GetClassColor(classFilename)
if classColor then text:SetTextColor(classColor.r, classColor.g, classColor.b)
else text:SetTextColor(1, 0, 0) end
text:SetFont(GetSelectedFont(), (ClassPetWatcherDB and ClassPetWatcherDB.textSize) or 32, GetSelectedFontFlags())
text:SetShadowOffset(1, -1)
text:SetShadowColor(0, 0, 0, 1)

------------------------------------------------------------
-- Fade animation
------------------------------------------------------------
local fade = text:CreateAnimationGroup()
fade:SetLooping("REPEAT")
local fadeIn = fade:CreateAnimation("Alpha")
fadeIn:SetOrder(1); fadeIn:SetDuration(1.5); fadeIn:SetFromAlpha(0); fadeIn:SetToAlpha(1)
local fadeOut = fade:CreateAnimation("Alpha")
fadeOut:SetOrder(2); fadeOut:SetDuration(1.5); fadeOut:SetToAlpha(0)

local function PlayFade()
    if ClassPetWatcherDB and ClassPetWatcherDB.motionText then
        if not fade:IsPlaying() then fade:Play() end
    else StopFade() end
end
StopFade = function() if fade:IsPlaying() then fade:Stop(); text:SetAlpha(1) end end

------------------------------------------------------------
-- Constants
------------------------------------------------------------
local PET_PASSIVE_ICON = 132276
local PET_PASSIVE_TEXT = L("PET_PASSIVE")

local PET_INFO = {
    HUNTER     = { [0] = { iconID = 136095,  text = L("HUNTER_PET_MISSING"), spellID = 883   } },
    WARLOCK    = { [0] = { iconID = 236292,  text = L("WARLOCK_PET_MISSING"), spellID = 688  } },
    DEATHKNIGHT= { [0] = { iconID = 1100170, text = L("DK_PET_MISSING"),    specID = 252, spellID = 46584 } },
    MAGE       = { [0] = { iconID = 135862,  text = L("MAGE_PET_MISSING"),  specID = 64,  spellID = 31687 } },
}

local HUNTER_NO_PET = { [466846] = true, [1232995] = true }
local MAGE_WATER_ELEMENTAL_SPELLID = 31687
local DEMONOLOGY_SPEC_ID = 266
local FELGUARD_SPELL_ID = 30146

------------------------------------------------------------
-- Utilities
------------------------------------------------------------
local function IsPetOnPassive()
    if not UnitExists("pet") or not PetHasActionBar() then return false end
    local SLOT_COUNT = NUM_PET_ACTION_SLOTS or 10
    for slot = 1, SLOT_COUNT do
        local name, _, isToken, isActive = GetPetActionInfo(slot)
        if isToken and name == "PET_MODE_PASSIVE" and isActive then return true end
    end
    return false
end

local function PetCheckAllowed(class)
    local zero = PET_INFO[class] and PET_INFO[class][0]
    if not zero then return false end
    if class == "HUNTER" then
        for spellID in pairs(HUNTER_NO_PET) do if IsSpellKnownSafe(spellID) then return false end end
        return true
    end
    if class == "MAGE" then
        local specIndex = GetSpecialization()
        local specID = specIndex and select(1, GetSpecializationInfo(specIndex))
        if specID ~= 64 then return false end
        if not IsSpellKnownSafe(MAGE_WATER_ELEMENTAL_SPELLID) then return false end
        return true
    end
    if zero.specID then
        local specIndex = GetSpecialization()
        local specID = specIndex and select(1, GetSpecializationInfo(specIndex))
        return specID == zero.specID
    end
    return true
end

local function IsPlayerMountedOrInVehicleOrTaxi()
    return IsMounted() or UnitOnTaxi("player") or UnitHasVehicleUI("player")
end

local function IsInPvPContext()
    local inInstance, instanceType = IsInInstance()
    if inInstance and (instanceType == "pvp" or instanceType == "arena") then return true end
    if C_PvP and C_PvP.IsWarModeActive and C_PvP.IsWarModeActive() then return true end
    return false
end

local function IsInNeighborhood()
    if not C_Housing then return false end
    local inHouse = C_Housing.IsInsideHouseOrPlot and C_Housing.IsInsideHouseOrPlot()
    local onMap   = C_Housing.IsOnNeighborhoodMap   and C_Housing.IsOnNeighborhoodMap()
    return inHouse or onMap
end

local function unitStringLower(s) if s then return string.lower(tostring(s)) else return "" end end
local function IsPetFelguard()
    if not UnitExists("pet") then return false end
    for i = 1, NUM_PET_ACTION_SLOTS do
        local _, _, _, _, _, _, spellID = GetPetActionInfo(i)
        if spellID and FELGUARD_ABILITY_IDS[spellID] then return true end
    end
    local npcID = GetNPCID("pet")
    if npcID and FELGUARD_NPC_IDS[npcID] then return true end
    if not issecure() then return false end
    local family = UnitCreatureFamily("pet") or ""
    local name   = UnitName("pet") or ""
    local lf = unitStringLower(family)
    local ln = unitStringLower(name)
    local felguardNames = {"felguard","teufelswache","zornw","지옥수호병","지옥수호병 소환","강력한 근접 전투형 투사인 지옥수호병","이직툰","izikthun","страж ужаса","guardia vil"}
    for _, fname in ipairs(felguardNames) do
        if lf:find(fname) or ln:find(fname) then return true end
    end
    return false
end

------------------------------------------------------------
-- Main Update (original logic — untouched frame behavior)
-- The only addition: SetSummonSpell() to show/hide the
-- overlay button for pet-missing & wrong-pet warnings.
------------------------------------------------------------
UpdatePetStatus = function()
    -- Grimoire of Sacrifice special case
    if HasGrimoireOfSacrifice() then
        if UnitExists("pet") then
            icon:SetTexture(236292)
            icon:SetShown(showIcon)
            grimoireText:SetText("Grimoire  Alive!")
            grimoireText:Show()
            text:Hide()
            SetSummonSpell(nil)
            frame:Show(); PlayFade(); return
        else
            grimoireText:Hide()
            text:Hide()
            SetSummonSpell(nil)
            frame:Hide()
            StopFade()
            return
        end
    else
        grimoireText:Hide()
        text:Show()
    end

    -- hide if player is dead or ghost
    if UnitIsDeadOrGhost("player") then
        SetSummonSpell(nil); frame:Hide(); StopFade(); return
    end

    -- hide while mounted, on a flight path, or in a vehicle
    if IsPlayerMountedOrInVehicleOrTaxi() then
        SetSummonSpell(nil); frame:Hide(); StopFade(); return
    end

    -- hide if in a housing neighborhood and the option is enabled
    if ClassPetWatcherDB and ClassPetWatcherDB.hideInNeighborhood and IsInNeighborhood() then
        SetSummonSpell(nil); frame:Hide(); StopFade(); return
    end

    -- hide if not in instance and onlyInInstance is enabled
    if onlyInInstance and not IsInInstance() then
        SetSummonSpell(nil); frame:Hide(); StopFade(); return
    end

    local _, class = UnitClass("player")
    local info = PET_INFO[class]
    if not info then SetSummonSpell(nil); frame:Hide(); StopFade(); return end

    if ClassPetWatcherDB and ClassPetWatcherDB.iconSize then
        icon:SetSize(ClassPetWatcherDB.iconSize, ClassPetWatcherDB.iconSize)
    end
    if ClassPetWatcherDB and ClassPetWatcherDB.textSize then
        text:SetFont(GetSelectedFont(), ClassPetWatcherDB.textSize, GetSelectedFontFlags())
    end

    -- Passive alert (original — display only, no click)
    if UnitExists("pet") and IsPetOnPassive()
        and (ClassPetWatcherDB == nil or ClassPetWatcherDB.showPassiveAlert ~= false)
        and (ClassPetWatcherDB == nil or ClassPetWatcherDB.showPassiveAlertPvP ~= false or not IsInPvPContext()) then
        icon:SetTexture(PET_PASSIVE_ICON)
        icon:SetShown(showIcon)
        SetSummonSpell(nil)
        local family = issecure() and UnitCreatureFamily("pet") or nil
        text:SetText((family and (family .. " " .. L("PET_PASSIVE"))) or PET_PASSIVE_TEXT)
        frame:Show(); PlayFade(); return
    end

    -- Wrong pet (warlock Demo needs Felguard)
    if class == "WARLOCK" then
        local specIndex = GetSpecialization()
        local specID = specIndex and select(1, GetSpecializationInfo(specIndex))
        if specID == DEMONOLOGY_SPEC_ID and IsSpellKnownSafe(FELGUARD_SPELL_ID) then
            if UnitExists("pet") and not IsPetFelguard() then
                icon:SetTexture(info[0] and info[0].iconID or PET_PASSIVE_ICON)
                icon:SetShown(showIcon)
                text:SetText(L("WRONG_PET_FELGUARD"))
                -- Clickable: summon chosen demon
                local chosenID = GetWarlockSelectedSpellID()
                SetSummonSpell(SafeGetSpellName(chosenID))
                frame:Show(); PlayFade(); return
            end
        end
    end

    -- Pet missing
    if info[0] and PetCheckAllowed(class) and not UnitExists("pet") then
        local warningIconID = info[0].iconID
        if class == "HUNTER" then
            local chosenID = GetHunterSelectedSpellID()
            warningIconID = select(1, GetHunterSlotVisualData(chosenID)) or warningIconID
        end
        icon:SetTexture(warningIconID)
        icon:SetShown(showIcon)
        text:SetText(info[0].text)
        -- Clickable: summon pet
        local summonSpellName
        if class == "WARLOCK" then
            local chosenID = GetWarlockSelectedSpellID()
            summonSpellName = SafeGetSpellName(chosenID)
        elseif class == "HUNTER" then
            local chosenID = GetHunterSelectedSpellID()
            summonSpellName = SafeGetSpellName(chosenID)
        else
            summonSpellName = SafeGetSpellName(info[0].spellID)
        end
        SetSummonSpell(summonSpellName)
        frame:Show(); PlayFade(); return
    end

    SetSummonSpell(nil)
    frame:Hide()
    StopFade()
end

------------------------------------------------------------
-- Dismount delay handling
------------------------------------------------------------
local dismountTimer = nil
local DISMOUNT_DELAY = 5.0

local function SchedulePostDismountCheck()
    if dismountTimer and dismountTimer.Cancel then
        dismountTimer:Cancel(); dismountTimer = nil
    end
    dismountTimer = C_Timer.NewTimer(DISMOUNT_DELAY, function()
        dismountTimer = nil
        UpdatePetStatus()
    end)
end

------------------------------------------------------------
-- Events
------------------------------------------------------------
--frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("UNIT_PET")
frame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
frame:RegisterEvent("SPELLS_CHANGED")
frame:RegisterEvent("PET_BAR_UPDATE")
frame:RegisterEvent("PET_BAR_UPDATE_COOLDOWN")
frame:RegisterEvent("PET_INFO_UPDATE")
frame:RegisterEvent("PET_STABLE_UPDATE")
frame:RegisterEvent("PLAYER_MOUNT_DISPLAY_CHANGED")
frame:RegisterEvent("UNIT_ENTERED_VEHICLE")
frame:RegisterEvent("UNIT_EXITED_VEHICLE")
frame:RegisterEvent("PLAYER_FLAGS_CHANGED")
frame:RegisterEvent("PLAYER_ALIVE")
frame:RegisterEvent("PLAYER_UNGHOST")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")

frame:SetScript("OnEvent", function(self, event, arg1, ...)
    if event == "ADDON_LOADED" and arg1 ~= "OrzUI" then return end
    if event == "UNIT_PET" and arg1 ~= "player" then return end
    if event == "UNIT_ENTERED_VEHICLE" and arg1 ~= "player" then return end
    if event == "UNIT_EXITED_VEHICLE" and arg1 ~= "player" then return end
    if event == "PLAYER_FLAGS_CHANGED" and arg1 and arg1 ~= "player" then return end

    --if event == "ADDON_LOADED" then
        --print("|cff00ff00Type  Addon ClassPetWatcher   /petinstance if you wanna see reminders in dungeon or raids or to enable again for solo|r")
    --end

    if event == "PLAYER_MOUNT_DISPLAY_CHANGED" then
        if IsMounted() then
            if dismountTimer and dismountTimer.Cancel then dismountTimer:Cancel(); dismountTimer = nil end
            frame:Hide(); StopFade(); return
        else
            SchedulePostDismountCheck(); return
        end
    end

    if dismountTimer and event ~= "PLAYER_MOUNT_DISPLAY_CHANGED" then
        if dismountTimer and dismountTimer.Cancel then dismountTimer:Cancel(); dismountTimer = nil end
        UpdatePetStatus(); return
    end

    if UnitIsDeadOrGhost("player") then
        frame:Hide(); StopFade(); return
    end

    UpdatePetStatus()
end)