-- test_lumber_two_harvests.lua
-- Repro: after my 2026-05-24 fixes (positional key + nil-coord skip + zone-
-- filter strip), user reports radar still shows only 1 blip when 2 harvests
-- happened at different positions. Reproduce via reducer dispatches to
-- isolate whether the bug is data-side (state/selector) or paint-side.

dofile("wow_mock.lua")
dofile("../Core/HDGR_SchemeConstants.lua")
dofile("../Core/HDGR_Constants.lua")
dofile("../Core/HDGR_Format.lua")
dofile("../Core/HDGR_Paths.lua")
dofile("../Core/HDGR_Log.lua")
dofile("../Core/HDGR_Memo.lua")
dofile("../Core/HDGR_TableUtils.lua")
dofile("../Core/HDGR_Modules.lua")
dofile("../Core/HDGR_Middleware.lua")
dofile("../Core/HDGR_StoreFurnishings.lua")
dofile("../Core/HDGR_Store.lua")
-- NOTE: skip HDGR_Init.lua -- Init.lua transitively reads HDG.Theme:GetScheme()
-- when building the Environment slot catalog, which isn't loaded in this slim
-- reducer/selector harness. test_lumber_state.lua + test_shopping_smoke.lua
-- follow the same skip-Init pattern.
dofile("../UI/HDGR_Selectors.lua")
dofile("../UI/HDGR_Selectors_Lumber.lua")

local A         = HDG.Constants.ACTIONS
local Selectors = HDG.Selectors
local IRONWOOD  = 245586
local SHADOWMOON = 2169

local function assertEq(a, b, label)
    if a ~= b then error(label .. ": expected " .. tostring(b) .. ", got " .. tostring(a), 2) end
end

HDG_DB = {}
HDG.Store:LoadFromSavedVariables()
local state = HDG.Store:GetState()
state.session.identity.charKey = "Vamoose"

_G.GetTime = function() return 1000 end

-- Harvest #1: south of player at (0.45, 0.50)
HDG.Store:Dispatch({
    type = A.LUMBER_SESSION_START,
    payload = { lumberID = IRONWOOD, timestamp = 1000, startCount = 0 },
})
HDG.Store:Dispatch({
    type = A.LUMBER_HARVESTED,
    payload = { lumberID = IRONWOOD, qty = 1,
                x = 0.45, y = 0.50, mapID = SHADOWMOON, timestamp = 1000 },
})

assertEq(#state.session.lumber.blips, 1, "after harvest 1: state has 1 blip")

-- Harvest #2: north of player at (0.55, 0.60) -- player has moved
_G.GetTime = function() return 1010 end
HDG.Store:Dispatch({
    type = A.LUMBER_HARVESTED,
    payload = { lumberID = IRONWOOD, qty = 1,
                x = 0.55, y = 0.60, mapID = SHADOWMOON, timestamp = 1010 },
})

assertEq(#state.session.lumber.blips, 2, "after harvest 2: state has 2 blips")

-- Selector should return both with ageSec computed
local blips = Selectors:Call("lumber.blipsForRadar", state, {})
assertEq(#blips, 2, "selector returns both blips")

-- Newest first
assertEq(blips[1].x, 0.55, "blips[1] = newer (x=0.55)")
assertEq(blips[2].x, 0.45, "blips[2] = older (x=0.45)")

-- Harvest #3 at SAME position as #1 -- positional key collision is intentional
-- (same node re-harvested -> same blip refreshed). But state still appends.
_G.GetTime = function() return 1020 end
HDG.Store:Dispatch({
    type = A.LUMBER_HARVESTED,
    payload = { lumberID = IRONWOOD, qty = 1,
                x = 0.45, y = 0.50, mapID = SHADOWMOON, timestamp = 1020 },
})

assertEq(#state.session.lumber.blips, 3, "after harvest 3: state has 3 blips (selector dedups, state doesn't)")

local blips2 = Selectors:Call("lumber.blipsForRadar", state, {})
assertEq(#blips2, 3, "selector returns all 3 blips")

-- Edge case: harvest with nil coords. Reducer should skip the blip append
-- but still bump tick.
_G.GetTime = function() return 1030 end
local tickBefore = state.session.lumber.tick
HDG.Store:Dispatch({
    type = A.LUMBER_HARVESTED,
    payload = { lumberID = IRONWOOD, qty = 1,
                x = nil, y = nil, mapID = nil, timestamp = 1030 },
})
assertEq(#state.session.lumber.blips, 3, "nil-coord harvest: no blip appended")
assertEq(state.session.lumber.tick, tickBefore + 1, "nil-coord harvest: tick still bumped")

print("test_lumber_two_harvests.lua passed")
