---@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 assertEq(actual, expected, msg)
    if actual ~= expected then
        error(string.format("%s: expected %s, got %s",
            msg or "assertEq", tostring(expected), tostring(actual)), 2)
    end
end

-- Case 1: byView shape on fresh init
local s = VDS.Store:GetState()
for _, view in ipairs({"category","custom","theme","crafting","herbs","canvas"}) do
    if type(s.session.ui.byView[view]) ~= "table" then
        error("byView." .. view .. " missing or not a table")
    end
end
print("  [OK] case 1: byView shape on fresh init")

-- Case 2: SET_SELECTED_DYE writes to the FLAT session.ui.selectedDyeID slot
-- (NOT byView). Selection is a top-level concern -- moving it back out of
-- byView fixed a hover-storm where every mouse-over caused a byView-wide
-- invalidation (~16MB/s allocation). See ActionMeta SET_SELECTED_DYE comment.
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "category" } })
VDS.Store:Dispatch({ type = A.SET_SELECTED_DYE, payload = { id = 42 } })
s = VDS.Store:GetState()
assertEq(s.session.ui.selectedDyeID, 42, "flat selectedDyeID set to 42")
assertEq(s.session.ui.byView.category.selectedDyeID, nil, "no byView leak")
print("  [OK] case 2: SET_SELECTED_DYE writes flat (not byView)")

-- Case 3: SET_FILTER_MODE doesn't clear selection (flat slot is view-global).
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "theme" } })
s = VDS.Store:GetState()
assertEq(s.session.ui.selectedDyeID, 42, "selection survives tab change")
print("  [OK] case 3: selection persists across SET_FILTER_MODE")

-- Case 4: re-entering category preserves selection
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "category" } })
s = VDS.Store:GetState()
assertEq(s.session.ui.selectedDyeID, 42, "selection persists across leave/re-enter")
print("  [OK] case 4: selection sticky across tab switches")

-- Case 5: subfilter slots also scope per-tab
VDS.Store:Dispatch({ type = A.SET_ACTIVE_SUBFILTER, payload = { kind = "colorGroup", value = "Red" } })
s = VDS.Store:GetState()
assertEq(s.session.ui.byView.category.activeColorGroup, "Red", "Red filter stored in category bucket")
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "herbs" } })
VDS.Store:Dispatch({ type = A.SET_ACTIVE_SUBFILTER, payload = { kind = "herbGroup", value = "Black" } })
s = VDS.Store:GetState()
assertEq(s.session.ui.byView.herbs.activeHerbGroup, "Black", "Black filter stored in herbs bucket")
assertEq(s.session.ui.byView.category.activeColorGroup, "Red", "category Red filter still present")
print("  [OK] case 5: subfilter slots scoped per-tab")

-- Case 6: canvas scope + category filters live under byView.canvas
-- (CANVAS_TOGGLE_EXPAND / expandedDecors retired in Phase 5 with the tree
-- picker; scope + selectedCategory are the current byView.canvas slots.)
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "canvas" } })
VDS.Store:Dispatch({ type = A.CANVAS_SET_SCOPE, payload = { value = { kind = "theme", name = "Ardenweald" } } })
VDS.Store:Dispatch({ type = A.CANVAS_SET_CATEGORY, payload = { value = 12 } })
s = VDS.Store:GetState()
assertEq(s.session.ui.byView.canvas.scope.name, "Ardenweald", "scope stored in canvas bucket")
assertEq(s.session.ui.byView.canvas.selectedCategory, 12, "category stored in canvas bucket")
-- Sticky across tab switches (ADR-008): leave + re-enter canvas keeps both.
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "category" } })
VDS.Store:Dispatch({ type = A.SET_FILTER_MODE, payload = { mode = "canvas" } })
s = VDS.Store:GetState()
assertEq(s.session.ui.byView.canvas.selectedCategory, 12, "canvas category sticky across tab switch")
print("  [OK] case 6: canvas scope/category live under byView.canvas (sticky)")

print("test_tab_scoped_state.lua passed")
