-- VDS.Layout:DescribeView -- debug pretty-printer for the layout engine.
--
-- Walks raw config + live placements; emits a multi-line dump for the Debug
-- tab. Lives separate from VDS_Layout.lua so the engine stays focused on
-- Compute / Apply / BuildAll / Validate.
--
-- Card-grid math:
--   cardgrid_inner = N * cellSize + (N - 1) * cellSpacing
--   scrollbox_width = host - VDS.UI.SCROLLBOX_SCROLLBAR_RESERVE

VDS = VDS or {}
VDS.Layout = VDS.Layout or {}

function VDS.Layout:DescribeView(viewName)
    local config = VDS.LayoutConfig  -- exception(false-positive): debug inspector; depth mirrors the config tree
    if not (config and config.window and config.window.views) then  -- exception(false-positive): debug inspector probes partial state
        return "Layout:DescribeView: VDS.LayoutConfig missing"
    end
    local viewSpec = config.window.views[viewName]
    if not viewSpec then
        local known = {}
        for name in pairs(config.window.views) do known[#known + 1] = name end
        table.sort(known)
        return ("unknown view %q -- known: %s"):format(tostring(viewName), table.concat(known, ", "))
    end

    local mainFrame  = VDS.MainFrame.frame
    local placements = mainFrame and mainFrame.placements or {}  -- exception(false-positive): debug inspector probes partial state
    local out = {}

    -- View dims via a fresh Normalize (what Compute would see).
    local n = self:Normalize(config, {
        view = viewName, state = VDS.Store:GetState(), intrinsics = {},
    })
    out[#out + 1] = ("view %s: %dx%d"):format(viewName, n.window.frameW, n.window.frameH)
    if viewSpec.columns then
        out[#out + 1] = ("  columns: { %s }"):format(table.concat(viewSpec.columns, ", "))
    end
    if viewSpec.rows then
        local rowStrs = {}
        for _, r in ipairs(viewSpec.rows) do rowStrs[#rowStrs + 1] = tostring(r) end
        out[#out + 1] = ("  rows: { %s }"):format(table.concat(rowStrs, ", "))
    end

    local childrenOf = {}
    local function addChild(parentId, id, kind, spec)
        if not parentId then return end
        childrenOf[parentId] = childrenOf[parentId] or {}
        childrenOf[parentId][#childrenOf[parentId] + 1] = {
            id = id, kind = kind, spec = spec, order = spec.order or 0  -- exception(optional): order optional in widget specs; default 0
        }
    end
    for id, spec in pairs(config.sections or {}) do addChild(spec["in"], id, "section", spec) end
    for id, spec in pairs(config.widgets  or {}) do addChild(spec["in"], id, "widget",  spec) end
    for _, list in pairs(childrenOf) do
        table.sort(list, function(a, b) return a.order < b.order end)
    end

    local function walk(parentId, indent)
        local list = childrenOf[parentId]
        if not list then return end
        for _, c in ipairs(list) do
            local p = placements[c.id]
            local spec = c.spec
            local placedStr = p and ("%dx%d"):format(p.width or 0, p.height or 0)
                                or "(not placed)"
            local specW = spec.width or "?"
            local specH = spec.height or "?"
            local extras = {}
            if spec.chrome  then extras[#extras + 1] = "chrome=" .. spec.chrome end
            if spec.padding then extras[#extras + 1] = "pad="    .. tostring(spec.padding) end
            if spec.gap     then extras[#extras + 1] = "gap="    .. tostring(spec.gap) end
            if spec.layout  then extras[#extras + 1] = "layout=" .. spec.layout end
            if spec.kind    then extras[#extras + 1] = "kind="   .. spec.kind end
            local extraStr = #extras > 0 and ("  [" .. table.concat(extras, ", ") .. "]") or ""
            out[#out + 1] = ("%s%-7s %s: %s  (spec %sx%s)%s"):format(
                indent, c.kind, c.id, placedStr, tostring(specW), tostring(specH), extraStr)
            walk(c.id, indent .. "  ")
        end
    end

    for panelId, panelSpec in pairs(config.panels or {}) do
        local cellName = panelSpec.cell and panelSpec.cell[viewName]
        if cellName and viewSpec.cells and viewSpec.cells[cellName] then
            local p = placements[panelId]
            local placedStr = p and ("%dx%d"):format(p.width or 0, p.height or 0) or "(not placed)"
            out[#out + 1] = ("panel  %s [cell=%s]: %s"):format(panelId, cellName, placedStr)
            if panelSpec.slots then
                for slotName in pairs(panelSpec.slots) do
                    out[#out + 1] = ("  slot %s"):format(slotName)
                end
            end
            walk(panelId, "  ")
        end
    end

    out[#out + 1] = ""
    out[#out + 1] = ("scrollbox scrollbar reserve: %d px"):format(
        VDS.UI.SCROLLBOX_SCROLLBAR_RESERVE or 0)  -- exception(false-positive): debug inspector probes partial state

    return table.concat(out, "\n")
end
