#include "elementdao.h"
#include "../mapplication.h"

bool ElementDAO::create(const ElementData& element)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("INSERT INTO ELEMENT (CODE, TITLE, DESCRIPTION, UNIT_ID, TYPE1, PURCHASE_PRICE) "
                "VALUES (:CODE, :TITLE, :DESCRIPTION, :UNIT_ID, :TYPE1, :PURCHASE_PRICE)");
    qry.bindValue(":CODE", element.code);
    qry.bindValue(":TITLE", element.title);
    qry.bindValue(":DESCRIPTION", element.description);
    qry.bindValue(":UNIT_ID", element.unitId);
    qry.bindValue(":TYPE1", element.type1);
    qry.bindValue(":PURCHASE_PRICE", element.purchasePrice);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::create error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::read(const QString& code, ElementData& element)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("SELECT * FROM ELEMENT WHERE CODE = :CODE");
    qry.bindValue(":CODE", code);

    bool ok = qry.exec();
    if (ok && qry.next()) {
        element.code = code;
        element.title = qry.value("TITLE").toString();
        element.description = qry.value("DESCRIPTION").toString();
        element.unitId = qry.value("UNIT_ID").toString();
        element.type1 = qry.value("TYPE1").toInt();
        element.purchasePrice = qry.value("PURCHASE_PRICE").toDouble();
        // Add other fields as needed
    } else {
        ok = false;
        qDebug() << "ElementDAO::read error:" << qry.lastError().text();
    }
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::update(const ElementData& element)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("UPDATE ELEMENT SET "
                "TITLE = :TITLE, DESCRIPTION = :DESCRIPTION, UNIT_ID = :UNIT_ID, "
                "TYPE1 = :TYPE1, PURCHASE_PRICE = :PURCHASE_PRICE "
                "WHERE CODE = :CODE");
    qry.bindValue(":CODE", element.code);
    qry.bindValue(":TITLE", element.title);
    qry.bindValue(":DESCRIPTION", element.description);
    qry.bindValue(":UNIT_ID", element.unitId);
    qry.bindValue(":TYPE1", element.type1);
    qry.bindValue(":PURCHASE_PRICE", element.purchasePrice);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::update error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::remove(const QString& code)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("DELETE FROM ELEMENT WHERE CODE = :CODE");
    qry.bindValue(":CODE", code);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::remove error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::exists(const QString& code)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("SELECT COUNT(*) FROM ELEMENT WHERE CODE = :CODE");
    qry.bindValue(":CODE", code);
    bool exists = false;
    if (qry.exec() && qry.next())
        exists = qry.value(0).toInt() > 0;
    dApp->Enterprise().close();
    return exists;
}

// Composition methods
QVector<ElementDAO::CompositionItem> ElementDAO::getComposition(const QString& elementCode)
{
    QVector<CompositionItem> composition;
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("SELECT ELEMENT_CODE, ELEMENT_AMOUNT FROM ELEMENTCOMPOSITION WHERE CODE = :CODE");
    qry.bindValue(":CODE", elementCode);

    if (qry.exec()) {
        while (qry.next()) {
            CompositionItem item;
            item.childElementCode = qry.value("ELEMENT_CODE").toString();
            item.amount = qry.value("ELEMENT_AMOUNT").toDouble();
            composition.append(item);
        }
    }
    dApp->Enterprise().close();
    return composition;
}

bool ElementDAO::addCompositionElement(const QString& elementCode, const QString& childElementCode, double amount)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("INSERT INTO ELEMENTCOMPOSITION (CODE, ELEMENT_CODE, ELEMENT_AMOUNT) "
                "VALUES (:CODE, :ELEMENT_CODE, :ELEMENT_AMOUNT)");
    qry.bindValue(":CODE", elementCode);
    qry.bindValue(":ELEMENT_CODE", childElementCode);
    qry.bindValue(":ELEMENT_AMOUNT", amount);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::addCompositionElement error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::removeCompositionElement(const QString& elementCode, const QString& childElementCode)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = :CODE AND ELEMENT_CODE = :ELEMENT_CODE");
    qry.bindValue(":CODE", elementCode);
    qry.bindValue(":ELEMENT_CODE", childElementCode);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::removeCompositionElement error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::updateCompositionElement(const QString& elementCode, const QString& childElementCode, double amount)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("UPDATE ELEMENTCOMPOSITION SET ELEMENT_AMOUNT = :AMOUNT "
                "WHERE CODE = :CODE AND ELEMENT_CODE = :ELEMENT_CODE");
    qry.bindValue(":CODE", elementCode);
    qry.bindValue(":ELEMENT_CODE", childElementCode);
    qry.bindValue(":AMOUNT", amount);

    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::updateCompositionElement error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}

bool ElementDAO::removeAllComposition(const QString& elementCode)
{
    dApp->Enterprise().open();
    QSqlQuery qry(dApp->Enterprise());
    qry.prepare("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = :CODE");
    qry.bindValue(":CODE", elementCode);
    bool ok = qry.exec();
    if (!ok) qDebug() << "ElementDAO::removeAllComposition error:" << qry.lastError().text();
    dApp->Enterprise().close();
    return ok;
}