#include "message_bus/pipeline/DynamicRuleRegistry.h"

#include <mutex>
#include <shared_mutex>

namespace softbus::message_bus::pipeline
{

DynamicRuleRegistry& DynamicRuleRegistry::instance()
{
    static DynamicRuleRegistry registry;
    return registry;
}

bool DynamicRuleRegistry::addFilterRule(const FilterRule& rule)
{
    if (rule.id.isEmpty()) {
        return false;
    }
    std::unique_lock<std::shared_mutex> lk(m_mtx);
    m_filterRules.insert(rule.id, rule);
    return true;
}

bool DynamicRuleRegistry::removeFilterRule(const QString& id)
{
    std::unique_lock<std::shared_mutex> lk(m_mtx);
    return m_filterRules.remove(id) > 0;
}

bool DynamicRuleRegistry::addTransformRule(const TransformRule& rule)
{
    if (rule.id.isEmpty()) {
        return false;
    }
    std::unique_lock<std::shared_mutex> lk(m_mtx);
    m_transformRules.insert(rule.id, rule);
    return true;
}

bool DynamicRuleRegistry::removeTransformRule(const QString& id)
{
    std::unique_lock<std::shared_mutex> lk(m_mtx);
    return m_transformRules.remove(id) > 0;
}

std::vector<FilterRule> DynamicRuleRegistry::snapshotFilterRules(
    const QString& endpoint, int deviceId, const QString& stableKey) const
{
    std::shared_lock<std::shared_mutex> lk(m_mtx);
    std::vector<FilterRule> out;
    out.reserve(static_cast<std::size_t>(m_filterRules.size()));
    for (auto it = m_filterRules.constBegin(); it != m_filterRules.constEnd(); ++it) {
        if (matchScope(it.value().scope, endpoint, deviceId, stableKey)) {
            out.push_back(it.value());
        }
    }
    return out;
}

std::vector<TransformRule> DynamicRuleRegistry::snapshotTransformRules(
    const QString& endpoint, int deviceId, const QString& stableKey) const
{
    std::shared_lock<std::shared_mutex> lk(m_mtx);
    std::vector<TransformRule> out;
    out.reserve(static_cast<std::size_t>(m_transformRules.size()));
    for (auto it = m_transformRules.constBegin(); it != m_transformRules.constEnd(); ++it) {
        if (matchScope(it.value().scope, endpoint, deviceId, stableKey)) {
            out.push_back(it.value());
        }
    }
    return out;
}

QJsonObject DynamicRuleRegistry::status() const
{
    std::shared_lock<std::shared_mutex> lk(m_mtx);
    QJsonObject o;
    o.insert(QStringLiteral("filterRuleCount"), m_filterRules.size());
    o.insert(QStringLiteral("transformRuleCount"), m_transformRules.size());
    return o;
}

bool DynamicRuleRegistry::matchScope(
    const RuleScope& scope, const QString& endpoint, int deviceId, const QString& stableKey) const
{
    // hybrid scope: global + endpoint/device/stableKey selective match
    const bool endpointOk = scope.endpoint.isEmpty() || scope.endpoint == endpoint;
    const bool deviceOk = scope.deviceId < 0 || scope.deviceId == deviceId;
    const bool stableKeyOk = scope.stableKey.isEmpty() || scope.stableKey == stableKey;
    return endpointOk && deviceOk && stableKeyOk;
}

} // namespace softbus::message_bus::pipeline

