-- GATE for the ProfessionsDB -> DecorDB decor-recipe migration
-- (spec: docs/superpowers/specs/2026-06-09-hdg-decor-recipe-db-migration-design.md).
-- Asserts every decor recipe's DIRECT reagents agree between the curated DecorDB
-- (reagents) and ProfessionsDB (basic slots), comparing as QUALITY-VARIANT GROUPS
-- (the two DBs reference different reagent quality tiers for ~8 recipes; readiness
-- is tier-agnostic via GetQualityVariants, so group-equality is the correct check).
-- If this fails on anything beyond a quality-tier swap, the migration must stop.
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("../Modules/HDGR_StaticData.lua")
dofile("../data/HDGR_DecorDB.lua")          -- REAL data
dofile("../data/HDGR_ProfessionsDB.lua")    -- REAL data

local Recipes     = HDG.StaticData.Recipes
local Professions = HDG.StaticData.Professions

-- Canonical quality-group representative: the smallest itemID across {itemID} + its
-- quality siblings (siblings come from ProfessionsDB slot.variants via GetQualityVariants).
local function canon(itemID)
    local vars = Professions:GetQualityVariants(itemID)
    if not vars then return itemID end
    local m = itemID
    for _, v in ipairs(vars) do if v < m then m = v end end
    return m
end

-- ProfessionsDB indexed by produced itemID (it is itemID-keyed, but build from the
-- .itemID field to be robust against any key/field drift).
local profByItem = {}
for _, e in pairs(Professions:GetAll()) do
    if e.itemID then profByItem[e.itemID] = e end
end

local function decorReagentMap(entry)
    local m = {}
    for rid, info in pairs(entry.reagents or {}) do m[canon(rid)] = info.qty end
    return m
end

local function profBasicMap(entry)
    local m = {}
    for _, slot in ipairs(entry.slots or {}) do
        if slot.type == "basic" and slot.itemID and slot.qty then
            m[canon(slot.itemID)] = (m[canon(slot.itemID)] or 0) + slot.qty
        end
    end
    return m
end

local function mapsEqual(a, b)
    for k, v in pairs(a) do if b[k] ~= v then return false end end
    for k, v in pairs(b) do if a[k] ~= v then return false end end
    return true
end

local total, missing, mismatch = 0, 0, 0
for _, entry in pairs(Recipes:GetAll()) do
    if entry.itemID and entry.reagents then
        total = total + 1
        local prof = profByItem[entry.itemID]
        if not prof then
            missing = missing + 1
            io.stderr:write(("  MISSING in ProfessionsDB: %s (item %d)\n")
                :format(entry.name or "?", entry.itemID))
        elseif not mapsEqual(decorReagentMap(entry), profBasicMap(prof)) then
            mismatch = mismatch + 1
            io.stderr:write(("  REAGENT MISMATCH: %s (item %d)\n")
                :format(entry.name or "?", entry.itemID))
        end
    end
end

io.stderr:write(("parity: %d decor recipes checked, %d missing, %d mismatched\n")
    :format(total, missing, mismatch))

if missing > 0 or mismatch > 0 then
    io.stderr:write("test_decordb_professions_parity.lua FAILED\n")
    os.exit(1)
end
print("test_decordb_professions_parity.lua passed (" .. total .. " decor recipes, reagents agree as quality groups)")
