-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the 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.

local log = require 'mc.logging'
local mdb_service = require 'mc.mdb.mdb_service'
local custom_messages = require 'messages.custom'

local m = {}

function m.get_multihost_fru_list(system_ids)
    local real_path, sub_paths
    local result_paths = {}

    -- 未输入system_ids时，默认为1
    if system_ids == nil then
        system_ids = { "1" }
    end

    for idx, system_id in ipairs(system_ids) do
        result_paths[idx] = ""
        real_path = '/bmc/kepler/Systems/' .. tostring(system_id) .. '/FruCtrl'
        sub_paths = mdb_service.get_sub_paths(bus, real_path, 1, { 'bmc.kepler.Systems.FruCtrl' }).SubPaths
        if type(sub_paths) ~= 'table' then
            goto continue
        end

        table.sort(sub_paths)
        for _, v in ipairs(sub_paths) do
            -- interface参数为空或者父资源有相同的interface，GetSubPaths返回结果会包含父资源树路径，此处需要剔除父资源树
            if v ~= real_path then
                -- FruCtrl子路径只需要第一个合法值
                result_paths[idx] = v
                break
            end
        end
        ::continue::
    end
    return result_paths
end

function m.is_valid_system_ids(system_ids)
    local path
    local ok, rsp

    -- 未输入system_ids时，默认为1
    if system_ids == nil then
        system_ids = { "1" }
    end

    for _, system_id in ipairs(system_ids) do
        path = '/bmc/kepler/Systems/' .. system_id
        ok, rsp = pcall(mdb_service.is_valid_path, bus, path)
        if not ok or not rsp.Result then
            log:error('Invalid SystemId(%s), err(%s)', system_id, rsp.message)
            error(custom_messages.ActionParameterValueInvalid(system_id, 'SystemId'))
        end
    end

    return rsp.Result
end

local function is_valid_system_id(id)
    local path = '/bmc/kepler/Systems/' .. id

    local ok, rsp = pcall(mdb_service.is_valid_path, bus, path)
    if not ok then
        log:error('Invalid SystemId(%s), err(%s)', id, rsp.message)
        error(rsp)
    end

    return rsp.Result
end

local function valid_system_id(v)
    local err
    if v.SystemId == nil then
        err = base_messages.PropertyMissing('SystemId')
        err.RelatedProperties = { '#/Systems', '#/SystemId' }
        error(err)
    end

    if not is_valid_system_id(v.SystemId) then
        err = custom_messages.ActionParameterValueInvalid(v.SystemId, 'SystemId')
        err.RelatedProperties = { '#/Systems', '#/SystemId' }
        error(err)
    end
end

function m.get_req_bios_attributes(systems)
    local result = {}
    local data
    local err

    for _, v in ipairs(systems) do
        valid_system_id(v)

        data = cjson.json_object_new_object()
        if v.BiosSettings ~= nil and v.BiosSettings.Attributes ~= nil then
            if not cjson.json_object_is_object(v.BiosSettings.Attributes) then
                err = base_messages.PropertyValueTypeError(v.BiosSettings.Attributes, 'Attributes')
                err.RelatedProperties = { '#/Systems', '#/Attributes' }
                error(err)
            end

            data['Attributes'] = v.BiosSettings.Attributes
            table.insert(result, {
                Param = cjson.json_object_ordered_encode(data),
                Path = '/bmc/kepler/Systems/' .. v.SystemId .. '/Bios'
            })
        end
    end

    return result
end

function m.get_req_bootoptions(systems, req_prop)
    local result = {}

    for _, v in ipairs(systems) do
        valid_system_id(v)

        if v.Boot ~= nil and v.Boot[req_prop] ~= nil then
            table.insert(result,
                { Param = v.Boot[req_prop], Path = '/bmc/kepler/Systems/' .. v.SystemId .. '/BootOptions' })
        end
    end

    return result
end

return m
