// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2025 Derek Lin <derekhongdalin@gmail.com>

#include "vmlistmodel.h"

#include "karton.h"
#include "karton_debug.h"

VMModel::VMModel(QObject *parent)
    : QAbstractListModel(parent)
    , m_karton(Karton::self())
{
    // qCDebug(KARTON_DEBUG) << "vmmodellist: Karton instance:" << m_karton;
    if (m_karton) {
        connect(m_karton, &Karton::domainsChanged, this, &VMModel::onDomainsChanged);
        refreshAllDomains();
    } else {
        qCCritical(KARTON_DEBUG) << "vmmodellist: karton is null!";
    }
}
int VMModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return m_datas.size();
}

VMModel::~VMModel()
{
    m_datas.clear();
}

VMModel *VMModel::self()
{
    static VMModel *v = new VMModel(Karton::self());
    return v;
}

VMModel *VMModel::create(QQmlEngine *qmlEngine, QJSEngine *)
{
    Q_UNUSED(qmlEngine);

    return VMModel::self();
}

QVariant VMModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= m_datas.size()) {
        return {};
    }

    const Domain *domain = m_datas[index.row()];

    if (role == DomainRole) {
        return QVariant::fromValue(domain);
    }
    return {};
}
QHash<int, QByteArray> VMModel::roleNames() const
{
    return {{DomainRole, "domain"}};
}

void VMModel::onDomainsChanged(const virDomainPtr domainPtr, int event, int detail)
{
    Q_UNUSED(event);
    Q_UNUSED(detail);

    if (domainPtr) {
        updateDomains(domainPtr);
    }
}
void VMModel::refreshAllDomains()
{
    qCInfo(KARTON_DEBUG) << "vmlistmodel: Refreshing all domains.";
    beginResetModel();
    m_datas.clear();
    m_karton->refreshDomainList();
    m_datas = m_karton->domains();
    endResetModel();
}

void VMModel::updateDomains(const virDomainPtr domainPtr)
{
    QString domainUuid = Domain::uuidString(domainPtr);
    qCDebug(KARTON_DEBUG) << "Domain UUID:" << domainUuid;

    bool domainExists = false;
    virDomainInfo info;
    int ret = virDomainGetInfo(domainPtr, &info);
    domainExists = (ret == 0);

    if (!domainExists) {
        refreshAllDomains();
        return;
    }

    int modelIndex = -1;
    for (int i = 0; i < m_datas.size(); ++i) {
        if (m_datas[i]->config()->uuid() == domainUuid) {
            modelIndex = i;
            break;
        }
    }

    if (modelIndex >= 0) {
        qCDebug(KARTON_DEBUG) << "Found matching domain in model at index" << modelIndex;
        m_karton->refreshDomain(domainPtr);

        QModelIndex qModelIndex = createIndex(modelIndex, 0);
        Q_EMIT dataChanged(qModelIndex, qModelIndex);
    } else {
        refreshAllDomains();
    }
}