-- Copyright (c) 2024-2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
--
-- 使用 ORM 对象管理 NetworkAdapterPreload，属性赋值即触发持久化，无需 db:select/save。

local base_messages = require 'messages.base'
local log = require 'mc.logging'
local util = require 'config_mgmt.import_export_util'

local c_device_manager = require 'device.device_manager'
local c_network_adapter_preload = require 'device.class.network_adapter_preload'

local M = {}

local CLASS_NAME = 'NetworkAdapterPreload'
local LOOKUP_KEY = 'NodeId'

-- 可导入属性配置：属性名 -> 处理方式
-- true: 直接赋值 obj[prop_name] = new_val
-- function(obj, new_val, ctx): 自定义处理
local function import_port_count(obj, ctx, new_val)
    c_device_manager.get_instance():set_preload_port_count(obj, ctx, new_val)
end

local IMPORTABLE_PROPS = {
    PortCount = import_port_count,
}

-- 导出属性列表（MDS 配置保证属性非 nil）
local EXPORT_PROPS = { 'NodeId', 'PortCount', 'PortCountAllowableValues' }

function M.new()
    return setmetatable({}, {__index = M})
end

local function apply_import(obj, prop_name, new_val, handler, ctx)
    if handler == true then
        obj[prop_name] = new_val
        return true
    end
    return handler(obj, ctx, new_val)
end

local function process_import_prop(obj, initiator, ctx, prop_name, prop_val)
    if prop_name == LOOKUP_KEY then return end
    if not prop_val or not util.should_import(prop_val, obj[prop_name]) then return end
    local handler = IMPORTABLE_PROPS[prop_name]
    if not handler then
        log:error('[network_adapter] import preload: unknown property %s, skip', prop_name)
        return
    end
    local new_val = prop_val['Value']
    -- set_preload_port_count 等自定义处理函数内部已记录操作日志，此处不再重复记录
    pcall(apply_import, obj, prop_name, new_val, handler, ctx)
end

function M:import(ctx, obj_prop_list)
    local lookup_val = obj_prop_list and obj_prop_list[LOOKUP_KEY]
    if not lookup_val or not lookup_val['Value'] then
        log:error('[network_adapter] import preload: %s required', LOOKUP_KEY)
        error(base_messages.PropertyUnknown(CLASS_NAME .. '/' .. LOOKUP_KEY))
    end
    local node_id = lookup_val['Value']

    local obj = c_network_adapter_preload.collection:find({[LOOKUP_KEY] = node_id})
    if not obj then
        log:warning('[network_adapter] import preload: %s=%s not found', LOOKUP_KEY, node_id)
        return
    end

    local initiator = util.get_initiator(ctx)
    for prop_name, prop_val in pairs(obj_prop_list) do
        process_import_prop(obj, initiator, ctx, prop_name, prop_val)
    end
end

function M:export()
    local result = {}
    c_network_adapter_preload.collection:fold(function(_, obj)
        local item = {}
        for _, prop_name in ipairs(EXPORT_PROPS) do
            item[prop_name] = obj[prop_name]
        end
        table.insert(result, item)
    end)
    return result
end

return M
