-- test_migration_chain.lua
-- ============================================================================
-- Migration chain — for each historical SavedVars shape (v0 missing-slots,
-- v1 current), construct a representative VDS_DB at that version, run
-- LoadFromSavedVariables, assert the resulting state matches the canonical
-- shape AND that user data was preserved (not stomped).
--
-- LESSON (HDG 2.39 migration): a non-destructive Ensure*-style migration is
-- the only safe pattern. A `state.account = NewAccount()` wholesale rewrite
-- detaches the by-reference link to SavedVariables and wipes user data on
-- next /reload. The Ensure* approach migrates in place.
--
-- LESSON (VFN, HDGR): every shipped schemaVersion needs a test case here.
-- When you add a new version, do NOT delete prior cases — leaving them in
-- proves the ladder still climbs from v0 through every intermediate.

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

local A = VDS.Constants.ACTIONS
dofile("../Core/VDS_ActionMeta.lua")
VDS.Store:ValidateActionMetaExhaustiveness()

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

local function resetStore()
    VDS.Store:_RawReset()
    _G[VDS.Constants.SAVEDVAR_KEY] = nil
end

-- ============================================================================
-- Case 1: Fresh install — no VDS_DB at all → default shape
-- ============================================================================

resetStore()
VDS.Store:LoadFromSavedVariables()
do
    local s = VDS.Store:GetState()
    assertEq(s.account.config.scheme, "DefaultDark", "fresh install: default scheme")
    assertEq(s.account.config.debug, false, "fresh install: default debug=false")
    assertTrue(s.account.ui ~= nil, "fresh install: ui slot present")
    assertEq(s.account.cart, nil, "fresh install: cart absent (selector-derived now)")
end
print("  [OK] case 1: fresh install → default shape")

-- ============================================================================
-- Case 2: v0 (pre-Ensure*) — partial account, missing newer slots.
-- Simulates a user who installed an early version and never opened the
-- addon since the schema grew.
-- ============================================================================

resetStore()
VDS_DB = {
    account = {
        minimap = { hide = false, minimapPos = 137 },   -- preserved user data
        cart    = { shoppingList = { [42] = 3 } },      -- legacy cart data: should be dropped
        -- config: MISSING (added later)
        -- ui:     MISSING
        -- customThemes / canvas / live: MISSING
    },
}
VDS.Store:LoadFromSavedVariables()
do
    local s = VDS.Store:GetState()
    assertEq(s.account.minimap.minimapPos, 137, "v0 user data PRESERVED across migration")
    assertEq(s.account.cart, nil, "v0 legacy cart slot dropped on migration")
    assertTrue(s.account.config ~= nil, "v0: config slot back-filled")
    assertEq(s.account.config.scheme, "DefaultDark", "v0: config defaults applied")
    assertTrue(s.account.ui ~= nil, "v0: ui slot back-filled")
    assertTrue(s.account.canvas ~= nil, "v0: canvas slot back-filled")
end
print("  [OK] case 2: v0 missing-slots → migrated + user data preserved + legacy cart dropped")

-- ============================================================================
-- Case 3: by-reference contract holds across migration.
-- After load, mutating state.account MUST be visible in VDS_DB. If
-- LoadFromSavedVariables replaces account with a fresh table, the link is
-- gone and the next /reload loses everything.
-- ============================================================================

resetStore()
VDS_DB = { account = { config = { debug = true } } }
VDS.Store:LoadFromSavedVariables()
VDS.Store:Dispatch({ type = A.MINIMAP_POSITION_SAVE, payload = { pos = 217 } })
assertEq(VDS_DB.account.minimap.minimapPos, 217,
    "by-reference link broken: VDS_DB and state.account are different tables")
print("  [OK] case 3: by-reference link survives migration")

-- ============================================================================
-- Case 4: HARD_RESET migration — wipes account back to defaults.
-- This is the user-invoked migration; covered separately because the path
-- through the reducer is different from the LoadFromSavedVariables path.
-- ============================================================================

resetStore()
VDS_DB = { account = { minimap = { hide = true, minimapPos = 42 } } }
VDS.Store:LoadFromSavedVariables()
VDS.Store:Dispatch({ type = A.HARD_RESET })
do
    local s = VDS.Store:GetState()
    assertEq(s.account.cart, nil, "HARD_RESET leaves cart absent (selector-derived)")
    assertEq(s.account.minimap.hide, false, "HARD_RESET restored minimap defaults")
    assertTrue(s.account.config ~= nil, "HARD_RESET re-built config")
end
print("  [OK] case 4: HARD_RESET produces default shape")

print("test_migration_chain.lua passed")
