-- 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 lu = require 'luaunit'
local skynet = require 'skynet'

TestLedPolicy = {}

function TestLedPolicy:setUp()
    -- mock skynet.fork
    self.original_fork = skynet.fork
    skynet.fork = function(cb) cb() end

    -- mock led_service
    self.last_health_status = nil
    local mock_led_instance = {
        set_led_by_sys_health = function(_, health)
            self.last_health_status = health
        end,
        sys_obj_ready = {
            on = function(_, cb)
                self.sys_obj_ready_callback = cb
            end
        }
    }
    local mock_led_service = {
        get_instance = function() return mock_led_instance end
    }

    -- mock client
    self.event_health = 'Normal'
    self.sensor_health = 'Normal'
    local mock_client = {
        GetEventsObjects = function()
            return { ['/bmc/kepler/Systems/1/Events'] = { Health = self.event_health } }
        end,
        GetSensorsObjects = function()
            return { ['/bmc/kepler/Chassis/1/Sensors'] = { Health = self.sensor_health } }
        end,
        OnEventsPropertiesChanged = function(cb, _)
            self.events_callback = cb
        end,
        OnSensorsPropertiesChanged = function(cb, _)
            self.sensors_callback = cb
        end
    }

    package.loaded['led_service'] = mock_led_service
    package.loaded['chassis.client'] = mock_client
    package.loaded['led_policy_service'] = nil
    self.led_policy_service = require 'led_policy_service'
end

function TestLedPolicy:tearDown()
    skynet.fork = self.original_fork
end

-- 测试execute_once_strategy函数
function TestLedPolicy:test_execute_once_strategy()
    local service = self.led_policy_service.new()
    service.led_policy_obj = {
        SeverityReferenceSource = 'Event'
    }

    -- 测试execute_once_strategy不会崩溃
    local ok = pcall(function()
        service:execute_once_strategy()
    end)
    lu.assertEquals(ok, true, 'execute_once_strategy应该成功执行')

    -- 验证健康状态被设置
    lu.assertEquals(self.last_health_status, 'Normal', '健康状态应该被正确设置')
end

-- 测试不同健康状态
function TestLedPolicy:test_different_health_statuses()
    local service = self.led_policy_service.new()
    service.led_policy_obj = {
        SeverityReferenceSource = 'Event'
    }

    local healths = { 'Normal', 'Minor', 'Major', 'Critical' }
    for _, h in ipairs(healths) do
        self.event_health = h
        service:execute_once_strategy()
        lu.assertEquals(self.last_health_status, h, '健康状态 ' .. h .. ' 应该被正确处理')
    end
end

-- 测试健康状态获取失败
function TestLedPolicy:test_health_status_failure()
    local service = self.led_policy_service.new()
    service.led_policy_obj = {
        SeverityReferenceSource = 'Event'
    }

    self.event_health = nil
    service:execute_once_strategy()
    lu.assertNil(self.last_health_status, '健康状态获取失败时不应该设置LED状态')
end