local lu = require 'luaunit'
local c_drive = require 'drive.drive_object'
local c_storageconfig = require 'storageconfig.storageconfig_object'

local hook_tasks = require 'hook_tasks'

TEST_Drive_Object = {}

function TEST_Drive_Object:setUp()
    self.tasks = hook_tasks:hook()
end

function TEST_Drive_Object:tearDown()
    hook_tasks.unhook()
end

function TEST_Drive_Object:test_monitor_fault_state()
    local config = c_storageconfig.new({bus = 0, db = 1})
    config.all_ctrl_loaded = false
    local obj = {
        new_task = function(...) return {
            loop = function(obj, cb)
                cb(1)
                return {set_timeout_ms = function(...) return end}
            end
        } end,
        Protocol = 3,
        RefControllerId = 0,
        Presence = 0,
        LocateLed = 0,
        FaultLed = 1,
        InAFailedArray = 2,
        cont_bin = {
            get_debounced_val = function(i, n) return n end
        },
        FirmwareStatusError = true
    }
    c_drive.monitor_fault_state(obj)
    lu.assertEquals(obj.InAFailedArray, 1)
    obj.Presence = 1
    c_drive.monitor_fault_state(obj)
    lu.assertEquals(obj.InAFailedArray, 0)
end

function TEST_Drive_Object:test_nvme_identified()
    local config = c_storageconfig.new({bus = 0, db = 1})
    config.all_ctrl_loaded = false
    local obj = {
        stop_task = function(...) return {
            loop = function(obj, cb)
                cb(1)
                return {set_timeout_ms = function(...) return end}
            end
        } end,
        set_default_values = function()
        end,
        set_presence = function()
        end
    }
    c_drive.nvme_identified(obj)
    lu.assertEquals(obj.SerialNumber, 'N/A')
end

-- 测试nvme_static_identified函数 - 全量覆盖
function TEST_Drive_Object:test_nvme_static_identified_with_nvme_object()
    -- 测试用例1：nvme对象存在且identify_pd为false的情况
    local task_created = false
    local task_loop_executed = false
    local static_info_updated = false
    local asset_info_updated = false
    local timeout_set_correctly = false

    local mock_nvme = {
        -- 模拟nvme对象
        slot = 1,
        model = "Test NVMe"
    }

    local task_obj = {}
    local obj = {
        ObjectName = "TestDrive",
        identify_pd = false,
        new_task = function(self, task_name)
            task_created = true
            lu.assertEquals(task_name[1], 'update_nvme_static')
            lu.assertEquals(task_name[2], "TestDrive")
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        task_loop_executed = true
        -- 执行回调函数测试内部逻辑
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        timeout_set_correctly = (timeout == 120000)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        static_info_updated = true
        lu.assertEquals(nvme, mock_nvme)
    end

    obj.update_asset_data_info = function(self)
        asset_info_updated = true
    end

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证结果
    lu.assertTrue(task_created, "任务应该被创建")
    lu.assertTrue(task_loop_executed, "任务循环应该被执行")
    lu.assertTrue(static_info_updated, "静态信息应该被更新")
    lu.assertTrue(asset_info_updated, "资产信息应该被更新")
    lu.assertTrue(timeout_set_correctly, "超时时间应该设置为120000毫秒")
end

function TEST_Drive_Object:test_nvme_static_identified_with_identify_pd_true()
    -- 测试用例2：nvme对象存在但identify_pd为true的情况（应该提前返回）
    local task_created = false
    local static_info_updated = false
    local asset_info_updated = false

    local mock_nvme = {
        slot = 1,
        model = "Test NVMe"
    }

    local task_obj = {}
    local obj = {
        ObjectName = "TestDrive",
        identify_pd = true, -- 设置为true，应该提前返回
        new_task = function(self, task_name)
            task_created = true
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        -- 执行回调函数测试内部逻辑
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        static_info_updated = true
    end

    obj.update_asset_data_info = function(self)
        asset_info_updated = true
    end

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证结果
    lu.assertTrue(task_created, "任务应该被创建")
    lu.assertFalse(static_info_updated, "identify_pd为true时，静态信息不应该被更新")
    lu.assertFalse(asset_info_updated, "identify_pd为true时，资产信息不应该被更新")
end

function TEST_Drive_Object:test_nvme_static_identified_with_nil_nvme()
    -- 测试用例3：nvme对象为nil的情况（应该停止任务）
    local stop_task_called = false
    local stopped_task_name = nil

    local obj = {
        ObjectName = "TestDrive",
        stop_task = function(self, task_name)
            stop_task_called = true
            stopped_task_name = task_name
        end
    }

    -- 执行测试
    c_drive.nvme_static_identified(obj, nil)

    -- 验证结果
    lu.assertTrue(stop_task_called, "应该调用stop_task")
    lu.assertEquals(stopped_task_name[1], 'update_nvme_static')
    lu.assertEquals(stopped_task_name[2], "TestDrive")
end

function TEST_Drive_Object:test_nvme_static_identified_edge_cases()
    -- 测试用例4：边界情况测试
    local function_calls = {}

    local task_obj = {}
    local obj = {
        ObjectName = "",   -- 空字符串测试
        identify_pd = nil, -- nil值测试
        new_task = function(self, task_name)
            table.insert(function_calls, "new_task")
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        table.insert(function_calls, "loop")
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        table.insert(function_calls, "set_timeout_ms")
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        table.insert(function_calls, "update_drive_static_info_by_sepecific_obj")
    end

    obj.update_asset_data_info = function(self)
        table.insert(function_calls, "update_asset_data_info")
    end

    local mock_nvme = {}

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证调用顺序
    local expected_calls = { "new_task", "loop", "update_drive_static_info_by_sepecific_obj", "update_asset_data_info",
        "set_timeout_ms" }
    lu.assertEquals(function_calls, expected_calls)
end

function TEST_Drive_Object:test_nvme_static_identified_task_name_generation()
    -- 测试用例5：测试任务名称生成的正确性
    local captured_task_names = {}

    local task_obj = {}
    local obj = {
        ObjectName = "Drive_Slot_5",
        identify_pd = false,
        new_task = function(self, task_name)
            table.insert(captured_task_names, { task_name[1], task_name[2] })
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme) end
    obj.update_asset_data_info = function(self) end

    local mock_nvme = { model = "Samsung NVMe" }

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证任务名称
    lu.assertEquals(#captured_task_names, 1)
    lu.assertEquals(captured_task_names[1][1], 'update_nvme_static')
    lu.assertEquals(captured_task_names[1][2], "Drive_Slot_5")
end