-- Copyright (c) 2026 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.

-- Description: fructl相关函数

local log = require 'mc.logging'
local context = require 'mc.context'
local skynet = require 'skynet'
local client = require 'storage.client'

local fructrl_handle = {}

local MAX_RETRY_COUNT = 5
local GET_OBJ_RETRY_COUNT = 5
local APP_NAME = 'storage'

-- 获取下电锁对象（带重试机制）
-- @return 成功返回对象，失败返回 nil
local function get_power_off_lock_obj()
    local cnt = 0
    local obj = nil
    local objs = nil

    repeat
        objs = client:GetPowerOffLockObjects()
        if objs and next(objs) then
            for _, v in pairs(objs) do
                obj = v
                break
            end
        end

        if cnt < GET_OBJ_RETRY_COUNT then
            skynet.sleep(100)
        end
        cnt = cnt + 1
    until obj or cnt > GET_OBJ_RETRY_COUNT

    if not obj then
        log:error('[Power Off Lock] Failed to get power off lock object after %s retries', GET_OBJ_RETRY_COUNT)
    end

    return obj
end

-- 设置下电锁
-- @param locked: 锁定状态（true = 锁定, false = 解锁）
-- @param timeout: 超时时间（秒），取值范围 [10, 3600]
-- @param reason: 原因字符串
-- @return 成功返回 true，失败返回 nil
function fructrl_handle.set_power_off_lock(locked, timeout, reason)
    local obj = get_power_off_lock_obj()
    if not obj then
        return nil
    end
    return obj.pcall:SetPowerOffLock(context.new(), locked, timeout, APP_NAME, reason)
end

-- 设置下电锁（带重试机制）
-- @param locked: 锁定状态（true = 锁定, false = 解锁）
-- @param timeout: 超时时间（秒），取值范围 [10, 3600]
-- @param reason: 原因字符串
-- @return 成功返回 true，失败返回 false
function fructrl_handle.set_power_off_lock_until_success(locked, timeout, reason)
    local res
    local cnt = 0

    repeat
        res = fructrl_handle.set_power_off_lock(locked, timeout, reason)
        if not res then
            skynet.sleep(100)
        end
        cnt = cnt + 1
    until res or cnt > MAX_RETRY_COUNT

    if cnt > MAX_RETRY_COUNT and not res then
        log:error('[Power Off Lock] Failed to set power off lock after %s retries, state: %s',
            MAX_RETRY_COUNT, locked and 'lock' or 'unlock')
        return false
    end

    log:notice('[Power Off Lock] Set power off lock successfully, state: %s, timeout: %ds, reason: %s',
        locked and 'lock' or 'unlock', timeout, reason)
    return true
end

return fructrl_handle