/***************************************************************************
 * SPDX-FileCopyrightText: 2026 S. MANKOWSKI stephane@mankowski.fr
 * SPDX-License-Identifier: GPL-3.0-or-later
 ***************************************************************************/
#include "skgmreferenceproxymodel.h"

#include "skgobjectmodelbase.h"
#include "skgservices.h"

#include <klocalizedstring.h>

#include "skgtraces.h"
#include <qabstractproxymodel.h>
#include <qlocale.h>
#include <qstringbuilder.h>

SKGMReferenceProxyModel::SKGMReferenceProxyModel(QObject *iParent)
    : QIdentityProxyModel(iParent)
{
}

void SKGMReferenceProxyModel::setKind(ReferenceKind iKind)
{
    if (m_kind == iKind) {
        return;
    }
    m_kind = iKind;
    if (rowCount() > 0) {
        Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0));
    }
}

void SKGMReferenceProxyModel::setObjectModel(const SKGObjectModelBase *iObjectModel)
{
    m_objectModel = iObjectModel;
}

void SKGMReferenceProxyModel::setAmountUnitSymbol(const QString &iSymbol)
{
    if (m_amountUnitSymbol == iSymbol) {
        return;
    }
    m_amountUnitSymbol = iSymbol;
    if (rowCount() > 0) {
        Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AmountTextRole});
    }
}

QVariant SKGMReferenceProxyModel::data(const QModelIndex &iIndex, int iRole) const
{
    SKGTRACEINFUNC(1)
    if (!iIndex.isValid() || m_objectModel == nullptr) {
        return {};
    }

    const QModelIndex sourceIndex = mapToSource(iIndex);
    if (!sourceIndex.isValid()) {
        return {};
    }

    switch (iRole) {
    case NameRole:
        switch (m_kind) {
        case TrackerKind:
        case PayeeKind:
            return stringAttribute(sourceIndex, QStringLiteral("t_name"));
        case CategoryKind:
            return stringAttribute(sourceIndex, QStringLiteral("t_fullname"));
        case UnitKind: {
            const QString name = stringAttribute(sourceIndex, QStringLiteral("t_name"));
            const QString symbol = stringAttribute(sourceIndex, QStringLiteral("t_symbol"));
            return symbol.isEmpty() ? name : name % QStringLiteral(" (") % symbol % u')';
        }
        }
        break;
    case SubtitleRole:
        switch (m_kind) {
        case TrackerKind: {
            const QString operations = stringAttribute(sourceIndex, QStringLiteral("i_NBOPERATIONS"));
            return operations.isEmpty() ? QString() : i18nc("@info:tracker operations", "%1 transactions", operations);
        }
        case PayeeKind: {
            const QString category = stringAttribute(sourceIndex, QStringLiteral("t_CATEGORY"));
            const QString operations = stringAttribute(sourceIndex, QStringLiteral("i_NBOPERATIONS"));
            if (operations.isEmpty()) {
                return category;
            }
            return category.isEmpty() ? i18nc("@info:payee operations", "%1 transactions", operations)
                                      : i18nc("@info:payee subtitle", "%1 - %2 operations", category, operations);
        }
        case CategoryKind: {
            const QString operations = stringAttribute(sourceIndex, QStringLiteral("i_SUMNBOPERATIONS"));
            return operations.isEmpty() ? QString() : i18nc("@info:category operations", "%1 transactions", operations);
        }
        case UnitKind:
            return stringAttribute(sourceIndex, QStringLiteral("t_TYPENLS"));
        }
        break;
    case AmountRole:
        switch (m_kind) {
        case TrackerKind:
        case PayeeKind:
            return doubleAttribute(sourceIndex, QStringLiteral("f_CURRENTAMOUNT"));
        case CategoryKind:
            return doubleAttribute(sourceIndex, QStringLiteral("f_SUMCURRENTAMOUNT"));
        case UnitKind:
            return doubleAttribute(sourceIndex, QStringLiteral("f_AMOUNTOWNED"));
        }
        break;
    case AmountTextRole: {
        const double amount = data(iIndex, AmountRole).toDouble();
        return formatAmount(amount);
    }
    case ClosedRole:
        if (m_kind == TrackerKind) {
            return stringAttribute(sourceIndex, QStringLiteral("t_close")) == QStringLiteral("Y");
        }
        return false;
    default:
        return QIdentityProxyModel::data(iIndex, iRole);
    }

    return {};
}

QHash<int, QByteArray> SKGMReferenceProxyModel::roleNames() const
{
    return {
        {NameRole, "name"},
        {SubtitleRole, "subtitle"},
        {AmountRole, "amount"},
        {AmountTextRole, "amountText"},
        {ClosedRole, "closed"},
    };
}

QString SKGMReferenceProxyModel::stringAttribute(const QModelIndex &iSourceIndex, const QString &iAttribute) const
{
    SKGTRACEINFUNC(1)
    const QModelIndex objectIndex = mapToObjectModelIndex(iSourceIndex);
    if (!objectIndex.isValid()) {
        return {};
    }
    return m_objectModel->getObject(objectIndex).getAttribute(iAttribute);
}

double SKGMReferenceProxyModel::doubleAttribute(const QModelIndex &iSourceIndex, const QString &iAttribute) const
{
    SKGTRACEINFUNC(1)
    const QModelIndex objectIndex = mapToObjectModelIndex(iSourceIndex);
    if (!objectIndex.isValid()) {
        return 0.0;
    }
    return SKGServices::stringToDouble(m_objectModel->getObject(objectIndex).getAttribute(iAttribute));
}

QModelIndex SKGMReferenceProxyModel::mapToObjectModelIndex(const QModelIndex &iSourceIndex) const
{
    SKGTRACEINFUNC(1)
    QModelIndex current = iSourceIndex;
    const QAbstractItemModel *model = sourceModel();
    while (auto proxy = qobject_cast<const QAbstractProxyModel *>(model)) {
        current = proxy->mapToSource(current);
        model = proxy->sourceModel();
    }
    if (model != m_objectModel) {
        return {};
    }
    return current;
}

QString SKGMReferenceProxyModel::formatAmount(double iAmount) const
{
    QString text = QLocale().toString(iAmount, 'f', 2);
    if (!m_amountUnitSymbol.isEmpty()) {
        text = text % u' ' % m_amountUnitSymbol;
    }
    return text;
}
