-- HousingDecorGuide/Core/HDG_DecorFilter.lua
-- Pure filter / predicate primitives for decor row lists. Used by the
-- Crate picker (and intended for Preview tab refactor later — same logic
-- without the surrounding tab UI).
--
-- An "item" passed in is the picker's flat row record:
--   {
--     decorID         = 1234,
--     itemID          = 5678,
--     name            = "Iron Brazier",
--     categoryID      = 1,
--     subcategoryID   = 12,
--     isCollected     = true,
--     isCraftable     = false,
--     hasVendorSource = true,
--     iconTexture     = ...,
--     iconAtlas       = ...,
--   }
--
-- This module assumes the producer fills isCollected / isCraftable /
-- hasVendorSource with truthy/nil. It does NOT call WoW APIs itself.

local _, privateDB = ...
local M = {}

-- Lowercased substring match — basic but covers the v1 "search box" UX.
function M.MatchText(item, query)
    if not query or query == "" then return true end
    if not item or not item.name then return false end
    local needle = query:lower()
    local hay    = item._lowerName  -- producer can pre-cache
    if not hay then hay = item.name:lower() end
    return hay:find(needle, 1, true) ~= nil
end

-- Single-status predicate. Pass any of: "owned" | "missing" | "craftable" | "vendor".
-- Returns true if the item matches the requested status.
function M.MatchStatus(item, statusKey)
    if not statusKey or statusKey == "" then return true end
    if statusKey == "owned"     then return item.isCollected     == true end
    if statusKey == "missing"   then return item.isCollected     ~= true end
    if statusKey == "craftable" then return item.isCraftable     == true end
    if statusKey == "vendor"    then return item.hasVendorSource == true end
    return true
end

-- Pass-set conjunction over an items array. statusSet is a map of status
-- keys → true; multiple selected statuses act as an OR (e.g. owned+missing
-- = no filter). Pure function — does not mutate items.
function M.Apply(items, query, statusSet, categoryID, subcategoryID)
    if type(items) ~= "table" then return {} end
    local out = {}
    local hasStatusSet = false
    if type(statusSet) == "table" then
        for _ in pairs(statusSet) do hasStatusSet = true; break end
    end

    for i = 1, #items do
        local it = items[i]
        local keep = true
        if categoryID    and it.categoryID    ~= categoryID    then keep = false end
        if keep and subcategoryID and it.subcategoryID ~= subcategoryID then keep = false end
        if keep and not M.MatchText(it, query) then keep = false end

        if keep and hasStatusSet then
            -- Treat selected statuses as OR.
            local anyMatch = false
            for k in pairs(statusSet) do
                if M.MatchStatus(it, k) then anyMatch = true; break end
            end
            if not anyMatch then keep = false end
        end

        if keep then out[#out + 1] = it end
    end
    return out
end

-- Bucket helpers for carousel population. Returns:
--   { [categoryID] = { count = N, owned = M, items = { ... } } }
function M.GroupByCategory(items)
    local out = {}
    for i = 1, #items do
        local it = items[i]
        local cid = it.categoryID
        if cid then
            local b = out[cid] or { count = 0, owned = 0, items = {} }
            b.count = b.count + 1
            if it.isCollected then b.owned = b.owned + 1 end
            b.items[#b.items + 1] = it
            out[cid] = b
        end
    end
    return out
end

function M.GroupBySubcategory(items, categoryID)
    local out = {}
    for i = 1, #items do
        local it = items[i]
        if (not categoryID) or it.categoryID == categoryID then
            local sid = it.subcategoryID
            if sid then
                local b = out[sid] or { count = 0, owned = 0, items = {} }
                b.count = b.count + 1
                if it.isCollected then b.owned = b.owned + 1 end
                b.items[#b.items + 1] = it
                out[sid] = b
            end
        end
    end
    return out
end

if privateDB then privateDB.HDG_DecorFilter = M end
return M
