#include "CoreService.h"

#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray> 
#include <QDir>
#include <QFileInfo>

#include "utils/logs/logging.h"
#include "device_bus/DeviceBus.h"
#include "message_bus/pipeline/PayloadRef.h"
#include "message_bus/pipeline/PipelineContext.h"

CoreService* CoreService::instance()
{
    static CoreService inst;
    return &inst;
}

CoreService::CoreService(QObject* parent)
    : QObject(parent)
    , m_initialized(false)
{
}

CoreService::~CoreService()
{

}

bool CoreService::initialize()
{
    if (m_initialized) {
        LOG_WARNING() << "CoreService already initialized";
        return true;
    }

    LOG_INFO() << "CoreService initializing";
    qRegisterMetaType<softbus::message_bus::pipeline::PayloadRef>("softbus::message_bus::pipeline::PayloadRef");
    qRegisterMetaType<softbus::message_bus::pipeline::PipelineContext>("softbus::message_bus::pipeline::PipelineContext");

    // 1. 解析配置路径（放在用户 home 下的相对固定目录：~/softbus/config）
    const QString configPath =
        QDir::homePath() + QStringLiteral("/softbus/config/daemon_config.json");
    const QString deviceTreePath =
        QDir::homePath() + QStringLiteral("/softbus/config/device_tree.json");

    auto& bus = softbus::device_bus::DeviceBus::instance();
    bus.setConfigPath(configPath);
    bus.setDeviceTreePath(deviceTreePath);

    QJsonObject root;
    const QFileInfo fi(configPath);
    if (!fi.exists()) {
        LOG_WARNING() << "CoreService: config not found, skip load:" << configPath;
        root = QJsonObject{};
    } else {
        QFile f(configPath);
        if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
            LOG_ERROR() << "CoreService: failed to open" << configPath;
            return false;
        }

        const QByteArray data = f.readAll();
        f.close();

        QJsonParseError pe;
        const QJsonDocument doc = QJsonDocument::fromJson(data, &pe);
        if (pe.error != QJsonParseError::NoError || !doc.isObject()) {
            LOG_ERROR() << "CoreService: invalid JSON in" << configPath << ":" << pe.errorString();
            return false;
        }

        root = doc.object();
    }
    const QFileInfo treeFi(deviceTreePath);
    if (treeFi.exists()) {
        QFile treeFile(deviceTreePath);
        if (!treeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            LOG_ERROR() << "CoreService: failed to open" << deviceTreePath;
            return false;
        }
        const QByteArray treeData = treeFile.readAll();
        treeFile.close();

        QJsonParseError treePe;
        const QJsonDocument treeDoc = QJsonDocument::fromJson(treeData, &treePe);
        if (treePe.error != QJsonParseError::NoError || !treeDoc.isArray()) {
            LOG_ERROR() << "CoreService: invalid JSON array in" << deviceTreePath << ":" << treePe.errorString();
            return false;
        }
        root.insert(QStringLiteral("device_tree"), treeDoc.array());
    } else {
        if (!root.contains(QStringLiteral("device_tree")) || !root.value(QStringLiteral("device_tree")).isArray()) {
            root.insert(QStringLiteral("device_tree"), QJsonArray{});
        }
        bus.markDeviceTreeDirty(); // 首次独立设备树文件缺失：退出时落一份初始文件
    }

    auto resolvePluginPaths = [&](const QString& key) {
        QJsonObject plugins = root.value(QStringLiteral("plugins")).toObject();
        QJsonArray arr = plugins.value(key).toArray();
        if (arr.isEmpty()) {
            return;
        }

        const QString configDir = fi.dir().absolutePath();
        const QString appDir = QCoreApplication::applicationDirPath();
        for (int i = 0; i < arr.size(); ++i) {
            QJsonObject obj = arr.at(i).toObject();
            const QString rawPath = obj.value(QStringLiteral("path")).toString();
            if (rawPath.isEmpty() || QFileInfo(rawPath).isAbsolute()) {
                continue;
            }
            // 先尝试绝对路径，再尝试相对路径 TODO 后续可以优化为只尝试相对路径
            const QStringList candidates = {
                QDir(configDir).filePath(rawPath),
                QDir(configDir).filePath(QStringLiteral("../") + rawPath),
                QDir(appDir).filePath(rawPath),
                QDir(appDir).filePath(QStringLiteral("../") + rawPath),
            };

            QString resolved = rawPath;
            for (const auto& c : candidates) {
                if (QFileInfo::exists(c)) {
                    resolved = QFileInfo(c).absoluteFilePath();
                    break;
                }
            }
            obj.insert(QStringLiteral("path"), resolved);
            arr[i] = obj;
        }

        plugins.insert(key, arr);
        root.insert(QStringLiteral("plugins"), plugins);
    };
    resolvePluginPaths(QStringLiteral("protocols"));
    resolvePluginPaths(QStringLiteral("framers"));

    // 2. 初始化 device_bus（交给 DeviceBus facade 处理具体设备）
    if (!bus.initialize(root)) {
        return false;
    }

    m_initialized = true;
    return true;
}

void CoreService::shutdown()
{
    if (!m_initialized) {
        LOG_DEBUG() << "CoreService shutdown called while not initialized";
        return;
    }

    LOG_INFO() << "CoreService shutting down";
    softbus::device_bus::DeviceBus::instance().shutdown();
    m_initialized = false;
}

bool CoreService::isInitialized() const
{
    return m_initialized;
}
