local addonName, TOAST = ...

-- Session-only protocol trace for beta testing. It deliberately records
-- envelope metadata only: never payload records, keys, scores, or messages.

local MAX_ENTRIES = 50
local entries = {}

local TYPE_LABELS = {
    H = "HELLO",
    S = "SELF STATE",
    Q = "STATE REQUEST",
    Y = "CACHE SYNC",
    B = "BRIDGE REQUEST",
    F = "FETCH REQUEST",
    U = "UPDATE POLICY",
    X = "CLAIM RELEASE",
}

local function FieldsFromMessage(message)
    if type(message) ~= "string" then return nil end
    local fields = {}
    for field in (message .. "|"):gmatch("(.-)|") do
        fields[#fields + 1] = field
        if #fields > 12 then return nil end
    end
    return fields[1] == "CS1" and fields or nil
end

local function TypeLabel(messageOrFields)
    -- A caller that is not logging a protocol message may name the row itself,
    -- e.g. { label = "TARGET OFFLINE" } for a transport event.
    if type(messageOrFields) == "table" and type(messageOrFields.label) == "string" then
        return messageOrFields.label
    end
    local fields = type(messageOrFields) == "table" and messageOrFields or FieldsFromMessage(messageOrFields)
    if not fields then return "UNKNOWN" end
    local kind = fields[2]
    if kind == "M" then return (fields[3] or "TRANSFER") .. " BEGIN" end
    if kind == "D" then return string.format("%s CHUNK %s", fields[3] or "TRANSFER", fields[5] or "?") end
    if kind == "E" then return (fields[3] or "TRANSFER") .. " END" end
    if kind == "A" then return "ACK " .. (fields[4] or "?") end
    if kind == "C" then return (fields[4] or "CACHE") .. " CLAIM" end
    return TYPE_LABELS[kind] or (kind or "UNKNOWN")
end

function TOAST.LogCommsTrace(direction, channel, messageOrFields, peer, result)
    entries[#entries + 1] = {
        time = date("%H:%M:%S"),
        direction = direction == "IN" and "IN" or direction == "LOCAL" and "LOCAL" or "OUT",
        channel = tostring(channel or "?"),
        type = TypeLabel(messageOrFields),
        peer = tostring(peer or "-"),
        result = tostring(result or "-"),
    }
    if #entries > MAX_ENTRIES then table.remove(entries, 1) end
    if TOAST.RefreshCommsTrace then TOAST.RefreshCommsTrace() end
end

function TOAST.GetCommsTrace()
    return entries
end

function TOAST.ClearCommsTrace()
    for index = #entries, 1, -1 do entries[index] = nil end
end
