/**
 * Copyright (c) 2026 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

#ifndef GE_FRAMEWORK_RUNTIME_DUMP_DUMP_CONFIG_H_
#define GE_FRAMEWORK_RUNTIME_DUMP_DUMP_CONFIG_H_

#include <cstdint>
#include <string>
#include <unordered_set>
#include <mutex>
#include <vector>
#include "common/ge_common/ge_types.h"
#include "nlohmann/json.hpp"

namespace ge {
namespace dump {

const uint32_t ACL_GE_INVALID_DUMP_CONFIG = 100009U;
constexpr int32_t MAX_DUMP_PATH_LENGTH = 512;
constexpr int32_t MAX_IPV4_ADDRESS_LENGTH = 4;
constexpr int32_t MAX_IPV4_ADDRESS_VALUE = 255;
constexpr int32_t DECIMAL = 10;
const uint64_t AIC_ERR_BRIEF_DUMP_BIT = 0x4;
const uint64_t AIC_ERR_NORM_DUMP_BIT = 0x8;

const std::string GE_DUMP_MODE_INPUT = "input";
const std::string GE_DUMP_MODE_OUTPUT = "output";
const std::string GE_DUMP_MODE_ALL = "all";
const std::string GE_DUMP_STATUS_ON = "on";
const std::string GE_DUMP_STATUS_OFF = "off";
const std::string GE_DUMP_LEVEL_OP = "op";
const std::string GE_DUMP_LEVEL_KERNEL = "kernel";
const std::string GE_DUMP_LEVEL_ALL = "all";
const std::string GE_DUMP = "dump";

constexpr uint32_t kAicoreOverflow = 0x1U;
constexpr uint32_t kAtomicOverflow = 0x2U;
constexpr uint32_t kAllOverflow = kAicoreOverflow | kAtomicOverflow;

const std::string GE_DUMP_PATH = "dump_path";
const std::string GE_DUMP_MODE = "dump_mode";
const std::string GE_DUMP_STATUS = "dump_status";
const std::string GE_DUMP_OP_SWITCH = "dump_op_switch";
const std::string GE_DUMP_DEBUG = "dump_debug";
const std::string GE_DUMP_STEP = "dump_step";
const std::string GE_DUMP_DATA = "dump_data";
const std::string GE_DUMP_LEVEL = "dump_level";
const std::string GE_DUMP_STATS = "dump_stats";
const std::string GE_DUMP_LIST = "dump_list";
const std::string GE_DUMP_MODEL_NAME = "model_name";
const std::string GE_DUMP_LAYER = "layer";
const std::string GE_DUMP_WATCHER_NODES = "watcher_nodes";
const std::string GE_DUMP_OPTYPE_BLACKLIST = "optype_blacklist";
const std::string GE_DUMP_OPNAME_BLACKLIST = "opname_blacklist";
const std::string GE_DUMP_BLACKLIST_NAME = "name";
const std::string GE_DUMP_BLACKLIST_POS = "pos";
const std::string GE_DUMP_OPNAME_RANGE = "opname_range";
const std::string GE_DUMP_OPNAME_RANGE_BEGIN = "begin";
const std::string GE_DUMP_OPNAME_RANGE_END = "end";
const std::string GE_DUMP_SCENE = "dump_scene";
const std::string GE_DUMP_LITE_EXCEPTION = "lite_exception";
const std::string GE_DUMP_EXCEPTION_AIC_ERR_BRIEF = "aic_err_brief_dump";
const std::string GE_DUMP_EXCEPTION_AIC_ERR_NORM = "aic_err_norm_dump";
const std::string GE_DUMP_EXCEPTION_AIC_ERR_DETAIL = "aic_err_detail_dump";
const std::string GE_DUMP_SCENE_WATCHER = "watcher";

const std::string GE_DUMP_MODE_DEFAULT = "output";
const std::string GE_DUMP_STATUS_DEFAULT = "on";
const std::string GE_DUMP_OP_SWITCH_DEFAULT = "off";
const std::string GE_DUMP_DEBUG_DEFAULT = "off";
const std::string GE_DUMP_STEP_DEFAULT = "";
const std::string GE_DUMP_DATA_DEFAULT = "tensor";
const std::string GE_DUMP_LEVEL_DEFAULT = "all";
const std::string GE_DUMP_SCENE_DEFAULT = "";

class DumpConfig {
 public:
  static DumpConfig &Instance();

  // 开关
  bool IsDataDumpEnabled() const;
  bool IsExceptionDumpEnabled() const;
  bool IsOverflowDumpEnabled() const;

  void SetDataDumpEnabled(bool enabled);
  void SetExceptionDumpEnabled(bool enabled);
  void SetOverflowDumpEnabled(bool enabled);

  // 配置项
  const std::string &GetDumpPath() const;
  const std::string &GetDumpStep() const;
  const std::string &GetDumpMode() const;
  const std::string &GetDumpData() const;
  const std::unordered_set<std::string> &GetOpList() const;

  void SetDumpPath(const std::string &path);
  void SetDumpStep(const std::string &step);
  void SetDumpMode(const std::string &mode);
  void SetDumpData(const std::string &data);
  void SetOpList(const std::unordered_set<std::string> &op_list);

  // 重置配置
  void Reset();

  // 新增:完整配置解析与校验
  Status ParseAndValidate(const char *dumpData, int32_t size);
  bool IsValidDumpConfig(const nlohmann::json &js) const;

  // 新增:完整 Dump 支持的配置获取接口
  const std::string &GetDumpLevel() const;
  const std::string &GetDumpStatus() const;
  const std::string &GetDumpOpSwitch() const;
  const std::string &GetDumpDebug() const;
  uint32_t GetOpDebugMode() const;
  const std::vector<std::string> &GetDumpStats() const;
  const std::string &GetDumpScene() const;
  const std::vector<ModelDumpConfig> &GetModelDumpConfigList() const;

  // 配置是否需要 Dump
  bool NeedDump() const;

  // 判断该算子是否需要 dump
  bool IsOpNeedDump(const std::string &model_name, const std::string &root_graph_name,
                    const std::string &op_name) const;

 private:
  DumpConfig() = default;
  ~DumpConfig() = default;

  // 检查 OM2 不支持的配置项并打印 warning
  static void CheckUnsupportedConfigs(const nlohmann::json &jsDumpConfig);

  // 校验辅助函数
  static bool CheckDumpSceneSwitch(const nlohmann::json &jsDumpConfig, std::string &dumpScene);
  static bool CheckDumpPath(const nlohmann::json &jsDumpConfig);
  static bool CheckDumpStep(const nlohmann::json &jsDumpConfig);
  static bool CheckDumplist(const nlohmann::json &jsDumpConfig, const std::string &dumpLevel);
  static bool CheckDumpOpSwitch(const std::string &dumpOpSwitch);
  static bool CheckIpAddress(const DumpConfig &config);
  static bool ValidateIpAddress(const std::string &ipAddress);
  static bool IsDumpPathValid(const std::string &dumpPath);
  static bool DumpDebugCheck(const nlohmann::json &jsDumpConfig);
  static bool DumpStatsCheck(const nlohmann::json &jsDumpConfig);
  static bool IsDumpDebugEnabled(const nlohmann::json &jsDumpConfig);
  static bool ValidateNormalDumpConfig(const nlohmann::json &jsDumpConfig);
  static bool ValidateDumpPath(const nlohmann::json &jsDumpConfig);
  static bool ValidateDumpMode(const nlohmann::json &jsDumpConfig);
  static bool ValidateDumpLevel(const nlohmann::json &jsDumpConfig);
  static bool ValidateOtherDumpConfigs(const nlohmann::json &jsDumpConfig);
  static std::string GetDumpLevel(const nlohmann::json &jsDumpConfig);
  static bool CheckDumpModelConfig(const nlohmann::json &modelJson);

  // 解析辅助函数
  Status ParseDumpConfigFromJson(const nlohmann::json &dumpJson);
  void ParseBasicConfigurations(const nlohmann::json &dumpJson);
  void ParseComplexConfigs(const nlohmann::json &dumpJson);
  static bool ParseModelDumpConfig(const nlohmann::json &modelJson, ModelDumpConfig &modelConfig);
  static void ParseBlacklist(const nlohmann::json &blacklistJson, DumpBlacklist &blacklist);
  static void ParseStringArray(const nlohmann::json &jsonArray, std::vector<std::string> &output);
  static void ParseModelDumpConfigList(const nlohmann::json &jsonArray, std::vector<ModelDumpConfig> &output);
  static std::string GetConfigWithDefault(const nlohmann::json &json, const std::string &key,
                                          const std::string &defaultValue);
  static std::vector<std::string> Split(const std::string &str, const char_t *const delimiter);

  mutable std::mutex mutex_;

  bool data_dump_enabled_ = false;
  bool exception_dump_enabled_ = false;
  bool overflow_dump_enabled_ = false;

  std::string dump_path_;
  std::string dump_step_;
  std::string dump_mode_;
  std::string dump_data_;
  std::unordered_set<std::string> op_list_;

  // 新增:扩展配置字段
  std::string dump_level_;
  std::string dump_status_;
  std::string dump_op_switch_;
  std::string dump_debug_;
  uint32_t op_debug_mode_ = 0U;
  std::vector<std::string> dump_stats_;
  std::string dump_scene_;  // 对应原始 dump_exception
  std::vector<ModelDumpConfig> model_dump_config_list_;
};

}  // namespace dump
}  // namespace ge

#endif  // GE_COMMON_DUMP_DUMP_CONFIG_H_