#pragma once

#include <nlohmann/json.hpp>
#include <fstream>
#include <memory>
#include <iostream>
#include <common/Spdlogger.h>

using njson = nlohmann::json;

/// =============================================================================================
/// 使用说明：
 
/// 创建 -------------
// json j;
// j["name"] = "Alice";
// j["age"] = 25;
// j["address"] = {{"city", "Beijing"}, {"country", "China"}};

/// 字符串解析 -------------
// json::parse(R"({"name": "Alice", "age": 25})");
// 说明：解析失败会抛出异常
// try {
//    auto j = json::parse("invalid json");
// }
// catch (json::parse_error& e) {
//    std::cerr << "JSON 解析错误: " << e.what() << std::endl;
// }

/// 文件解析 -------------
// std::ifstream file("data.json");
// json j;
// file >> j;

/// 访问 JSON 数据 -------------
// std::string name = j["name"]; // 直接访问
// int age = j.at("age");        // 使用 at() 检查 key 是否存在
// auto address = j["address"];  // 获取数组

/// 序列化为字符串 -------------
// std::string json_str = j.dump(4); // 4 表示缩进，美化输出

/// 数组解析 -------------
// json jArray = json::array()
// jArray.push_back(1);
// jArray.push_back(2);
// json j;
// j["data"] = {1,2,3,4,5};
// std::vector<int> v1;
// v1 = j.at["data"].get<std::vector<int>>()

class JSON
{
public:
    static bool load(std::string jsonfile, njson& json);

    static bool parse(std::string jsonstr, njson& json);
    
    template <typename T>
    static bool read(njson& json, std::string k, T& v)
    {
        try 
        { 
            if (json.contains(k)) 
            { 
                v = json.at(k).get<T>(); 
                return true;
            } 
        }
        catch (const nlohmann::detail::exception& e) { Spdlogger::info("JSON read error: k={}, err={}", k, e.what()); }
        return false;
    }

    template <typename T>
    static T read(njson& json, std::string k)
    {
        T v {};
        try { if (json.contains(k)) { v = json.at(k).get<T>(); } }
        catch (const nlohmann::detail::exception& e) { Spdlogger::info("JSON read error: k={}, err={}", k, e.what()); }
        return v;
    }

    template <typename T> 
    static T get(njson& json)
    {
        T v {};
        try { v = json.get<T>(); }
        catch (const nlohmann::detail::exception& e) { Spdlogger::info("JSON read error: err={}, json={}", e.what(), json.dump()); }
        return v;
    }

    static std::string readStr(njson& json, std::string k);
    
    static std::string toStr(njson& json);

    template <typename T>
    static void parseArray(std::string jsonstr, std::vector<T>& vd)
    {
        njson json;
        if (JSON::parse(jsonstr, json))
        {
            try { vd = json.get<std::vector<T>>(); }
            catch (const nlohmann::detail::exception& e) { Spdlogger::info("JSON read error: err={}, json={}", e.what(), json.dump()); }
        }
    }
};


