-- HousingDecorGuide/UI/Tabs/Styles/HDG_ST_Landing.lua
-- Data-building layer for the Styles tab landing page. Owns the row-data
-- aggregation that the orchestrator's RefreshLanding pushes through the
-- WowScrollBoxList.
--
-- Section assembly order (top-to-bottom in the rendered landing):
--   1. My Styles      -- player-curated handpicked lists (tier == "curated")
--   2. Filtered Sets  -- smart tag-rule sets (tier == "custom")
--   3. Shopping Lists -- Store.shoppingLists, each row links into ShoppingList detail
--   4. Snapshots      -- snapshot tier + Recent Edit Sessions interleaved
--   5. Room Concepts  -- thematic/themed/faction tiers (merged group)
--   6. Collections    -- pinned (Recently Learned, Dyeable, Trophies) + alphabetical rest
--
-- Each row has the shape consumed by UpdateStyleRow in HDG_StylesTab.lua:
--   { styleId, displayName, icon, iconAtlas, color, description, tier, tierLabel,
--     collected, total, isSnapshot, canEdit, canExport, canDelete,
--     previewIcons = {{itemID, decorID, isCollected}, ...} }
--
-- Stats lookups read from the orchestrator's statsCache (passed in via the
-- options table on M:BuildData(opts)).
--
-- Loaded after HDG_ST_State.lua so privateDB.HDG_ST.State is available.

local _, privateDB = ...

local HDG = _G.HousingDecorGuide

privateDB.HDG_ST = privateDB.HDG_ST or {}
local State = privateDB.HDG_ST.State

local M = {}
privateDB.HDG_ST.Landing = M

-- =============================================================================
-- LANDING CATEGORIES (chip strip)
-- =============================================================================

-- Order matches the section sequence below so the chip row reads top-to-bottom
-- alongside the sections it filters to.
M.LANDING_CAT_DEFS = {
    { key = nil,            label = "All" },
    { key = "curated",      label = "My Styles" },        -- player-curated lists (fileable)
    { key = "custom",       label = "Filtered Sets" },    -- smart tag-rule sets (rule-defined)
    { key = "shoppinglist", label = "Shopping" },
    { key = "snapshot",     label = "Snapshots" },
    { key = "thematic",     label = "Room Concepts" },    -- thematic + themed + faction (merged)
    { key = "collection",   label = "Collections" },
}

-- =============================================================================
-- INTERNAL HELPERS
-- =============================================================================

local function GetStyleEngine() return privateDB and privateDB.HDG_StyleEngine end

-- Item-preview row picker: returns up to 6 {itemID, decorID, isCollected} for
-- the row's preview-icon strip. Prefers collected items when there are more
-- than 6 candidates, then fills with uncollected.
local function buildPreviewIcons(styleId, def)
    local SE = GetStyleEngine()
    if not SE then return {} end
    local items = SE:GetStyleItems(styleId)
    if not items then return {} end
    local bucket
    if def and def.tier == "snapshot" and items.items then
        bucket = items.items
    elseif items.curated then
        bucket = items.curated
    elseif def and def.subcategories and def.subcategories[1] then
        bucket = items[def.subcategories[1].key]
    elseif items.first then
        bucket = items.first
    end
    if not bucket then return {} end

    local coll, uncoll = {}, {}
    for _, item in ipairs(bucket) do
        if HDG_Data and HDG_Data.IsItemCollected(item.itemID) then
            if #coll < 6 then coll[#coll + 1] = { itemID = item.itemID, decorID = item.decorID, isCollected = true } end
        else
            if #uncoll < 6 then uncoll[#uncoll + 1] = { itemID = item.itemID, decorID = item.decorID, isCollected = false } end
        end
        if #coll >= 6 then break end
    end
    local picks = {}
    for _, p in ipairs(coll) do picks[#picks + 1] = p; if #picks >= 6 then break end end
    if #picks < 6 then
        for _, p in ipairs(uncoll) do picks[#picks + 1] = p; if #picks >= 6 then break end end
    end
    return picks
end
M._buildPreviewIcons = buildPreviewIcons -- exposed for tests / future reuse

-- Recent edit sessions: rows that link into the session detail view. Pulls
-- live session list from HDG.RecentActivity for the current house.
local function buildRecentSessionRows(passFilter)
    local rows = {}
    if not (HDG.RecentActivity and HDG.RecentActivity.GetSessions) then return rows end
    if not (C_Housing and C_Housing.GetCurrentHouseInfo) then return rows end
    local houseInfo = C_Housing.GetCurrentHouseInfo()
    local houseGUID = houseInfo and houseInfo.houseGUID
    if not houseGUID then return rows end

    local sessions = HDG.RecentActivity:GetSessions(houseGUID)
    for _, s in ipairs(sessions) do
        local label
        if s.isActive then
            label = "Edit session - Now"
        else
            local stamp = date("%b %d %I:%M %p", s.endedAt or s.startedAt)
            ---@cast stamp string
            label = "Edit session - " .. stamp:gsub(" 0", " ")
        end
        if passFilter(label, "snapshot") then
            table.insert(rows, {
                styleId         = "_session_" .. s.sessionID,
                displayName     = label,
                iconAtlas       = s.isActive and "communities-chat-icon-plus" or "communities-icon-clock",
                color           = { r = 0.6, g = 0.7, b = 0.9 },
                description     = s.eventCount .. " events",
                tier            = "snapshot",
                tierLabel       = "Recent Edit Sessions / House Snapshots",
                collected       = s.eventCount,
                total           = s.eventCount,
                isSnapshot      = false,
                isRecentSession = true,
                sessionID       = s.sessionID,
                houseGUID       = houseGUID,
                canEdit         = false, canExport = false, canDelete = false,
                previewIcons    = (function()
                    local previews = {}
                    if HDG.RecentActivity and HDG.RecentActivity.GetEventGroups then
                        local groups = HDG.RecentActivity:GetEventGroups(houseGUID, s.sessionID)
                        for i = 1, math.min(6, #groups) do
                            local g = groups[i]
                            table.insert(previews, {
                                iconID      = g.icon,
                                isCollected = (g.eventType == "placed" and g.liveCount > 0),
                            })
                        end
                    end
                    return previews
                end)(),
            })
        end
    end
    return rows
end

-- =============================================================================
-- PUBLIC API: BuildData -- returns the flat row array for landing render.
-- =============================================================================
-- opts.statsCache : statsCache table from the orchestrator. Each entry is
--                   { collected, total } keyed by styleId.
-- Returns: array of row tables (see file header for shape).

function M:BuildData(opts)
    opts = opts or {}
    local statsCache = opts.statsCache or {}
    local rows = {}
    local searchLower = State.landingSearchText ~= "" and State.landingSearchText:lower() or nil
    local catFilter = State.selectedLandingCategory

    local function passFilter(displayName, tier)
        if searchLower and not displayName:lower():find(searchLower, 1, true) then return false end
        if catFilter then
            if catFilter == "shoppinglist" and tier ~= "_shoppinglist" then return false end
            if catFilter == "collection" and tier ~= "collection" then return false end
            if catFilter == "thematic" and tier ~= "thematic" and tier ~= "themed" and tier ~= "faction" then return false end
            if catFilter == "curated" and tier ~= "curated" then return false end
            if catFilter == "custom" and tier ~= "custom" then return false end
            if catFilter == "snapshot" and tier ~= "snapshot" then return false end
        end
        return true
    end

    -- Helper: add custom/curated styles for a tier key (sorted alphabetically)
    local function addCustomStyles(tierKey, tierLabel)
        if not (HDG.Store and HDG.Store.Collection_ListByType) then return end
        local startIdx = #rows + 1
        for collID, def in pairs(HDG.Store:Collection_ListByType("style")) do
            local styleId = collID:sub(7) -- strip "style:" prefix
            if def and def.tier == tierKey then
                if passFilter(def.displayName, def.tier or tierKey) then
                    local st = statsCache[styleId] or { collected = 0, total = 0 }
                    local isSnap = (def.tier == "snapshot")
                    rows[#rows + 1] = {
                        styleId = styleId,
                        displayName = def.displayName,
                        icon = def.icon,
                        iconAtlas = def.iconAtlas or (isSnap and "decor-controls-decoratemode-active" or nil),
                        color = def.color or { r = 0.7, g = 0.7, b = 0.7 },
                        description = def.description or "",
                        tier = tierKey,
                        tierLabel = tierLabel,
                        collected = st.collected,
                        total = st.total,
                        isSnapshot = isSnap,
                        canEdit = not isSnap,
                        canExport = true,
                        canDelete = true,
                        previewIcons = buildPreviewIcons(styleId, def),
                    }
                end
            end
        end
        -- Sort this section alphabetically by name
        local endIdx = #rows
        if endIdx > startIdx then
            local section = {}
            for i = startIdx, endIdx do section[#section + 1] = rows[i] end
            table.sort(section, function(a, b) return (a.displayName or ""):lower() < (b.displayName or ""):lower() end)
            for i, rd in ipairs(section) do rows[startIdx + i - 1] = rd end
        end
    end

    -- Helper: add built-in styles for a tier key.
    -- groupTier (optional) overrides the row's `tier` field so multiple
    -- selection-tier passes (e.g. thematic/themed/faction) can be merged
    -- under a single section header.
    local function addBuiltinStyles(tierKey, tierLabel, groupTier)
        if not HDG_StyleOrder or not HDG_StyleDefinitions then return end
        for _, styleId in ipairs(HDG_StyleOrder) do
            local def = HDG_StyleDefinitions[styleId]
            if def and def.tier == tierKey and passFilter(def.displayName, tierKey) then
                local st = statsCache[styleId] or { collected = 0, total = 0 }
                rows[#rows + 1] = {
                    styleId = styleId,
                    displayName = def.displayName,
                    icon = def.icon,
                    iconAtlas = def.iconAtlas,
                    color = def.color or { r = 0.7, g = 0.7, b = 0.7 },
                    description = def.description or "",
                    tier = groupTier or tierKey,
                    tierLabel = tierLabel,
                    collected = st.collected,
                    total = st.total,
                    isSnapshot = false,
                    canEdit = false, canExport = false, canDelete = false,
                    previewIcons = buildPreviewIcons(styleId, def),
                }
            end
        end
    end

    -- 1a. My Styles -- player-curated handpicked lists (fileable via Curator)
    addCustomStyles("curated", "My Styles  -  built with Style Curator")
    -- 1b. Filtered Sets -- smart styles defined by tag rules (rule-derived)
    addCustomStyles("custom", "Filtered Sets  -  built with Smart Set Builder")

    -- 2. Shopping Lists
    local slLists = HDG.Store and HDG.Store:GetShoppingLists() or {}
    for _, listInfo in ipairs(slLists) do
        if passFilter(listInfo.name, "_shoppinglist") then
            local previews = {}
            local fullList = HDG.Store.state and HDG.Store.state.vendorShoppingLists
                             and HDG.Store.state.vendorShoppingLists[listInfo.id]
            if fullList and fullList.items then
                for _, entry in ipairs(fullList.items) do
                    local itemID = entry.itemID or entry.id
                    if itemID and #previews < 6 then
                        previews[#previews + 1] = {
                            itemID      = itemID,
                            isCollected = HDG_Data and HDG_Data.IsItemCollected(itemID) or false,
                        }
                    end
                end
            end
            local meta = fullList and fullList.meta
            local isWowhead = meta and meta.source == "wowhead"
            local slDesc = ""
            if isWowhead and meta.url then
                slDesc = meta.url
            elseif meta and meta.source then
                slDesc = meta.source:sub(1, 1):upper() .. meta.source:sub(2) .. " import"
            end
            rows[#rows + 1] = {
                styleId       = "_sl_" .. listInfo.id,
                displayName   = listInfo.name,
                icon          = isWowhead and "Interface\\AddOns\\HousingDecorGuide\\textures\\wowhead_logo" or nil,
                iconAtlas     = not isWowhead and "wowcodex-itemicon-bag" or nil,
                color         = { r = 0.3, g = 0.8, b = 0.6 },
                description   = slDesc,
                tier          = "_shoppinglist",
                tierLabel     = "Shopping Lists  -  import from wowhead.com, housing.wowdb.com or build from Acquire / Preview tab",
                collected     = 0,
                total         = listInfo.count or 0,
                isSnapshot    = false,
                listId        = listInfo.id,
                url           = meta and meta.url or nil,
                canEdit       = false, canExport = false, canDelete = false,
                previewIcons  = previews,
            }
        end
    end

    -- 3. Snapshots
    addCustomStyles("snapshot", "Recent Edit Sessions / House Snapshots")

    -- 3b. Recent edit sessions interleaved under the same tier
    do
        local sessionRows = buildRecentSessionRows(passFilter)
        for _, r in ipairs(sessionRows) do
            rows[#rows + 1] = r
        end
    end

    -- 4. Built-in style tiers -- thematic/themed/faction merged under one
    -- "Room Concepts" header (groupTier = "roomconcepts" so all three
    -- selection passes share the same section).
    addBuiltinStyles("thematic", "Room Concepts  -  pre-made themes from smart sets", "roomconcepts")
    addBuiltinStyles("themed",   "Room Concepts  -  pre-made themes from smart sets", "roomconcepts")
    addBuiltinStyles("faction",  "Room Concepts  -  pre-made themes from smart sets", "roomconcepts")

    -- 5. Collections (last -- pinned specials first, then alphabetical)
    if HDG_CollectionDefinitions and HDG_CollectionOrder then
        local pinned = { ["recently-learned"] = true, ["dyeable"] = true, ["trophies"] = true }
        -- Add pinned collections first (in order)
        for _, collectionId in ipairs(HDG_CollectionOrder) do
            if pinned[collectionId] then
                local def = HDG_CollectionDefinitions[collectionId]
                if def and passFilter(def.displayName, "collection") then
                    local st = statsCache[collectionId] or { collected = 0, total = 0 }
                    rows[#rows + 1] = {
                        styleId = collectionId, displayName = def.displayName,
                        icon = def.icon, iconAtlas = def.iconAtlas,
                        color = def.color or { r = 0.7, g = 0.7, b = 0.7 },
                        description = def.description or "",
                        tier = "collection",
                        tierLabel = "Useful Collections  -  prepared sets for use in the house editor",
                        collected = st.collected, total = st.total, isSnapshot = false,
                        canEdit = false, canExport = false, canDelete = false,
                        previewIcons = buildPreviewIcons(collectionId, def),
                    }
                end
            end
        end
        -- Add remaining collections
        local restStartIdx = #rows + 1
        for _, collectionId in ipairs(HDG_CollectionOrder) do
            if not pinned[collectionId] then
                local def = HDG_CollectionDefinitions[collectionId]
                if def and passFilter(def.displayName, "collection") then
                    local st = statsCache[collectionId] or { collected = 0, total = 0 }
                    rows[#rows + 1] = {
                        styleId = collectionId, displayName = def.displayName,
                        icon = def.icon, iconAtlas = def.iconAtlas,
                        color = def.color or { r = 0.7, g = 0.7, b = 0.7 },
                        description = def.description or "",
                        tier = "collection",
                        tierLabel = "Useful Collections  -  prepared sets for use in the house editor",
                        collected = st.collected, total = st.total, isSnapshot = false,
                        canEdit = false, canExport = false, canDelete = false,
                        previewIcons = buildPreviewIcons(collectionId, def),
                    }
                end
            end
        end
        -- Sort the rest of collections alphabetically by name
        local restEndIdx = #rows
        if restEndIdx > restStartIdx then
            local section = {}
            for i = restStartIdx, restEndIdx do section[#section + 1] = rows[i] end
            table.sort(section, function(a, b)
                return (a.displayName or ""):lower() < (b.displayName or ""):lower()
            end)
            for i, rd in ipairs(section) do rows[restStartIdx + i - 1] = rd end
        end
    end

    return rows
end

return M
