-- Lua error capture + on-screen log (uses MythicMateNS.State from Bootstrap).
local MythicMateNS = _G.MythicMate
if not MythicMateNS then return end

local whatLockoutErrorHandlerInstalled = false
local whatLockoutErrorHandlerSupported = false
local whatLockoutErrorLogsFrame = nil
local whatLockoutErrorLogsText = nil

function MythicMate_IsErrorFromThisAddon(stack)
    if not stack or type(stack) ~= "string" then return false end
    if stack:find("MythicMate.lua", 1, true) then return true end
    if stack:find("MythicMate_", 1, true) then return true end
    if stack:find("Interface\\AddOns\\MythicMate", 1, true) then return true end
    if stack:find("Interface/AddOns/MythicMate", 1, true) then return true end
    return false
end

function MythicMate_FormatLuaErrorEntry(entry)
    local t = entry.t or 0
    local whenStr = tostring(t)
    if type(date) == "function" then
        local ok, s = pcall(function()
            return date("%H:%M:%S", t)
        end)
        if ok and s and s ~= "" then whenStr = s end
    end

    local errStr = entry.err or "(unknown error)"
    if type(errStr) ~= "string" then errStr = tostring(errStr) end

    local out = {}
    table.insert(out, string.format("[%s] %s", whenStr, errStr))

    local stack = entry.stack or ""
    if type(stack) == "string" and stack ~= "" then
        local count = 0
        for line in stack:gmatch("[^\r\n]+") do
            count = count + 1
            if count > 10 then
                table.insert(out, "... (stack truncated)")
                break
            end
            table.insert(out, "  " .. line)
        end
    end
    return table.concat(out, "\n")
end

function MythicMate_RefreshErrorLogsView()
    if not whatLockoutErrorLogsFrame or not whatLockoutErrorLogsText then return end
    local logs = MythicMateNS.State._luaErrorLogs or {}
    local maxEntries = 50

    local n = #logs
    if n == 0 then
        if not whatLockoutErrorHandlerSupported then
            whatLockoutErrorLogsText:SetText("No Lua errors captured yet.\n(seterrorhandler not available)\n")
        else
            whatLockoutErrorLogsText:SetText("No Lua errors captured yet.\n")
        end
        return
    end

    local startIdx = math.max(1, n - maxEntries + 1)
    local lines = {}
    table.insert(lines, "Lua error log (newest at bottom):")
    table.insert(lines, "-----------------------------------")
    for i = startIdx, n do
        local entry = logs[i]
        if entry then
            table.insert(lines, MythicMate_FormatLuaErrorEntry(entry))
            table.insert(lines, "")
        end
    end
    whatLockoutErrorLogsText:SetText(table.concat(lines, "\n"))
    if whatLockoutErrorLogsFrame and whatLockoutErrorLogsFrame:IsShown() then
        whatLockoutErrorLogsFrame:Show()
    end

    if whatLockoutErrorLogsFrame and whatLockoutErrorLogsFrame.scrollFrame and type(whatLockoutErrorLogsFrame.scrollFrame.UpdateScrollChildRect) == "function" then
        whatLockoutErrorLogsFrame.scrollFrame:UpdateScrollChildRect()
    end
end

function MythicMate_ToggleErrorLogsView(forceOpen)
    MythicMateNS.State._logsEnabled = not not forceOpen
    if not whatLockoutErrorLogsFrame then
        whatLockoutErrorLogsFrame = CreateFrame("Frame", "MythicMateErrorLogsFrame", UIParent, "BackdropTemplate")
        whatLockoutErrorLogsFrame:SetSize(650, 420)
        whatLockoutErrorLogsFrame:SetPoint("CENTER")
        whatLockoutErrorLogsFrame:SetFrameStrata("DIALOG")
        whatLockoutErrorLogsFrame:EnableMouse(true)
        -- Remember where the user drags this window (persists across reloads).
        if type(_G.MythicMate_PersistFrame) == "function" then
            _G.MythicMate_PersistFrame(whatLockoutErrorLogsFrame, "errorlogs")
        else
            whatLockoutErrorLogsFrame:SetMovable(true)
            whatLockoutErrorLogsFrame:RegisterForDrag("LeftButton")
            whatLockoutErrorLogsFrame:SetScript("OnDragStart", whatLockoutErrorLogsFrame.StartMoving)
            whatLockoutErrorLogsFrame:SetScript("OnDragStop", whatLockoutErrorLogsFrame.StopMovingOrSizing)
        end
        whatLockoutErrorLogsFrame:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8x8",
            edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
            tile = true, tileSize = 16, edgeSize = 24,
            insets = { left = 8, right = 8, top = 8, bottom = 8 },
        })
        whatLockoutErrorLogsFrame:SetBackdropColor(0.05, 0.05, 0.1, 0.95)
        whatLockoutErrorLogsFrame:SetBackdropBorderColor(0.8, 0.7, 1.0, 1)

        local closeBtn = CreateFrame("Button", nil, whatLockoutErrorLogsFrame, "UIPanelCloseButton")
        closeBtn:SetPoint("TOPRIGHT", whatLockoutErrorLogsFrame, "TOPRIGHT", -4, -4)
        closeBtn:SetScript("OnClick", function()
            MythicMateNS.State._logsEnabled = false
            if whatLockoutErrorLogsFrame then whatLockoutErrorLogsFrame:Hide() end
        end)

        local title = whatLockoutErrorLogsFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
        title:SetPoint("TOPLEFT", 12, -10)
        title:SetText("MythicMate - Lua Error Log")

        local scrollFrame = CreateFrame("ScrollFrame", nil, whatLockoutErrorLogsFrame, "UIPanelScrollFrameTemplate")
        scrollFrame:SetPoint("TOPLEFT", 12, -40)
        scrollFrame:SetPoint("BOTTOMRIGHT", -28, 12)

        local text = scrollFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        text:SetPoint("TOPLEFT", 0, 0)
        text:SetWidth(600)
        text:SetJustifyH("LEFT")
        text:SetJustifyV("TOP")
        scrollFrame:SetScrollChild(text)

        whatLockoutErrorLogsFrame.scrollFrame = scrollFrame
        whatLockoutErrorLogsText = text
    end

    if MythicMateNS.State._logsEnabled then
        MythicMate_RefreshErrorLogsView()
        whatLockoutErrorLogsFrame:Show()
        if whatLockoutErrorLogsFrame.Raise then whatLockoutErrorLogsFrame:Raise() end
        if whatLockoutErrorLogsFrame:IsShown() and whatLockoutErrorLogsFrame.SetFocus then
            whatLockoutErrorLogsFrame:SetFocus()
        end
    else
        if whatLockoutErrorLogsFrame then whatLockoutErrorLogsFrame:Hide() end
    end
end

function MythicMate_InstallLuaErrorHandler()
    if whatLockoutErrorHandlerInstalled then return end
    whatLockoutErrorHandlerInstalled = true
    if type(seterrorhandler) ~= "function" then return end
    whatLockoutErrorHandlerSupported = true

    local maxEntries = 200
    -- Capture the currently-installed handler BEFORE replacing it. seterrorhandler()
    -- returns nothing in WoW, so we must read the previous handler via geterrorhandler()
    -- and chain to it below; otherwise other addons' / Blizzard's error reporting is
    -- silently dropped once MythicMate loads.
    local previousErrorHandler = (type(geterrorhandler) == "function") and geterrorhandler() or nil
    seterrorhandler(function(err)
        local stack = nil
        if type(debug) == "table" and type(debug.traceback) == "function" then
            local ok, tb = pcall(function()
                return debug.traceback(tostring(err), 2)
            end)
            if ok and type(tb) == "string" and tb ~= "" then stack = tb end
        end
        if not stack then
            stack = tostring(err)
        end

        if MythicMate_IsErrorFromThisAddon(stack) then
            local logs = MythicMateNS.State._luaErrorLogs
            if type(logs) ~= "table" then
                logs = {}
                MythicMateNS.State._luaErrorLogs = logs
            end
            if type(stack) == "string" and #stack > 8000 then
                stack = stack:sub(1, 8000) .. "\n... (stack truncated in storage)"
            end
            local entry = {
                t = (type(time) == "function" and time() or 0),
                err = err,
                stack = stack,
            }
            logs[#logs + 1] = entry
            if #logs > maxEntries then
                table.remove(logs, 1)
            end

            if MythicMateNS.State._logsEnabled then
                pcall(MythicMate_RefreshErrorLogsView)
            end
        end

        if previousErrorHandler then
            local ok, res = pcall(previousErrorHandler, err)
            if ok then return res end
        end
        return err
    end)
end

MythicMateNS.RefreshErrorLogsView = MythicMate_RefreshErrorLogsView
MythicMateNS.ToggleErrorLogsView = MythicMate_ToggleErrorLogsView

MythicMate_InstallLuaErrorHandler()
