local NS = rawget(_G, "MCDVoiceCooldownNS") or {}
_G.MCDVoiceCooldownNS = NS

NS.ImportFullProcessor = NS.ImportFullProcessor or {}

local Processor = NS.ImportFullProcessor
local CONST = NS.Constants or {}
local CollectionStore = NS.CollectionStore or {}
local ImportExportUtil = NS.ImportExportUtil or {}
local ImportEntryProcessor = NS.ImportEntryProcessor or {}

local ALL_CLASSES_ID = CONST.ALL_CLASSES_ID or 0
local ALL_SPECS_ID = CONST.ALL_SPECS_ID or 0

local function GetApi()
    return NS.API
end

local function EnsureRootDB()
    if CollectionStore.EnsureRootDB then
        return CollectionStore.EnsureRootDB()
    end
    if type(MCDVoiceCooldownDB) ~= "table" then
        MCDVoiceCooldownDB = {}
    end
    return MCDVoiceCooldownDB
end

local function EnsureSavedListOrderDB()
    local db = EnsureRootDB()
    if type(db.savedListOrder) ~= "table" then
        db.savedListOrder = {}
    end
    if type(db.savedListOrder.loaded) ~= "table" then
        db.savedListOrder.loaded = {}
    end
    if type(db.savedListOrder.unloaded) ~= "table" then
        db.savedListOrder.unloaded = {}
    end
    return db.savedListOrder
end

local function NormalizeCollectionScope(scope, entryMap, scopeClassID, scopeSpecID)
    if CollectionStore.NormalizeCollectionScope then
        return CollectionStore.NormalizeCollectionScope(scope, entryMap, scopeClassID, scopeSpecID, GetApi())
    end
    return scope
end

local function DeepCopyTable(value, seen)
    if ImportExportUtil and type(ImportExportUtil.DeepCopyTable) == "function" then
        return ImportExportUtil:DeepCopyTable(value, seen)
    end
    return value
end

local function SanitizeEntryForImport(entry)
    if ImportExportUtil and type(ImportExportUtil.SanitizeEntryForImport) == "function" then
        return ImportExportUtil:SanitizeEntryForImport(entry)
    end
    return nil
end

local function ClearDeletedEntryMarker(classID, specID, entry, index)
    local api = GetApi()
    if api and type(api.ClearEntryDeletedMarker) == "function" then
        api.ClearEntryDeletedMarker(classID, specID, entry, index)
    end
end

local function FindMatchingEntryIndexBySpell(map, spellId, entryType, objectType)
    if ImportEntryProcessor and type(ImportEntryProcessor.FindMatchingEntryIndexBySpell) == "function" then
        return ImportEntryProcessor:FindMatchingEntryIndexBySpell(map, spellId, entryType, objectType)
    end
    return nil
end

function Processor:Import(payload)
    local api = GetApi()
    if not api then
        return false, 0
    end
    local db = EnsureRootDB()
    if type(db.specConfigs) ~= "table" then
        db.specConfigs = {}
    end
    local importedRoot = type(payload.specConfigs) == "table" and payload.specConfigs or {}
    local importedCount = 0

    for classIDKey, classMap in pairs(importedRoot) do
        local classID = tonumber(classIDKey)
        if classID and classID >= 0 and type(classMap) == "table" then
            if type(db.specConfigs[classID]) ~= "table" then
                db.specConfigs[classID] = {}
            end
            for specIDKey, importedMap in pairs(classMap) do
                local specID = tonumber(specIDKey)
                if specID and specID >= 0 and type(importedMap) == "table" then
                    if classID == ALL_CLASSES_ID then
                        specID = ALL_SPECS_ID
                    end
                    local oldMap = db.specConfigs[classID][specID]
                    if type(oldMap) ~= "table" then
                        oldMap = {}
                    end
                    local usedOld = {}
                    local newMap = {}
                    local importedIndices = {}
                    for index, entry in pairs(importedMap) do
                        index = tonumber(index) or 0
                        if index > 0 and type(entry) == "table" and (tonumber(entry.spellId) or 0) > 0 then
                            importedIndices[#importedIndices + 1] = index
                        end
                    end
                    table.sort(importedIndices)
                    for _, index in ipairs(importedIndices) do
                        local sanitized = SanitizeEntryForImport(importedMap[index])
                        if sanitized then
                            local oldIndex = FindMatchingEntryIndexBySpell(oldMap, sanitized.spellId, sanitized.entryType, sanitized.objectType)
                            if oldIndex then
                                usedOld[oldIndex] = true
                            end
                            ClearDeletedEntryMarker(classID, specID, sanitized, index)
                            newMap[index] = sanitized
                            importedCount = importedCount + 1
                        end
                    end
                    local oldIndices = api.GetOrderedEntryIndices(oldMap)
                    for _, oldIndex in ipairs(oldIndices) do
                        if not usedOld[oldIndex] then
                            local oldEntry = api.GetEntry(oldMap, oldIndex)
                            local sanitizedOld = SanitizeEntryForImport(oldEntry)
                            if sanitizedOld then
                                local targetIndex = oldIndex
                                while type(newMap[targetIndex]) == "table" and (tonumber(newMap[targetIndex].spellId) or 0) > 0 do
                                    targetIndex = targetIndex + 1
                                end
                                ClearDeletedEntryMarker(classID, specID, sanitizedOld, targetIndex)
                                newMap[targetIndex] = sanitizedOld
                            end
                        end
                    end
                    db.specConfigs[classID][specID] = newMap
                end
            end
        end
    end

    if type(payload.collectionData) == "table" then
        if type(db.collectionData) ~= "table" then
            db.collectionData = {}
        end
        for classIDKey, classMap in pairs(payload.collectionData) do
            local classID = tonumber(classIDKey)
            if classID and classID >= 0 and type(classMap) == "table" then
                if type(db.collectionData[classID]) ~= "table" then
                    db.collectionData[classID] = {}
                end
                for specIDKey, scope in pairs(classMap) do
                    local specID = tonumber(specIDKey)
                    if specID and specID >= 0 and type(scope) == "table" then
                        if classID == ALL_CLASSES_ID then
                            specID = ALL_SPECS_ID
                        end
                        db.collectionData[classID][specID] = DeepCopyTable(scope)
                        NormalizeCollectionScope(db.collectionData[classID][specID], api.GetStoredEntryMap(classID, specID), classID, specID)
                    end
                end
            end
        end
    end

    if type(payload.savedListOrder) == "table" then
        db.savedListOrder = DeepCopyTable(payload.savedListOrder)
    end
    EnsureSavedListOrderDB()

    if type(payload.bloodlustConfig) == "table" then
        db.bloodlustConfig = DeepCopyTable(payload.bloodlustConfig)
    end
    db.collectionSerial = math.max(tonumber(db.collectionSerial) or 0, tonumber(payload.collectionSerial) or 0)
    return true, importedCount
end
