/**
 * @file json_runner_cli_config.h
 * @brief RM JSON 指令运行器命令行参数解析接口。
 *
 * @author mashiro
 * @date 2026-07-09
 * @last_modified 2026-07-09
 *
 * @details
 * 本文件只声明 `rm_json_runner` 可执行程序的命令行参数结构和解析函数。
 * 设计上把命令行解析从 `main.cpp` 中移出，是为了让入口文件只负责装配依赖
 * 和启动应用流程，同时让参数解析逻辑可以在不连接真实机械臂的情况下单元测试。
 *
 * 设计原则：
 * - 只处理命令行文本，不读取 JSON 文件；
 * - 只返回结构化配置和错误原因，不直接退出进程；
 * - 不依赖 RealMan RM_API2，避免 CLI 单元测试访问真实硬件；
 * - 保持现有 `rm_json_runner <commands.json> [--validate-only]` 运行方式不变。
 *
 * @dependencies
 * - rm_control/common/result.h
 *
 * @note
 * 后续如果新增 `rm_json_runner` 命令行选项，应优先扩展本文件中的配置结构，
 * 不应把解析逻辑重新写回 `RM/src/main.cpp`。
 */
#pragma once

#include "rm_control/common/result.h"

#include <iosfwd>
#include <string>

namespace rm_control::config {

/**
 * @brief `rm_json_runner` 命令行解析后的结构化配置。
 *
 * @author mashiro
 * @date 2026-07-09
 * @last_modified 2026-07-09
 *
 * @details
 * 该结构体只表达启动参数层面的意图，不保存已经解析好的 JSON 指令内容。
 * 这样 `main.cpp` 可以先处理帮助信息，再把 `command_file_path` 交给 JSON
 * 配置模块读取，避免 CLI 层和 JSON 文件解析层相互耦合。
 *
 * @note
 * `help_requested=true` 时，调用方应打印 usage 并返回成功退出码。
 */
struct JsonRunnerCliConfig {
    bool help_requested = false;          ///< 是否请求帮助信息。
    bool validate_only = false;           ///< 是否只校验 JSON 文件，不连接 SDK。
    std::string command_file_path;        ///< JSON 指令文件路径。
};

/**
 * @brief 打印 `rm_json_runner` 的命令行使用说明。
 *
 * @author mashiro
 * @date 2026-07-09
 * @last_modified 2026-07-09
 *
 * @details
 * 该函数只负责把稳定的 usage 文本写入输出流，不解析参数、不访问文件、
 * 不连接真实机械臂。之所以单独封装，是为了让 `main.cpp` 在错误和帮助场景
 * 复用同一份提示文本，避免不同分支输出不一致。
 *
 * @param[in] program_name 当前进程名，可以为空指针；为空时使用固定占位名称。
 * @param[out] out 使用说明输出流，通常是 `std::cout` 或测试中的字符串流。
 *
 * @return 无返回值。
 *
 * @throws 本函数不主动抛出异常；如果输出流自身异常，由调用方处理。
 *
 * @note
 * - 不读取环境变量。
 * - 不修改全局状态。
 *
 * @warning
 * 如果后续新增命令行选项，必须同步更新此函数的输出内容。
 *
 * @thread_safety
 * 函数内部不使用全局可变状态；多个线程写同一个输出流时需要调用方加锁。
 *
 * @par 边界条件
 * `program_name == nullptr` 时仍能输出可读 usage。
 *
 * @par 后续维护
 * 保持 usage 和 `ParseJsonRunnerCliArguments()` 的实际解析规则一致。
 */
void PrintJsonRunnerUsage(const char *program_name, std::ostream &out);

/**
 * @brief 解析 `rm_json_runner` 的命令行参数。
 *
 * @author mashiro
 * @date 2026-07-09
 * @last_modified 2026-07-09
 *
 * @details
 * 该函数把 `argc/argv` 转换为 `JsonRunnerCliConfig`。它只做参数数量、
 * 帮助选项和 `--validate-only` 选项校验，不读取 JSON 文件，也不访问真实机械臂。
 * 这样设计可以保证命令行解析逻辑可独立测试，并让 `main.cpp` 保持简洁。
 *
 * @param[in] argc 命令行参数数量，来自 `main()`。
 * @param[in] argv 命令行参数数组，来自 `main()`，允许数组元素为空指针。
 *
 * @return 成功时返回解析后的 `JsonRunnerCliConfig`。
 * @return 失败时返回错误原因，例如参数数量错误或未知选项。
 *
 * @throws 本函数不主动抛出异常；内部通过 `Result` 返回错误。
 *
 * @note
 * - `-h` 和 `--help` 只允许作为第一个业务参数。
 * - `--validate-only` 只允许作为第二个业务参数。
 *
 * @warning
 * 本函数不判断 JSON 文件是否存在，文件存在性由配置加载层负责。
 *
 * @thread_safety
 * 函数只读取输入参数并返回局部对象，不使用全局可变状态，线程安全。
 *
 * @par 边界条件
 * `argv[1] == nullptr` 或空路径会返回失败，避免后续文件读取错误不明确。
 *
 * @par 后续维护
 * 新增选项时应保持向后兼容，不破坏现有命令格式。
 */
common::Result<JsonRunnerCliConfig> ParseJsonRunnerCliArguments(int argc, char **argv);

} // namespace rm_control::config
