EbonholdHub.AffixLoadout = {}

local function CloneEntry(entry)
    if not entry then return nil end
    return {
        id      = entry.id,
        name    = entry.name,
        rank    = entry.rank,
        affixId = entry.affixId,
    }
end

function EbonholdHub.AffixLoadout.Clone(loadout)
    local copy = {}
    if type(loadout) ~= "table" then return copy end
    for key, entry in pairs(loadout) do
        copy[key] = CloneEntry(entry)
    end
    return copy
end

function EbonholdHub.AffixLoadout.Ensure(build)
    build.affixLoadout = build.affixLoadout or {}
    return build.affixLoadout
end

function EbonholdHub.AffixLoadout.GetActive()
    if EbonholdHubDB._isEditingBuild then
        EbonholdHubDB.pendingAffixLoadout = EbonholdHubDB.pendingAffixLoadout or {}
        return EbonholdHubDB.pendingAffixLoadout
    end
    local build = EbonholdHub.Build.GetActive()
    if build then
        return EbonholdHub.AffixLoadout.Ensure(build)
    end
    EbonholdHubDB.pendingAffixLoadout = EbonholdHubDB.pendingAffixLoadout or {}
    return EbonholdHubDB.pendingAffixLoadout
end

function EbonholdHub.AffixLoadout.GetSlot(slotKey)
    local loadout = EbonholdHub.AffixLoadout.GetActive()
    return loadout[slotKey]
end

function EbonholdHub.AffixLoadout.SetSlot(slotKey, entry)
    local loadout = EbonholdHub.AffixLoadout.GetActive()
    if entry then
        loadout[slotKey] = CloneEntry(entry)
    else
        loadout[slotKey] = nil
    end
end

function EbonholdHub.AffixLoadout.CopyFromUnitTo(unit, loadout)
    loadout = loadout or EbonholdHub.AffixLoadout.GetActive()
    unit = unit or "player"
    local AD = EbonholdHub.AffixData
    AD.GetCatalog(true)
    local copied = 0
    for _, slotDef in ipairs(AD.SLOTS) do
        local entry = AD.ReadAffixFromInventorySlot(unit, slotDef.invSlot)
        if entry then
            loadout[slotDef.key] = CloneEntry(entry)
            copied = copied + 1
        end
    end
    return copied
end

function EbonholdHub.AffixLoadout.CopyFromPlayerTo(loadout)
    return EbonholdHub.AffixLoadout.CopyFromUnitTo("player", loadout)
end

function EbonholdHub.AffixLoadout.CopyFromPlayer()
    return EbonholdHub.AffixLoadout.CopyFromPlayerTo(EbonholdHub.AffixLoadout.GetActive())
end

function EbonholdHub.AffixLoadout.CountFilled(loadout)
    loadout = loadout or EbonholdHub.AffixLoadout.GetActive()
    local n = 0
    for _, entry in pairs(loadout) do
        if entry and entry.name then n = n + 1 end
    end
    return n
end

function EbonholdHub.AffixLoadout.ListFilled(loadout)
    loadout = loadout or EbonholdHub.AffixLoadout.GetActive()
    local rows = {}
    for _, slot in ipairs(EbonholdHub.AffixData.SLOTS) do
        local entry = loadout[slot.key]
        if entry and entry.name then
            rows[#rows + 1] = {
                slotKey = slot.key,
                slotLabel = slot.label,
                id = entry.id,
                name = entry.name,
                rank = entry.rank,
            }
        end
    end
    return rows
end

function EbonholdHub.AffixLoadout.ChecksumPart(loadout)
    if type(loadout) ~= "table" then return "" end
    local keys = {}
    for key in pairs(loadout) do keys[#keys + 1] = key end
    table.sort(keys)
    local parts = {}
    for _, key in ipairs(keys) do
        local e = loadout[key]
        if e and e.name then
            parts[#parts + 1] = key .. "=" .. (e.id or e.name) .. "@" .. tostring(e.rank or "W")
        end
    end
    return table.concat(parts, ";")
end
