-- 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 bios_app = require 'bios_app'
local bios_service = require 'service.bios_service'
local lu = require 'luaunit'
local bios_factory = require 'factory.bios_factory'
local smbios_service = require 'service.smbios_service'
local boot_options_service = require 'service.boot_options_service'
local upgrade_service = require 'service.upgrade_service'
local pfr_service = require 'service.pfr_service'
local secure_boot_options_service = require 'service.secure_boot_options_service'
local boot_service = require 'service.boot_service'
local firmware_collection = require 'interface.mdb.firmware_multihost_collection'
local clsmgmt = require 'mc.class_mgnt'
local peripherals_device = require 'service.peripherals_device'

local open_db = require 'bios.db'
local test_common = require 'test_common.utils'
local bus = test_common.dbus_launch('../.dbus', nil, true)

local PATH<const> = '/bmc/kepler/Systems/1/'

TestBiosApp = {}

local function construct_db()
    local ok, datas = pcall(require, 'bios.datas')
    if not ok then
        -- 如果没有datas配置，证明当前组件不需要datas，仅打开数据库
        datas = nil
    end
    local db = open_db(':memory:', datas)
    return db
end

function TestBiosApp:test_ExportFirmware()
    local object = {
        path = PATH
    }
    local ctx = {}
    local ret, _ = pcall(bios_app.ExportFirmware, bios_app, ctx, object)
    lu.assertEquals(ret, true)

    local get_service = bios_factory.get_service
    bios_factory.get_service = function ()
        local obj = {}
        function obj:set_collection(...)
            return true
        end
        function obj:export_bios_firmware(...)
            return true
        end
        return obj
    end
    local ret, _ = pcall(bios_app.ExportFirmware, bios_app, ctx, object)
    lu.assertEquals(ret, true)

    ret, _ = pcall(bios_app.ExportBiosFirmware, bios_app, ctx, object)
    lu.assertEquals(ret, true)
    bios_factory.get_service = get_service
end

function TestBiosApp:test_on_add_object_extra()
    local class_name = 'SPIChannel'
    local object = {
        Channel = 1,
        ObjectName = 'SPIChannel'
    }
    bios_app.bios_service = bios_service
    local c_spi_channel = bios_app.bios_service.spi_channel
    bios_app:on_add_object_extra(class_name, object)
    lu.assertEquals(bios_app.bios_service.spi_channel.Channel, 1)
    bios_app.bios_service.spi_channel = c_spi_channel

    class_name = 'BIOSMultihostConfig'
    object = {
        ObjectName = 'BIOSMultihostConfig'
    }
    bios_app:on_add_object_extra(class_name, object)

    class_name = 'SystemFirmwareProgress'
    object = {
        ObjectName = 'SystemFirmwareProgress',
        register_mdb_objects = function()
            return true
        end
    }
    local c_peripherals_device = bios_app.peripherals_device
    bios_app.peripherals_device = {
        add_object = function()
            return true
        end
    }
    bios_app:on_add_object_extra(class_name, object)
    bios_app.peripherals_device = c_peripherals_device
end

function TestBiosApp:test_get_preserved_config_cb()
    local test_table = {}
    local test_bios = {
        key_mgmt_client = {
            get_domain_id = function ()
                return 123
            end
        }
    }
    bios_app.get_preserved_config_cb(test_bios, test_table)
end

local CreateBootOptions = bios_app.CreateBootOptions
local CreateSmBios = bios_app.CreateSmBios
local CreateBiosUpgradeService = bios_app.CreateBiosUpgradeService
local get_firmware = firmware_collection.get_firmware
local clsmgmt_mock = clsmgmt

local function init_service()
    bios_app.CreateBootOptions = function ()
        return {}
    end
    bios_app.CreateSmBios = function ()
        return {}
    end
    bios_app.CreateBiosUpgradeService = function ()
        return {}
    end
    clsmgmt('Bios', {})
    clsmgmt('BootOptions', {})
    clsmgmt('SecureBootOptions', {})
    clsmgmt('SmBios', {})
    clsmgmt('BiosUpgradeService', {})
    clsmgmt('BaseOSBoot', {})
    clsmgmt('SystemFirmwareProgress', {})
    bios_app.bios_service = bios_service.new(bus, construct_db())
    bios_app.boot_service = boot_service.new(construct_db(), {})
    bios_app.smbios_service = smbios_service.new(construct_db())
    bios_app.boot_options_service = boot_options_service.new(construct_db())
    bios_app.upgrade_service = upgrade_service.new(construct_db(), bus)
    bios_app.pfr_service = pfr_service.new(construct_db())
    bios_app.secure_boot_options_service = secure_boot_options_service.new(construct_db())
    bios_app.peripherals_device = peripherals_device.new(bus)
    firmware_collection.get_firmware = function ()
        return {}
    end
end

local function recover_service()
    bios_app.CreateBootOptions = CreateBootOptions
    bios_app.CreateSmBios = CreateSmBios
    bios_app.CreateBiosUpgradeService = CreateBiosUpgradeService
    firmware_collection.get_firmware = get_firmware
    clsmgmt = clsmgmt_mock
end

function TestBiosApp:test_on_delete_object()
    init_service()
    local object = {
        Slot = 0,
        path = '/bmc/kepler/Systems/1/',
        get_system_id = function ()
            return 1
        end,
        register_mdb_objects = function ()
        end,
        get_mdb_object = function ()
            return 'aaaaa'
        end
    }
    bios_app:on_delete_object('Bios', nil, '010101')
    bios_app:on_add_object('Bios', object, '010101')
    lu.assertEquals(#bios_app.bios_service.bios_object_collection, 1)
    lu.assertEquals(#bios_app.boot_service.boot_object_collection, 1)
    lu.assertEquals(#bios_app.smbios_service.smbios_object_collection, 1)
    lu.assertEquals(#bios_app.boot_options_service.boot_option_collection, 1)
    lu.assertEquals(#bios_app.upgrade_service.package_snapshot_collection, 1)
    lu.assertEquals(#bios_app.pfr_service.gold_package_collection, 1)
    bios_app:on_add_object('SecureBootOptions', object, '010101')
    local obj = bios_app.secure_boot_options_service.obj_collection[1]
    lu.assertEquals(#bios_app.secure_boot_options_service.obj_collection, 1)
    lu.assertEquals(obj.position, '010101')
    bios_app:on_add_object('SecureBootOptions', object, '010102')
    lu.assertEquals(#bios_app.secure_boot_options_service.obj_collection, 1)
    lu.assertEquals(obj.position, '010102')

    bios_app:on_delete_object('Bios', object, '010101')
    lu.assertEquals(#bios_app.bios_service.bios_object_collection, 0)
    lu.assertEquals(#bios_app.boot_service.boot_object_collection, 0)
    lu.assertEquals(#bios_app.smbios_service.smbios_object_collection, 0)
    lu.assertEquals(#bios_app.boot_options_service.boot_option_collection, 0)
    lu.assertEquals(#bios_app.upgrade_service.package_snapshot_collection, 0)
    lu.assertEquals(#bios_app.pfr_service.gold_package_collection, 0)
    bios_app:on_delete_object('SecureBootOptions', object, '010102')
    lu.assertEquals(#bios_app.secure_boot_options_service.obj_collection, 0)

    bios_app:on_add_object('BaseOSBoot', object, '010101')
    lu.assertEquals(bios_app.bios_service.mdb_os_boot, 'aaaaa')
    bios_app:on_delete_object('BaseOSBoot', object, '010101')
    lu.assertEquals(bios_app.bios_service.mdb_os_boot, nil)

    bios_app:on_add_object_extra('SystemFirmwareProgress', object, '010101')
    lu.assertEquals(#bios_app.peripherals_device.sys_fw_progress, 1)
    bios_app:on_delete_object('SystemFirmwareProgress', object, '010101')
    lu.assertEquals(#bios_app.peripherals_device.sys_fw_progress, 0)

    recover_service()
end