#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <thread>

#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"

#include "interfaces/action/move_waist.hpp"

using namespace std::chrono_literals;

// MoveWaistNode 节点：
// - 启动一个 MoveWaist 动作服务端（默认话题名称：/move_waist，可通过参数 action_name 修改）
// - 接受目标后模拟进度反馈，支持取消，并在完成后返回结果
class MoveWaistNode : public rclcpp::Node
{
public:
  using MoveWaist = interfaces::action::MoveWaist;
  using GoalHandleMoveWaist = rclcpp_action::ServerGoalHandle<MoveWaist>;

  // 构造函数：
  // - 声明参数 action_name（默认 "move_waist"，统一使用首字母大写形式避免重复）
  // - 创建 MoveWaist 动作服务端，并绑定目标处理、取消处理和接收回调
  MoveWaistNode()
  : Node("move_waist_node")
  {
  // Declare a parameter for action name (default: "MoveWaist")
  action_name_ = this->declare_parameter<std::string>("action_name", "move_waist");

    using std::placeholders::_1;
    using std::placeholders::_2;

    server_ = rclcpp_action::create_server<MoveWaist>(
      this->get_node_base_interface(),
      this->get_node_clock_interface(),
      this->get_node_logging_interface(),
      this->get_node_waitables_interface(),
      action_name_,
      std::bind(&MoveWaistNode::handle_goal, this, _1, _2),
      std::bind(&MoveWaistNode::handle_cancel, this, _1),
      std::bind(&MoveWaistNode::handle_accepted, this, _1));

    RCLCPP_INFO(
      this->get_logger(), "MoveWaist action server started on '%s'",
      action_name_.c_str());
  }

private:
  // 目标处理回调：
  // - 参数 uuid：目标的唯一标识
  // - 参数 goal：ArmSpaceControl 的目标数据（target pose）
  // - 返回值：是否接受目标，这里直接接受并执行
  rclcpp_action::GoalResponse handle_goal(
    const rclcpp_action::GoalUUID & uuid,
    std::shared_ptr<const MoveWaist::Goal> goal)
  {
    (void)uuid;
    RCLCPP_INFO(
      this->get_logger(), "Received MoveWaist goal: move_pitch_degree=%f, move_yaw_degree=%f",
      goal->move_pitch_degree, goal->move_yaw_degree);
    // Accept all goals for now. You can validate mode/effort here.
    return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
  }

  // 取消处理回调：
  // - 当客户端请求取消时被调用，这里统一接受取消请求
  rclcpp_action::CancelResponse handle_cancel(
    const std::shared_ptr<GoalHandleMoveWaist>/*goal_handle*/)
  {
    RCLCPP_INFO(this->get_logger(), "Received request to cancel MoveWaist goal");
    return rclcpp_action::CancelResponse::ACCEPT;
  }

  // 接受目标回调：
  // - 收到新的目标后，开启独立线程执行，避免阻塞执行器线程
  void handle_accepted(const std::shared_ptr<GoalHandleMoveWaist> goal_handle)
  {
    // Execute goal in a new thread to avoid blocking executor thread
    std::thread{std::bind(&MoveWaistNode::execute, this, std::placeholders::_1), goal_handle}.detach();
  }

  // 执行函数：
  // - 模拟执行流程，按 10% 递增发布反馈(progress)
  // - 如果检测到取消请求，则返回取消结果
  // - 正常完成后返回 success=true，并附带简单描述信息
  void execute(const std::shared_ptr<GoalHandleMoveWaist> goal_handle)
  {
    const auto goal = goal_handle->get_goal();

    auto feedback = std::make_shared<MoveWaist::Feedback>();
    auto result = std::make_shared<MoveWaist::Result>();

    // Simulate progress from 0 to 100 with small delay; react to cancel requests
    for (int i = 0; i <= 100; i += 10) {
      if (goal_handle->is_canceling()) {
        result->success = false;
        goal_handle->canceled(result);
        RCLCPP_INFO(this->get_logger(), "MoveWaist goal canceled");
        return;
      }
      // feedback->progress = static_cast<float>(i);
      // feedback->command_id = goal->command_id;
      // feedback->int_lenth = i;
      goal_handle->publish_feedback(feedback);
      RCLCPP_INFO(this->get_logger(), "MoveWaist progress: %d", i);
      std::this_thread::sleep_for(100ms);
    }

    // Complete successfully
    result->success = true;
    // result->message = std::string("MoveWaist moved to target in frame '") +
    //   goal->target.header.frame_id + "'";
    goal_handle->succeed(result);
    RCLCPP_INFO(this->get_logger(), "MoveWaist goal succeeded");
  }

private:
  std::string action_name_;
  rclcpp_action::Server<MoveWaist>::SharedPtr server_;
};

// 主函数：
// - 初始化 ROS，启动 MotionNode，进入自旋，退出时关闭
// 测试：
// ros2 action send_goal --feedback /MoveWaist interfaces/action/MoveWaist "{target: {header: {frame_id: base_link}, pose: {position: {x: 0.5, y: 0.0, z: 0.3}, orientation: {w: 1.0, x: 0.0, y: 0.0, z: 0.0}}}}"

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  auto node = std::make_shared<MoveWaistNode>();
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}
