local ldb = LibStub("LibDataBroker-1.1", true)
local dbicon = LibStub("LibDBIcon-1.0", true)
local L = LibStub("AceLocale-3.0"):GetLocale("CritMatic")

local ICON_PATH = "Interface\\AddOns\\CritMatic\\Media\\Textures\\critmatic-medallion.tga"

local function TopRecords()
    local bestCrit, bestCritName = 0, nil
    local bestHit, bestHitName = 0, nil
    local bestHeal, bestHealName = 0, nil
    for spellID, d in pairs(CritMaticData or {}) do
        if d.highestCrit and d.highestCrit > bestCrit then
            bestCrit = d.highestCrit
            bestCritName = Critmatic.GetRecordName(spellID, d)
        end
        if d.highestNormal and d.highestNormal > bestHit then
            bestHit = d.highestNormal
            bestHitName = Critmatic.GetRecordName(spellID, d)
        end
        if d.highestHealCrit and d.highestHealCrit > bestHeal then
            bestHeal = d.highestHealCrit
            bestHealName = Critmatic.GetRecordName(spellID, d)
        end
    end
    return bestCrit, bestCritName, bestHit, bestHitName, bestHeal, bestHealName
end

local function ColorHex(c, fallback)
    if type(c) ~= "table" then return fallback end
    local r = math.floor((c[1] or 1) * 255 + 0.5)
    local g = math.floor((c[2] or 1) * 255 + 0.5)
    local b = math.floor((c[3] or 1) * 255 + 0.5)
    return string.format("ff%02x%02x%02x", r, g, b)
end

if ldb then
    Critmatic.brokerObject = ldb:NewDataObject("CritMatic", {
        type = "data source",
        text = "CritMatic",
        icon = ICON_PATH,
        OnClick = function(_, button)
            if button == "RightButton" then
                Critmatic:OpenOptions()
            else
                Critmatic:OpenCritLog()
            end
        end,
        OnTooltipShow = function(tooltip)
            local bestCrit, bestCritName, bestHit, bestHitName, bestHeal, bestHealName = TopRecords()
            local broker = (Critmatic.db and Critmatic.db.profile and Critmatic.db.profile.brokerSettings) or {}
            tooltip:AddLine("|cffffd700CritMatic|r")
            local function addCritLine()
                if bestCrit > 0 then
                    tooltip:AddDoubleLine(L["broker_top_crit"], (bestCritName and (bestCrit .. "  " .. bestCritName)) or tostring(bestCrit))
                end
            end
            local function addHitLine()
                if bestHit > 0 then
                    tooltip:AddDoubleLine(L["broker_top_hit"], (bestHitName and (bestHit .. "  " .. bestHitName)) or tostring(bestHit))
                end
            end
            if broker.hitFirst then
                addHitLine()
                addCritLine()
            else
                addCritLine()
                addHitLine()
            end
            if bestHeal > 0 then
                tooltip:AddDoubleLine(L["broker_top_crit_heal"], (bestHealName and (bestHeal .. "  " .. bestHealName)) or tostring(bestHeal))
            end
            tooltip:AddLine(L["broker_left_click_crit_log"], 0.8, 0.8, 0.8)
            tooltip:AddLine(L["broker_right_click_options"], 0.8, 0.8, 0.8)
        end,
    })
end

function Critmatic.UpdateBroker()
    if not Critmatic.brokerObject then return end
    local bestCrit, _, bestHit = TopRecords()
    local critHex, hitHex = "ffffd700", "ffffffff"
    if Critmatic.db and Critmatic.db.profile and Critmatic.db.profile.fontSettings then
        critHex = ColorHex(Critmatic.db.profile.fontSettings.fontColorCrit, critHex)
        hitHex = ColorHex(Critmatic.db.profile.fontSettings.fontColor, hitHex)
    end
    local broker = (Critmatic.db and Critmatic.db.profile and Critmatic.db.profile.brokerSettings) or {}

    local critLabel, hitLabel, separator
    if broker.compactNumbers then
        critLabel, hitLabel, separator = "", "", "/"
    elseif broker.compactInitials then
        critLabel, hitLabel, separator = L["broker_crit_initial"] .. ":", L["broker_hit_initial"] .. ":", " "
    elseif broker.compactLabels then
        critLabel, hitLabel, separator = L["broker_crit_short"] .. ": ", L["broker_hit_short"] .. ": ", "  "
    else
        critLabel, hitLabel, separator = L["broker_top_crit"] .. ": ", L["broker_top_hit"] .. ": ", "  "
    end

    local critPart, hitPart
    if bestCrit and bestCrit > 0 then
        critPart = "|c" .. critHex .. critLabel .. bestCrit .. "|r"
    end
    if bestHit and bestHit > 0 then
        hitPart = "|c" .. hitHex .. hitLabel .. bestHit .. "|r"
    end

    local first, second
    if broker.hitFirst then
        first, second = hitPart, critPart
    else
        first, second = critPart, hitPart
    end

    local parts = {}
    if first then parts[#parts + 1] = first end
    if second then parts[#parts + 1] = second end

    if #parts > 0 then
        Critmatic.brokerObject.text = table.concat(parts, separator)
    else
        Critmatic.brokerObject.text = "CritMatic"
    end
end

function Critmatic.SetupMinimapIcon()
    if not dbicon or not Critmatic.brokerObject then return end
    if not Critmatic.db or not Critmatic.db.profile then return end
    Critmatic.db.profile.minimap = Critmatic.db.profile.minimap or { hide = false }
    if not dbicon:IsRegistered("CritMatic") then
        dbicon:Register("CritMatic", Critmatic.brokerObject, Critmatic.db.profile.minimap)
    elseif dbicon.Refresh then
        -- Rebind to the active profile's minimap table after a profile switch,
        -- otherwise drags and the hide state keep writing to the old profile.
        dbicon:Refresh("CritMatic", Critmatic.db.profile.minimap)
    end
    if Critmatic.db.profile.minimap.hide then
        dbicon:Hide("CritMatic")
    else
        dbicon:Show("CritMatic")
    end
end

function Critmatic.SetMinimapHidden(hide)
    if not Critmatic.db or not Critmatic.db.profile then return end
    Critmatic.db.profile.minimap = Critmatic.db.profile.minimap or { hide = false }
    Critmatic.db.profile.minimap.hide = hide and true or false
    if not dbicon then return end
    if hide then
        dbicon:Hide("CritMatic")
    else
        dbicon:Show("CritMatic")
    end
end
