-- Copyright (c) 2024 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 lu = require 'luaunit'
local file_sec = require 'utils.file'
local fan_service = require 'fan_service'
local c_fan_object = require 'fan_object'
local c_fan_type_object = require 'fan_type_object'
local client = require 'thermal_mgmt.client'

TestFanService = {}

function TestFanService:test_get_dump_pwm_by_fan_obj()
    local fan_obj1 = {
        HardwarePWM = 66,
        PowerGood = 1,
        standbyfan = false
    }
    local fan_obj2 = {
        HardwarePWM = 66,
        PowerGood = 0,
        standbyfan = true
    }
    local fan_obj3 = {
        HardwarePWM = 66,
        PowerGood = 0,
        standbyfan = false
    }

    local pwm = fan_service.get_dump_pwm_by_fan_obj(fan_obj1)
    lu.assertEquals(pwm, 66)
    pwm = fan_service.get_dump_pwm_by_fan_obj(fan_obj2)
    lu.assertEquals(pwm, 66)
    pwm = fan_service.get_dump_pwm_by_fan_obj(fan_obj3)
    lu.assertEquals(pwm, 0)
end

function TestFanService:test_dump_obj_infos()
    local path = "/tmp/test.txt"
    local fp_w = file_sec.open_s(path, 'w+')

    local fan_objs = {
        {['ObjectNmae'] = "Fan_1",
         ['FanId'] = 1,
         ['RearStatus'] =  0,
         ['FrontStatus'] =  0,
         get_all_prop_names = function(...) return {} end
        }
    }
    c_fan_object.collection.fold = function (_, func, acc)
        local exit_loop = false
        for _, fan_obj in pairs(fan_objs) do
            acc, exit_loop = func(acc, fan_obj)
            if exit_loop then
                break
            end
        end
        return acc
    end

    local fan_type_objs = {
        {['ObjectNmae'] = "Fan_type_1",
         get_all_prop_names = function(...) return {} end
        }
    }
    c_fan_type_object.collection.fold = function (_, func, acc)
        local exit_loop = false
        for _, fan_type_obj in pairs(fan_type_objs) do
            acc, exit_loop = func(acc, fan_type_obj)
            if exit_loop then
                break
            end
        end
        return acc
    end
    local ok = pcall(fan_service.dump_obj_infos, fan_service, fp_w)
    lu.assertTrue(ok)
end

function TestFanService:test_fan_board_listenning()
    local origin = client.OnUnitPropertiesChanged
    client.OnUnitPropertiesChanged = function(self, cb)
        cb('', '', '')
    end
    fan_service.listener = {}
    local ok = pcall(fan_service.fan_board_listenning, fan_service, '', '')
    lu.assertTrue(ok)
    client.OnUnitPropertiesChanged = origin
end

-- 测试单转子风扇转子异常场景
function TestFanService:test_single_rotator_abnormal()
    local fan_service_obj = fan_service.new()

    -- 创建单转子风扇，后转子异常
    local fan_obj = {
        FanId = 1,
        IsTwins = false,
        RearStatus = 2,  -- 异常状态
        FrontStatus = 0,
        ExpectedPWM = 128,
        get_max_supported_pwm = function(self)
            return 255
        end
    }

    -- Mock c_fan_object.collection.fold
    local original_fold = c_fan_object.collection.fold
    c_fan_object.collection.fold = function(_, func, acc)
        acc = func(acc, fan_obj)
        return acc
    end

    -- Mock basic_cooling_config和c_fan_group_policy的collection.fold
    local basic_cooling_config = require 'basic_cooling_config'
    local c_fan_group_policy = require 'fan_group_policy_object'
    local original_basic_fold = basic_cooling_config.collection.fold
    local original_policy_fold = c_fan_group_policy.collection.fold
    basic_cooling_config.collection.fold = function(_, func, acc)
        return acc
    end
    c_fan_group_policy.collection.fold = function(_, func, acc)
        return acc
    end

    -- 初始转速表（l_pwm[0]不等于1，确保执行转速调整逻辑）
    local l_pwm = {[0] = 0, [1] = 50}  -- 初始设置为50%

    -- 调用fan_group_speed_adjust
    l_pwm = fan_service_obj:fan_group_speed_adjust(l_pwm)

    -- 验证：单转子风扇后转子异常时，l_pwm应该被设置为ExpectedPWM对应的百分比
    -- ExpectedPWM=128, MaxSupportedPWM=255, 百分比 = 128/255*100 = 50.19... ≈ 50
    local expected_pwm_percent = math.floor((128 / 255 * 100) + 0.5)
    lu.assertEquals(l_pwm[1], expected_pwm_percent, "单转子风扇后转子异常时，应该使用ExpectedPWM对应的百分比")

    -- 恢复原始函数
    c_fan_object.collection.fold = original_fold
    basic_cooling_config.collection.fold = original_basic_fold
    c_fan_group_policy.collection.fold = original_policy_fold
end

-- 测试双转子风扇单转子异常场景
function TestFanService:test_dual_rotator_single_abnormal()
    local fan_service_obj = fan_service.new()

    -- 创建双转子风扇，仅单转子异常（前转子异常，后转子正常）
    local fan_obj = {
        FanId = 1,
        IsTwins = true,
        RearStatus = 0,  -- 正常
        FrontStatus = 2,  -- 异常
        ExpectedPWM = 128,
        get_max_supported_pwm = function(self)
            return 255
        end
    }

    -- Mock c_fan_object.collection.fold
    local original_fold = c_fan_object.collection.fold
    c_fan_object.collection.fold = function(_, func, acc)
        acc = func(acc, fan_obj)
        return acc
    end

    -- Mock basic_cooling_config和c_fan_group_policy的collection.fold
    local basic_cooling_config = require 'basic_cooling_config'
    local c_fan_group_policy = require 'fan_group_policy_object'
    local original_basic_fold = basic_cooling_config.collection.fold
    local original_policy_fold = c_fan_group_policy.collection.fold
    basic_cooling_config.collection.fold = function(_, func, acc)
        return acc
    end
    c_fan_group_policy.collection.fold = function(_, func, acc)
        return acc
    end

    -- 初始转速表
    local l_pwm = {[1] = 50}  -- 初始设置为50%
    local original_pwm = l_pwm[1]

    -- 调用fan_group_speed_adjust
    l_pwm = fan_service_obj:fan_group_speed_adjust(l_pwm)

    -- 验证：双转子风扇仅单转子异常时，l_pwm不应该被修改，正常进行转速下发
    lu.assertEquals(l_pwm[1], original_pwm, "双转子风扇仅单转子异常时，应该正常进行转速下发，不修改l_pwm")

    -- 恢复原始函数
    c_fan_object.collection.fold = original_fold
    basic_cooling_config.collection.fold = original_basic_fold
    c_fan_group_policy.collection.fold = original_policy_fold
end

-- 测试双转子风扇双转子异常场景
function TestFanService:test_dual_rotator_abnormal()
    local fan_service_obj = fan_service.new()

    -- 创建双转子风扇，双转子都异常
    local fan_obj = {
        FanId = 1,
        IsTwins = true,
        RearStatus = 2,  -- 异常
        FrontStatus = 2,  -- 异常
        ExpectedPWM = 128,
        get_max_supported_pwm = function(self)
            return 255
        end
    }

    -- Mock c_fan_object.collection.fold
    local original_fold = c_fan_object.collection.fold
    c_fan_object.collection.fold = function(_, func, acc)
        acc = func(acc, fan_obj)
        return acc
    end

    -- Mock basic_cooling_config和c_fan_group_policy的collection.fold
    local basic_cooling_config = require 'basic_cooling_config'
    local c_fan_group_policy = require 'fan_group_policy_object'
    local original_basic_fold = basic_cooling_config.collection.fold
    local original_policy_fold = c_fan_group_policy.collection.fold
    basic_cooling_config.collection.fold = function(_, func, acc)
        return acc
    end
    c_fan_group_policy.collection.fold = function(_, func, acc)
        return acc
    end

    -- 初始转速表（l_pwm[0]不等于1，确保执行转速调整逻辑）
    local l_pwm = {[0] = 0, [1] = 50}  -- 初始设置为50%

    -- 调用fan_group_speed_adjust
    l_pwm = fan_service_obj:fan_group_speed_adjust(l_pwm)

    -- 验证：双转子风扇双转子都异常时，l_pwm应该被设置为ExpectedPWM对应的百分比
    local expected_pwm_percent = math.floor((128 / 255 * 100) + 0.5)
    lu.assertEquals(l_pwm[1], expected_pwm_percent, "双转子风扇双转子都异常时，应该使用ExpectedPWM对应的百分比")

    -- 恢复原始函数
    c_fan_object.collection.fold = original_fold
    basic_cooling_config.collection.fold = original_basic_fold
    c_fan_group_policy.collection.fold = original_policy_fold
end

-- 测试风扇转子正常场景
function TestFanService:test_rotator_normal()
    local fan_service_obj = fan_service.new()

    -- 创建双转子风扇，双转子都正常
    local fan_obj = {
        FanId = 1,
        IsTwins = true,
        RearStatus = 0,  -- 正常
        FrontStatus = 0,  -- 正常
        ExpectedPWM = 128,
        get_max_supported_pwm = function(self)
            return 255
        end
    }

    -- Mock c_fan_object.collection.fold
    local original_fold = c_fan_object.collection.fold
    c_fan_object.collection.fold = function(_, func, acc)
        acc = func(acc, fan_obj)
        return acc
    end

    -- Mock basic_cooling_config和c_fan_group_policy的collection.fold
    local basic_cooling_config = require 'basic_cooling_config'
    local c_fan_group_policy = require 'fan_group_policy_object'
    local original_basic_fold = basic_cooling_config.collection.fold
    local original_policy_fold = c_fan_group_policy.collection.fold
    basic_cooling_config.collection.fold = function(_, func, acc)
        return acc
    end
    c_fan_group_policy.collection.fold = function(_, func, acc)
        return acc
    end

    -- 初始转速表
    local l_pwm = {[1] = 50}  -- 初始设置为50%
    local original_pwm = l_pwm[1]

    -- 调用fan_group_speed_adjust
    l_pwm = fan_service_obj:fan_group_speed_adjust(l_pwm)

    -- 验证：风扇正常时，l_pwm不应该被修改，正常进行转速下发
    lu.assertEquals(l_pwm[1], original_pwm, "风扇转子正常时，应该正常进行转速下发，不修改l_pwm")

    -- 恢复原始函数
    c_fan_object.collection.fold = original_fold
    basic_cooling_config.collection.fold = original_basic_fold
    c_fan_group_policy.collection.fold = original_policy_fold
end