-- HDG_HT_RecordsAggregator.lua  (D2)
-- Read-only derivation of "Personal Records" stats from existing logs:
--   - HDG_DB.recentActivity   (per-house session events)
--   - HDG.Store craftingHistory  (lifetime crafted/learned entries)
--   - HDG_DB.records.dailyXP  (NEW tiny log; one int per date, written by
--                               HDG_HT_DailyXPTracker.lua)
-- No persistence beyond what those modules already write (plus dailyXP).
-- Single entry point: RecordsAggregator.Build() -> snapshot table consumed
-- by HDG_HT_W_Records.lua.

local _, privateDB = ...
privateDB.HDG_HT = privateDB.HDG_HT or {}
local R = {}
privateDB.HDG_HT.RecordsAggregator = R

local DAY_SECONDS = 86400

-- ---------------------------------------------------------------------------
-- Helpers
-- ---------------------------------------------------------------------------
local function dateKey(t)  -- YYYY-MM-DD bucketing for streak/active-day calc
    return date("%Y-%m-%d", t or time())
end

-- ---------------------------------------------------------------------------
-- RecentActivity-derived stats
-- ---------------------------------------------------------------------------
local function scanRecentActivity()
    local out = {
        firstPlacement = nil,        -- earliest event timestamp across all houses
        totalPlaced    = 0,
        bestSession    = 0,          -- max placed events in a single session
        activeDates    = {},         -- {[YYYY-MM-DD] = true}
    }
    local RA = HDG_DB and HDG_DB.recentActivity
    if type(RA) ~= "table" then return out end
    for _, bucket in pairs(RA) do
        for _, sess in pairs(bucket.sessions or {}) do
            local placedThisSess = 0
            for _, ev in pairs(sess.events or {}) do
                if ev.eventType == "placed" then
                    out.totalPlaced = out.totalPlaced + 1
                    placedThisSess = placedThisSess + 1
                    local ts = ev.timestamp or 0
                    if ts > 0 then
                        if not out.firstPlacement or ts < out.firstPlacement then
                            out.firstPlacement = ts
                        end
                        out.activeDates[dateKey(ts)] = true
                    end
                end
            end
            if placedThisSess > out.bestSession then out.bestSession = placedThisSess end
        end
    end
    return out
end

-- ---------------------------------------------------------------------------
-- CraftingHistory-derived stats (HDG.Store state.craftingHistory)
-- ---------------------------------------------------------------------------
local function scanCraftingHistory()
    local out = { totalCrafted = 0, totalLearned = 0 }
    local HDG = _G.HousingDecorGuide
    local state = HDG and HDG.Store and HDG.Store:GetState()
    local hist = state and state.craftingHistory
    if type(hist) ~= "table" then return out end
    for _, entry in ipairs(hist) do
        if entry.source == "Crafted" then out.totalCrafted = out.totalCrafted + 1
        elseif entry.source == "Learned" then out.totalLearned = out.totalLearned + 1 end
    end
    return out
end

-- ---------------------------------------------------------------------------
-- DailyXP delta log  (HDG_DB.records.dailyXP[YYYY-MM-DD] = xpDelta)
-- ---------------------------------------------------------------------------
local function scanDailyXP()
    local out = { bestDay = 0, bestDate = nil, longestStreak = 0 }
    HDG_DB = HDG_DB or {}
    HDG_DB.records = HDG_DB.records or {}
    HDG_DB.records.dailyXP = HDG_DB.records.dailyXP or {}
    local log = HDG_DB.records.dailyXP

    -- Best single-day XP gain
    for d, xp in pairs(log) do
        if (xp or 0) > out.bestDay then
            out.bestDay  = xp
            out.bestDate = d
        end
    end

    -- Longest active-date streak (dates where xp > 0)
    local sortedDates = {}
    for d, xp in pairs(log) do
        if (xp or 0) > 0 then sortedDates[#sortedDates + 1] = d end
    end
    table.sort(sortedDates)
    local cur, best = 0, 0
    local prevTime
    for _, d in ipairs(sortedDates) do
        local y, m, dy = d:match("(%d+)-(%d+)-(%d+)")
        local yn, mn, dyn = tonumber(y or ""), tonumber(m or ""), tonumber(dy or "")
        if yn and mn and dyn then
            local t = time({ year = yn, month = mn, day = dyn })
            if prevTime and (t - prevTime) <= DAY_SECONDS + 60 then  -- consecutive
                cur = cur + 1
            else
                cur = 1
            end
            if cur > best then best = cur end
            prevTime = t
        end
    end
    out.longestStreak = best
    return out
end

-- ---------------------------------------------------------------------------
-- Public: Build()
-- ---------------------------------------------------------------------------
function R.Build()
    local ra  = scanRecentActivity()
    local ch  = scanCraftingHistory()
    local dx  = scanDailyXP()

    local now = time()
    local houseAgeDays = ra.firstPlacement
        and math.floor((now - ra.firstPlacement) / DAY_SECONDS)
        or 0

    return {
        houseAgeDays  = houseAgeDays,
        firstPlacement = ra.firstPlacement,
        totalPlaced   = ra.totalPlaced,
        bestSession   = ra.bestSession,
        totalCrafted  = ch.totalCrafted,
        totalLearned  = ch.totalLearned,
        bestDay       = dx.bestDay,
        bestDate      = dx.bestDate,
        longestStreak = dx.longestStreak,
    }
end

return R
