// 简化版JSON库 - 仅包含测试所需功能
#ifndef SIMPLE_JSON_HPP
#define SIMPLE_JSON_HPP

#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <stdexcept>
#include <cstdint>
#include <cmath>

namespace simple {

class json {
public:
    enum class type_t {
        null,
        boolean,
        number,
        string,
        array,
        object
    };

    json() : type_(type_t::null) {}
    json(std::nullptr_t) : type_(type_t::null) {}
    json(bool b) : type_(type_t::boolean), bool_val_(b) {}
    json(int n) : type_(type_t::number), num_val_(n) {}
    json(int64_t n) : type_(type_t::number), num_val_(static_cast<double>(n)) {}
    json(uint64_t n) : type_(type_t::number), num_val_(static_cast<double>(n)) {}
    json(double n) : type_(type_t::number), num_val_(n) {}
    json(const char* s) : type_(type_t::string), str_val_(s) {}
    json(const std::string& s) : type_(type_t::string), str_val_(s) {}

    type_t type() const { return type_; }
    bool is_null() const { return type_ == type_t::null; }
    bool is_bool() const { return type_ == type_t::boolean; }
    bool is_number() const { return type_ == type_t::number; }
    bool is_string() const { return type_ == type_t::string; }
    bool is_array() const { return type_ == type_t::array; }
    bool is_object() const { return type_ == type_t::object; }

    size_t size() const {
        if (type_ == type_t::array) return arr_val_.size();
        if (type_ == type_t::object) return obj_val_.size();
        return 0;
    }

    // Array access
    json& operator[](size_t idx) {
        if (type_ != type_t::array) {
            type_ = type_t::array;
            arr_val_.clear();
        }
        if (idx >= arr_val_.size()) arr_val_.resize(idx + 1);
        return arr_val_[idx];
    }

    const json& operator[](size_t idx) const {
        static json null_val;
        if (type_ != type_t::array || idx >= arr_val_.size()) return null_val;
        return arr_val_[idx];
    }

    // Object access
    json& operator[](const std::string& key) {
        if (type_ != type_t::object) {
            type_ = type_t::object;
            obj_val_.clear();
        }
        return obj_val_[key];
    }

    const json& operator[](const std::string& key) const {
        static json null_val;
        if (type_ != type_t::object) return null_val;
        auto it = obj_val_.find(key);
        return (it != obj_val_.end()) ? it->second : null_val;
    }

    // const char* overload to avoid ambiguity
    json& operator[](const char* key) {
        return (*this)[std::string(key)];
    }

    const json& operator[](const char* key) const {
        return (*this)[std::string(key)];
    }

    bool contains(const std::string& key) const {
        return type_ == type_t::object && obj_val_.find(key) != obj_val_.end();
    }

    // Value getters
    bool get_bool() const { return bool_val_; }
    double get_double() const { return num_val_; }
    int64_t get_int64() const { return static_cast<int64_t>(num_val_); }
    uint64_t get_uint64() const { return static_cast<uint64_t>(num_val_); }
    int get_int() const { return static_cast<int>(num_val_); }
    const std::string& get_string() const { return str_val_; }

    // Implicit conversions
    operator bool() const { return type_ == type_t::boolean ? bool_val_ : false; }
    operator int() const { return static_cast<int>(num_val_); }
    operator int64_t() const { return static_cast<int64_t>(num_val_); }
    operator uint64_t() const { return static_cast<uint64_t>(num_val_); }
    operator double() const { return num_val_; }
    operator std::string() const { return str_val_; }

    // Push back for arrays
    void push_back(const json& val) {
        if (type_ != type_t::array) {
            type_ = type_t::array;
            arr_val_.clear();
        }
        arr_val_.push_back(val);
    }

    // Serialization
    std::string dump(int indent = -1) const {
        std::ostringstream ss;
        dump_impl(ss, indent >= 0 ? indent : -1, 0);
        return ss.str();
    }

    static json parse(const std::string& str) {
        size_t pos = 0;
        return parse_impl(str, pos);
    }

    static json array() {
        json j;
        j.type_ = type_t::array;
        return j;
    }

    static json object() {
        json j;
        j.type_ = type_t::object;
        return j;
    }

    // Iterator support for arrays
    std::vector<json>::iterator begin() { return arr_val_.begin(); }
    std::vector<json>::iterator end() { return arr_val_.end(); }
    std::vector<json>::const_iterator begin() const { return arr_val_.begin(); }
    std::vector<json>::const_iterator end() const { return arr_val_.end(); }

    // Get object items
    std::map<std::string, json>::const_iterator obj_begin() const { return obj_val_.begin(); }
    std::map<std::string, json>::const_iterator obj_end() const { return obj_val_.end(); }

private:
    type_t type_ = type_t::null;
    bool bool_val_ = false;
    double num_val_ = 0.0;
    std::string str_val_;
    std::vector<json> arr_val_;
    std::map<std::string, json> obj_val_;

    void dump_impl(std::ostringstream& ss, int indent, int level) const {
        switch (type_) {
            case type_t::null:
                ss << "null";
                break;
            case type_t::boolean:
                ss << (bool_val_ ? "true" : "false");
                break;
            case type_t::number:
                if (num_val_ == static_cast<int64_t>(num_val_)) {
                    ss << static_cast<int64_t>(num_val_);
                } else {
                    ss << num_val_;
                }
                break;
            case type_t::string:
                ss << '"';
                for (char c : str_val_) {
                    switch (c) {
                        case '"': ss << "\\\""; break;
                        case '\\': ss << "\\\\"; break;
                        case '\n': ss << "\\n"; break;
                        case '\r': ss << "\\r"; break;
                        case '\t': ss << "\\t"; break;
                        default: ss << c;
                    }
                }
                ss << '"';
                break;
            case type_t::array:
                ss << '[';
                if (indent >= 0) {
                    ss << '\n';
                    for (int i = 0; i <= level; ++i) ss << std::string(indent, ' ');
                }
                for (size_t i = 0; i < arr_val_.size(); ++i) {
                    if (i > 0) {
                        ss << ',';
                        if (indent >= 0) ss << '\n' << std::string((level + 1) * indent, ' ');
                    }
                    arr_val_[i].dump_impl(ss, indent, level + 1);
                }
                if (indent >= 0) ss << '\n' << std::string(level * indent, ' ');
                ss << ']';
                break;
            case type_t::object:
                ss << '{';
                if (indent >= 0) ss << '\n' << std::string((level + 1) * indent, ' ');
                bool first = true;
                for (const auto& p : obj_val_) {
                    if (!first) {
                        ss << ',';
                        if (indent >= 0) ss << '\n' << std::string((level + 1) * indent, ' ');
                    }
                    first = false;
                    ss << '"' << p.first << "\":";
                    if (indent >= 0) ss << ' ';
                    p.second.dump_impl(ss, indent, level + 1);
                }
                if (indent >= 0) ss << '\n' << std::string(level * indent, ' ');
                ss << '}';
                break;
        }
    }

    static json parse_impl(const std::string& str, size_t& pos) {
        skip_whitespace(str, pos);
        if (pos >= str.size()) throw std::runtime_error("Unexpected end of input");

        char c = str[pos];
        if (c == 'n') {
            pos += 4;
            return json();
        } else if (c == 't') {
            pos += 4;
            return json(true);
        } else if (c == 'f') {
            pos += 5;
            return json(false);
        } else if (c == '"') {
            return json(parse_string(str, pos));
        } else if (c == '[') {
            return parse_array(str, pos);
        } else if (c == '{') {
            return parse_object(str, pos);
        } else if (c == '-' || std::isdigit(c)) {
            return parse_number(str, pos);
        }
        throw std::runtime_error(std::string("Unexpected character: ") + c);
    }

    static void skip_whitespace(const std::string& str, size_t& pos) {
        while (pos < str.size() && std::isspace(str[pos])) ++pos;
    }

    static std::string parse_string(const std::string& str, size_t& pos) {
        ++pos; // skip opening quote
        std::string result;
        while (pos < str.size() && str[pos] != '"') {
            if (str[pos] == '\\' && pos + 1 < str.size()) {
                ++pos;
                switch (str[pos]) {
                    case '"': result += '"'; break;
                    case '\\': result += '\\'; break;
                    case 'n': result += '\n'; break;
                    case 'r': result += '\r'; break;
                    case 't': result += '\t'; break;
                    default: result += str[pos];
                }
            } else {
                result += str[pos];
            }
            ++pos;
        }
        if (pos < str.size()) ++pos; // skip closing quote
        return result;
    }

    static json parse_number(const std::string& str, size_t& pos) {
        size_t start = pos;
        if (str[pos] == '-') ++pos;
        while (pos < str.size() && std::isdigit(str[pos])) ++pos;
        if (pos < str.size() && str[pos] == '.') {
            ++pos;
            while (pos < str.size() && std::isdigit(str[pos])) ++pos;
        }
        if (pos < str.size() && (str[pos] == 'e' || str[pos] == 'E')) {
            ++pos;
            if (pos < str.size() && (str[pos] == '+' || str[pos] == '-')) ++pos;
            while (pos < str.size() && std::isdigit(str[pos])) ++pos;
        }
        return json(std::stod(str.substr(start, pos - start)));
    }

    static json parse_array(const std::string& str, size_t& pos) {
        json arr = json::array();
        ++pos; // skip '['
        skip_whitespace(str, pos);
        if (pos < str.size() && str[pos] == ']') {
            ++pos;
            return arr;
        }
        while (pos < str.size()) {
            arr.push_back(parse_impl(str, pos));
            skip_whitespace(str, pos);
            if (pos >= str.size() || str[pos] == ']') {
                ++pos;
                break;
            }
            if (str[pos] == ',') ++pos;
            skip_whitespace(str, pos);
        }
        return arr;
    }

    static json parse_object(const std::string& str, size_t& pos) {
        json obj = json::object();
        ++pos; // skip '{'
        skip_whitespace(str, pos);
        if (pos < str.size() && str[pos] == '}') {
            ++pos;
            return obj;
        }
        while (pos < str.size()) {
            skip_whitespace(str, pos);
            if (str[pos] != '"') throw std::runtime_error("Expected string key");
            std::string key = parse_string(str, pos);
            skip_whitespace(str, pos);
            if (pos >= str.size() || str[pos] != ':') throw std::runtime_error("Expected ':'");
            ++pos;
            obj[key] = parse_impl(str, pos);
            skip_whitespace(str, pos);
            if (pos >= str.size() || str[pos] == '}') {
                ++pos;
                break;
            }
            if (str[pos] == ',') ++pos;
        }
        return obj;
    }
};

// Type alias for compatibility
using nlohmann_json = json;

} // namespace simple

namespace nlohmann {
    using json = simple::json;
}

#endif // SIMPLE_JSON_HPP
