local WhatLockoutNS = _G.WhatLockout
if not WhatLockoutNS then return end

WhatLockoutNS.CommsHelpers = WhatLockoutNS.CommsHelpers or {}
local CommsHelpers = WhatLockoutNS.CommsHelpers

-- Locale-stable dungeon row state (internal codes). Falls back to English progress strings from older payloads.
function CommsHelpers.GetDungeonStatusCode(entry)
    if type(entry) ~= "table" then return "UNKNOWN" end
    local status = tostring(entry.status or ""):upper()
    if status == "AVAILABLE" or status == "EXPIRED" or status == "LOCKED_IN_PROGRESS" or status == "LOCKED_DONE" then
        return status
    end
    local p = tostring(entry.progress or ""):lower()
    if p == "available" then return "AVAILABLE" end
    if p == "expired" then return "EXPIRED" end
    if p == "in progress" then return "LOCKED_IN_PROGRESS" end
    if p == "done" then return "LOCKED_DONE" end
    return "UNKNOWN"
end

-- Raids: merge encounter kills, progress "X/Y", and synced bossSummary.
function CommsHelpers.GetRaidBossDisplayCounts(e)
    local ed, et = 0, 0
    if type(e) == "table" and type(e.encounters) == "table" then
        for _, enc in ipairs(e.encounters) do
            if enc and enc.name then
                et = et + 1
                if enc.killed then
                    ed = ed + 1
                end
            end
        end
    end
    local pd, pt = 0, 0
    if type(e) == "table" and type(e.progress) == "string" then
        local p1, p2 = e.progress:match("^(%d+)%s*/%s*(%d+)$")
        if p1 and p2 then
            pt = tonumber(p2) or 0
            pd = tonumber(p1) or 0
        end
    end
    local sd = tonumber(e and e.bossDefeatedCount) or 0
    local st = tonumber(e and e.bossTotalCount) or 0

    if et > 0 then
        local t = (pt > 0) and math.max(pt, et) or et
        local d = math.max(pd, ed, sd)
        return d, t
    end
    if pt > 0 then
        return math.max(pd, sd), pt
    end
    return sd, st
end

function CommsHelpers.RaidDifficultyLetter(diff)
    local function fromDifficultyID(v)
        local id = tonumber(v or 0) or 0
        if id <= 0 then return nil end
        -- Retail + legacy raid IDs (locale-independent).
        if id == 16 then return "M" end -- Mythic
        if id == 15 or id == 5 or id == 6 then return "H" end -- Heroic
        if id == 17 or id == 7 then return "L" end -- LFR / Raid Finder
        if id == 14 or id == 3 or id == 4 or id == 9 then return "N" end -- Normal
        return nil
    end

    local byID = fromDifficultyID(diff)
    if byID then return byID end

    local s = tostring(diff or ""):lower()
    if s == "" then return nil end

    local function hasAny(haystack, needles)
        for i = 1, #needles do
            if haystack:find(needles[i], 1, true) then
                return true
            end
        end
        return false
    end

    -- Fallback for localized names when only difficulty text is available.
    if hasAny(s, {
        "mythic", "mythisch", "mítico", "mitico", "mythique",
        "epico", "épico", "эпох", "신화", "史诗", "史詩",
    }) then
        return "M"
    end
    if hasAny(s, {
        "hero", "heroisch", "héro", "heroico", "héroïque",
        "геро", "영웅", "英雄",
    }) then
        return "H"
    end
    if hasAny(s, {
        "lfr", "raid finder", "finder", "sucher", "browser", "buscador",
        "recherche de raid", "поиск рейда", "공격대 찾기", "随机",
    }) then
        return "L"
    end
    if hasAny(s, {
        "normal", "normaal", "normale", "normalny", "обыч",
        "일반", "普通",
    }) then
        return "N"
    end
    return nil
end

function CommsHelpers.ExtractMplusSummaryFromRows(rows)
    if type(rows) ~= "table" then return nil end

    local highestRow = nil
    for _, r in ipairs(rows) do
        if type(r) == "table" and r.isHighest then
            highestRow = r
            break
        end
    end
    if not highestRow then return nil end

    local highestKey = nil
    if type(highestRow.progress) == "string" then
        highestKey = tonumber(highestRow.progress:match("^%+?(%d+)$")) or nil
    end

    local mapsAtMax = highestRow.mapsAtMax
    if type(mapsAtMax) ~= "table" then
        mapsAtMax = {}
    end

    if highestKey and highestKey > 0 then
        return { highestKey = highestKey, mapsAtMax = mapsAtMax }
    end

    return { highestKey = nil, mapsAtMax = mapsAtMax }
end
