local addonName, addon = ...

addon.UserData = addon.UserData or {}

local UserData = addon.UserData

local function DeepCopyMissing(target, source)
    if type(target) ~= "table" or type(source) ~= "table" then
        return
    end

    for key, value in pairs(source) do
        if target[key] == nil then
            if type(value) == "table" then
                local copy = {}
                DeepCopyMissing(copy, value)
                target[key] = copy
            else
                target[key] = value
            end
        elseif type(target[key]) == "table" and type(value) == "table" then
            DeepCopyMissing(target[key], value)
        end
    end
end

local function EnsureRoots()
    WhatsNextUserData = type(WhatsNextUserData) == "table" and WhatsNextUserData or {}
    WhatsNextCache = type(WhatsNextCache) == "table" and WhatsNextCache or {}
end

local function MigrateLegacy()
    EnsureRoots()

    -- Versions <= 0.18.x stored user state and runtime caches together in
    -- WhatsNextDB.  Keep the legacy variable in the TOC only so old installs
    -- can be migrated once.  New code never writes to it.
    if type(WhatsNextDB) ~= "table" then
        return
    end

    local legacy = WhatsNextDB

    -- User-authored / user-specific persistent state.
    local userCopy = {}
    for key, value in pairs(legacy) do
        if key ~= "lootTrackerEnglishNames"
            and key ~= "lootTrackerEnglishBuilder"
        then
            if type(value) == "table" then
                local copy = {}
                DeepCopyMissing(copy, value)
                userCopy[key] = copy
            else
                userCopy[key] = value
            end
        end
    end

    -- Profession scan data is a rebuildable client cache, not user content.
    if type(userCopy.lootTracker) == "table" then
        userCopy.lootTracker.professionRecipes = nil
        userCopy.lootTracker.professionScan = nil
    end

    DeepCopyMissing(WhatsNextUserData, userCopy)

    -- Rebuildable/runtime caches get their own SavedVariables root.
    if type(legacy.lootTracker) == "table" then
        if type(legacy.lootTracker.professionRecipes) == "table"
            and WhatsNextCache.professionRecipes == nil
        then
            WhatsNextCache.professionRecipes = legacy.lootTracker.professionRecipes
        end

        if type(legacy.lootTracker.professionScan) == "table"
            and WhatsNextCache.professionScan == nil
        then
            WhatsNextCache.professionScan = legacy.lootTracker.professionScan
        end
    end

    if type(legacy.lootTrackerEnglishNames) == "table"
        and WhatsNextCache.englishNames == nil
    then
        WhatsNextCache.englishNames = legacy.lootTrackerEnglishNames
    end

    if type(legacy.lootTrackerEnglishBuilder) == "table"
        and WhatsNextCache.englishBuilder == nil
    then
        WhatsNextCache.englishBuilder = legacy.lootTrackerEnglishBuilder
    end

    WhatsNextUserData.migration = WhatsNextUserData.migration or {}
    WhatsNextUserData.migration.legacyWhatsNextDB = true
    WhatsNextUserData.migration.completedAt = WhatsNextUserData.migration.completedAt or time()

    -- Important: keep the old global nil so it is not written back as a
    -- duplicate SavedVariable. It remains listed in the TOC only for upgrades
    -- from old releases.
    WhatsNextDB = nil
end

function UserData:Initialize()
    MigrateLegacy()
    EnsureRoots()

    WhatsNextUserData.schema = tonumber(WhatsNextUserData.schema) or 1
    WhatsNextCache.schema = tonumber(WhatsNextCache.schema) or 1
end

function UserData:Get()
    EnsureRoots()
    return WhatsNextUserData
end

function UserData:GetCache()
    EnsureRoots()
    return WhatsNextCache
end

UserData:Initialize()
