AddonDiagnostics = AddonDiagnostics or {}
AddonDiagnostics.EnhancedDiagnosticsBroker = {}
local EnhancedDiagnosticsBroker = AddonDiagnostics.EnhancedDiagnosticsBroker

local PROTOCOL_IDENTIFIER = "Enhanced Diagnostics"
local SUPPORTED_PROTOCOL_VERSION = 1
local MAX_REGISTERED_PROVIDERS = 32
local MAX_PENDING_REGISTRATIONS = 32
local MAX_PROVIDER_ID_CHARACTERS = 80
local MAX_DISPLAY_NAME_CHARACTERS = 80
local MAX_ADDON_VERSION_CHARACTERS = 64
local MAX_PROVIDER_SUMMARY_CHARACTERS = 12000

local MAX_BREADCRUMBS_PER_SESSION = 200
local MAX_BREADCRUMBS_PER_PROVIDER = 100
local MAX_BREADCRUMBS_PER_PROVIDER_PER_SECOND = 20
local MAX_BREADCRUMBS_GLOBAL_PER_SECOND = 80
local MAX_BREADCRUMB_FIELDS = 8
local MAX_BREADCRUMB_MODULE_CHARACTERS = 64
local MAX_BREADCRUMB_ACTION_CHARACTERS = 64
local MAX_BREADCRUMB_FIELD_NAME_CHARACTERS = 48
local MAX_BREADCRUMB_STRING_CHARACTERS = 160
local MAX_BREADCRUMB_EVIDENCE_CHARACTERS = 24000
local MAX_PASSIVE_BREADCRUMBS = 40
local MAX_PASSIVE_BREADCRUMBS_PER_PROVIDER = 20
local MAX_PASSIVE_BREADCRUMBS_PER_PROVIDER_PER_SECOND = 5
local MAX_PASSIVE_BREADCRUMBS_GLOBAL_PER_SECOND = 20
local MAX_PASSIVE_BREADCRUMB_ENTRY_CHARACTERS = 640
local MAX_PASSIVE_BREADCRUMB_EVIDENCE_CHARACTERS = 12000
local MAX_PASSIVE_BREADCRUMB_AGE_SECONDS = 30

local registeredProviderCount = 0
local rejectedProviderCount = 0
local registeredProviderIDs = "|"
local registeredProviderIDList = {}
local breadcrumbProviderIDs = "|"
local spanProviderIDs = "|"
local snapshotProviderIDs = "|"
local providerSummary = ""
local providerSummaryTruncated = false
local pendingRegistrationOverflow = false
local lastRejectedReason = nil
local brokerEventFrame = nil

local breadcrumbSessionActive = false
local breadcrumbSessionStartedAt = nil
local breadcrumbCount = 0
local droppedBreadcrumbCount = 0
local hardCapacityDroppedBreadcrumbCount = 0
local rateLimitedBreadcrumbCount = 0
local coalescedBreadcrumbCount = 0
local rejectedBreadcrumbCount = 0
local lastBreadcrumbReason = nil
local breadcrumbEvidence = ""
local breadcrumbEvidenceTruncated = false
local breadcrumbEntries = {}
local breadcrumbCharacters = 0
local breadcrumbLastByStream = {}
local breadcrumbProviderSessionCounts = {}
local breadcrumbProviderWindowStarts = {}
local breadcrumbProviderWindowCounts = {}
local breadcrumbGlobalWindowStart = nil
local breadcrumbGlobalWindowCount = 0
local passiveBreadcrumbs = {}
local passiveBreadcrumbCount = 0
local passiveBreadcrumbCharacters = 0
local passiveBreadcrumbDroppedCount = 0
local passiveBreadcrumbEvictedCount = 0
local passiveBreadcrumbProviderWindowStarts = {}
local passiveBreadcrumbProviderWindowCounts = {}
local passiveBreadcrumbGlobalWindowStart = nil
local passiveBreadcrumbGlobalWindowCount = 0
local originalSessionStart = nil
local originalSessionStop = nil

local function RefreshCoverageDisplay()
    local controller = AddonDiagnostics.SessionController
    if not controller or type(controller.RefreshCoverageSummary) ~= "function" then
        return
    end

    controller:RefreshCoverageSummary()
end

local function RejectRegistration(reason)
    rejectedProviderCount = rejectedProviderCount + 1
    lastRejectedReason = reason
    RefreshCoverageDisplay()
    return false, reason
end

local function RejectBreadcrumb(reason)
    rejectedBreadcrumbCount = rejectedBreadcrumbCount + 1
    lastBreadcrumbReason = reason
    return false, reason
end

local function DropBreadcrumb(reason)
    droppedBreadcrumbCount = droppedBreadcrumbCount + 1
    rateLimitedBreadcrumbCount = rateLimitedBreadcrumbCount + 1
    breadcrumbEvidenceTruncated = true
    lastBreadcrumbReason = reason
    return false, reason
end

local function RecordHardCapacityDrop(reason)
    droppedBreadcrumbCount = droppedBreadcrumbCount + 1
    hardCapacityDroppedBreadcrumbCount = hardCapacityDroppedBreadcrumbCount + 1
    breadcrumbEvidenceTruncated = true
    lastBreadcrumbReason = reason
end

local function DropHardCapacityBreadcrumb(reason)
    RecordHardCapacityDrop(reason)
    return false, reason
end

local function IsSafeShortString(value, maximumCharacters, allowEmpty)
    if type(value) ~= "string" then
        return false
    end

    if not allowEmpty and value == "" then
        return false
    end

    if string.len(value) > maximumCharacters then
        return false
    end

    if string.find(value, "\n", 1, true) then
        return false
    end

    if string.find(value, "\r", 1, true) then
        return false
    end

    return true
end

local function IsSafeBreadcrumbText(value, maximumCharacters, allowEmpty)
    if not IsSafeShortString(value, maximumCharacters, allowEmpty) then
        return false
    end

    if string.find(value, "|", 1, true) then
        return false
    end

    return true
end

local function IsAccessibleValue(value)
    if type(issecretvalue) == "function" and issecretvalue(value) then
        return false
    end

    if type(canaccessvalue) == "function" and not canaccessvalue(value) then
        return false
    end

    return true
end

local function HasProviderID(container, providerID)
    local marker = string.format("|%s|", providerID)
    return string.find(container, marker, 1, true) ~= nil
end

local function AddProviderID(container, providerID)
    return string.format("%s%s|", container, providerID)
end

local function IsOptionalBoolean(value)
    return value == nil or type(value) == "boolean"
end

local function BuildCapabilityText(capabilities)
    local text = ""

    if capabilities.breadcrumbs == true then
        text = "breadcrumbs"
    end

    if capabilities.spans == true then
        if text == "" then
            text = "spans"
        else
            text = string.format("%s, spans", text)
        end
    end

    if capabilities.snapshots == true then
        if text == "" then
            text = "snapshots"
        else
            text = string.format("%s, snapshots", text)
        end
    end

    if text == "" then
        text = "none"
    end

    return text
end

local function AppendProviderSummary(providerID, displayName, addonVersion, capabilityText)
    local line = string.format(
        "%s | %s | %s | Enhanced Diagnostics v1: %s",
        providerID,
        displayName,
        addonVersion,
        capabilityText
    )
    local nextSummary = line

    if providerSummary ~= "" then
        nextSummary = string.format("%s\n%s", providerSummary, line)
    end

    if string.len(nextSummary) > MAX_PROVIDER_SUMMARY_CHARACTERS then
        providerSummaryTruncated = true
        return
    end

    providerSummary = nextSummary
end

local function FormatBreadcrumbValue(value)
    if not IsAccessibleValue(value) then
        return nil, "protected or secret breadcrumb value"
    end

    local valueType = type(value)

    if valueType == "boolean" then
        if value then
            return "true", nil
        end
        return "false", nil
    end

    if valueType == "number" then
        if value ~= value or value == math.huge or value == -math.huge then
            return nil, "invalid breadcrumb number"
        end
        return string.format("%.17g", value), nil
    end

    if valueType == "string" then
        if not IsSafeBreadcrumbText(value, MAX_BREADCRUMB_STRING_CHARACTERS, true) then
            return nil, "invalid breadcrumb string"
        end
        return value, nil
    end

    return nil, "unsupported breadcrumb value type"
end

local function BuildBreadcrumbFields(fields)
    if fields == nil then
        return "", nil
    end

    if not IsAccessibleValue(fields) or type(fields) ~= "table" then
        return nil, "breadcrumb fields must be a table"
    end

    local formattedFields = {}
    local fieldName = nil

    for index = 1, MAX_BREADCRUMB_FIELDS + 1 do
        fieldName = next(fields, fieldName)

        if fieldName == nil then
            table.sort(formattedFields)
            return table.concat(formattedFields, ", "), nil
        end

        if index > MAX_BREADCRUMB_FIELDS then
            return nil, "breadcrumb field limit exceeded"
        end

        if not IsAccessibleValue(fieldName) then
            return nil, "protected or secret breadcrumb field name"
        end

        if not IsSafeBreadcrumbText(fieldName, MAX_BREADCRUMB_FIELD_NAME_CHARACTERS, false) then
            return nil, "invalid breadcrumb field name"
        end

        if string.find(fieldName, "=", 1, true) then
            return nil, "invalid breadcrumb field-name delimiter"
        end

        local valueText, valueReason = FormatBreadcrumbValue(rawget(fields, fieldName))
        if valueText == nil then
            return nil, valueReason
        end

        table.insert(formattedFields, string.format("%s=%s", fieldName, valueText))
    end

    return nil, "breadcrumb field limit exceeded"
end

local function IsRecording()
    if not AddonDiagnostics.SessionController or not AddonDiagnostics.SessionController.IsRecording then
        return false
    end

    return AddonDiagnostics.SessionController:IsRecording() == true
end

local function ResetBreadcrumbSession()
    breadcrumbSessionActive = true
    breadcrumbSessionStartedAt = GetTime()
    breadcrumbCount = 0
    droppedBreadcrumbCount = 0
    hardCapacityDroppedBreadcrumbCount = 0
    rateLimitedBreadcrumbCount = 0
    coalescedBreadcrumbCount = 0
    rejectedBreadcrumbCount = 0
    lastBreadcrumbReason = nil
    breadcrumbEvidence = ""
    breadcrumbEvidenceTruncated = false
    breadcrumbEntries = {}
    breadcrumbCharacters = 0
    breadcrumbLastByStream = {}
    breadcrumbProviderSessionCounts = {}
    breadcrumbProviderWindowStarts = {}
    breadcrumbProviderWindowCounts = {}
    breadcrumbGlobalWindowStart = nil
    breadcrumbGlobalWindowCount = 0
end

local function GetBreadcrumbElapsed()
    if not breadcrumbSessionStartedAt then
        return 0
    end

    return math.max(0, GetTime() - breadcrumbSessionStartedAt)
end

local function CheckBreadcrumbRate(providerID, elapsed)
    if breadcrumbGlobalWindowStart == nil or elapsed - breadcrumbGlobalWindowStart >= 1 then
        breadcrumbGlobalWindowStart = elapsed
        breadcrumbGlobalWindowCount = 0
    end

    local providerWindowStart = rawget(breadcrumbProviderWindowStarts, providerID)
    if providerWindowStart == nil or elapsed - providerWindowStart >= 1 then
        rawset(breadcrumbProviderWindowStarts, providerID, elapsed)
        rawset(breadcrumbProviderWindowCounts, providerID, 0)
    end

    local providerWindowCount = rawget(breadcrumbProviderWindowCounts, providerID) or 0
    if providerWindowCount >= MAX_BREADCRUMBS_PER_PROVIDER_PER_SECOND then
        return false, "provider breadcrumb rate limit reached"
    end

    if breadcrumbGlobalWindowCount >= MAX_BREADCRUMBS_GLOBAL_PER_SECOND then
        return false, "global breadcrumb rate limit reached"
    end

    return true, nil
end

local function CommitBreadcrumbRate(providerID)
    rawset(breadcrumbProviderWindowCounts, providerID, (rawget(breadcrumbProviderWindowCounts, providerID) or 0) + 1)
    breadcrumbGlobalWindowCount = breadcrumbGlobalWindowCount + 1
end

local function BuildBreadcrumbStreamKey(providerID, moduleName, action)
    return string.format("%d:%s|%d:%s|%d:%s", string.len(providerID), providerID, string.len(moduleName), moduleName, string.len(action), action)
end

local function BuildBreadcrumbSignature(streamKey, fieldText)
    return string.format("%s|%d:%s", streamKey, string.len(fieldText), fieldText)
end

local function EstimateBreadcrumbCharacters(providerID, moduleName, action, fieldText)
    return string.len(providerID) + string.len(moduleName) + string.len(action) + string.len(fieldText) + 128
end

local function RemoveBreadcrumbEvidence(index, reason)
    local entry = rawget(breadcrumbEntries, index)
    if entry == nil then return false end
    if rawget(breadcrumbLastByStream, entry.streamKey) == entry then
        rawset(breadcrumbLastByStream, entry.streamKey, nil)
    end
    table.remove(breadcrumbEntries, index)
    breadcrumbCount = math.max(0, breadcrumbCount - 1)
    breadcrumbCharacters = math.max(0, breadcrumbCharacters - (tonumber(entry.characterCount) or 0))
    local providerCount = rawget(breadcrumbProviderSessionCounts, entry.providerID) or 0
    rawset(breadcrumbProviderSessionCounts, entry.providerID, math.max(0, providerCount - 1))
    RecordHardCapacityDrop(reason)
    return true
end

local function FindOldestBreadcrumbIndex(providerID)
    local oldestIndex = nil
    local oldestElapsed = nil
    for index = 1, MAX_BREADCRUMBS_PER_SESSION do
        local entry = rawget(breadcrumbEntries, index)
        if entry == nil then return oldestIndex end
        if providerID == nil or entry.providerID == providerID then
            local elapsed = tonumber(entry.lastElapsed) or 0
            if oldestElapsed == nil or elapsed < oldestElapsed then
                oldestElapsed = elapsed
                oldestIndex = index
            end
        end
    end
    return oldestIndex
end

local function EvictOldestProviderBreadcrumb(providerID)
    local index = FindOldestBreadcrumbIndex(providerID)
    if index == nil then return false end
    return RemoveBreadcrumbEvidence(index, "provider breadcrumb hard capacity reached")
end

local function EvictOldestBreadcrumb()
    local index = FindOldestBreadcrumbIndex(nil)
    if index == nil then return false end
    return RemoveBreadcrumbEvidence(index, "breadcrumb hard capacity reached")
end

local function EnsureBreadcrumbCapacity(providerID, entryCharacters)
    if (rawget(breadcrumbProviderSessionCounts, providerID) or 0) >= MAX_BREADCRUMBS_PER_PROVIDER then
        EvictOldestProviderBreadcrumb(providerID)
    end
    for index = 1, MAX_BREADCRUMBS_PER_SESSION do
        if breadcrumbCount < MAX_BREADCRUMBS_PER_SESSION
            and breadcrumbCharacters + entryCharacters <= MAX_BREADCRUMB_EVIDENCE_CHARACTERS then
            return true
        end
        if not EvictOldestBreadcrumb() then return false end
    end
    return breadcrumbCount < MAX_BREADCRUMBS_PER_SESSION
        and breadcrumbCharacters + entryCharacters <= MAX_BREADCRUMB_EVIDENCE_CHARACTERS
end

local function TryCoalesceBreadcrumb(providerID, moduleName, action, fieldText, elapsed)
    local streamKey = BuildBreadcrumbStreamKey(providerID, moduleName, action)
    local signature = BuildBreadcrumbSignature(streamKey, fieldText)
    local previousEntry = rawget(breadcrumbLastByStream, streamKey)
    if previousEntry ~= nil and previousEntry.signature == signature then
        previousEntry.lastElapsed = elapsed
        previousEntry.occurrenceCount = math.min(999999, (tonumber(previousEntry.occurrenceCount) or 1) + 1)
        coalescedBreadcrumbCount = coalescedBreadcrumbCount + 1
        return true, streamKey, signature
    end
    return false, streamKey, signature
end

local function AppendBreadcrumbEvidence(entry)
    table.insert(breadcrumbEntries, entry)
    breadcrumbCount = breadcrumbCount + 1
    breadcrumbCharacters = breadcrumbCharacters + entry.characterCount
    rawset(breadcrumbProviderSessionCounts, entry.providerID, (rawget(breadcrumbProviderSessionCounts, entry.providerID) or 0) + 1)
    rawset(breadcrumbLastByStream, entry.streamKey, entry)
    return true
end

local function RenderBreadcrumbEntry(entry)
    local line = string.format("%.3fs | %s | %s | %s", entry.lastElapsed, entry.providerID, entry.moduleName, entry.action)
    if entry.fieldText ~= "" then line = string.format("%s | %s", line, entry.fieldText) end
    if (tonumber(entry.occurrenceCount) or 1) > 1 then
        line = string.format("%s | first=%.3fs, occurrences=%d", line, entry.firstElapsed, entry.occurrenceCount)
    end
    return line
end

local function CompareBreadcrumbEntries(left, right)
    local leftElapsed = tonumber(left.lastElapsed) or 0
    local rightElapsed = tonumber(right.lastElapsed) or 0
    if leftElapsed == rightElapsed then
        return (tonumber(left.firstElapsed) or 0) < (tonumber(right.firstElapsed) or 0)
    end
    return leftElapsed < rightElapsed
end

local function RenderBreadcrumbEvidence()
    local orderedEntries = {}
    for index = 1, MAX_BREADCRUMBS_PER_SESSION do
        local entry = rawget(breadcrumbEntries, index)
        if entry ~= nil then table.insert(orderedEntries, entry) end
    end
    table.sort(orderedEntries, CompareBreadcrumbEntries)

    local output = ""
    for index = 1, MAX_BREADCRUMBS_PER_SESSION do
        local entry = rawget(orderedEntries, index)
        if entry == nil then return output end
        local line = RenderBreadcrumbEntry(entry)
        local nextOutput = output == "" and line or string.format("%s\n%s", output, line)
        if string.len(nextOutput) > MAX_BREADCRUMB_EVIDENCE_CHARACTERS then
            breadcrumbEvidenceTruncated = true
            return output
        end
        output = nextOutput
    end
    return output
end

local function RemovePassiveBreadcrumb(index)
    local entry = rawget(passiveBreadcrumbs, index)
    if entry ~= nil then
        passiveBreadcrumbCharacters = math.max(0, passiveBreadcrumbCharacters - string.len(tostring(entry.line or "")))
        table.remove(passiveBreadcrumbs, index)
        passiveBreadcrumbCount = math.max(0, passiveBreadcrumbCount - 1)
        passiveBreadcrumbEvictedCount = passiveBreadcrumbEvictedCount + 1
    end
end

local function EvictExpiredPassiveBreadcrumbs(now)
    for index = 1, MAX_PASSIVE_BREADCRUMBS do
        local entry = rawget(passiveBreadcrumbs, 1)
        if entry ~= nil and now - (tonumber(entry.capturedAt) or now) > MAX_PASSIVE_BREADCRUMB_AGE_SECONDS then
            RemovePassiveBreadcrumb(1)
        end
    end
end

local function CountPassiveProviderBreadcrumbs(providerID)
    local count = 0
    for index = 1, MAX_PASSIVE_BREADCRUMBS do
        local entry = rawget(passiveBreadcrumbs, index)
        if entry == nil then return count end
        if entry.providerID == providerID then count = count + 1 end
    end
    return count
end

local function EvictOldestPassiveProviderBreadcrumb(providerID)
    for index = 1, MAX_PASSIVE_BREADCRUMBS do
        local entry = rawget(passiveBreadcrumbs, index)
        if entry == nil then return false end
        if entry.providerID == providerID then
            RemovePassiveBreadcrumb(index)
            return true
        end
    end
    return false
end

local function CheckPassiveBreadcrumbRate(providerID, now)
    if passiveBreadcrumbGlobalWindowStart == nil or now - passiveBreadcrumbGlobalWindowStart >= 1 then
        passiveBreadcrumbGlobalWindowStart = now
        passiveBreadcrumbGlobalWindowCount = 0
    end
    local providerStart = rawget(passiveBreadcrumbProviderWindowStarts, providerID)
    if providerStart == nil or now - providerStart >= 1 then
        rawset(passiveBreadcrumbProviderWindowStarts, providerID, now)
        rawset(passiveBreadcrumbProviderWindowCounts, providerID, 0)
    end
    if (rawget(passiveBreadcrumbProviderWindowCounts, providerID) or 0) >= MAX_PASSIVE_BREADCRUMBS_PER_PROVIDER_PER_SECOND then
        return false, "passive provider breadcrumb rate limit reached"
    end
    if passiveBreadcrumbGlobalWindowCount >= MAX_PASSIVE_BREADCRUMBS_GLOBAL_PER_SECOND then
        return false, "passive global breadcrumb rate limit reached"
    end
    return true, nil
end

local function CommitPassiveBreadcrumbRate(providerID)
    rawset(passiveBreadcrumbProviderWindowCounts, providerID, (rawget(passiveBreadcrumbProviderWindowCounts, providerID) or 0) + 1)
    passiveBreadcrumbGlobalWindowCount = passiveBreadcrumbGlobalWindowCount + 1
end

local function RetainPassiveBreadcrumb(providerID, moduleName, action, fieldText)
    local now = GetTime()
    EvictExpiredPassiveBreadcrumbs(now)
    local withinRate, rateReason = CheckPassiveBreadcrumbRate(providerID, now)
    if not withinRate then
        passiveBreadcrumbDroppedCount = passiveBreadcrumbDroppedCount + 1
        return false, rateReason
    end
    local line = string.format("%s | %s | %s", providerID, moduleName, action)
    if fieldText ~= "" then line = string.format("%s | %s", line, fieldText) end
    if string.len(line) > MAX_PASSIVE_BREADCRUMB_ENTRY_CHARACTERS then
        passiveBreadcrumbDroppedCount = passiveBreadcrumbDroppedCount + 1
        return false, "passive breadcrumb entry limit reached"
    end
    if CountPassiveProviderBreadcrumbs(providerID) >= MAX_PASSIVE_BREADCRUMBS_PER_PROVIDER then
        EvictOldestPassiveProviderBreadcrumb(providerID)
    end
    for index = 1, MAX_PASSIVE_BREADCRUMBS do
        if passiveBreadcrumbCount >= MAX_PASSIVE_BREADCRUMBS or passiveBreadcrumbCharacters + string.len(line) > MAX_PASSIVE_BREADCRUMB_EVIDENCE_CHARACTERS then
            RemovePassiveBreadcrumb(1)
        end
    end
    local entry = {}
    entry.providerID = providerID
    entry.capturedAt = now
    entry.line = line
    table.insert(passiveBreadcrumbs, entry)
    passiveBreadcrumbCount = passiveBreadcrumbCount + 1
    passiveBreadcrumbCharacters = passiveBreadcrumbCharacters + string.len(line)
    CommitPassiveBreadcrumbRate(providerID)
    return true, "retained passive"
end

function EnhancedDiagnosticsBroker:RegisterProvider(provider)
    if type(provider) ~= "table" then
        return RejectRegistration("provider metadata must be a table")
    end

    local providerID = provider.providerID
    if not IsSafeShortString(providerID, MAX_PROVIDER_ID_CHARACTERS, false) then
        return RejectRegistration("invalid providerID")
    end

    if string.find(providerID, "|", 1, true) then
        return RejectRegistration("invalid providerID delimiter")
    end

    local displayName = provider.displayName
    if not IsSafeShortString(displayName, MAX_DISPLAY_NAME_CHARACTERS, false) then
        return RejectRegistration("invalid displayName")
    end

    local addonVersion = provider.addonVersion
    if addonVersion == nil then
        addonVersion = "version not declared"
    elseif not IsSafeShortString(addonVersion, MAX_ADDON_VERSION_CHARACTERS, false) then
        return RejectRegistration("invalid addonVersion")
    end

    if type(provider.protocolVersion) ~= "number" or provider.protocolVersion ~= SUPPORTED_PROTOCOL_VERSION then
        return RejectRegistration("unsupported protocol version")
    end

    local capabilities = provider.capabilities
    if type(capabilities) ~= "table" then
        return RejectRegistration("capabilities must be a table")
    end

    if not IsOptionalBoolean(capabilities.breadcrumbs) then
        return RejectRegistration("invalid breadcrumbs capability")
    end

    if not IsOptionalBoolean(capabilities.spans) then
        return RejectRegistration("invalid spans capability")
    end

    if not IsOptionalBoolean(capabilities.snapshots) then
        return RejectRegistration("invalid snapshots capability")
    end

    if HasProviderID(registeredProviderIDs, providerID) then
        return true, "already registered"
    end

    if registeredProviderCount >= MAX_REGISTERED_PROVIDERS then
        return RejectRegistration("provider registration limit reached")
    end

    local capabilityText = BuildCapabilityText(capabilities)
    registeredProviderIDs = AddProviderID(registeredProviderIDs, providerID)

    if capabilities.breadcrumbs == true then
        breadcrumbProviderIDs = AddProviderID(breadcrumbProviderIDs, providerID)
    end

    if capabilities.spans == true then
        spanProviderIDs = AddProviderID(spanProviderIDs, providerID)
    end

    if capabilities.snapshots == true then
        snapshotProviderIDs = AddProviderID(snapshotProviderIDs, providerID)
    end

    registeredProviderCount = registeredProviderCount + 1
    table.insert(registeredProviderIDList, providerID)
    AppendProviderSummary(providerID, displayName, addonVersion, capabilityText)
    RefreshCoverageDisplay()
    return true, "registered"
end

function EnhancedDiagnosticsBroker:GetProviderCount()
    return registeredProviderCount
end

function EnhancedDiagnosticsBroker:GetRejectedProviderCount()
    return rejectedProviderCount
end

function EnhancedDiagnosticsBroker:GetLastRejectedReason()
    return lastRejectedReason
end

function EnhancedDiagnosticsBroker:IsProviderSummaryTruncated()
    return providerSummaryTruncated
end

function EnhancedDiagnosticsBroker:DidPendingRegistrationOverflow()
    return pendingRegistrationOverflow
end

function EnhancedDiagnosticsBroker:GetProviderSummary()
    if providerSummary == "" then
        return "No Enhanced Diagnostics providers registered."
    end

    return providerSummary
end

function EnhancedDiagnosticsBroker:ResolveRegisteredProviderID(providerHint)
    if not IsSafeShortString(providerHint, MAX_PROVIDER_ID_CHARACTERS, false) then
        return nil
    end
    if HasProviderID(registeredProviderIDs, providerHint) then
        return providerHint
    end
    local lowered = string.lower(providerHint)
    for index = 1, MAX_REGISTERED_PROVIDERS do
        local registeredID = rawget(registeredProviderIDList, index)
        if registeredID == nil then return nil end
        if string.lower(registeredID) == lowered then return registeredID end
    end
    return nil
end

function EnhancedDiagnosticsBroker:SupportsCapability(providerID, capability)
    if type(providerID) ~= "string" then
        return false
    end

    if capability == "breadcrumbs" then
        return HasProviderID(breadcrumbProviderIDs, providerID)
    end

    if capability == "spans" then
        return HasProviderID(spanProviderIDs, providerID)
    end

    if capability == "snapshots" then
        return HasProviderID(snapshotProviderIDs, providerID)
    end

    return false
end

function EnhancedDiagnosticsBroker:StartSession()
    ResetBreadcrumbSession()
end

function EnhancedDiagnosticsBroker:StopSession()
    breadcrumbSessionActive = false
    breadcrumbSessionStartedAt = nil
end

function EnhancedDiagnosticsBroker:Breadcrumb(providerID, moduleName, action, fields)
    if type(providerID) ~= "string" or not HasProviderID(registeredProviderIDs, providerID) then
        return RejectBreadcrumb("provider is not registered")
    end
    if not HasProviderID(breadcrumbProviderIDs, providerID) then
        return RejectBreadcrumb("provider does not advertise breadcrumbs")
    end
    if not IsSafeBreadcrumbText(moduleName, MAX_BREADCRUMB_MODULE_CHARACTERS, false) then
        return RejectBreadcrumb("invalid breadcrumb module")
    end
    if not IsSafeBreadcrumbText(action, MAX_BREADCRUMB_ACTION_CHARACTERS, false) then
        return RejectBreadcrumb("invalid breadcrumb action")
    end
    local fieldText, fieldReason = BuildBreadcrumbFields(fields)
    if fieldText == nil then return RejectBreadcrumb(fieldReason) end

    if not IsRecording() then
        return RetainPassiveBreadcrumb(providerID, moduleName, action, fieldText)
    end
    if not breadcrumbSessionActive then ResetBreadcrumbSession() end
    local elapsed = GetBreadcrumbElapsed()
    local coalesced, streamKey, signature = TryCoalesceBreadcrumb(providerID, moduleName, action, fieldText, elapsed)
    if coalesced then return true, "coalesced" end

    local withinRate, rateReason = CheckBreadcrumbRate(providerID, elapsed)
    if not withinRate then return DropBreadcrumb(rateReason) end
    CommitBreadcrumbRate(providerID)

    local entryCharacters = EstimateBreadcrumbCharacters(providerID, moduleName, action, fieldText)
    if not EnsureBreadcrumbCapacity(providerID, entryCharacters) then
        return DropHardCapacityBreadcrumb("breadcrumb hard capacity unavailable")
    end

    local entry = {}
    entry.providerID = providerID
    entry.moduleName = moduleName
    entry.action = action
    entry.fieldText = fieldText
    entry.firstElapsed = elapsed
    entry.lastElapsed = elapsed
    entry.occurrenceCount = 1
    entry.streamKey = streamKey
    entry.signature = signature
    entry.characterCount = entryCharacters
    AppendBreadcrumbEvidence(entry)
    return true, "recorded unique"
end

function EnhancedDiagnosticsBroker:GetPassiveBreadcrumbEvidence(providerID)
    local resolved = self:ResolveRegisteredProviderID(providerID)
    if resolved == nil then return "", 0, passiveBreadcrumbEvictedCount, passiveBreadcrumbDroppedCount end
    local now = GetTime()
    EvictExpiredPassiveBreadcrumbs(now)
    local output = ""
    local count = 0
    for index = 1, MAX_PASSIVE_BREADCRUMBS do
        local entry = rawget(passiveBreadcrumbs, index)
        if entry == nil then return output, count, passiveBreadcrumbEvictedCount, passiveBreadcrumbDroppedCount end
        if entry.providerID == resolved then
            local age = math.max(0, now - (tonumber(entry.capturedAt) or now))
            local line = string.format("-%.3fs | %s", age, tostring(entry.line or ""))
            local nextOutput = output == "" and line or string.format("%s\n%s", output, line)
            if string.len(nextOutput) <= MAX_PASSIVE_BREADCRUMB_EVIDENCE_CHARACTERS then
                output = nextOutput
                count = count + 1
            end
        end
    end
    return output, count, passiveBreadcrumbEvictedCount, passiveBreadcrumbDroppedCount
end

function EnhancedDiagnosticsBroker:GetPassiveBreadcrumbStats()
    return passiveBreadcrumbCount, passiveBreadcrumbEvictedCount, passiveBreadcrumbDroppedCount, passiveBreadcrumbCharacters
end

function EnhancedDiagnosticsBroker:GetBreadcrumbCount()
    return breadcrumbCount
end

function EnhancedDiagnosticsBroker:GetBreadcrumbEvidence()
    breadcrumbEvidence = RenderBreadcrumbEvidence()
    return breadcrumbEvidence
end

function EnhancedDiagnosticsBroker:GetBreadcrumbStats()
    return breadcrumbCount,
        droppedBreadcrumbCount,
        rejectedBreadcrumbCount,
        breadcrumbEvidenceTruncated,
        lastBreadcrumbReason,
        coalescedBreadcrumbCount,
        hardCapacityDroppedBreadcrumbCount,
        rateLimitedBreadcrumbCount
end

function EnhancedDiagnosticsBroker:RefreshPendingRegistrations()
    if type(EnhancedDiagnostics) ~= "table" then
        return 0
    end

    if type(EnhancedDiagnostics.pendingProviders) ~= "table" then
        EnhancedDiagnostics.pendingProviders = {}
        return 0
    end

    local processed = 0
    for index = 1, MAX_PENDING_REGISTRATIONS do
        local provider = table.remove(EnhancedDiagnostics.pendingProviders, 1)
        if provider == nil then
            return processed
        end

        EnhancedDiagnosticsBroker:RegisterProvider(provider)
        processed = processed + 1
    end

    local overflowProvider = table.remove(EnhancedDiagnostics.pendingProviders, 1)
    if overflowProvider ~= nil then
        pendingRegistrationOverflow = true
        rejectedProviderCount = rejectedProviderCount + 1
        lastRejectedReason = "pending registration limit exceeded"
        EnhancedDiagnostics.pendingProviders = {}
        RefreshCoverageDisplay()
    end

    return processed
end

local function WrappedSessionStart(self)
    local started = originalSessionStart(self)
    if started then
        EnhancedDiagnosticsBroker:StartSession()
    end
    return started
end

local function WrappedSessionStop(self)
    local stopped, elapsed = originalSessionStop(self)
    if stopped then
        EnhancedDiagnosticsBroker:StopSession()
    end
    return stopped, elapsed
end

local function AttachSessionLifecycle()
    local controller = AddonDiagnostics.SessionController
    if not controller then
        return
    end

    if type(controller.Start) ~= "function" or type(controller.Stop) ~= "function" then
        return
    end

    if originalSessionStart ~= nil or originalSessionStop ~= nil then
        return
    end

    originalSessionStart = controller.Start
    originalSessionStop = controller.Stop
    controller.Start = WrappedSessionStart
    controller.Stop = WrappedSessionStop
end

function AddonDiagnostics_EnhancedDiagnosticsRegisterProvider(provider)
    return EnhancedDiagnosticsBroker:RegisterProvider(provider)
end

function AddonDiagnostics_EnhancedDiagnosticsRefreshPendingRegistrations()
    return EnhancedDiagnosticsBroker:RefreshPendingRegistrations()
end

function AddonDiagnostics_EnhancedDiagnosticsGetProviderCount()
    return EnhancedDiagnosticsBroker:GetProviderCount()
end

function AddonDiagnostics_EnhancedDiagnosticsGetProviderSummary()
    return EnhancedDiagnosticsBroker:GetProviderSummary()
end

function AddonDiagnostics_EnhancedDiagnosticsGetRejectedProviderCount()
    return EnhancedDiagnosticsBroker:GetRejectedProviderCount()
end

function AddonDiagnostics_EnhancedDiagnosticsBreadcrumb(providerID, moduleName, action, fields)
    return EnhancedDiagnosticsBroker:Breadcrumb(providerID, moduleName, action, fields)
end

if type(EnhancedDiagnostics) ~= "table" then
    EnhancedDiagnostics = {}
end

if type(EnhancedDiagnostics.pendingProviders) ~= "table" then
    EnhancedDiagnostics.pendingProviders = {}
end

EnhancedDiagnostics.protocolIdentifier = PROTOCOL_IDENTIFIER
EnhancedDiagnostics.protocolVersion = SUPPORTED_PROTOCOL_VERSION
EnhancedDiagnostics.RegisterProvider = AddonDiagnostics_EnhancedDiagnosticsRegisterProvider
EnhancedDiagnostics.RefreshPendingRegistrations = AddonDiagnostics_EnhancedDiagnosticsRefreshPendingRegistrations
EnhancedDiagnostics.GetProviderCount = AddonDiagnostics_EnhancedDiagnosticsGetProviderCount
EnhancedDiagnostics.GetProviderSummary = AddonDiagnostics_EnhancedDiagnosticsGetProviderSummary
EnhancedDiagnostics.GetRejectedProviderCount = AddonDiagnostics_EnhancedDiagnosticsGetRejectedProviderCount
EnhancedDiagnostics.Breadcrumb = AddonDiagnostics_EnhancedDiagnosticsBreadcrumb

EnhancedDiagnosticsBroker:RefreshPendingRegistrations()
RefreshCoverageDisplay()
AttachSessionLifecycle()

local function OnEnhancedDiagnosticsEvent(self, event)
    if event == "ADDON_LOADED" then
        EnhancedDiagnosticsBroker:RefreshPendingRegistrations()
        RefreshCoverageDisplay()
    end
end

brokerEventFrame = CreateFrame("Frame")
brokerEventFrame:RegisterEvent("ADDON_LOADED")
brokerEventFrame:SetScript("OnEvent", OnEnhancedDiagnosticsEvent)
