#include <softbus_core/models/ObjectModel.h>

#include <fstream>
#include <nlohmann/json.hpp>
#include <sstream>

namespace softbus::core {

std::string ObjectRef::toPath() const
{
    std::ostringstream oss;
    oss << site << '/' << system << '/' << asset << '/' << device;
    if (!point.empty()) {
        oss << '/' << point;
    }
    return oss.str();
}

ObjectRef ObjectRef::fromPath(const std::string& path)
{
    ObjectRef ref;
    std::istringstream iss(path);
    std::string token;
    std::string parts[5];
    int idx = 0;
    while (std::getline(iss, token, '/') && idx < 5) {
        parts[idx++] = token;
    }
    if (idx >= 4) {
        ref.site = parts[0];
        ref.system = parts[1];
        ref.asset = parts[2];
        ref.device = parts[3];
        if (idx >= 5) {
            ref.point = parts[4];
        }
    }
    return ref;
}

bool ObjectRef::isValid() const
{
    return !site.empty() && !system.empty() && !asset.empty() && !device.empty();
}

bool ObjectRef::hasPoint() const
{
    return isValid() && !point.empty();
}

bool ObjectModelTree::loadFromFile(const std::string& path)
{
    std::ifstream ifs(path);
    if (!ifs) {
        return false;
    }
    nlohmann::json j;
    ifs >> j;
    site = j.value("site", "");
    system = j.value("system", "");
    asset = j.value("asset", "");
    devices.clear();
    if (!j.contains("devices")) {
        return isValid();
    }
    for (const auto& dev : j["devices"]) {
        DeviceDef device;
        device.stableDeviceKey = dev.value("stableDeviceKey", "");
        device.protocol = dev.value("protocol", "");
        if (dev.contains("points")) {
            for (const auto& pt : dev["points"]) {
                PointDef point;
                point.name = pt.value("name", "");
                point.registerAddress = pt.value("register", 0);
                point.domain = pt.value("domain", "Process");
                point.signalType = pt.value("signalType", "AI");
                point.physicalChannel = pt.value("physicalChannel", "");
                point.unit = pt.value("unit", "");
                point.scale = pt.value("scale", 1.0);
                point.access = pt.value("access", "read");
                point.writable = pt.value("writable", false);
                if (pt.contains("range") && pt["range"].is_array() && pt["range"].size() >= 2) {
                    point.minValue = pt["range"][0].get<double>();
                    point.maxValue = pt["range"][1].get<double>();
                } else {
                    point.minValue = pt.value("min", 0.0);
                    point.maxValue = pt.value("max", 100.0);
                }
                if (point.access == "read_write" || point.access == "write") {
                    point.writable = true;
                }
                device.points.push_back(std::move(point));
            }
        }
        devices.push_back(std::move(device));
    }
    return isValid();
}

bool ObjectModelTree::isValid() const
{
    return !site.empty() && !system.empty() && !asset.empty();
}

} // namespace softbus::core
