#include "omni_node/omni_engine.hpp"

#include <algorithm>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <sstream>
#include <iomanip>
#include <regex>

#include <nlohmann/json.hpp>

using json = nlohmann::json;

namespace {

const std::vector<std::string> kRequiredFields = {
    "visual_hbm_path",
    "audio_hbm_path",
    "text_hbm_path",
    "embed_tokens",
    "tokenizer_dir",
    "model_type",
    "online_mode",
};

std::string WritePromptJsonToFile(const std::string& json_str) {
  std::ostringstream ss;
  ss << "/tmp/omni_prompt_" << std::hex << std::time(nullptr) << "_" << rand() << ".json";
  std::string path = ss.str();
  std::ofstream ofs(path);
  if (!ofs.is_open()) {
    std::cerr << "[OmniEngine] Failed to write temp prompt file: " << path << std::endl;
    return "";
  }
  ofs << json_str;
  ofs.close();
  return path;
}

std::string Trim(const std::string& s) {
  size_t start = s.find_first_not_of(" \t\n\r");
  if (start == std::string::npos) return "";
  size_t end = s.find_last_not_of(" \t\n\r");
  return s.substr(start, end - start + 1);
}

std::string GetPlanId() {
  std::ostringstream ss;
  ss << "plan_" << std::hex << std::time(nullptr) << "_" << rand();
  return ss.str();
}

bool JsonArrayEmpty(const json& arr) {
  return !arr.is_array() || arr.empty();
}

bool JsonObjectEmpty(const json& obj) {
  return !obj.is_object() || obj.empty();
}

}  // namespace

OmniEngine* OmniEngine::current_instance_ = nullptr;

OmniEngine::OmniEngine(const std::string& config_path)
    : config_path_(config_path),
      handle_(nullptr),
      current_mode_(Mode::kLegacyDialog),
      planner_separator_seen_(false),
      planner_stream_emitted_len_(0) {
  current_instance_ = this;
}

OmniEngine::~OmniEngine() {
  if (handle_ != nullptr) {
    xlm_destroy(&handle_);
    handle_ = nullptr;
  }
  if (current_instance_ == this) {
    current_instance_ = nullptr;
  }
}

bool OmniEngine::Init() {
  std::ifstream config_file(config_path_);
  if (!config_file.is_open()) {
    std::cerr << "[OmniEngine] Failed to open config file: " << config_path_ << std::endl;
    return false;
  }

  json config;
  try {
    config_file >> config;
  } catch (const std::exception& e) {
    std::cerr << "[OmniEngine] Failed to parse JSON: " << e.what() << std::endl;
    return false;
  }

  for (const auto& field : kRequiredFields) {
    if (!config.contains(field)) {
      std::cerr << "[OmniEngine] Missing required field: " << field << std::endl;
      return false;
    }
  }

  config_.visual_hbm_path = config["visual_hbm_path"];
  config_.audio_hbm_path = config["audio_hbm_path"];
  config_.text_hbm_path = config["text_hbm_path"];
  config_.embed_tokens = config["embed_tokens"];
  config_.tokenizer_dir = config["tokenizer_dir"];
  config_.model_type = config["model_type"];
  config_.online_mode = config["online_mode"].get<bool>();
  config_.bpu_core = config.value("bpu_core", -1);
  config_.system_prompt = config.value("system_prompt",
      "You are Qwen, a virtual human developed by the Qwen Team, Alibaba "
      "Group, capable of perceiving auditory and visual inputs, as well as "
      "generating text and speech.");

  config_.enable_legacy_asr_mode = config.value("enable_legacy_asr_mode", true);
  config_.enable_planner_mode = config.value("enable_planner_mode", true);
  config_.dialog_system_prompt = config.value("dialog_system_prompt",
      "你是一个机器人助手，负责与用户自然对话。");
  config_.planner_system_prompt = config.value("planner_system_prompt",
      "你是机器人智能体。任务：1. 先给用户输出一段自然语言回复（可直接播报）2. 然后输出 <FINAL_JSON> 分隔符 3. 最后输出严格 JSON 对象（包含 plan）");
  config_.model_response_separator = config.value("model_response_separator", "<FINAL_JSON>");
  config_.fallback_response_message = config.value("fallback_response_message",
      "抱歉，我没有完全理解您的请求，请再说一次。");

  // 加载 planner_rules 配置
  if (config.contains("planner_rules") && config["planner_rules"].is_object()) {
    auto& rules = config["planner_rules"];
    config_.planner_output_protocol = rules.value("output_protocol", "=== 输出协议 ===\n1. 自然语言回复\n2. <FINAL_JSON>\n3. JSON 对象\n");
    config_.planner_input_classification = rules.value("input_classification", "=== 输入分类 ===\nA. 身份/闲聊 → speak\nB. 状态查询 → speak/query_world\nC. 明确任务 → execute\nD. 缺信息 → ask_user\n");
    config_.planner_ask_user_rules = rules.value("ask_user_rules", "=== ask_user 规则 ===\n- 直接问，不说\"我将执行\"\n");
    config_.planner_capability_rules = rules.value("capability_question_rules", "=== 能力说明类问题 ===\n- 基于可用能力说明回答\n- 用 speak 回答\n");

    if (rules.contains("example1") && rules["example1"].is_object()) {
      config_.planner_example1_user = rules["example1"].value("user_input", "你是谁");
      config_.planner_example1_response = rules["example1"].value("natural_response", "我是机器人助手。");
      config_.planner_example1_json = rules["example1"].value("json", "");
    }

    if (rules.contains("example2") && rules["example2"].is_object()) {
      config_.planner_example2_user = rules["example2"].value("user_input", "打开风扇");
      config_.planner_example2_response = rules["example2"].value("natural_response", "请问您想打开哪个房间的风扇？");
      config_.planner_example2_json = rules["example2"].value("json", "");
    }

    config_.planner_prohibited = rules.value("prohibited", "禁止：markdown、解释文字、省略 JSON。");
    std::cout << "[OmniEngine] planner_rules loaded from config" << std::endl;
  }

  std::cout << "[OmniEngine] Config loaded:" << std::endl;
  std::cout << "  enable_legacy_asr_mode: " << (config_.enable_legacy_asr_mode ? "true" : "false") << std::endl;
  std::cout << "  enable_planner_mode: " << (config_.enable_planner_mode ? "true" : "false") << std::endl;

  if (!config_.enable_legacy_asr_mode && !config_.enable_planner_mode) {
    std::cerr << "[OmniEngine] FATAL: Both legacy_asr_mode and planner_mode are disabled!" << std::endl;
    std::cerr << "[OmniEngine] Please enable at least one mode in config file." << std::endl;
    return false;
  }

  xlm_common_params_t param = xlm_create_default_param();
  param.omni_visual_model_path = config_.visual_hbm_path.c_str();
  param.omni_audio_model_path = config_.audio_hbm_path.c_str();
  param.omni_text_model_path = config_.text_hbm_path.c_str();
  param.embed_tokens = config_.embed_tokens.c_str();
  param.token_config_path = config_.tokenizer_dir.c_str();
  param.model_type = static_cast<xlm_model_type>(config_.model_type);
  param.omni_online_mode = config_.online_mode;

  int32_t ret = xlm_init(&param, StaticCallback, &handle_);
  if (ret != 0) {
    std::cerr << "[OmniEngine] xlm_init failed with code: " << ret << std::endl;
    return false;
  }

  std::cout << "[OmniEngine] xlm init success" << std::endl;
  return true;
}

void OmniEngine::SetStreamCallback(StreamCallback callback) {
  stream_callback_ = std::move(callback);
}

void OmniEngine::SetPlannerResponseCallback(PlannerResponseCallback callback) {
  planner_response_callback_ = std::move(callback);
}

std::string OmniEngine::BuildLegacyPrompt(const std::string& user_text) {
  std::ostringstream prompt;
  prompt << config_.dialog_system_prompt << "\n\n";
  prompt << "当前用户输入：\n" << user_text << "\n\n";
  prompt << "请直接回复自然语言。";
  return prompt.str();
}

bool OmniEngine::ParsePlannerRequest(const std::string& json_request,
                                      std::string& request_id,
                                      std::string& session_id,
                                      std::string& user_text,
                                      std::string& memory_text,
                                      std::string& mode,
                                      std::string& planner_mode,
                                      json& world_snapshot,
                                      json& available_tools,
                                      json& tool_descriptions,
                                      json& domain_rules,
                                      json& current_state) {
  try {
    auto j = json::parse(json_request);

    request_id = j.value("request_id", "unknown");
    session_id = j.value("session_id", "default");
    user_text = j.value("user_text", "");
    memory_text = j.value("memory_text", "");  // 新增：解析记忆上下文
    mode = j.value("mode", "dialog_and_decision");
    planner_mode = j.value("planner_mode", "hybrid");

    if (j.contains("world_snapshot")) {
      // 支持 object 或 string 类型
      if (j["world_snapshot"].is_object()) {
        world_snapshot = j["world_snapshot"];
      } else if (j["world_snapshot"].is_string()) {
        // string 类型直接存储为字符串形式的 JSON
        world_snapshot = json::object({{"_text", j["world_snapshot"].get<std::string>()}});
      } else {
        world_snapshot = json::object();
        std::cerr << "[OmniEngine] WARNING: world_snapshot exists but is not object/string, fallback to {}" << std::endl;
      }
    } else {
      world_snapshot = json::object();
    }

    if (j.contains("available_tools")) {
      if (j["available_tools"].is_array()) {
        available_tools = j["available_tools"];
      } else {
        available_tools = json::array();
        std::cerr << "[OmniEngine] WARNING: available_tools exists but is not array, fallback to []" << std::endl;
      }
    } else {
      available_tools = json::array();
    }

    // 新增：解析 tool_descriptions
    if (j.contains("tool_descriptions")) {
      if (j["tool_descriptions"].is_array()) {
        tool_descriptions = j["tool_descriptions"];
        std::cerr << "[OmniEngine] ParsePlannerRequest: tool_descriptions count=" << tool_descriptions.size() << std::endl;
      } else {
        tool_descriptions = json::array();
        std::cerr << "[OmniEngine] WARNING: tool_descriptions exists but is not array, fallback to []" << std::endl;
      }
    } else {
      tool_descriptions = json::array();
      std::cerr << "[OmniEngine] WARNING: tool_descriptions not found, fallback to []" << std::endl;
    }

    if (j.contains("domain_rules")) {
      if (j["domain_rules"].is_object()) {
        domain_rules = j["domain_rules"];
      } else {
        domain_rules = json::object();
        std::cerr << "[OmniEngine] WARNING: domain_rules exists but is not object, fallback to {}" << std::endl;
      }
    } else {
      domain_rules = json::object();
    }

    if (j.contains("current_state")) {
      if (j["current_state"].is_object()) {
        current_state = j["current_state"];
      } else {
        current_state = json::object();
        std::cerr << "[OmniEngine] WARNING: current_state exists but is not object, fallback to {}" << std::endl;
      }
    } else {
      current_state = json::object();
    }

    return true;
  } catch (const json::parse_error& e) {
    std::cerr << "[OmniEngine] JSON parse error: " << e.what() << std::endl;
    return false;
  } catch (const std::exception& e) {
    std::cerr << "[OmniEngine] Failed to parse planner request: " << e.what() << std::endl;
    return false;
  }
}

// BuildToolDescriptions - 优先使用 tool_descriptions，生成可用能力说明
std::string OmniEngine::BuildToolDescriptions(const json& tool_descriptions) {
  std::ostringstream desc;

  // 如果 tool_descriptions 非空，使用 plannerNode 提供的语义
  if (tool_descriptions.is_array() && !tool_descriptions.empty()) {
    desc << "=== 可用能力说明 ===\n";
    for (const auto& item : tool_descriptions) {
      if (!item.is_object()) continue;

      std::string name = item.value("name", "");
      if (name.empty()) continue;

      std::string description = item.value("description", "(未定义)");
      std::string tool_call_type = item.value("tool_call_type", "execute");
      std::string category = item.value("category", "action");

      desc << "- " << name << ": " << description
           << " (tool_call_type=" << tool_call_type
           << ", category=" << category << ")\n";
    }
    std::cerr << "[OmniEngine] BuildToolDescriptions: using plannerNode provided descriptions, count="
              << tool_descriptions.size() << std::endl;
    return desc.str();
  }

  // tool_descriptions 为空时，返回空描述
  std::cerr << "[OmniEngine] BuildToolDescriptions: tool_descriptions empty" << std::endl;
  return "";
}

// BuildPlannerSystemPrompt - 以 config_.planner_system_prompt 为主体，使用配置中的规则
std::string OmniEngine::BuildPlannerSystemPrompt(const json& request_data) {
  std::ostringstream system_prompt;

  // 主体：使用 config 中的 planner_system_prompt
  system_prompt << config_.planner_system_prompt << "\n\n";

  // 补充规则：使用配置中的 planner_rules
  if (!config_.planner_output_protocol.empty()) {
    system_prompt << config_.planner_output_protocol << "\n";
  }

  if (!config_.planner_input_classification.empty()) {
    system_prompt << config_.planner_input_classification << "\n";
  }

  if (!config_.planner_ask_user_rules.empty()) {
    system_prompt << config_.planner_ask_user_rules << "\n";
  }

  if (!config_.planner_capability_rules.empty()) {
    system_prompt << config_.planner_capability_rules << "\n";
  }

  // 示例1
  if (!config_.planner_example1_user.empty()) {
    system_prompt << "=== 示例1 ===\n";
    system_prompt << "用户：" << config_.planner_example1_user << "\n";
    system_prompt << config_.planner_example1_response << "\n";
    system_prompt << config_.model_response_separator << "\n";
    system_prompt << config_.planner_example1_json << "\n\n";
  }

  // 示例2
  if (!config_.planner_example2_user.empty()) {
    system_prompt << "=== 示例2 ===\n";
    system_prompt << "用户：" << config_.planner_example2_user << "\n";
    system_prompt << config_.planner_example2_response << "\n";
    system_prompt << config_.model_response_separator << "\n";
    system_prompt << config_.planner_example2_json << "\n\n";
  }

  if (!config_.planner_prohibited.empty()) {
    system_prompt << config_.planner_prohibited << "\n";
  }

  std::cerr << "[OmniEngine] BuildPlannerSystemPrompt: base prompt len=" << config_.planner_system_prompt.length()
            << ", total len=" << system_prompt.str().length() << std::endl;

  return system_prompt.str();
}

// BuildPlannerUserContext - 使用 tool_descriptions 优先，支持 memory_text
std::string OmniEngine::BuildPlannerUserContext(const json& request_data) {
  std::string request_id = request_data.value("request_id", "unknown");
  std::string session_id = request_data.value("session_id", "default");
  std::string user_text = request_data.value("user_text", "");
  std::string memory_text = request_data.value("memory_text", "");  // 新增：记忆上下文
  std::string mode = request_data.value("mode", "dialog_and_decision");
  std::string planner_mode = request_data.value("planner_mode", "hybrid");

  json world_snapshot = request_data.value("world_snapshot", json::object());
  json available_tools = request_data.value("available_tools", json::array());
  json tool_descriptions = request_data.value("tool_descriptions", json::array());
  json domain_rules = request_data.value("domain_rules", json::object());
  json current_state = request_data.value("current_state", json::object());

  // 支持字符串或 object 类型的 world_snapshot
  std::string world_snapshot_text;
  if (world_snapshot.contains("_text")) {
    world_snapshot_text = world_snapshot["_text"].get<std::string>();
  } else if (world_snapshot.is_object()) {
    world_snapshot_text = world_snapshot.dump(2);
  } else {
    world_snapshot_text = "{}";
  }
  std::string domain_rules_text = domain_rules.is_object() ? domain_rules.dump(2) : "{}";
  std::string current_state_text = current_state.is_object() ? current_state.dump(2) : "{}";

  // 使用 tool_descriptions 生成能力说明
  std::string tools_desc = BuildToolDescriptions(tool_descriptions);

  std::ostringstream user_context;

  user_context << "=== 当前请求 ===\n";
  user_context << "request_id: " << request_id << "\n";
  user_context << "session_id: " << session_id << "\n";
  user_context << "mode: " << mode << ", planner_mode: " << planner_mode << "\n";
  user_context << "用户输入: " << user_text << "\n\n";

  // 记忆上下文（来自 MemoryNode）
  if (!memory_text.empty()) {
    user_context << "=== 记忆上下文 ===\n";
    user_context << memory_text << "\n\n";
    std::cerr << "[OmniEngine] BuildPlannerUserContext: memory_text length=" << memory_text.length() << std::endl;
  }

  user_context << "=== 世界状态 ===\n";
  user_context << world_snapshot_text << "\n\n";

  user_context << "=== 规则约束 ===\n";
  user_context << domain_rules_text << "\n\n";

  user_context << "=== 系统状态 ===\n";
  user_context << current_state_text << "\n\n";

  user_context << "=== 可用能力说明 ===\n";
  user_context << tools_desc << "\n";

  std::cerr << "[OmniEngine] BuildPlannerUserContext: tool_descriptions count="
            << tool_descriptions.size() << ", available_tools count=" << available_tools.size()
            << ", memory_text length=" << memory_text.length() << std::endl;

  return user_context.str();
}

std::string OmniEngine::ExtractJsonFromResponse(const std::string& full_text) {
  std::string json_str;

  // 第一优先级：严格按 <FINAL_JSON> 后面的内容解析
  size_t sep_pos = full_text.rfind(config_.model_response_separator);
  if (sep_pos != std::string::npos) {
    json_str = full_text.substr(sep_pos + config_.model_response_separator.length());
    json_str = Trim(json_str);

    if (!json_str.empty()) {
      try {
        auto j = json::parse(json_str);
        std::cerr << "[OmniEngine] ExtractJson: separator extraction success, json_len=" << json_str.length() << std::endl;
        return json_str;
      } catch (...) {
        std::cerr << "[OmniEngine] ExtractJson: separator found but parse failed" << std::endl;
      }
    }
  }

  // 第二优先级：从最后一个完整 JSON 对象兜底提取
  // 从后往前找最后一段合理 JSON
  size_t last_brace = full_text.rfind('{');
  if (last_brace != std::string::npos) {
    // 从 last_brace 开始向前扩展，尝试找到完整的 JSON 对象
    size_t search_start = last_brace;
    // 向前查找可能更早的 {，但只取最后一段完整 JSON
    size_t first_brace_candidate = search_start;

    // 尝试从 last_brace 开始匹配完整的 JSON
    size_t brace_count = 0;
    size_t json_start = last_brace;
    size_t json_end = std::string::npos;

    for (size_t i = last_brace; i < full_text.length(); ++i) {
      if (full_text[i] == '{') brace_count++;
      else if (full_text[i] == '}') brace_count--;
      if (brace_count == 0) {
        json_end = i + 1;
        break;
      }
    }

    if (json_end != std::string::npos) {
      std::string potential_json = full_text.substr(json_start, json_end - json_start);
      try {
        auto j = json::parse(potential_json);
        if (j.contains("request_id") || j.contains("plan")) {
          json_str = potential_json;
          std::cerr << "[OmniEngine] ExtractJson: fallback brace extraction success, json_len=" << json_str.length() << std::endl;
          return json_str;
        }
      } catch (...) {
        std::cerr << "[OmniEngine] ExtractJson: fallback extraction failed" << std::endl;
      }
    }
  }

  std::cerr << "[OmniEngine] ExtractJson: extraction failed, will use fallback" << std::endl;
  return "";
}

std::string OmniEngine::BuildFallbackJson() {
  json fallback;
  fallback["request_id"] = current_request_id_;
  fallback["session_id"] = current_session_id_;
  fallback["plan"] = json::object();
  fallback["plan"]["plan_id"] = GetPlanId();
  fallback["plan"]["goal"] = "无法可靠解析模型输出";
  fallback["plan"]["reasoning"] = "LLM 输出 JSON 解析失败，返回安全 fallback";
  fallback["plan"]["risk_level"] = "low";
  fallback["plan"]["requires_confirmation"] = false;
  fallback["plan"]["confirmation_message"] = nullptr;
  fallback["plan"]["steps"] = json::array();

  json step;
  step["step_id"] = 1;
  step["action"] = "ask_user";
  step["tool_call_type"] = "ask_user";
  step["parameters"] = json::object();
  step["parameters"]["question"] = config_.fallback_response_message;
  step["preconditions"] = json::object();
  step["fallback"] = nullptr;
  step["status"] = "pending";
  step["description"] = "fallback: 请求用户重新描述";
  step["requires_confirmation"] = false;
  step["confirmation_message"] = nullptr;
  step["metadata"] = json::object();
  step["metadata"]["fallback_reason"] = "json_parse_failed";

  fallback["plan"]["steps"].push_back(step);
  fallback["plan"]["status"] = "created";
  fallback["plan"]["source"] = "omni_fallback";
  fallback["plan"]["metadata"] = json::object();
  fallback["plan"]["metadata"]["response_type"] = "fallback";
  fallback["plan"]["metadata"]["fallback"] = true;

  std::cerr << "[OmniEngine] Fallback triggered: request_id=" << current_request_id_
            << ", session_id=" << current_session_id_
            << ", reason=json_parse_failed" << std::endl;

  return fallback.dump(2);
}

void OmniEngine::ExecuteFeed(const std::string& prompt, Mode mode) {
  accumulated_text_.clear();

  // 重置 planner 流式状态
  planner_separator_seen_ = false;
  planner_stream_emitted_len_ = 0;

  if (config_.online_mode) {
    omni_online_text_t text_input;
    text_input.system_text = prompt.c_str();
    text_input.user_text = "";

    int ret = xlm_omni_feed_text_online(handle_, text_input);
    if (ret != 0) {
      std::cerr << "[OmniEngine] xlm_omni_feed_text_online failed: " << ret << std::endl;
      fflush(stderr);
      return;
    }
  } else {
    json conversation = json::array();

    json system_msg;
    system_msg["role"] = "system";
    system_msg["content"] = json::array();
    system_msg["content"].push_back({
      {"type", "text"},
      {"text", prompt}
    });
    conversation.push_back(system_msg);

    json user_msg;
    user_msg["role"] = "user";
    user_msg["content"] = json::array();
    user_msg["content"].push_back({
      {"type", "text"},
      {"text", ""}
    });
    conversation.push_back(user_msg);

    json root;
    root["conversation"] = conversation;
    pending_json_ = root.dump();
    pending_json_file_ = WritePromptJsonToFile(pending_json_);
    if (pending_json_file_.empty()) {
      std::cerr << "[OmniEngine] Failed to create prompt json file" << std::endl;
      return;
    }
  }

  pending_requests_.resize(1);
  auto& request = pending_requests_[0];
  memset(&request, 0, sizeof(xlm_lm_request_t));
  request.type = XLM_INPUT_PROMPT;
  request.system_prompt = nullptr;
  request.prompt_json = config_.online_mode ? nullptr : pending_json_file_.c_str();
  if (config_.bpu_core == -1) {
    request.infer_backend = XLM_INFER_BACKEND_BPU_ANY;
  } else {
    // 直接使用 bpu_core 作为 backend 值
    request.infer_backend = static_cast<xlm_infer_backend>(config_.bpu_core);
  }

  xlm_input_s input;
  memset(&input, 0, sizeof(xlm_input_s));
  input.request_num = 1;
  input.requests = pending_requests_.data();

  int ret = xlm_omni(handle_, &input, nullptr);
  std::cerr << "[OmniEngine] xlm_omni returned: " << ret << std::endl;
  fflush(stderr);
  if (ret != 0) {
    std::cerr << "[OmniEngine] xlm_omni failed: " << ret << std::endl;
    fflush(stderr);
  }
}

void OmniEngine::ExecutePlannerFeed(const std::string& system_prompt, const std::string& user_context, Mode mode) {
  accumulated_text_.clear();

  // 重置 planner 流式状态
  planner_separator_seen_ = false;
  planner_stream_emitted_len_ = 0;

  std::cerr << "[OmniEngine] ExecutePlannerFeed: system_prompt_len=" << system_prompt.length()
            << ", user_context_len=" << user_context.length() << std::endl;

  if (config_.online_mode) {
    // online 模式：合并 system + user 作为完整 prompt
    std::string combined = system_prompt + "\n" + user_context;
    omni_online_text_t text_input;
    text_input.system_text = combined.c_str();
    text_input.user_text = "";

    int ret = xlm_omni_feed_text_online(handle_, text_input);
    if (ret != 0) {
      std::cerr << "[OmniEngine] ExecutePlannerFeed: xlm_omni_feed_text_online failed: " << ret << std::endl;
      fflush(stderr);
      return;
    }
  } else {
    // offline 模式：分 system/user message
    json conversation = json::array();

    // system message：规则与协议
    json system_msg;
    system_msg["role"] = "system";
    system_msg["content"] = json::array();
    system_msg["content"].push_back({
      {"type", "text"},
      {"text", system_prompt}
    });
    conversation.push_back(system_msg);

    // user message：当前请求上下文
    json user_msg;
    user_msg["role"] = "user";
    user_msg["content"] = json::array();
    user_msg["content"].push_back({
      {"type", "text"},
      {"text", user_context}
    });
    conversation.push_back(user_msg);

    json root;
    root["conversation"] = conversation;
    pending_json_ = root.dump();
    pending_json_file_ = WritePromptJsonToFile(pending_json_);
    if (pending_json_file_.empty()) {
      std::cerr << "[OmniEngine] ExecutePlannerFeed: Failed to create prompt json file" << std::endl;
      return;
    }
  }

  pending_requests_.resize(1);
  auto& request = pending_requests_[0];
  memset(&request, 0, sizeof(xlm_lm_request_t));
  request.type = XLM_INPUT_PROMPT;
  request.system_prompt = nullptr;
  request.prompt_json = config_.online_mode ? nullptr : pending_json_file_.c_str();
  if (config_.bpu_core == -1) {
    request.infer_backend = XLM_INFER_BACKEND_BPU_ANY;
  } else {
    // 直接使用 bpu_core 作为 backend 值
    request.infer_backend = static_cast<xlm_infer_backend>(config_.bpu_core);
  }

  xlm_input_s input;
  memset(&input, 0, sizeof(xlm_input_s));
  input.request_num = 1;
  input.requests = pending_requests_.data();

  int ret = xlm_omni(handle_, &input, nullptr);
  std::cerr << "[OmniEngine] ExecutePlannerFeed: xlm_omni returned: " << ret << std::endl;
  fflush(stderr);
  if (ret != 0) {
    std::cerr << "[OmniEngine] ExecutePlannerFeed: xlm_omni failed: " << ret << std::endl;
    fflush(stderr);
  }
}

void OmniEngine::FeedText(const std::string& user_text) {
  if (!config_.enable_legacy_asr_mode) {
    std::cerr << "[OmniEngine] Legacy ASR mode is disabled, ignoring FeedText" << std::endl;
    return;
  }

  current_mode_ = Mode::kLegacyDialog;
  current_request_id_.clear();
  current_session_id_.clear();

  std::cerr << "[OmniEngine] [Legacy Mode] Processing user text: " << user_text << std::endl;

  std::string prompt = BuildLegacyPrompt(user_text);
  ExecuteFeed(prompt, Mode::kLegacyDialog);
}

void OmniEngine::FeedPlannerRequest(const std::string& json_request) {
  if (!config_.enable_planner_mode) {
    std::cerr << "[OmniEngine] Planner mode is disabled, ignoring FeedPlannerRequest" << std::endl;
    return;
  }

  std::string request_id, session_id, user_text, memory_text, mode, planner_mode;
  json world_snapshot, available_tools, tool_descriptions, domain_rules, current_state;

  bool parse_success = ParsePlannerRequest(json_request, request_id, session_id,
                                           user_text, memory_text, mode, planner_mode,
                                           world_snapshot, available_tools,
                                           tool_descriptions,
                                           domain_rules, current_state);

  if (!parse_success) {
    std::cerr << "[OmniEngine] [Planner Mode] Parse failed, using fallback for request parsing" << std::endl;
  }

  current_mode_ = Mode::kPlannerDialog;
  current_request_id_ = request_id;
  current_session_id_ = session_id;

  std::cerr << "[OmniEngine] [Planner Mode] Processing request_id: " << request_id
            << ", session_id: " << session_id << ", user_text: " << user_text << std::endl;
  std::cerr << "[OmniEngine] [Planner Mode] tool_descriptions count: " << tool_descriptions.size()
            << ", memory_text length: " << memory_text.length() << std::endl;

  json request_data;
  request_data["request_id"] = request_id;
  request_data["session_id"] = session_id;
  request_data["user_text"] = user_text;
  request_data["memory_text"] = memory_text;  // 新增：记忆上下文
  request_data["mode"] = mode;
  request_data["planner_mode"] = planner_mode;
  request_data["world_snapshot"] = world_snapshot;
  request_data["available_tools"] = available_tools;
  request_data["tool_descriptions"] = tool_descriptions;
  request_data["domain_rules"] = domain_rules;
  request_data["current_state"] = current_state;

  std::string system_prompt = BuildPlannerSystemPrompt(request_data);
  std::string user_context = BuildPlannerUserContext(request_data);
  ExecutePlannerFeed(system_prompt, user_context, Mode::kPlannerDialog);
}

void OmniEngine::StaticCallback(xlm_result_s* result, xlm_state_e state, void* /* userdata */) {
  if (current_instance_ == nullptr) {
    return;
  }
  current_instance_->HandleCallback(result, state);
}

void OmniEngine::HandleCallback(xlm_result_s* result, xlm_state_e state) {
  std::string text;

  if (result != nullptr && result->text != nullptr) {
    std::string raw = result->text;

    if (!raw.empty() && raw.front() == '{') {
      try {
        auto j = json::parse(raw);
        if (j.is_object() && j.contains("text") && !j["text"].is_null()) {
          text = j["text"].get<std::string>();
        } else {
          text = raw;
        }
      } catch (...) {
        text = raw;
      }
    } else {
      text = raw;
    }
  }

  if (state == XLM_STATE_END) {
    std::cerr << "[OmniEngine] Inference END, mode=" << (current_mode_ == Mode::kPlannerDialog ? "planner" : "legacy")
              << ", accumulated_text length: " << accumulated_text_.length() << std::endl;

    // Planner mode 下打印完整 accumulated_text_ 便于调试
    if (current_mode_ == Mode::kPlannerDialog) {
      std::cerr << "[OmniEngine] Full accumulated_text (planner mode):\n" << accumulated_text_ << std::endl;
    }

    if (current_mode_ == Mode::kPlannerDialog) {
      std::cerr << "[OmniEngine] XLM_STATE_END in Planner mode, NOT calling stream_callback_" << std::endl;
      // 注意：新的 prefix guard 机制会在遇到 <FINAL 时停止发送
      // 推理结束时，accumulated_text_ 包含完整响应（包括分隔符和 JSON）
      // 无需再发送剩余内容

      std::string json_response = ExtractJsonFromResponse(accumulated_text_);

      if (json_response.empty()) {
        std::cerr << "[OmniEngine] JSON extraction failed, using fallback" << std::endl;
        json_response = BuildFallbackJson();
      } else {
        try {
          auto j = json::parse(json_response);

          // 补齐顶层字段
          if (!j.contains("request_id") || j["request_id"].is_null() ||
              j["request_id"].get<std::string>().empty()) {
            j["request_id"] = current_request_id_;
          }
          if (!j.contains("session_id") || j["session_id"].is_null() ||
              j["session_id"].get<std::string>().empty()) {
            j["session_id"] = current_session_id_;
          }

          // 补齐 plan 层字段
          if (!j.contains("plan") || !j["plan"].is_object()) {
            j["plan"] = json::object();
          }
          auto& plan = j["plan"];
          if (!plan.contains("status") || plan["status"].is_null()) {
            plan["status"] = "created";
          }
          if (!plan.contains("source") || plan["source"].is_null()) {
            plan["source"] = "llm";
          }
          if (!plan.contains("metadata") || !plan["metadata"].is_object()) {
            plan["metadata"] = json::object();
          }

          // 补齐每个 step 的字段
          if (plan.contains("steps") && plan["steps"].is_array()) {
            for (auto& step : plan["steps"]) {
              if (!step.contains("preconditions") || !step["preconditions"].is_object()) {
                step["preconditions"] = json::object();
              }
              if (!step.contains("fallback") || step["fallback"].is_null()) {
                step["fallback"] = nullptr;
              }
              if (!step.contains("status") || step["status"].is_null()) {
                step["status"] = "pending";
              }
              if (!step.contains("requires_confirmation")) {
                step["requires_confirmation"] = false;
              }
              if (!step.contains("confirmation_message") || step["confirmation_message"].is_null()) {
                step["confirmation_message"] = nullptr;
              }
              if (!step.contains("metadata") || !step["metadata"].is_object()) {
                step["metadata"] = json::object();
              }
            }
          }

          json_response = j.dump(2);
        } catch (...) {
          std::cerr << "[OmniEngine] JSON normalization failed, using fallback" << std::endl;
          json_response = BuildFallbackJson();
        }
      }

      std::cerr << "[OmniEngine] Publishing planner response: request_id="
                << current_request_id_ << ", is_fallback="
                << (json_response.find("omni_fallback") != std::string::npos ? "true" : "false")
                << ", json_length=" << json_response.length() << std::endl;

      if (planner_response_callback_) {
        planner_response_callback_(json_response, true);
      }
    } else if (current_mode_ == Mode::kLegacyDialog) {
      // Legacy Dialog 模式结束时，发送空消息作为流结束标记
      if (stream_callback_) {
        stream_callback_("", true);
      }
    }

    accumulated_text_.clear();
    // 重置 planner 流式状态
    planner_separator_seen_ = false;
    planner_stream_emitted_len_ = 0;

  } else if (state == XLM_STATE_ERROR) {
    std::cerr << "[OmniEngine] Inference error" << std::endl;

    if (current_mode_ == Mode::kPlannerDialog) {
      std::string json_response = BuildFallbackJson();
      if (planner_response_callback_) {
        planner_response_callback_(json_response, true);
      }
    }

    if (stream_callback_) {
      stream_callback_("[ERROR] Inference failed", true);
    }

    // 重置 planner 流式状态
    planner_separator_seen_ = false;
    planner_stream_emitted_len_ = 0;

  } else {
    if (!text.empty()) {
      accumulated_text_ += text;

      // Planner mode 流式处理：检测 "<" 分隔符
      if (current_mode_ == Mode::kPlannerDialog && stream_callback_) {
        // 如果已检测到分隔符，不再发送任何内容
        if (planner_separator_seen_) {
          // 停止发送
        } else {
          // 查找分隔符 "<"
          size_t sep_pos = accumulated_text_.find('<');

          if (sep_pos != std::string::npos) {
            // 发现 "<"，发送之前未发送过的自然语言内容
            size_t emit_start = planner_stream_emitted_len_;
            size_t emit_end = sep_pos;

            if (emit_end > emit_start) {
              std::string to_emit = accumulated_text_.substr(emit_start, emit_end - emit_start);
              if (!to_emit.empty()) {
                // 去除末尾空白字符
                size_t last_valid = to_emit.find_last_not_of(" \t\n\r");
                if (last_valid != std::string::npos) {
                  to_emit = to_emit.substr(0, last_valid + 1);
                }
                if (!to_emit.empty()) {
                  stream_callback_(to_emit, false);
                  std::cerr << "[OmniEngine] Planner emit len=" << to_emit.length()
                            << " (stopped at < separator)" << std::endl;
                }
              }
            }
            // 更新已发送位置
            planner_stream_emitted_len_ = emit_end;
            // 设置标志：已检测到分隔符，停止发送后续内容
            planner_separator_seen_ = true;
          } else {
            // 没有 "<"，发送 text
            stream_callback_(text, false);
            // 更新已发送位置为当前 accumulated_text_ 的长度
            planner_stream_emitted_len_ = accumulated_text_.length();
          }
        }
      }

      // Legacy Dialog 模式流式输出
      if (current_mode_ == Mode::kLegacyDialog && stream_callback_) {
        stream_callback_(text, false);
      }
    }
  }
}
