-- ============================================================================
-- Housing Decor Guide - Store (Simplified)
-- Direct state management with persistence
-- ============================================================================

local addonName, privateDB = ...
local HDG = _G.HousingDecorGuide

-- Deep copy helper (only used for array operations)
local function DeepCopy(orig)
    local copy
    if type(orig) == "table" then
        copy = {}
        for k, v in pairs(orig) do
            copy[k] = DeepCopy(v)
        end
    else
        copy = orig
    end
    return copy
end

-- Default state template
local DEFAULT_STATE = {
    config = {
        debug = false,
        showMinimapButton = true,
        theme = "HDGDefault",
        scale = 1.0,
        fontScale = 0,
        fontFamily = "FRIZQT__",
        bgOpacity = 0.95,
        quotesEnabled = true,
        vamooseChattiness = 30,
        vamooseChatOutput = false,
        lumberQuotesEnabled = true,
        craftQuotesEnabled = true,
        quotesOnlyChat = false,
        closeProfWindowAfterCraft = true,
        showProfessionButtons = true,
        preferredPriceAddon = nil,
        showRawMaterials = false,
        materialSortMode = "totals",
        craftableFilter = false,
        searchReagents = false,
        uncollectedFilter = false,
        lumberFocusMode = true,
        lumberAutoShow = true,
        showLumberMaterials = false,
        lumberHUDEnabled = true,
        lumberHUDPosition = nil,
        lumberHUDVisible = false,
        lumberRadarPinToTracker = false,
        zoneScannerEnabled = false,
        zoneScannerSound = false,
    },
    ui = {
        framePosition = nil,
        activeTab = "recipes",
        professionFilter = "All",
        characterProfessionFilter = {},
        collapsedMaterials = {},
        trainersCollapsed = {},
        lumberPinned = false,
        pinnedLumberPosition = nil,
        vendorListPosition = nil,
    },
    shoppingList = {},
    characters = {},
    craftingHistory = {},
    trackedReagents = {},
    minimap = {
        hide = false,
        minimapPos = 220,
        lock = false,
        showMinimapButton = true,
        showInCompartment = true,
        icon = nil,
    },
    lumberCoordinates = {},
    farmingHistory = {},
    vendorShoppingList = {},
    layout = {},
    userNotes = {},
    vendorNotes = {},
    dbVersion = 4,
    _runtime = { pendingCraftInfo = { itemID = nil, remaining = 0 } },
}

HDG.Store = {
    state = DeepCopy(DEFAULT_STATE),
    saveTimer = nil,
    onThemeChange = nil,  -- Theme change callback
}

function HDG.Store:GetState()
    return self.state
end

-- ============================================================================
-- PERSISTENCE (Simplified auto-serialize)
-- ============================================================================

function HDG.Store:LoadFromSavedVariables()
    HDG_DB = HDG_DB or {}

    -- Merge saved data into state (preserves defaults for new keys)
    local function MergeTable(target, source)
        if not source then return end
        for k, v in pairs(source) do
            if type(v) == "table" and type(target[k]) == "table" then
                MergeTable(target[k], v)
            else
                target[k] = v
            end
        end
    end

    MergeTable(self.state.config, HDG_DB.config)
    MergeTable(self.state.ui, HDG_DB.ui)
    MergeTable(self.state.minimap, HDG_DB.minimap)

    -- Direct assignments for data tables
    if HDG_DB.shoppingList then self.state.shoppingList = HDG_DB.shoppingList end
    if HDG_DB.characters then self.state.characters = HDG_DB.characters end
    if HDG_DB.craftingHistory then self.state.craftingHistory = HDG_DB.craftingHistory end
    if HDG_DB.trackedReagents then self.state.trackedReagents = HDG_DB.trackedReagents end
    if HDG_DB.lumberCoordinates then self.state.lumberCoordinates = HDG_DB.lumberCoordinates end
    if HDG_DB.farmingHistory then self.state.farmingHistory = HDG_DB.farmingHistory end
    if HDG_DB.vendorShoppingList then self.state.vendorShoppingList = HDG_DB.vendorShoppingList end
    if HDG_DB.layout then self.state.layout = HDG_DB.layout end
    if HDG_DB.userNotes then self.state.userNotes = HDG_DB.userNotes end
    if HDG_DB.vendorNotes then self.state.vendorNotes = HDG_DB.vendorNotes end
    if HDG_DB.dbVersion then self.state.dbVersion = HDG_DB.dbVersion end

    if self.state.config.debug then
        print("|cFF14b8a6[HDG Store]|r Loaded state from SavedVariables")
    end
end

function HDG.Store:QueueSave()
    if self.saveTimer then self.saveTimer:Cancel() end
    self.saveTimer = C_Timer.NewTimer(1, function() self:SaveToSavedVariables() end)
end

function HDG.Store:SaveToSavedVariables()
    local prevExport = HDG_DB and HDG_DB.catalogExport -- preserve debug export
    HDG_DB = {
        config = self.state.config,
        ui = self.state.ui,
        minimap = self.state.minimap,
        shoppingList = self.state.shoppingList,
        characters = self.state.characters,
        craftingHistory = self.state.craftingHistory,
        trackedReagents = self.state.trackedReagents,
        lumberCoordinates = self.state.lumberCoordinates,
        farmingHistory = self.state.farmingHistory,
        vendorShoppingList = self.state.vendorShoppingList,
        layout = self.state.layout,
        userNotes = self.state.userNotes,
        vendorNotes = self.state.vendorNotes,
        dbVersion = self.state.dbVersion,
        catalogExport = prevExport,
    }
    if self.state.config.debug then
        print("|cFF14b8a6[HDG Store]|r Saved state to SavedVariables")
    end
end

function HDG.Store:Flush()
    if self.saveTimer then
        self.saveTimer:Cancel()
        self.saveTimer = nil
    end
    self:SaveToSavedVariables()
end

-- ============================================================================
-- DIRECT STATE METHODS (replaces reducers for simple operations)
-- ============================================================================

function HDG.Store:SetConfig(key, value)
    self.state.config[key] = value
    self:QueueSave()
end

function HDG.Store:SetTheme(themeName)
    self.state.config.theme = themeName
    if self.onThemeChange then self.onThemeChange(themeName) end
    self:QueueSave()
end

function HDG.Store:SetUI(key, value)
    self.state.ui[key] = value
    self:QueueSave()
end

function HDG.Store:SetMinimap(key, value)
    self.state.minimap[key] = value
    self:QueueSave()
end

function HDG.Store:UpdateLayout(frameName, layoutData)
    self.state.layout[frameName] = layoutData
    self:QueueSave()
end

-- ============================================================================
-- SHOPPING LIST METHODS
-- ============================================================================

function HDG.Store:AddToShoppingList(item)
    for i, existing in ipairs(self.state.shoppingList) do
        if existing.id == item.id then
            self.state.shoppingList[i].quantity = (existing.quantity or 1) + (item.quantity or 1)
            self:QueueSave()
            return
        end
    end
    table.insert(self.state.shoppingList, {
        id = item.id,
        name = item.name,
        spell = item.spell,
        reagents = item.reagents,
        expansion = item.expansion,
        quantity = item.quantity or 1,
    })
    self:QueueSave()
end

function HDG.Store:RemoveFromShoppingList(itemID)
    for i, item in ipairs(self.state.shoppingList) do
        if item.id == itemID then
            table.remove(self.state.shoppingList, i)
            self:QueueSave()
            return
        end
    end
end

function HDG.Store:UpdateShoppingItemQty(itemID, quantity)
    for i, item in ipairs(self.state.shoppingList) do
        if item.id == itemID then
            if quantity <= 0 then
                table.remove(self.state.shoppingList, i)
            else
                self.state.shoppingList[i].quantity = quantity
            end
            self:QueueSave()
            return
        end
    end
end

function HDG.Store:ClearShoppingList()
    self.state.shoppingList = {}
    self:QueueSave()
end

-- ============================================================================
-- CHARACTER DATA METHODS
-- ============================================================================

function HDG.Store:UpdateCharacterData(charKey, data)
    if not self.state.characters[charKey] then
        self.state.characters[charKey] = { professions = {}, lastUpdated = 0 }
    end
    local char = self.state.characters[charKey]

    if data.professions then
        for profName, profData in pairs(data.professions) do
            local existing = char.professions[profName]
            if existing then
                existing.knownRecipes = profData.knownRecipes
                existing.knownCount = profData.knownCount
                existing.totalCount = profData.totalCount
                if profData.skillLevels and next(profData.skillLevels) then
                    existing.skillLevels = profData.skillLevels
                end
            else
                char.professions[profName] = profData
            end
        end
    end

    if data.lumberInventory then char.lumberInventory = data.lumberInventory end
    if data.lumberUpdated then char.lumberUpdated = data.lumberUpdated end
    char.lastUpdated = data.lastUpdated or time()

    self:QueueSave()
end

function HDG.Store:RemoveCharacter(charKey)
    self.state.characters[charKey] = nil
    self:QueueSave()
end

-- ============================================================================
-- CRAFTING HISTORY METHODS
-- ============================================================================

function HDG.Store:AddCraftingHistory(entry)
    table.insert(self.state.craftingHistory, 1, {
        itemID = entry.itemID,
        itemName = entry.itemName,
        quantity = entry.quantity or 1,
        timestamp = entry.timestamp or time(),
        charName = entry.charName,
    })
    while #self.state.craftingHistory > 100 do
        table.remove(self.state.craftingHistory)
    end
    self:QueueSave()
end

function HDG.Store:ClearCraftingHistory()
    self.state.craftingHistory = {}
    self:QueueSave()
end

-- ============================================================================
-- TRACKED REAGENTS METHODS
-- ============================================================================

function HDG.Store:AddTrackedReagent(itemID, name, targetQty)
    self.state.trackedReagents[itemID] = {
        name = name,
        targetQty = targetQty or 0,
        addedTime = time(),
    }
    self:QueueSave()
end

function HDG.Store:RemoveTrackedReagent(itemID)
    self.state.trackedReagents[itemID] = nil
    self:QueueSave()
end

function HDG.Store:UpdateTrackedReagent(itemID, targetQty)
    if self.state.trackedReagents[itemID] then
        self.state.trackedReagents[itemID].targetQty = targetQty
        self:QueueSave()
    end
end

function HDG.Store:ClearTrackedReagents()
    self.state.trackedReagents = {}
    self:QueueSave()
end

-- ============================================================================
-- USER NOTES METHODS
-- ============================================================================

function HDG.Store:SetUserNote(itemID, text)
    self.state.userNotes[itemID] = { text = text, ts = time() }
    self:QueueSave()
end

function HDG.Store:GetUserNote(itemID)
    return self.state.userNotes[itemID]
end

function HDG.Store:RemoveUserNote(itemID)
    self.state.userNotes[itemID] = nil
    self:QueueSave()
end

function HDG.Store:GetAllUserNotes()
    return self.state.userNotes
end

-- ============================================================================
-- VENDOR NOTES METHODS
-- ============================================================================

function HDG.Store:SetVendorNote(npcID, text)
    self.state.vendorNotes[npcID] = { text = text, ts = time() }
    self:QueueSave()
end

function HDG.Store:GetVendorNote(npcID)
    return self.state.vendorNotes[npcID]
end

function HDG.Store:RemoveVendorNote(npcID)
    self.state.vendorNotes[npcID] = nil
    self:QueueSave()
end

function HDG.Store:GetAllVendorNotes()
    return self.state.vendorNotes
end

-- ============================================================================
-- EXPORT ALL NOTES
-- ============================================================================

function HDG.Store:ExportUserNotes()
    local itemNotes = self.state.userNotes
    local vendorNotes = self.state.vendorNotes
    local itemCount, vendorCount = 0, 0
    for _ in pairs(itemNotes) do itemCount = itemCount + 1 end
    for _ in pairs(vendorNotes) do vendorCount = vendorCount + 1 end
    if itemCount == 0 and vendorCount == 0 then return "No notes to export." end

    local lines = {}
    table.insert(lines, "=== HDG Notes Export ===")
    table.insert(lines, "Date: " .. date("%Y-%m-%d"))
    table.insert(lines, string.format("Total: %d item notes, %d vendor notes", itemCount, vendorCount))
    table.insert(lines, "")

    if vendorCount > 0 then
        table.insert(lines, "--- Vendor Notes ---")
        table.insert(lines, "")
        local sorted = {}
        for npcID, note in pairs(vendorNotes) do
            table.insert(sorted, { npcID = npcID, text = note.text, ts = note.ts })
        end
        table.sort(sorted, function(a, b) return a.ts > b.ts end)
        for _, entry in ipairs(sorted) do
            local ve = HDG_VendorDB and HDG_VendorDB[entry.npcID]
            local name = ve and ve[1] or ("NPC #" .. entry.npcID)
            local zone = ve and ve[2] or "Unknown Zone"
            table.insert(lines, string.format("[NPC %d] %s — %s", entry.npcID, name, zone))
            table.insert(lines, "  Note: " .. entry.text)
            if entry.ts and entry.ts > 0 then
                table.insert(lines, "  Added: " .. date("%Y-%m-%d %H:%M", entry.ts))
            end
            table.insert(lines, "")
        end
    end

    if itemCount > 0 then
        table.insert(lines, "--- Item Notes ---")
        table.insert(lines, "")
        local sorted = {}
        for itemID, note in pairs(itemNotes) do
            table.insert(sorted, { itemID = itemID, text = note.text, ts = note.ts })
        end
        table.sort(sorted, function(a, b) return a.ts > b.ts end)
        for _, entry in ipairs(sorted) do
            local name = HDG_Data and HDG_Data.GetCachedItemName(entry.itemID) or ("Unknown Item")
            table.insert(lines, string.format("[%d] %s", entry.itemID, name))
            table.insert(lines, "  Note: " .. entry.text)
            if entry.ts and entry.ts > 0 then
                table.insert(lines, "  Added: " .. date("%Y-%m-%d %H:%M", entry.ts))
            end
            table.insert(lines, "")
        end
    end

    return table.concat(lines, "\n")
end

-- ============================================================================
-- LUMBER COORDINATES METHODS
-- ============================================================================

function HDG.Store:AddLumberCoordinate(node)
    table.insert(self.state.lumberCoordinates, node)
    self:QueueSave()
end

function HDG.Store:SetLumberCoordinates(coordinates)
    self.state.lumberCoordinates = coordinates or {}
    self:QueueSave()
end

function HDG.Store:ClearLumberCoordinates()
    self.state.lumberCoordinates = {}
    self:QueueSave()
end

-- ============================================================================
-- FARMING HISTORY METHODS
-- ============================================================================

function HDG.Store:UpsertFarmingSession(session)
    local sessionId = session.sessionId
    if sessionId then
        for _, entry in ipairs(self.state.farmingHistory) do
            if entry.sessionId == sessionId then
                entry.collected = session.collected or entry.collected
                entry.duration = session.duration or entry.duration
                entry.perHour = session.perHour or entry.perHour
                entry.timestamp = session.timestamp or entry.timestamp
                entry.zone = session.zone or entry.zone
                self:QueueSave()
                return
            end
        end
    end
    table.insert(self.state.farmingHistory, 1, session)
    while #self.state.farmingHistory > 100 do
        table.remove(self.state.farmingHistory)
    end
    self:QueueSave()
end

function HDG.Store:ClearFarmingHistory()
    self.state.farmingHistory = {}
    self:QueueSave()
end

function HDG.Store:DeleteMostRecentFarmingSession()
    if #self.state.farmingHistory > 0 then
        table.remove(self.state.farmingHistory, 1)  -- Most recent is at index 1
        self:QueueSave()
        return true
    end
    return false
end

-- ============================================================================
-- VENDOR SHOPPING LIST METHODS
-- ============================================================================

function HDG.Store:AddToVendorShoppingList(itemID, npcID)
    if not itemID or not npcID then return false end
    for _, entry in ipairs(self.state.vendorShoppingList) do
        if entry.itemID == itemID and entry.npcID == npcID then return false end -- dedup
    end
    table.insert(self.state.vendorShoppingList, { itemID = itemID, npcID = npcID, addedAt = time() })
    self:QueueSave()
    return true
end

function HDG.Store:RemoveFromVendorShoppingList(itemID, npcID)
    for i = #self.state.vendorShoppingList, 1, -1 do
        local entry = self.state.vendorShoppingList[i]
        if entry.itemID == itemID and entry.npcID == npcID then
            table.remove(self.state.vendorShoppingList, i)
            self:QueueSave()
            return true
        end
    end
    return false
end

function HDG.Store:ClearVendorShoppingList()
    wipe(self.state.vendorShoppingList)
    self:QueueSave()
end

function HDG.Store:IsOnVendorShoppingList(itemID, npcID)
    for _, entry in ipairs(self.state.vendorShoppingList) do
        if entry.itemID == itemID and entry.npcID == npcID then return true end
    end
    return false
end

function HDG.Store:PruneCollectedFromVendorShoppingList()
    if not HDG_Data or not HDG_Data.IsItemCollected then return end
    local changed = false
    for i = #self.state.vendorShoppingList, 1, -1 do
        if HDG_Data.IsItemCollected(self.state.vendorShoppingList[i].itemID) then
            table.remove(self.state.vendorShoppingList, i)
            changed = true
        end
    end
    if changed then self:QueueSave() end
end

function HDG.Store:GetVendorShoppingListCount()
    return #self.state.vendorShoppingList
end

-- ============================================================================
-- LEGACY DISPATCH SUPPORT (for backward compatibility during transition)
-- ============================================================================

HDG.Store.reducers = {}

function HDG.Store:RegisterReducer(action, reducerFn)
    self.reducers[action] = reducerFn
end

function HDG.Store:Dispatch(action, payload)
    if self.state.config.debug then
        print("|cFF14b8a6[HDG Store]|r Dispatching:", action)
    end

    -- Map dispatch calls to new methods
    if action == "SET_CONFIG" and payload.key then
        self:SetConfig(payload.key, payload.value)
    elseif action == "SET_THEME" then
        self:SetTheme(payload.theme)
    elseif action == "SET_FRAME_POSITION" then
        self:SetUI("framePosition", payload.position)
    elseif action == "SET_ACTIVE_TAB" then
        self:SetUI("activeTab", payload.tab)
    elseif action == "SET_PROFESSION_FILTER" then
        self:SetUI("professionFilter", payload.filter)
    elseif action == "SET_CHARACTER_PROFESSION_FILTER" then
        if payload.charKey then
            self.state.ui.characterProfessionFilter = self.state.ui.characterProfessionFilter or {}
            self.state.ui.characterProfessionFilter[payload.charKey] = payload.filter
        end
        self:SetUI("professionFilter", payload.filter)
    elseif action == "SET_COLLAPSED_MATERIAL" then
        self.state.ui.collapsedMaterials[payload.category] = payload.collapsed
        self:QueueSave()
    elseif action == "SET_TRAINER_COLLAPSED" then
        self.state.ui.trainersCollapsed[payload.profession] = payload.collapsed
        self:QueueSave()
    elseif action == "SET_LUMBER_PINNED" then
        self:SetUI("lumberPinned", payload.pinned)
    elseif action == "SET_LUMBER_POSITION" then
        self:SetUI("pinnedLumberPosition", payload.position)
    elseif action == "SET_MINIMAP" and payload.key then
        self:SetMinimap(payload.key, payload.value)
    elseif action == "UPDATE_LAYOUT" then
        self:UpdateLayout(payload.frame, {
            width = payload.width, height = payload.height,
            point = payload.point, relPoint = payload.relPoint,
            x = payload.x, y = payload.y,
        })
    elseif action == "ADD_TO_SHOPPING_LIST" then
        self:AddToShoppingList(payload.item)
    elseif action == "REMOVE_FROM_SHOPPING_LIST" then
        self:RemoveFromShoppingList(payload.itemID)
    elseif action == "UPDATE_SHOPPING_ITEM_QTY" then
        self:UpdateShoppingItemQty(payload.itemID, payload.quantity)
    elseif action == "CLEAR_SHOPPING_LIST" then
        self:ClearShoppingList()
    elseif action == "UPDATE_CHARACTER_DATA" then
        self:UpdateCharacterData(payload.charKey, payload)
    elseif action == "REMOVE_CHARACTER" then
        self:RemoveCharacter(payload.charKey)
    elseif action == "ADD_CRAFTING_HISTORY" then
        self:AddCraftingHistory(payload)
    elseif action == "CLEAR_CRAFTING_HISTORY" then
        self:ClearCraftingHistory()
    elseif action == "ADD_TRACKED_REAGENT" then
        self:AddTrackedReagent(payload.itemID, payload.name, payload.targetQty)
    elseif action == "REMOVE_TRACKED_REAGENT" then
        self:RemoveTrackedReagent(payload.itemID)
    elseif action == "UPDATE_TRACKED_REAGENT" then
        self:UpdateTrackedReagent(payload.itemID, payload.targetQty)
    elseif action == "CLEAR_TRACKED_REAGENTS" then
        self:ClearTrackedReagents()
    elseif action == "ADD_LUMBER_COORDINATE" then
        self:AddLumberCoordinate(payload.node)
    elseif action == "SET_LUMBER_COORDINATES" then
        self:SetLumberCoordinates(payload.coordinates)
    elseif action == "CLEAR_LUMBER_COORDINATES" then
        self:ClearLumberCoordinates()
    elseif action == "UPSERT_FARMING_SESSION" then
        self:UpsertFarmingSession(payload.session)
    elseif action == "CLEAR_FARMING_HISTORY" then
        self:ClearFarmingHistory()
    elseif action == "DELETE_MOST_RECENT_FARMING_SESSION" then
        self:DeleteMostRecentFarmingSession()
    elseif action == "ADD_TO_VENDOR_SHOPPING_LIST" then
        self:AddToVendorShoppingList(payload.itemID, payload.npcID)
    elseif action == "REMOVE_FROM_VENDOR_SHOPPING_LIST" then
        self:RemoveFromVendorShoppingList(payload.itemID, payload.npcID)
    elseif action == "CLEAR_VENDOR_SHOPPING_LIST" then
        self:ClearVendorShoppingList()
    else
        -- Fallback to legacy reducer if exists
        local reducer = self.reducers[action]
        if reducer then
            local newState = reducer(self.state, payload)
            if newState then self.state = newState end
            self:QueueSave()
        elseif self.state.config.debug then
            print("|cFFdc322f[HDG Store]|r Unknown action:", action)
        end
    end

    -- Trigger EventBus for listeners (backward compat)
    if HDG.EventBus then
        HDG.EventBus:Trigger("HDG_STATE_CHANGED", { action = action, state = self.state })
    end
end

-- Expose DeepCopy for other modules
HDG.Store.DeepCopy = DeepCopy
