-- test_action_meta_exhaustiveness.lua
-- ============================================================================
-- Every value in VDS.Constants.ACTIONS must have a key in the registered
-- action meta, and that key must carry an `invalidates` field (table | fn
-- | "*"). Boot validator catches this at runtime; this test makes the same
-- contract runnable in CI so regressions fail before first game load.
--
-- Also checks the INVERSE: no orphaned meta rows (in registry but not in
-- ACTIONS). Both directions catch drift between Constants and ActionMeta.

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")

-- ===== Boot validator runs (presence check) =====
VDS.Store:ValidateActionMetaExhaustiveness()

-- ===== Detailed check: every action has meta + invalidates of valid shape =====
local A = VDS.Constants.ACTIONS
local actionMeta = VDS.Store._actionMeta
local missingMeta, missingInvalidates = {}, {}
for name, value in pairs(A) do
    local row = actionMeta[value]
    if row == nil then
        missingMeta[#missingMeta + 1] = name
    else
        local inv = row.invalidates
        local invType = type(inv)
        local valid = invType == "table"
                   or invType == "function"
                   or (invType == "string" and inv == "*")
        if not valid then
            missingInvalidates[#missingInvalidates + 1] = name
        end
    end
end

if #missingMeta > 0 then
    table.sort(missingMeta)
    error("Action meta missing for actions:\n  " .. table.concat(missingMeta, "\n  ")
        .. "\nFix: add entries to VDS_ActionMeta.lua", 2)
end

if #missingInvalidates > 0 then
    table.sort(missingInvalidates)
    error("Action meta missing `invalidates` field for:\n  "
        .. table.concat(missingInvalidates, "\n  ")
        .. "\nFix: every meta row needs invalidates = {paths} | fn | \"*\"", 2)
end

-- ===== Inverse check: no orphaned meta rows =====
local knownValues = {}
for _, v in pairs(A) do knownValues[v] = true end
local orphaned = {}
for actionValue in pairs(actionMeta) do
    if not knownValues[actionValue] then
        orphaned[#orphaned + 1] = actionValue
    end
end
if #orphaned > 0 then
    table.sort(orphaned)
    error("Orphaned meta rows (registered but not in ACTIONS):\n  "
        .. table.concat(orphaned, "\n  ")
        .. "\nFix: remove from VDS_ActionMeta.lua or add to ACTIONS", 2)
end

-- ===== Sanity: ACTIONS table not suspiciously empty =====
local actionCount = 0
for _ in pairs(A) do actionCount = actionCount + 1 end
if actionCount < 20 then
    error("ACTIONS table has only " .. actionCount .. " entries -- suspiciously small; "
        .. "check VDS_Constants.lua loaded correctly", 2)
end

print(string.format(
    "test_action_meta_exhaustiveness.lua passed (%d actions, all have meta + invalidates)",
    actionCount))
