/***************************************************************************
 * SPDX-FileCopyrightText: 2024 S. MANKOWSKI stephane@mankowski.fr
 * SPDX-FileCopyrightText: 2024 G. DE BURE support@mankowski.fr
 * SPDX-License-Identifier: GPL-3.0-or-later
 ***************************************************************************/
/** @file
* This file defines classes SKGBudgetRuleObject.
*
* @author Stephane MANKOWSKI / Guillaume DE BURE
*/
#include "skgbudgetruleobject.h"

#include <klocalizedstring.h>

#include "skgbudgetobject.h"
#include "skgcategoryobject.h"
#include "skgdocumentbank.h"
#include "skgtraces.h"
#include "skgtransactionmng.h"

SKGBudgetRuleObject::SKGBudgetRuleObject()
    : SKGBudgetRuleObject(nullptr)
{}

SKGBudgetRuleObject::SKGBudgetRuleObject(SKGDocument* iDocument, int iID)
    : SKGObjectBase(iDocument, QLatin1String("v_budgetrule"), iID)
{}

SKGBudgetRuleObject::~SKGBudgetRuleObject()
    = default;

SKGBudgetRuleObject::SKGBudgetRuleObject(const SKGBudgetRuleObject& iObject)
    = default;

SKGBudgetRuleObject::SKGBudgetRuleObject(const SKGObjectBase& iObject)
{
    if (iObject.getRealTable() == QLatin1String("budgetrule")) {
        copyFrom(iObject);
    } else {
        *this = SKGObjectBase(iObject.getDocument(), QLatin1String("v_budgetrule"), iObject.getID());
    }
}

SKGBudgetRuleObject& SKGBudgetRuleObject::operator= (const SKGObjectBase& iObject)
{
    copyFrom(iObject);
    return *this;
}

SKGError SKGBudgetRuleObject::enableYearCondition(bool iEnable)
{
    return setAttribute(QLatin1String("t_year_condition"), iEnable ? QLatin1String("Y") : QLatin1String("N"));
}

bool SKGBudgetRuleObject::isYearConditionEnabled() const
{
    return (getAttribute(QLatin1String("t_year_condition")) == QLatin1String("Y"));
}

SKGError SKGBudgetRuleObject::enableMonthCondition(bool iEnable)
{
    return setAttribute(QLatin1String("t_month_condition"), iEnable ? QLatin1String("Y") : QLatin1String("N"));
}

bool SKGBudgetRuleObject::isMonthConditionEnabled() const
{
    return (getAttribute(QLatin1String("t_month_condition")) == QLatin1String("Y"));
}

SKGError SKGBudgetRuleObject::enableCategoryCondition(bool iEnable)
{
    return setAttribute(QLatin1String("t_category_condition"), iEnable ? QLatin1String("Y") : QLatin1String("N"));
}

bool SKGBudgetRuleObject::isCategoryConditionEnabled() const
{
    return (getAttribute(QLatin1String("t_category_condition")) == QLatin1String("Y"));
}

SKGError SKGBudgetRuleObject::setBudgetYear(int iYear)
{
    return setAttribute(QLatin1String("i_year"), SKGServices::intToString(iYear));
}

int SKGBudgetRuleObject::getBudgetYear() const
{
    return SKGServices::stringToInt(getAttribute(QLatin1String("i_year")));
}

SKGError SKGBudgetRuleObject::setBudgetMonth(int iMonth)
{
    return setAttribute(QLatin1String("i_month"), SKGServices::intToString(iMonth));
}

int SKGBudgetRuleObject::getBudgetMonth() const
{
    return SKGServices::stringToInt(getAttribute(QLatin1String("i_month")));
}

SKGError SKGBudgetRuleObject::setBudgetCategory(const SKGCategoryObject& iCategory)
{
    return setAttribute(QLatin1String("rc_category_id"), SKGServices::intToString(iCategory.getID()));
}

SKGError SKGBudgetRuleObject::getBudgetCategory(SKGCategoryObject& oCategory) const
{
    return getDocument()->getObject(QLatin1String("v_category"), "id=" % getAttribute(QLatin1String("rc_category_id")), oCategory);
}

SKGError SKGBudgetRuleObject::removeBudgetCategory()
{
    return setAttribute(QLatin1String("rc_category_id"), QLatin1String("0"));
}

SKGError SKGBudgetRuleObject::setCondition(SKGBudgetRuleObject::Condition iCondition)
{
    return setAttribute(QLatin1String("i_condition"), SKGServices::intToString(static_cast<int>(iCondition)));
}

SKGBudgetRuleObject::Condition SKGBudgetRuleObject::getCondition() const
{
    return static_cast<SKGBudgetRuleObject::Condition>(SKGServices::stringToInt(getAttribute(QLatin1String("i_condition"))));
}

SKGError SKGBudgetRuleObject::setQuantity(double iQuantity, bool iAbsolute)
{
    SKGError err = setAttribute(QLatin1String("f_quantity"), SKGServices::doubleToString(iQuantity));
    IFOKDO(err, setAttribute(QLatin1String("t_absolute"), iAbsolute ? QLatin1String("Y") : QLatin1String("N")))
    return err;
}

double SKGBudgetRuleObject::getQuantity() const
{
    return SKGServices::stringToDouble(getAttribute(QLatin1String("f_quantity")));
}

bool SKGBudgetRuleObject::isAbolute() const
{
    return getAttribute(QLatin1String("t_absolute")) != QLatin1String("N");
}

SKGError SKGBudgetRuleObject::enableCategoryChange(bool iEnable)
{
    return setAttribute(QLatin1String("t_category_target"), iEnable ? QLatin1String("Y") : QLatin1String("N"));
}

bool SKGBudgetRuleObject::isCategoryChangeEnabled() const
{
    return getAttribute(QLatin1String("t_category_target")) == QLatin1String("Y");
}

SKGError SKGBudgetRuleObject::setTransfer(SKGBudgetRuleObject::Mode iMode, const SKGCategoryObject& iCategory)
{
    SKGError err = setAttribute(QLatin1String("t_rule"), iMode == NEXT ? QLatin1String("N") : iMode == CURRENT ? QLatin1String("C") : QLatin1String("Y"));
    IFOKDO(err, setAttribute(QLatin1String("rc_category_id_target"), SKGServices::intToString(iCategory.getID())))
    return err;
}

SKGBudgetRuleObject::Mode SKGBudgetRuleObject::getTransferMode() const
{
    return (getAttribute(QLatin1String("t_rule")) == QLatin1String("N") ? NEXT : (getAttribute(QLatin1String("t_rule")) == QLatin1String("C") ? CURRENT : YEAR));
}

SKGError SKGBudgetRuleObject::getTransferCategory(SKGCategoryObject& oCategory) const
{
    return getDocument()->getObject(QLatin1String("v_category"), "id=" % getAttribute(QLatin1String("rc_category_id_target")), oCategory);
}

SKGError SKGBudgetRuleObject::processAllRules(SKGDocumentBank* iDocument)
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err)
    if (iDocument != nullptr) {
        // Initialize
        err = iDocument->executeSqliteOrder(QLatin1String("UPDATE budget SET f_budgeted_modified=f_budgeted  WHERE f_budgeted_modified!=f_budgeted"));
        IFOKDO(err, iDocument->executeSqliteOrder(QLatin1String("UPDATE budget SET f_transferred=0  WHERE f_transferred!=0")))

        // Get budgets ordered by date
        SKGObjectBase::SKGListSKGObjectBase budgets;
        IFOKDO(err, iDocument->getObjects(QLatin1String("vm_budget_tmp"), QLatin1String("length(t_RULES)>0 "
                                          "AND (t_PERIOD<=STRFTIME('%Y-%m', date('now', 'localtime')) OR t_PERIOD=STRFTIME('%Y', date('now', 'localtime'))) "
                                          "ORDER BY t_PERIOD, id"), budgets));
        int nb = budgets.count();
        if (!err && nb > 0) {
            err = iDocument->beginTransaction("#INTERNAL#" % i18nc("Progression step", "Apply rules"), nb);
            for (int i = 0; !err && i < nb; ++i) {
                SKGBudgetObject bud(budgets.at(i));
                err = bud.load();  // Reload to be sure that delta has been updated
                IFOKDO(err, bud.process())

                IFOKDO(err, iDocument->stepForward(i + 1))
            }

            IFOKDO(err, iDocument->setParameter(QLatin1String("SKG_LAST_BUDGET_PROCESSING"), QDate::currentDate().toString(QLatin1String("yyyy-MM-dd"))))

            SKGENDTRANSACTION(iDocument,  err)
        }
    }

    return err;
}

SKGError SKGBudgetRuleObject::setOrder(double iOrder)
{
    SKGError err;
    double order = iOrder;
    if (order == -1) {
        order = 1;
        SKGStringListList result;
        err = getDocument()->executeSelectSqliteOrder(QLatin1String("SELECT max(f_sortorder) from budgetrule"), result);
        if (!err && result.count() == 2) {
            order = SKGServices::stringToDouble(result.at(1).at(0)) + 1;
        }
    }
    IFOKDO(err, setAttribute(QLatin1String("f_sortorder"), SKGServices::doubleToString(order)))
    return err;
}

double SKGBudgetRuleObject::getOrder() const
{
    return SKGServices::stringToDouble(getAttribute(QLatin1String("f_sortorder")));
}

