-- 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 mdb_service = require 'mc.mdb.mdb_service'
local log = require 'mc.logging'

local ETH_OBJ_PATH<const> = '/bmc/kepler/Managers/1/EthernetInterfaces'
local ETH_OBJ_INTERFACE<const> = 'bmc.kepler.Managers.EthernetInterfaces'
local ETH_GROUP_INTERFACE<const> = 'bmc.kepler.Managers.EthernetInterfaces.EthGroup'

local m = {}

local function create_base_setting()
    local setting = {
        IsGroupIdValid = false,
        EthernetInterfaces = {
            Path = "",
            Interface = "",
            PortId = "PortId",
            VLANEnable = "VLANEnable"
        },
        Ipv4 = {
            Path = "",
            Interface = "",
            SetDefaultGateway = "SetDefaultGateway"
        },
        Ipv6 = {
            Path = "",
            Interface = "",
            IpMode = "IpMode",
            IpAddr = "IpAddr",
            DefaultGateway = "DefaultGateway",
            SetIpAddr = "SetIpAddr",
            SetDefaultGateway = "SetDefaultGateway"
        }
    }
    return setting
end

-- 获取和当前group_id匹配的ethGroup资源树对象
local function get_group_id_patched_ethgroup_object(group_id, sorted_ethGroup_objs)
    if group_id > 1 and sorted_ethGroup_objs and sorted_ethGroup_objs[group_id - 1]  then
        return sorted_ethGroup_objs[group_id - 1]
    end

    return nil
end

local function patch_group_id_to_ethgroup(group_id, eth_group_setting)
    local ok, rsp = pcall(mdb_service.get_sub_paths, bus, ETH_OBJ_PATH .. "/EthGroup", 1, {ETH_GROUP_INTERFACE})

    if not ok then
        log:debug('Incorrect parent path or interface')
        return false
    end

    local ethGroup_objs = {}
    for _, sub_path in pairs(rsp.SubPaths) do
        local ok, ethGroup_obj = pcall(mdb.get_object, bus, sub_path, ETH_GROUP_INTERFACE)
        if ok and ethGroup_obj.OutType == 2 and ethGroup_obj.Status then
            table.insert(ethGroup_objs, ethGroup_obj)
        end
    end

    if ethGroup_objs ~= nil then
        table.sort(ethGroup_objs, function(a, b)
            return a.GroupId < b.GroupId
        end)

        local ethGroup_obj = get_group_id_patched_ethgroup_object(group_id, ethGroup_objs)
        if ethGroup_obj ~= nil then
            eth_group_setting.EthernetInterfaces.Path = ethGroup_obj.path
            eth_group_setting.EthernetInterfaces.Interface = ETH_GROUP_INTERFACE
            eth_group_setting.EthernetInterfaces.PortId = "ActivePortId"
            eth_group_setting.EthernetInterfaces.VLANEnable = "VLANEnabled"
            eth_group_setting.Ipv4.Path = ethGroup_obj.path
            eth_group_setting.Ipv4.Interface = ETH_GROUP_INTERFACE
            eth_group_setting.Ipv6.Path = ethGroup_obj.path
            eth_group_setting.Ipv6.Interface = ETH_GROUP_INTERFACE
            eth_group_setting.Ipv6.IpMode = "Ipv6Mode" 
            eth_group_setting.Ipv6.IpAddr = "Ipv6Addr"
            eth_group_setting.Ipv6.DefaultGateway = "Ipv6DefaultGateway"
            eth_group_setting.Ipv6.SetIpAddr = "SetIpv6Addr"
            eth_group_setting.Ipv6.SetDefaultGateway = "SetIpv6DefaultGateway"
            return true
        end
    end
end

function m.patch_eth_info(group_id)
    if not group_id or group_id == 1 then
        local mdb_setting = create_base_setting()
        mdb_setting.EthernetInterfaces.Path = ETH_OBJ_PATH
        mdb_setting.EthernetInterfaces.Interface = ETH_OBJ_INTERFACE
        mdb_setting.Ipv4.Path = ETH_OBJ_PATH .. "/Ipv4"
        mdb_setting.Ipv4.Interface = ETH_OBJ_INTERFACE ..".Ipv4"
        mdb_setting.Ipv6.Path = ETH_OBJ_PATH .. "/Ipv6"
        mdb_setting.Ipv6.Interface = ETH_OBJ_INTERFACE ..".Ipv6"
        mdb_setting.IsGroupIdValid = true
        return mdb_setting
    end

    -- 符合EthGroup的group_id 
    local eth_group_setting = create_base_setting()
    if patch_group_id_to_ethgroup(group_id, eth_group_setting) then
        eth_group_setting.IsGroupIdValid = true
        return eth_group_setting
    end

    return create_base_setting()
end

return m