---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)

-- Parses a pasted raid-roster-style boss export (Private.rosterExport) into an ordered
-- array of encounter records: { id, name, difficulty, invitelist }.
-- Pure function of its argument -- no globals besides Private, no Ace/UI/comm
-- dependency -- so Phase 3/4 can reuse it without pulling in UI code.
function Private:ParseRosterExport(text)
    local encounters, seenIds, warnings = {}, {}, {}
    local current = nil

    local function finalizeCurrent()
        if not current then return end
        -- An empty invitelist (invitelist: line present but no names) is treated the
        -- same as a missing one: no button, warn instead. #{} == 0 is falsy-guarded
        -- here because {} is truthy in Lua and would otherwise render a dead button
        -- whose click passes nil to string.format("%s", ...) and hard-crashes.
        if current.invitelist and #current.invitelist > 0 then
            -- Claim the id only once a usable block is finalized, so a later valid
            -- duplicate is not silently dropped by an earlier empty block's header.
            seenIds[current.id] = true
            table.insert(encounters, current)
        else
            table.insert(warnings, ("Skipped encounter %d (%s): no invitelist"):format(current.id, current.name))
        end
    end

    if type(text) ~= "string" or text == "" then return {}, {} end

    -- [^\r\n]+ tolerates both CRLF and LF line endings without a separate
    -- normalization pass (existing idiom, originating in the pre-v2.0 Roster.lua
    -- MakeRoster note parsing, removed in the v2.0 rewrite).
    for line in text:gmatch("[^\r\n]+") do
        local id, difficulty, name = line:match("^EncounterID:(%d+);Difficulty:([^;]*);Name:(.-);?$")
        if id then
            finalizeCurrent()
            id = tonumber(id)
            if seenIds[id] then
                table.insert(warnings, ("Skipped duplicate EncounterID %d"):format(id))
                current = nil
            else
                current = { id = id, name = name, difficulty = difficulty, invitelist = nil }
            end
        elseif current and not current.invitelist then
            local rest = line:match("^invitelist:(.*)$")
            if rest then
                local list = {}
                -- Exclude only whitespace/comma/semicolon/colon (never a positive
                -- alphanumeric class) so multibyte UTF-8 names (MöWe, Pêpsy) survive
                -- intact -- %w/%a are ASCII-only under the WoW Lua C locale and would
                -- truncate at the first multibyte byte.
                for token in rest:gmatch("([^%s,;:]+)") do
                    table.insert(list, token)
                end
                current.invitelist = list
            end
        end
    end
    finalizeCurrent()

    for _, w in ipairs(warnings) do
        print("|cffff5555Wild Things:|r " .. w)
    end

    return encounters
end

-- Name/realm canonicalization (AsciiLower/StripRealm/Private:CanonicalKey) now
-- lives in the shipped RosterKeys.lua (KEYS-01), which loads before this dev-only
-- file. Every Private:CanonicalKey(...) call site in this file resolves to that
-- single shared definition -- no local copy here.
