-- test_catalog_ready.lua
-- ============================================================================
-- ADR-001 (amended 2026-05-20): CATALOG_READY is the lazy-resolve invalidation
-- seam for housing-catalog reads. Verifies:
--   1. CATALOG_READY exists in the closed taxonomy
--   2. Action meta invalidates session.catalog.tick
--   3. Dispatching bumps session.catalog.tick (so a `catalog.ready` selector
--      reading the tick invalidates on every catalog-completion event)
--   4. A subscriber sees the invalidation path in its callback (the
--      BindingEngine integration point)

---@diagnostic disable: undefined-global
dofile("wow_mock.lua")
dofile("../Core/VDS_Constants.lua")
dofile("../Core/VDS_SchemeConstants.lua")
dofile("../Core/VDS_Paths.lua")
dofile("../Core/VDS_Log.lua")
dofile("../Core/VDS_Store.lua")
dofile("../Core/VDS_ActionMeta.lua")
VDS.Store:ValidateActionMetaExhaustiveness()
VDS_DB = {}
VDS.Store:LoadFromSavedVariables()

local A = VDS.Constants.ACTIONS

local function assert_(v, label) if not v then error(label, 2) end end
local function eq(actual, expected, label)
    if actual ~= expected then
        error(label .. ": expected " .. tostring(expected) .. ", got " .. tostring(actual), 2)
    end
end

print("CATALOG_READY (ADR-001):")

-- ============================================================================
-- 1. Action exists in the closed taxonomy
-- ============================================================================

assert_(A.CATALOG_READY, "Constants.ACTIONS.CATALOG_READY missing")
print("  [OK] CATALOG_READY in Constants.ACTIONS")

-- ============================================================================
-- 2. Action meta invalidates session.catalog.tick
-- ============================================================================

local meta = VDS.Store:GetMeta(A.CATALOG_READY)
assert_(meta, "no meta row for CATALOG_READY")
local invalidatesTick = false
for _, p in ipairs(meta.invalidates) do
    if p == "session.catalog.tick" then invalidatesTick = true; break end
end
assert_(invalidatesTick, "CATALOG_READY does not invalidate session.catalog.tick")
print("  [OK] meta.invalidates includes session.catalog.tick")

-- ============================================================================
-- 3. Dispatching bumps the tick
-- ============================================================================

local tick0 = VDS.Store:GetState().session.catalog.tick
eq(tick0, 0, "session.catalog.tick initial value is 0")

VDS.Store:Dispatch({ type = A.CATALOG_READY })
eq(VDS.Store:GetState().session.catalog.tick, 1, "tick=1 after one dispatch")

VDS.Store:Dispatch({ type = A.CATALOG_READY })
eq(VDS.Store:GetState().session.catalog.tick, 2, "tick=2 after two dispatches")
print("  [OK] tick monotonically increments per dispatch")

-- ============================================================================
-- 4. Subscriber sees the invalidation paths
-- ============================================================================

local seen
VDS.Store:Subscribe(function(actionType, invalidation)
    if actionType == A.CATALOG_READY then seen = invalidation end
end)
VDS.Store:Dispatch({ type = A.CATALOG_READY })
assert_(seen, "subscriber did not fire for CATALOG_READY")
local sawTick = false
for _, p in ipairs(seen) do if p == "session.catalog.tick" then sawTick = true end end
assert_(sawTick, "subscriber's invalidation set did not include session.catalog.tick")
print("  [OK] subscriber receives invalidation set containing session.catalog.tick")

print("test_catalog_ready.lua passed")
