local ADDON_NAME, ns = ...

-- Always unify namespace (prevents nil Mixins / split-table bugs)
ns = _G[ADDON_NAME] or ns
_G[ADDON_NAME] = ns

ns.mixins = ns.mixins or {}
local Mixins = ns.mixins

local U = ns.util

-- =========================================================
-- pom_mixins.lua
-- =========================================================

-- ------------------------------------------------------------
-- Safe font apply (prevents "Font not set" + bad paths)
-- ------------------------------------------------------------
local function SafeSetFont(fs, path, size, flags)
    if not (fs and fs.SetFont) then return false end
    size  = tonumber(size) or 12
    flags = flags or ""

    local ok = pcall(fs.SetFont, fs, path, size, flags)
    if ok then return true end

    ok = pcall(fs.SetFont, fs, (_G.STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF"), size, flags)
    return ok and true or false
end

-- ------------------------------------------------------------
-- Secret number detection (12.0 / Midnight)
-- ------------------------------------------------------------
local function IsSecretNumber(v)
    if type(v) ~= "number" then return false end
    local f = _G.issecretvalue
    if type(f) ~= "function" then return false end
    local ok, r = pcall(f, v)
    return ok and r and true or false
end

-- ------------------------------------------------------------
-- Rare detection (classification)
-- ------------------------------------------------------------
local function IsRareUnit(unit)
    if not unit or not UnitExists(unit) then return false, nil end
    local cls = UnitClassification(unit)
    if cls == "rare" or cls == "rareelite" then
        return true, cls
    end
    return false, cls
end

-- ------------------------------------------------------------
-- DB helpers (READ-ONLY)
-- IMPORTANT:
--   Do NOT write defaults here. InitDB() in pom.lua owns all defaults+migrations.
-- ------------------------------------------------------------
local function GetBaseColorsDB(db)
    if db and type(db.baseColors) == "table" then
        return db.baseColors
    end
    if db and type(db.colors) == "table" then
        return db.colors
    end
    return nil
end

local function GetThreatDB(db)
    if db and type(db.threat) == "table" then
        return db.threat
    end
    return nil
end

local function GetKeyWithLegacy(tbl, modernKey, legacyKey)
    if type(tbl) ~= "table" then return nil end
    if tbl[modernKey] ~= nil then return tbl[modernKey] end
    return tbl[legacyKey]
end

local function GetSkinID(db, styleKey)
    local skins = db and db.skins
    if type(skins) ~= "table" then
        return 23
    end

    if styleKey == "boss" then
        return skins.boss or skins.highlevel or 23
    elseif styleKey == "eliteCaster" then
        return skins.eliteCaster or skins.caster or 23
    elseif styleKey == "eliteMelee" then
        return skins.eliteMelee or skins.melee or 23
    end

    return skins[styleKey] or 23
end

local function GetBaseColorForKey(bdb, colorKey)
    if type(bdb) ~= "table" then
        return { r = 0.8, g = 0.8, b = 0.8 }
    end

    if colorKey == "boss" then
        return bdb.boss or bdb.highlevel or { r = 0.8, g = 0.0, b = 1.0 }
    elseif colorKey == "eliteCaster" then
        return bdb.eliteCaster or bdb.caster or { r = 1.0, g = 0.4, b = 0.8 }
    elseif colorKey == "eliteMelee" then
        return bdb.eliteMelee or bdb.melee or { r = 0.0, g = 0.6, b = 1.0 }
    end

    return bdb[colorKey] or { r = 0.8, g = 0.8, b = 0.8 }
end

-- ------------------------------------------------------------
-- Classification / resolver helpers
-- ------------------------------------------------------------
local function GetSafeUnitLevel(unit)
    if not unit or not UnitExists(unit) then return nil end
    local lvl = UnitLevel(unit)
    if type(lvl) ~= "number" then return nil end
    return lvl
end

local function GetSafePlayerLevel()
    local lvl = UnitLevel("player")
    if type(lvl) ~= "number" then return nil end
    return lvl
end

local function GetEffectiveLevel(unit)
    if not unit or not UnitExists(unit) then return nil end

    if UnitEffectiveLevel then
        local lvl = UnitEffectiveLevel(unit)
        if type(lvl) == "number" then
            return lvl
        end
    end

    return GetSafeUnitLevel(unit)
end

local function IsBossLikeUnit(unit)
    if not unit or not UnitExists(unit) then return false end

    local lvl = GetSafeUnitLevel(unit)
    if lvl == -1 then
        return true
    end

    if UnitIsBossMob then
        local ok, r = pcall(UnitIsBossMob, unit)
        if ok and r then
            return true
        end
    end

    return false
end

local function ResolveEliteBucket(unit)
    if not unit or not UnitExists(unit) then
        return "eliteMelee"
    end

    -- Conservative split until we build better NPC heuristics
    local class = UnitClassBase and UnitClassBase(unit)
    if class == "PALADIN" then
        return "eliteCaster"
    end

    return "eliteMelee"
end

local function ResolveStyleKey(unit)
    if not unit or not UnitExists(unit) then
        return "normal"
    end

    local lvl = GetSafeUnitLevel(unit)
    local pl  = GetSafePlayerLevel()
    local cls = UnitClassification(unit)

    if IsBossLikeUnit(unit) then
        return "boss"
    end

    if lvl and pl and lvl >= pl + 2 then
        return "boss"
    end

    if lvl and pl and lvl == pl + 1 then
        return "plusOne"
    end

    if cls == "elite" then
        return ResolveEliteBucket(unit)
    end

    return "normal"
end

local function ResolveColorKey(unit)
    if not unit or not UnitExists(unit) then
        return "normal"
    end

    local lvl = GetEffectiveLevel(unit)
    local pl  = GetSafePlayerLevel()
    local cls = UnitClassification(unit)

    if IsBossLikeUnit(unit) then
        return "boss"
    end

    if lvl and pl and lvl >= pl + 2 then
        return "boss"
    end

    if lvl and pl and lvl == pl + 1 then
        return "plusOne"
    end

    if cls == "elite" then
        return ResolveEliteBucket(unit)
    end

    return "normal"
end

local function SafeSetText(fs, text)
    if not (fs and fs.SetText) then return end
    pcall(fs.SetText, fs, text or "")
end

local function EnsurePrimaryFonts(self)
    local hb = self and self.healthBar
    if not hb then return end

    local db = PlateOMaticDB or {}

    if hb.pomName then
        SafeSetFont(hb.pomName, db.fontPath, db.fontSize, db.fontOutline)
    end

    if hb.pomHealth then
        SafeSetFont(hb.pomHealth, db.fontPath, db.fontSize, db.fontOutline)
    end
end

-- ------------------------------------------------------------
-- Constructor
-- ------------------------------------------------------------
function Mixins:New(frame, skins)
    local o = {}
    for k, v in pairs(self) do
        if k ~= "New" then o[k] = v end
    end
    o.frame = frame
    o.skins = skins or ns.SKINS
    o.healthBar = frame.healthBar or (frame.HealthBarsContainer and frame.HealthBarsContainer.healthBar)
    if not o.healthBar then return o end
    o:Init()
    return o
end

-- ------------------------------------------------------------
-- Init (one-time per nameplate)
-- ------------------------------------------------------------
function Mixins:Init()
    local hb = self.healthBar
    if not hb then return end

    if not hb.pomBG then
        local bg = hb:CreateTexture(nil, "BACKGROUND")
        bg:SetAllPoints(hb)
        bg:SetTexture("Interface\\Buttons\\WHITE8x8")
        bg:SetVertexColor(0.25, 0.25, 0.25, 0.85)
        hb.pomBG = bg
    end

    if not hb.pomBorders then
        hb.pomBorders = U.MakeBorder(hb, "pomBorders")
    end

    if not hb.pomTextFrame then
        local tf = CreateFrame("Frame", nil, hb)
        tf:SetAllPoints(hb)
        tf:SetFrameLevel(hb:GetFrameLevel() + 20)
        hb.pomTextFrame = tf

        local fsName = tf:CreateFontString(nil, "OVERLAY")
        fsName:SetPoint("LEFT", tf, "LEFT", 4, 0)
        fsName:SetPoint("RIGHT", tf, "RIGHT", -40, 0)
        fsName:SetJustifyH("LEFT")
        fsName:SetWordWrap(false)
        hb.pomName = fsName

        local fsHealth = tf:CreateFontString(nil, "OVERLAY")
        fsHealth:SetPoint("RIGHT", tf, "RIGHT", -4, 0)
        fsHealth:SetJustifyH("RIGHT")
        hb.pomHealth = fsHealth
    end

    if not hb.pomThreatText then
        local ft = hb.pomTextFrame:CreateFontString(nil, "OVERLAY")
        ft:SetPoint("TOP", hb, "BOTTOM", 0, -2)
        hb.pomThreatText = ft
    end

    if not hb.pomRareText then
        local rt = hb.pomTextFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        rt:SetPoint("BOTTOM", hb, "TOP", 0, 2)
        rt:SetJustifyH("CENTER")
        rt:SetTextColor(0.8, 0.6, 1.0)
        rt:SetText("RARE")
        rt:Hide()
        hb.pomRareText = rt
    end

    if not hb.pomQuestIcon then
        local qi = hb:CreateTexture(nil, "OVERLAY")
        qi:SetTexture("Interface\\TargetingFrame\\PortraitQuestBadge")
        qi:SetSize(20, 20)
        qi:SetPoint("RIGHT", hb, "LEFT", -5, 5)
        qi:Hide()
        hb.pomQuestIcon = qi

        local qt = hb.pomTextFrame:CreateFontString(nil, "OVERLAY")
        qt:SetPoint("TOP", qi, "BOTTOM", 0, 2)
        qt:SetTextColor(1, 0.82, 0)
        hb.pomQuestText = qt
    end

    if not hb.pomArrows then
        hb.pomArrows = {}

        local arrowL = self.frame:CreateTexture(nil, "OVERLAY")
        arrowL:SetTexture("Interface\\Buttons\\UI-MicroStream-Yellow")
        arrowL:SetSize(24, 24)
        arrowL:Hide()
        hb.pomArrows.left = arrowL

        local arrowR = self.frame:CreateTexture(nil, "OVERLAY")
        arrowR:SetTexture("Interface\\Buttons\\UI-MicroStream-Yellow")
        arrowR:SetSize(24, 24)
        arrowR:SetTexCoord(1, 0, 0, 1)
        arrowR:Hide()
        hb.pomArrows.right = arrowR
    end

    if not hb.pomWarningGlow then
        local glow = hb:CreateTexture(nil, "OVERLAY", nil, 6)
        glow:SetAllPoints(hb)
        glow:SetTexture("Interface\\Buttons\\WHITE8x8")
        glow:SetVertexColor(1, 1, 0, 0.6)
        glow:SetBlendMode("ADD")
        glow:Hide()
        hb.pomWarningGlow = glow

        local ag = glow:CreateAnimationGroup()
        ag:SetLooping("BOUNCE")
        local a1 = ag:CreateAnimation("Alpha")
        a1:SetFromAlpha(0)
        a1:SetToAlpha(1)
        a1:SetDuration(0.4)
        a1:SetSmoothing("IN_OUT")
        hb.pomWarningAnim = ag
    end

    if not hb.pomTargetBorder then
        hb.pomTargetBorder = U.MakeBorder(hb, "pomTargetBorder")
        for i = 1, 4 do hb.pomTargetBorder[i]:Hide() end
    end
end

-- ------------------------------------------------------------
-- Visuals (fonts / name anchor)
-- ------------------------------------------------------------
function Mixins:UpdateVisuals()
    local hb = self.healthBar
    if not hb then return end
    local db = PlateOMaticDB or {}

    local tf = hb.pomTextFrame
    local fsName = hb.pomName
    if tf and fsName then
        fsName:ClearAllPoints()
        local pos = db.nameAnchor or "LEFT"

        if pos == "TOP" then
            fsName:SetPoint("BOTTOM", tf, "TOP", 0, 2)
            fsName:SetJustifyH("CENTER")
            fsName:SetPoint("LEFT", tf, "LEFT", -50, 0)
            fsName:SetPoint("RIGHT", tf, "RIGHT", 50, 0)
        elseif pos == "CENTER" then
            fsName:SetPoint("CENTER", tf, "CENTER", 0, 1)
            fsName:SetPoint("LEFT", tf, "LEFT", 4, 0)
            fsName:SetPoint("RIGHT", tf, "RIGHT", -40, 0)
            fsName:SetJustifyH("CENTER")
        else
            fsName:SetPoint("LEFT", tf, "LEFT", 4, 0)
            fsName:SetPoint("RIGHT", tf, "RIGHT", -40, 0)
            fsName:SetJustifyH("LEFT")
        end
    end

    if hb.pomName then
        SafeSetFont(hb.pomName, db.fontPath, db.fontSize, db.fontOutline)
        hb.pomName:SetTextColor(1, 1, 1)
        hb.pomName:Show()
    end

    if hb.pomHealth then
        SafeSetFont(hb.pomHealth, db.fontPath, db.fontSize, db.fontOutline)
        hb.pomHealth:SetTextColor(1, 1, 1)
        hb.pomHealth:Show()
    end

    if hb.pomThreatText then
        SafeSetFont(hb.pomThreatText, db.fontPath, (tonumber(db.fontSize) or 10) - 1, db.fontOutline)
    end

    if hb.pomRareText then
        SafeSetFont(hb.pomRareText, db.fontPath, (tonumber(db.fontSize) or 10) - 2, db.fontOutline)
    end

    if hb.pomQuestText then
        SafeSetFont(hb.pomQuestText, db.fontPath, (tonumber(db.fontSize) or 10) - 2, db.fontOutline)
    end
end

-- ------------------------------------------------------------
-- Heights (ONLY calls heights module; safe to run always)
-- ------------------------------------------------------------
function Mixins:UpdateHeight()
    local hb = self.healthBar
    if not hb then return end

    if ns and ns.heights and ns.heights.ApplyForUnit then
        ns.heights:ApplyForUnit(hb, self.frame.unit)
    end
end

-- ------------------------------------------------------------
-- Quest logic (tooltip scan)
-- ------------------------------------------------------------
function Mixins:UpdateQuest()
    local hb = self.healthBar
    if not hb or not hb.pomQuestIcon then return end

    local db = PlateOMaticDB or {}
    local showIcon = db.showQuestIcon
    local showProg = db.showQuestProg

    if not showIcon then
        hb.pomQuestIcon:Hide()
        if hb.pomQuestText then hb.pomQuestText:Hide() end
        return
    end

    local unit = self.frame.unit
    local isQuest = false
    local progressText = ""

    if C_TooltipInfo and C_TooltipInfo.GetUnit then
        local data = C_TooltipInfo.GetUnit(unit)
        if data then
            for _, line in ipairs(data.lines) do
                if line.type == 17 or line.type == 18 then
                    isQuest = true
                end
                if showProg and line.leftText and type(line.leftText) == "string" then
                    local ok, current, total = pcall(string.match, line.leftText, "(%d+)/(%d+)")
                    if ok and current and total then
                        progressText = current .. "/" .. total
                    else
                        local ok2, perc = pcall(string.match, line.leftText, "(%d+%%)")
                        if ok2 and perc then progressText = perc end
                    end
                end
            end
        end
    end

    if isQuest then
        hb.pomQuestIcon:Show()
        if showProg and progressText ~= "" then
            SafeSetText(hb.pomQuestText, progressText)
            hb.pomQuestText:Show()
        else
            hb.pomQuestText:Hide()
        end
    else
        hb.pomQuestIcon:Hide()
        if hb.pomQuestText then
            hb.pomQuestText:Hide()
        end
    end
end

-- ------------------------------------------------------------
-- Name + HP text
-- ------------------------------------------------------------
function Mixins:UpdateName()
    local hb = self.healthBar
    if not hb or not hb.pomName then return end

    EnsurePrimaryFonts(self)
    SafeSetText(hb.pomName, UnitName(self.frame.unit) or "")
end

function Mixins:UpdateHealth()
    local hb = self.healthBar
    if not hb or not hb.pomHealth then return end
    local unit = self.frame.unit

    EnsurePrimaryFonts(self)

    if not U.IsSafeUnit(unit) then
        SafeSetText(hb.pomHealth, "")
        return
    end

    if UnitIsDeadOrGhost(unit) then
        SafeSetText(hb.pomHealth, "0%")
        return
    end

    local percentValue
    if UnitHealthPercent then
        local scaling = (CurveConstants and CurveConstants.ScaleTo100) or 1
        percentValue = UnitHealthPercent(unit, true, scaling)
    else
        local maxH = UnitHealthMax(unit) or 1
        local curH = UnitHealth(unit, true) or 0
        percentValue = (curH / maxH) * 100
    end

    percentValue = tonumber(percentValue) or 0
    SafeSetText(hb.pomHealth, string.format("%d%%", percentValue))
end

-- =========================================================
-- UpdateState (skins + base colors + threat + target visuals)
-- =========================================================
function Mixins:UpdateState()
    local hb = self.healthBar
    if not hb then return end

    local db = PlateOMaticDB or {}
    local unit = self.frame.unit

    -- RARE label
    if hb.pomRareText then
        local isRare, cls = IsRareUnit(unit)
        if isRare then
            SafeSetText(hb.pomRareText, (cls == "rareelite") and "RARE+" or "RARE")
            hb.pomRareText:Show()
        else
            hb.pomRareText:Hide()
        end
    end

    -- Scale + target visuals
    local currentScale = db.globalScale or 1.0
    local isTarget = UnitIsUnit("target", unit)

    if isTarget then
        currentScale = currentScale * (db.targetScale or 1.15)

        if hb.pomArrows then
            if db.showTargetArrow then
                local arrL, arrR = hb.pomArrows.left, hb.pomArrows.right
                arrL:ClearAllPoints()
                arrR:ClearAllPoints()

                if db.arrowPointingOut then
                    arrL:SetPoint("RIGHT", hb, "LEFT", -4, 0); arrL:SetRotation(1.57)
                    arrR:SetPoint("LEFT", hb, "RIGHT", 4, 0);  arrR:SetRotation(-1.57)
                else
                    arrL:SetPoint("RIGHT", hb, "LEFT", -4, 0); arrL:SetRotation(-1.57)
                    arrR:SetPoint("LEFT", hb, "RIGHT", 4, 0);  arrR:SetRotation(1.57)
                end

                arrL:Show()
                arrR:Show()
            else
                hb.pomArrows.left:Hide()
                hb.pomArrows.right:Hide()
            end
        end
    else
        if hb.pomArrows then
            hb.pomArrows.left:Hide()
            hb.pomArrows.right:Hide()
        end
    end

    self.frame:SetScale(currentScale)

    -- Split style/color resolution
    local styleKey = ResolveStyleKey(unit)
    local colorKey = ResolveColorKey(unit)

    -- Keep resolved keys around for future debugging
    self.frame.POM_StyleKey = styleKey
    self.frame.POM_ColorKey = colorKey

    -- Skin texture
    local skins = (type(self.skins) == "table") and self.skins or ((type(ns.SKINS) == "table") and ns.SKINS or nil)
    local skinID = GetSkinID(db, styleKey)
    local skin = (skins and (skins[skinID] or skins[23])) or nil

    if skin and skin.texture then
        hb:SetStatusBarTexture(skin.texture)
    else
        hb:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
    end

    -- Base color
    local bdb = GetBaseColorsDB(db)
    local cBase = GetBaseColorForKey(bdb, colorKey)
    local finalR, finalG, finalB = cBase.r or 0.8, cBase.g or 0.8, cBase.b or 0.8

    if skin and skin.ignoreColor then
        finalR, finalG, finalB = 1, 1, 1
    end

    -- Neutral lock (reaction==4 and not in combat)
    local neutralLock = false
    if not (skin and skin.ignoreColor) and bdb and bdb.neutral then
        local reaction = tonumber(UnitReaction(unit, "player") or 0) or 0
        if reaction == 4 and not UnitIsPlayer(unit) then
            local nc = bdb.neutral
            finalR = nc.r or finalR
            finalG = nc.g or finalG
            finalB = nc.b or finalB
            neutralLock = not UnitAffectingCombat(unit)
        end
    end

    -- PvP: if active AND disableThreatInPvP => never run threat here.
    local pvpNoThreat = false
    if ns and ns.pvp and ns.pvp.IsActive and ns.pvp:IsActive() then
        local pdb = db.pvp
        if pdb and pdb.disableThreatInPvP then
            pvpNoThreat = true
        end
    end

    -- Solo override: keep ONLY base colors
    local isSolo = (not IsInGroup()) and (not IsInRaid())
    if db.useBaseColorsSolo and isSolo and not (skin and skin.ignoreColor) and not neutralLock then
        hb:SetStatusBarColor(finalR, finalG, finalB)

        if hb.pomThreatText then
            SafeSetText(hb.pomThreatText, "")
            hb.pomThreatText:Hide()
        end

        if hb.pomWarningGlow and hb.pomWarningAnim and self.frame.pomIsFlashing then
            self.frame.pomIsFlashing = false
            if self.frame.pomFlashTimer then self.frame.pomFlashTimer:Cancel() end
            hb.pomWarningGlow:Hide()
            hb.pomWarningAnim:Stop()
        end

    elseif pvpNoThreat then
        hb:SetStatusBarColor(finalR, finalG, finalB)

        if hb.pomThreatText then
            SafeSetText(hb.pomThreatText, "")
            hb.pomThreatText:Hide()
        end

        if hb.pomWarningGlow and hb.pomWarningAnim and self.frame.pomIsFlashing then
            self.frame.pomIsFlashing = false
            if self.frame.pomFlashTimer then self.frame.pomFlashTimer:Cancel() end
            hb.pomWarningGlow:Hide()
            hb.pomWarningAnim:Stop()
        end

    else
        -- Threat override
        local tdb = GetThreatDB(db) or {}

        local tr, tg, tb, shouldFlash, threatPct = nil, nil, nil, false, 0
        if not neutralLock and tdb.enabled and ns and ns.threat and ns.threat.GetState then
            tr, tg, tb, shouldFlash, threatPct = ns.threat:GetState(unit)
        end

        if not neutralLock and tr and not (skin and skin.ignoreColor) then
            finalR, finalG, finalB = tr, tg, tb
        end

        hb:SetStatusBarColor(finalR, finalG, finalB)

        -- Threat % text (SECRET-SAFE)
        if hb.pomThreatText and (not neutralLock) and tdb.showThreatPerc then
            local minPct = tonumber(tdb.pctTextMin) or 1

            local pctIsSecret = IsSecretNumber(threatPct)
            local pct = (not pctIsSecret) and (tonumber(threatPct) or 0) or 0

            if (not pctIsSecret) and pct >= minPct then
                SafeSetText(hb.pomThreatText, string.format("%.0f%%", pct))
                hb.pomThreatText:Show()

                if pct >= 100 then
                    hb.pomThreatText:SetTextColor(1, 0.2, 0.2)
                elseif pct >= 70 then
                    hb.pomThreatText:SetTextColor(1, 1, 0)
                else
                    hb.pomThreatText:SetTextColor(0.6, 0.6, 0.6)
                end
            else
                SafeSetText(hb.pomThreatText, "")
                hb.pomThreatText:Hide()
            end
        elseif hb.pomThreatText then
            SafeSetText(hb.pomThreatText, "")
            hb.pomThreatText:Hide()
        end

        if hb.pomWarningGlow and hb.pomWarningAnim then
            if neutralLock then
                if self.frame.pomIsFlashing then
                    self.frame.pomIsFlashing = false
                    if self.frame.pomFlashTimer then self.frame.pomFlashTimer:Cancel() end
                    hb.pomWarningGlow:Hide()
                    hb.pomWarningAnim:Stop()
                end
            else
                local wantFlash = (tdb.flashAggro and shouldFlash) and true or false

                if wantFlash then
                    if not self.frame.pomIsFlashing then
                        self.frame.pomIsFlashing = true
                        hb.pomWarningGlow:Show()
                        hb.pomWarningAnim:Play()

                        local dur = tonumber(tdb.flashDuration) or 0
                        if dur > 0 then
                            if self.frame.pomFlashTimer then self.frame.pomFlashTimer:Cancel() end
                            self.frame.pomFlashTimer = C_Timer.NewTimer(dur, function()
                                if self.frame then
                                    self.frame.pomIsFlashing = false
                                    if hb and hb.pomWarningGlow then
                                        hb.pomWarningGlow:Hide()
                                        hb.pomWarningAnim:Stop()
                                    end
                                end
                            end)
                        end
                    end
                else
                    if self.frame.pomIsFlashing then
                        self.frame.pomIsFlashing = false
                        if self.frame.pomFlashTimer then self.frame.pomFlashTimer:Cancel() end
                        hb.pomWarningGlow:Hide()
                        hb.pomWarningAnim:Stop()
                    end
                end
            end
        end
    end

    -- Borders
    if hb.pomBorders then
        U.LayoutBorder(hb.pomBorders, hb, 2)
        for i = 1, 4 do
            hb.pomBorders[i]:SetColorTexture(0, 0, 0, 1)
        end
    end

    -- Target border
    if hb.pomTargetBorder then
        if isTarget then
            local c = db.targetBorderColor or { r = 1, g = 0.82, b = 0, a = 1 }
            local r, g, b, a = c.r or 1, c.g or 1, c.b or 1, c.a or 1
            for i = 1, 4 do
                hb.pomTargetBorder[i]:SetColorTexture(r, g, b, a)
            end
            U.LayoutBorder(hb.pomTargetBorder, hb, 3)
            for i = 1, 4 do
                hb.pomTargetBorder[i]:Show()
            end
        else
            for i = 1, 4 do
                hb.pomTargetBorder[i]:Hide()
            end
        end
    end
end