#include "Source_Feed_Relation.h"
#include "Config.h"
#include "Global.h"
void Source_Feed_Relation::from_json(const Psc::JSON* that_json) {
    Get_J(key) Get_J(type)
    settings.write([&](auto& value) {
        value.from_base_json(that_json, true);
    });
}
Psc::JSON Source_Feed_Relation::to_json() const {
    auto ret = settings.read([](const auto& value) { return value.to_base_json(); });
    ret.append({"key", key});
    ret.append({"type", type});
    return ret;
}
void Source_Feed_Relation_Config::from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
    static_cast<void>(not_exist_use_default_value);
    auto j_list = that_json->get("list");
    for (const Psc::JSON& item : j_list->children) {
        auto relation = create_source_feed_relation_from_type(item.get_string("type"));
        relation->from_json(&item);
        validate(*relation);
        map.push_back(relation);
    }
}
Psc::JSON Source_Feed_Relation_Config::to_json() const {
    Psc::JSON ret = Psc::JSON::object();
    Psc::JSON list = Psc::JSON::array();
    for (const auto& relation : map.list())
        list.append(relation->to_json());
    ret.append(Psc::JSON("list", list));
    return ret;
}
void Source_Feed_Relation_Config::set_need_refresh() {
    for (const auto& source : Global::instance()->mode_acs.data_source_config.map.list())
        source->need_refresh_data_feed_key_list = true;
}
bool Source_Feed_Relation_Config::source_exists(std::string_view key) const {
    return Global::instance()->mode_acs.data_source_config.map.get(std::string(key)).has_value();
}
bool Source_Feed_Relation_Config::feed_exists(std::string_view key) const {
    return Global::instance()->mode_acs.data_feed_config.map.get(std::string(key)).has_value();
}
bool Source_Feed_Relation_Config::source_has_dependency(std::string_view key) const {
    for (const auto& relation : map.list()) {
        if (relation->type == "First_Source_To_All_Feed_Relation")
            continue;
        if (relation->settings.member<&Source_Feed_Relation_Data::source_key>().read([](const auto& value) { return value; }) == key)
            return true;
    }
    return false;
}
bool Source_Feed_Relation_Config::feed_has_dependency(std::string_view key) const {
    for (const auto& relation : map.list()) {
        const auto value = relation->settings.read([](const auto& value) { return value; });
        if (relation->type == "One_to_One_Relation" && value.feed_key == key)
            return true;
        if (relation->type == "Name_One_To_Many_Relation") {
            const auto& prefix = value.feed_name.empty() ? value.source_key : value.feed_name;
            if (key.starts_with(prefix))
                return true;
        }
    }
    return false;
}
void Source_Feed_Relation_Config::validate(const Source_Feed_Relation& relation, std::string_view current_key) const {
    if (relation.key.empty())
        throw std::invalid_argument("关系名称不能为空");
    auto existing = map.get(relation.key);
    if (existing.has_value() && relation.key != current_key)
        throw std::invalid_argument("关系名称已存在: " + relation.key);
    const auto value = relation.settings.read([](const auto& value) { return value; });
    if (relation.type == "One_to_One_Relation") {
        if (!source_exists(value.source_key))
            throw std::invalid_argument("数据源不存在: " + value.source_key);
        if (!feed_exists(value.feed_key))
            throw std::invalid_argument("数据馈送不存在: " + value.feed_key);
        for (const auto& item : map.list()) {
            if (item->key == current_key || item->type != "One_to_One_Relation")
                continue;
            if (item->settings.member<&Source_Feed_Relation_Data::feed_key>().read([](const auto& value) { return value; }) == value.feed_key)
                throw std::invalid_argument("数据馈送已存在一对一关系: " + value.feed_key);
        }
        return;
    }
    if (relation.type == "Name_One_To_Many_Relation") {
        if (!source_exists(value.source_key))
            throw std::invalid_argument("数据源不存在: " + value.source_key);
        return;
    }
    if (relation.type == "First_Source_To_All_Feed_Relation") {
        for (const auto& item : map.list()) {
            if (item->key != current_key && item->type == "First_Source_To_All_Feed_Relation")
                throw std::invalid_argument("默认关系只能存在一个");
        }
        return;
    }
    throw std::invalid_argument("未知关系类型: " + relation.type);
}
