#pragma once

#include "rm_control/common/result.h"

#include <string>
#include <vector>

namespace rm_control::core {

// 睿尔曼厂商原生“移动到拖动轨迹起点”接口固定使用 20% 速度。
inline constexpr int kNativeTrajectoryOriginRequiredSpeedPercent = 20;

/**
 * @brief 真实硬件动作执行前由各层共同提供的安全事实。
 *
 * @reason 将命令行授权、静态配置和运行时设备状态汇总成不可隐式补全的输入，
 *         使业务服务能够在调用任何运动接口前统一执行 fail-closed 判定。
 *
 * @author 唐永康
 * @date 2026-07-11
 *
 * @safety 所有字段默认拒绝执行；调用方不得用默认 true 或跳过未知状态。
 * @note 本结构只承载已经由对应模块验证过的事实，不负责连接设备或读取配置。
 */
struct HardwareExecutionGateInput {
    bool live_requested = false;
    bool hardware_execution_enabled = false;
    bool arm_connected = false;
    bool hand_connected = false;
    bool emergency_stop_verified = false;
    bool safety_limits_loaded = false;
    bool operator_confirmed = false;
    bool trajectory_validated = false;
    bool trajectory_sample_period_confirmed = false;
    bool vendor_raw_units_per_degree_confirmed = false;
    bool workspace_and_virtual_wall_verified = false;
    int configured_max_speed_percent = 0;
    bool native_replay_without_speed_control_accepted = false;
    bool native_replay_speed_within_config_verified = false;
};

/**
 * @brief 当前硬件动作对安全门控提出的附加要求。
 *
 * @reason 厂商原生回放和普通受控动作的速度、时间及单位前提不同，显式传入动作要求
 *         可以复用同一基础门控，同时避免把轨迹文件特有条件错误施加给其他动作。
 *
 * @author 唐永康
 * @date 2026-07-11
 *
 * @safety `required_speed_percent` 为动作实际需要的速度比例；0 表示该动作不声明速度。
 * @note 移动到原生轨迹起点应传入固定 20%；文件回放应显式要求采样周期和厂商单位比例确认。
 */
struct HardwareExecutionGateRequirements {
    int required_speed_percent = 0;
    bool require_native_replay_without_speed_control_acceptance = false;
    bool require_native_replay_speed_verification = false;
    bool require_confirmed_trajectory_sample_period = false;
    bool require_confirmed_vendor_raw_units_per_degree = false;
};

/**
 * @brief 安全门控的完整判定结果。
 *
 * @reason 保留全部拒绝原因便于操作者一次修正多个缺失条件，并为审计日志提供稳定输入。
 *
 * @author 唐永康
 * @date 2026-07-11
 *
 * @safety 只有 `execution_allowed` 为 true 时才允许调用真实硬件动作接口。
 * @note 拒绝原因不包含设备密钥、网络地址或其他敏感数据。
 */
struct HardwareExecutionGateDecision {
    bool execution_allowed = false;
    std::vector<std::string> rejection_reasons;
};

/**
 * @brief 评估真实硬件动作的全部安全门控条件。
 *
 * @reason 使用无副作用的纯软件判定，使服务层、单元测试和审计工具共享同一套拒绝规则。
 *
 * @author 唐永康
 * @date 2026-07-11
 *
 * @param input 已经由命令行、配置和设备服务确认的安全事实。
 * @param requirements 当前动作的速度与原生回放附加要求。
 * @return 返回允许标志及全部拒绝原因；本函数本身不以异常或错误码表示门控拒绝。
 *
 * @calls 仅调用本模块内部的纯软件校验函数。
 * @safety 本函数不连接设备、不触发运动；未知或非法输入一律产生拒绝结果。
 * @note `configured_max_speed_percent` 和声明的动作速度有效范围均为 1..100；动作速度可为 0 表示不声明。
 */
HardwareExecutionGateDecision EvaluateHardwareExecutionGate(
    const HardwareExecutionGateInput &input,
    const HardwareExecutionGateRequirements &requirements = {});

/**
 * @brief 以统一 `Result<void>` 形式要求真实硬件执行权限。
 *
 * @reason 服务层通常需要失败即返回的控制流，本函数把完整门控判定转换为包含上下文的错误。
 *
 * @author 唐永康
 * @date 2026-07-11
 *
 * @param input 已经由命令行、配置和设备服务确认的安全事实。
 * @param requirements 当前动作的速度与原生回放附加要求。
 * @return 全部条件满足时成功；否则返回合并后的全部拒绝原因。
 *
 * @calls EvaluateHardwareExecutionGate。
 * @safety 调用方必须在每次真实运动开始或继续前调用；成功结果不替代设备侧急停。
 * @note Pause 和 Stop 属于减险动作，应由服务层直接执行，不应被本门控阻止。
 */
common::Result<void> RequireHardwareExecutionPermission(
    const HardwareExecutionGateInput &input,
    const HardwareExecutionGateRequirements &requirements = {});

} // namespace rm_control::core
