local Catalog = {}

-- Walk the catalog's collection tree and collect entries. Returns a list of
-- { id = number, name = string, isSet = boolean, isSmart = boolean }.
local function walk(parent, prefix, includeSets, includeCollections, out)
    local sets = parent:getChildCollectionSets()
    for _, set in ipairs(sets) do
        local label = (prefix == '' and '' or (prefix .. ' / ')) .. set:getName()
        if includeSets then
            out[#out + 1] = {
                id = set.localIdentifier,
                name = label,
                isSet = true,
                isSmart = false,
                ref = set,
            }
        end
        walk(set, label, includeSets, includeCollections, out)
    end

    local collections = parent:getChildCollections()
    for _, col in ipairs(collections) do
        local label = (prefix == '' and '' or (prefix .. ' / ')) .. col:getName()
        if includeCollections then
            local isSmart = false
            -- LrCollection has isSmartCollection() in modern SDKs
            if col.type and col:type() == 'LrPublishedCollection' then
                -- Skip published collections; not in scope
            else
                if col.isSmartCollection then
                    local ok, val = pcall(function() return col:isSmartCollection() end)
                    if ok then isSmart = val end
                end
                out[#out + 1] = {
                    id = col.localIdentifier,
                    name = label,
                    isSet = false,
                    isSmart = isSmart,
                    ref = col,
                }
            end
        end
    end
end

function Catalog.allCollections(catalog)
    local out = {}
    walk(catalog, '', false, true, out)
    return out
end

function Catalog.allCollectionSets(catalog)
    local out = {}
    walk(catalog, '', true, false, out)
    return out
end

-- popup_menu items: { title = ..., value = ... }
function Catalog.collectionMenuItems(catalog, includeNone)
    local items = {}
    if includeNone then
        items[#items + 1] = { title = '(none)', value = 0 }
    end
    for _, entry in ipairs(Catalog.allCollections(catalog)) do
        local title = entry.name
        if entry.isSmart then title = title .. '  [smart]' end
        items[#items + 1] = { title = title, value = entry.id }
    end
    return items
end

function Catalog.collectionSetMenuItems(catalog, includeNone)
    local items = {}
    if includeNone then
        items[#items + 1] = { title = '(none)', value = 0 }
    end
    for _, entry in ipairs(Catalog.allCollectionSets(catalog)) do
        items[#items + 1] = { title = entry.name, value = entry.id }
    end
    return items
end

local function findInTree(parent, id, kind)
    if kind == 'set' then
        for _, set in ipairs(parent:getChildCollectionSets()) do
            if set.localIdentifier == id then return set end
            local found = findInTree(set, id, kind)
            if found then return found end
        end
    else
        for _, col in ipairs(parent:getChildCollections()) do
            if col.localIdentifier == id then return col end
        end
        for _, set in ipairs(parent:getChildCollectionSets()) do
            local found = findInTree(set, id, kind)
            if found then return found end
        end
    end
    return nil
end

function Catalog.findCollection(catalog, id)
    if not id or id == 0 then return nil end
    return findInTree(catalog, id, 'collection')
end

function Catalog.findCollectionSet(catalog, id)
    if not id or id == 0 then return nil end
    return findInTree(catalog, id, 'set')
end

return Catalog
