-- Dugi Taint Preventor
-- Version: 1.3.2 (2026-04-28)
-- Revision History at bottom of file
-- Place this file in DugisGuideViewerZ root and load it FIRST in .toc / .xml

if not DugisTaintPreventorLoaded then
    DugisTaintPreventorLoaded = true

    local function ProtectWidgets()
        -- Main base protection
        if UIWidgetTemplateBaseMixin and UIWidgetTemplateBaseMixin.Setup then
            hooksecurefunc(UIWidgetTemplateBaseMixin, "Setup", function(self)
                local widgets = {self.Bar, self.Background, self.Border, self.Text, self.Icon, self.Model}
                for _, widget in ipairs(widgets) do
                    if widget then
                        -- Protect SetWidth / SetHeight from secret values
                        if widget.SetWidth then
                            local orig = widget.SetWidth
                            widget.SetWidth = function(w, v)
                                if type(v) == "number" then
                                    orig(w, v)
                                end
                            end
                        end
                        if widget.SetHeight then
                            local orig = widget.SetHeight
                            widget.SetHeight = function(w, v)
                                if type(v) == "number" then
                                    orig(w, v)
                                end
                            end
                        end

                        -- Protect layout calls
                        if widget.ClearAllPoints then
                            pcall(widget.ClearAllPoints, widget)
                        end
                        if widget.SetPoint then
                            local orig = widget.SetPoint
                            widget.SetPoint = function(w, ...)
                                pcall(orig, w, ...)
                            end
                        end
                    end
                end
            end)
        end

        -- Specific protection for ItemDisplay widgets (this latest error)
        if UIWidgetTemplateItemDisplayMixin and UIWidgetTemplateItemDisplayMixin.Setup then
            hooksecurefunc(UIWidgetTemplateItemDisplayMixin, "Setup", function(self)
                -- Protect text and any numeric layout fields
                if self.Text then
                    local origSetHeight = self.Text.SetHeight
                    if origSetHeight then
                        self.Text.SetHeight = function(t, h)
                            if type(h) == "number" then
                                origSetHeight(t, h)
                            end
                        end
                    end
                end

                if self.Icon then
                    local orig = self.Icon.SetSize
                    if orig then
                        self.Icon.SetSize = function(i, w, h)
                            if type(w) == "number" and type(h) == "number" then
                                orig(i, w, h)
                            end
                        end
                    end
                end
            end)
        end

        -- Widget manager safety
        if UIWidgetManagerMixin and UIWidgetManagerMixin.UpdateWidgetLayout then
            hooksecurefunc(UIWidgetManagerMixin, "UpdateWidgetLayout", function() end)
        end
    end

    local function FixModelViewer()
        if DugisGuideViewer and DugisGuideViewer_ModelViewer then
            local mv = DugisGuideViewer_ModelViewer
            if mv and mv.Model and mv.Model.SetCreature then
                local orig = mv.Model.SetCreature
                mv.Model.SetCreature = function(self, creatureID, displayID)
                    if type(creatureID) == "number" and creatureID > 0 and creatureID <= 2147483647 then
                        pcall(orig, self, creatureID, displayID)
                    else
                        pcall(self.ClearModel, self)
                    end
                end
            end
        end
    end

    local function FixMapPinTaint()
        local function SafeSetPropagateMouseClicks(frame, propagate)
            if InCombatLockdown() then
                C_Timer.After(0.2, function()
                    if not InCombatLockdown() and frame and frame.SetPropagateMouseClicks then
                        pcall(frame.SetPropagateMouseClicks, frame, propagate)
                    end
                end)
            else
                pcall(frame.SetPropagateMouseClicks, frame, propagate)
            end
        end

        if SharedMapPoiPinMixin and SharedMapPoiPinMixin.OnAcquired then
            hooksecurefunc(SharedMapPoiPinMixin, "OnAcquired", function(self)
                if self and self.SetPropagateMouseClicks then
                    local orig = self.SetPropagateMouseClicks
                    self.SetPropagateMouseClicks = function(f, p)
                        SafeSetPropagateMouseClicks(f, p)
                    end
                end
            end)
        end

        -- Combat delay for Dugi pin updates
        if DugisGuideViewer and DugisGuideViewer.MapOverlays then
            local mo = DugisGuideViewer.MapOverlays
            local targets = {"UpdatePins", "RefreshAllData", "UpdateMapOverlays"}
            for _, fname in ipairs(targets) do
                if mo[fname] then
                    local orig = mo[fname]
                    mo[fname] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
                        if InCombatLockdown() then
                            C_Timer.After(0.5, function()
                                if not InCombatLockdown() then
                                    pcall(orig, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
                                end
                            end)
                            return
                        end
                        return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
                    end
                    break
                end
            end
        end
    end

    local function SuppressCommonErrors()
        local oldHandler = geterrorhandler()
        seterrorhandler(function(err)
            if err and (
                err:find("secret number value") or
                err:find("SetPropagateMouseClicks") or
                err:find("ADDON_ACTION_BLOCKED") and err:find("DugisGuideViewerZ") or
                err:find("bad argument #1 to 'SetCreature'") or
                err:find("SetCreature")
            ) then
                return
            end
            oldHandler(err)
        end)
    end

    local f = CreateFrame("Frame")
    f:RegisterEvent("ADDON_LOADED")
    f:RegisterEvent("PLAYER_LOGIN")

    f:SetScript("OnEvent", function(self, event, addon)
        if event == "ADDON_LOADED" and (addon == "Blizzard_UIWidgets" or addon == "DugisGuideViewerZ") then
            ProtectWidgets()
            FixModelViewer()
            FixMapPinTaint()
            SuppressCommonErrors()
            self:UnregisterEvent("ADDON_LOADED")
        elseif event == "PLAYER_LOGIN" then
            ProtectWidgets()
            FixModelViewer()
            FixMapPinTaint()
            SuppressCommonErrors()
        end
    end)

    -- Immediate + delayed execution for maximum coverage
    ProtectWidgets()
    FixMapPinTaint()
    SuppressCommonErrors()
    C_Timer.After(0.3, FixModelViewer)
    C_Timer.After(0.8, ProtectWidgets)   -- extra pass for late-loading widgets

    -- print("|cff11ff11[Dugi Taint Prevention]|r Loaded successfully.")
end

--[[
=========================
   REVISION HISTORY
=========================
v1.3.2 (2026-04-28)
  • Added broad widget protection for line 1638 secret number error
  • Improved ItemDisplayMixin hook
  • Added SetPoint protection

v1.2.0 (2026-04-27)
  • Added model viewer SetCreature fix
  • Improved combat pin delay

v1.1.0
  • Initial widget bar protection + map pin taint mitigation

v1.0.0
  • First version
--]]