#ifndef OMNI_ENGINE_HPP_
#define OMNI_ENGINE_HPP_

#include <string>
#include <vector>
#include <functional>
#include <memory>
#include <iostream>

#include "xlm.h"

#if __has_include(<nlohmann/json.hpp>)
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#else
namespace nlohmann {
  template<typename T> class basic_json;
}
using json = nlohmann::basic_json<int>;
#endif

class OmniEngine {
public:
  enum class Mode {
    kLegacyDialog = 0,
    kPlannerDialog = 1,
  };

  using StreamCallback = std::function<void(const std::string&, bool)>;
  using PlannerResponseCallback = std::function<void(const std::string&, bool)>;

  struct Config {
    std::string visual_hbm_path;
    std::string audio_hbm_path;
    std::string text_hbm_path;
    std::string embed_tokens;
    std::string tokenizer_dir;
    int32_t model_type;
    bool online_mode;
    int32_t bpu_core;
    std::string system_prompt;

    bool enable_legacy_asr_mode;
    bool enable_planner_mode;
    std::string dialog_system_prompt;
    std::string planner_system_prompt;
    std::string model_response_separator;
    std::string fallback_response_message;

    // planner 规则配置
    std::string planner_output_protocol;
    std::string planner_input_classification;
    std::string planner_ask_user_rules;
    std::string planner_capability_rules;
    std::string planner_example1_user;
    std::string planner_example1_response;
    std::string planner_example1_json;
    std::string planner_example2_user;
    std::string planner_example2_response;
    std::string planner_example2_json;
    std::string planner_prohibited;
  };

  explicit OmniEngine(const std::string& config_path);
  ~OmniEngine();

  OmniEngine(const OmniEngine&) = delete;
  OmniEngine& operator=(const OmniEngine&) = delete;

  bool Init();
  void SetStreamCallback(StreamCallback callback);
  void SetPlannerResponseCallback(PlannerResponseCallback callback);

  void FeedText(const std::string& user_text);
  void FeedPlannerRequest(const std::string& json_request);

  Mode GetCurrentMode() const { return current_mode_; }
  std::string GetCurrentRequestId() const { return current_request_id_; }
  std::string GetCurrentSessionId() const { return current_session_id_; }

  // 用于 Node 层同步配置，避免两层配置不一致
  void SetEnableMode(bool enable_legacy_asr_mode, bool enable_planner_mode) {
    config_.enable_legacy_asr_mode = enable_legacy_asr_mode;
    config_.enable_planner_mode = enable_planner_mode;
    std::cerr << "[OmniEngine] Mode sync from Node: legacy=" << enable_legacy_asr_mode
              << ", planner=" << enable_planner_mode << std::endl;
  }

private:
  static OmniEngine* current_instance_;
  static void StaticCallback(xlm_result_s* result, xlm_state_e state, void* userdata);
  void HandleCallback(xlm_result_s* result, xlm_state_e state);

  std::string BuildLegacyPrompt(const std::string& user_text);
  std::string BuildPlannerSystemPrompt(const json& request_data);
  std::string BuildPlannerUserContext(const json& request_data);
  std::string BuildToolDescriptions(const json& available_tools);

  std::string ExtractJsonFromResponse(const std::string& full_text);
  std::string BuildFallbackJson();

  bool 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);

  void ExecuteFeed(const std::string& prompt, Mode mode);
  void ExecutePlannerFeed(const std::string& system_prompt, const std::string& user_context, Mode mode);

  std::string config_path_;
  Config config_;
  xlm_handle_t handle_;
  StreamCallback stream_callback_;
  PlannerResponseCallback planner_response_callback_;

  Mode current_mode_;
  std::string current_request_id_;
  std::string current_session_id_;
  std::string accumulated_text_;
  std::string pending_json_;
  std::string pending_json_file_;
  std::vector<xlm_lm_request_t> pending_requests_;

  // Planner 流式状态管理
  bool planner_separator_seen_;     // 是否已检测到 <FINAL_JSON> 分隔符
  size_t planner_stream_emitted_len_; // 已发送给 /llm_response 的文本长度
};

#endif  // OMNI_ENGINE_HPP_
