#include "formbudget.h"
#include "ui_formbudget.h"
#include "qmtreeview.h"
#include "treemodel.h"
#include "treeitem.h"
#include "mapplication.h"

#include "../src/elementtype.h"

#include "widgetcomboboxpopuptable.h"

#include "itemnumberdelegate.h"
#include "itemtextdelegate.h"
#include "itemtextpopupdelegate.h"
#include "itemcomboboxdelegate.h"

#include <QStringList>
#include <QFile>
#include <QAction>
#include <QtSql>
#include "utils/dbutils.h"

formBudget::formBudget(QString aID, int amEditMode, QWidget *parent) :
    formBase(aID, amEditMode, parent),
    ui(new Ui::formBudget),
    m_changed(false)
{
    ui->setupUi(this);
    setupTreeView();
    setupConnections();

    // Prueba:
    connect(dApp, &QApplication::focusChanged, this, [=](QWidget* old, QWidget* now)
    {
        //qDebug() << "old: " << old << "\n" << "new: " << now;
        if (!this->isAncestorOf(old))
            qDebug() << "Se deshabilita la toolbox";

        //Q_UNUSED(old);
        //if (now != this && !this->isAncestorOf(now))
        if (now == this && !this->isAncestorOf(now))
        {
            //hide();
            qDebug() << "Se habilita la toolbox";
        }
    });

    dApp->Enterprise().open();
    QSqlQuery qry = QSqlQuery(dApp->Enterprise());
    if (qry.exec(QString("SELECT ID FROM SALEPROPOSAL ORDER BY ID DESC LIMIT 1;")))
    {
        int val = 0;
        while(qry.next())
            val = qry.value(qry.record().indexOf("ID")).toInt();

        ui->editCode->setText(QString("(PRO%1)").arg(val + 1));
    }

    dApp->Enterprise().close();

    // Connect form fields to track changes
    connect(ui->editTitle, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
    connect(ui->editClientCode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
    connect(ui->editClientName, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
    connect(ui->editProjectCode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
    connect(ui->editProjectName, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
    connect(ui->editCost, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
    connect(ui->editCost, &QLineEdit::textChanged, this, &formBudget::updateMargin);
    connect(ui->editPrice, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
    connect(ui->editPrice, &QLineEdit::textChanged, this, &formBudget::updateMargin);
    connect(ui->editdateCreated, &QDateEdit::dateChanged, this, &formBudget::onAnyChange);
    connect(ui->editdateValidUntill, &QDateEdit::dateChanged, this, &formBudget::onAnyChange);
    connect(ui->editVersion, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
}


formBudget::~formBudget()
{
    delete ui;
}

void formBudget::setupTreeView()
{
    QStringList headers = {
        tr("Índice"), tr("Código"), tr("Título"), tr("Descripción"),
        tr("Cantidad"), tr("Cantidad total"), tr("Unidad"),
        tr("N. Precio Unitario"), tr("N. Precio Total"), tr("Ganacia"),
        tr("Descuento"), tr("Precio Venta"), tr("Margen"), tr("Tipo"),
        tr("Imprimir"), tr("")
    };

    m_treeModel = new TreeModel(headers, QByteArray(), this);
    ui->treeView->setModel(m_treeModel);

    // Configurar anchos de columna
    QVector<int> widths = {120, 120, 250, 250, 80, 80, 50, 80, 80, 80, 80, 80, 80, 40};
    for (int i = 0; i < widths.size(); ++i) {
        ui->treeView->setColumnWidth(i, widths[i]);
    }

    ui->treeView->setColumnHidden(3, true);

    // Configurar delegados
    setupDelegates();
}

void formBudget::setupDelegates()
{
    // Texto con Popup
    auto* lineTextPopup = new ItemTextPopupDelegate(this);
    ui->treeView->setItemDelegateForColumn(1, lineTextPopup);

    // Texto simple
    auto* lineTextEditor = new ItemTextDelegate(this);
    ui->treeView->setItemDelegateForColumn(0, lineTextEditor);
    ui->treeView->setItemDelegateForColumn(2, lineTextEditor);

    // Números
    auto* doubleNumberEditor = new ItemNumberDelegate(0.0, 999999.99, 0.05, 2, this);
    ui->treeView->setItemDelegateForColumn(4, doubleNumberEditor);
    ui->treeView->setItemDelegateForColumn(7, doubleNumberEditor);
    ui->treeView->setItemDelegateForColumn(9, doubleNumberEditor);
    ui->treeView->setItemDelegateForColumn(10, doubleNumberEditor);

    // Combobox
    auto* comboboxEditor = new ItemComboboxDelegate(this);
    ui->treeView->setItemDelegateForColumn(6, comboboxEditor);

    connect(m_treeModel, &TreeModel::dataChanged,
            this, &formBudget::onModelDataChanged);
}

void formBudget::setupConnections()
{
    connect(ui->buttonInsertRow, &QPushButton::released,
            this, &formBudget::on_buttonInsertRow_released);

    connect(ui->buttonInsertChild, &QPushButton::released,
            this, &formBudget::on_buttonInsertChild_released);

    connect(ui->buttonRemoveRow, &QPushButton::released,
            this, &formBudget::on_buttonRemoveRow_released);

    // ... otras conexiones ...
}

void formBudget::initializeDocument()
{
    if (m_dbUtils.isConnected()) {
        QString lastId = m_dbUtils.getLastDocumentId("SALEPROPOSAL");
        ui->editCode->setText(QString("(PRO%1)").arg(lastId.toInt() + 1));
    }
}

void formBudget::newDocument()
{

}

void formBudget::openDocument(QString id)
{
    formBase::openDocument(id);
    m_changed = false;
}

void formBudget::save()
{
    QString budget;
    QString budgetdata;

    if(mEditMode == false)
    {
        budget = "INSERT INTO SALEPROPOSAL ("
                "ID, TYPE, CODE, TITLE, VERSION, "
                "CUSTOMER_CODE, CUSTOMER_NAME, PROJECT_CODE, PROJECT_TITLE, "
                "COST, PRICE, TAX, STATE, STATE_NUMBER, DESCRIPTION, "
                "CREATEDAT, VALIDUNTILL, DELIVERY_DATE, CREATEDBY"
                ") VALUES ("
                ":ID, :TYPE, :CODE, :TITLE, :VERSION, "
                ":CUSTOMER_CODE, :CUSTOMER_NAME, :PROJECT_CODE, :PROJECT_TITLE, "
                ":COST, :PRICE, :TAX, :STATE, :STATE_NUMBER, :DESCRIPTION, "
                ":CREATEDAT, :VALIDUNTILL, :DELIVERY_DATE, :CREATEDBY"
                ");";

        budgetdata = "INSERT INTO SALEPROPOSALDATA ("
                "ID, SALEDOCUMENT_CODE, VERSION, NODEINDEX, "
                "ELEMENT_CODE, ELEMENT_TYPE, ELEMENT_INDEX, ELEMENT_TITLE, ELEMENT_DESCRIPTION, "
                "ELEMENT_UNIT_AMOUNT, ELEMENT_TOTAL_AMOUNT, ELEMENT_UNIT, ELEMENT_PRICE, "
                "BENEFIT, DISCOUNT, TAX, PRINT, "
                "CREATEDAT, CREATEDBY"
                ") VALUES ("
                ":ID, :SALEDOCUMENT_CODE, :VERSION, :NODEINDEX, "
                ":ELEMENT_CODE, :ELEMENT_TYPE, :ELEMENT_INDEX, :ELEMENT_TITLE, :ELEMENT_DESCRIPTION, "
                ":ELEMENT_UNIT_AMOUNT, :ELEMENT_TOTAL_AMOUNT, :ELEMENT_UNIT, :ELEMENT_PRICE, "
                ":BENEFIT, :DISCOUNT,  :TAX, :PRINT, "
                ":CREATEDAT, :CREATEDBY"
                ");";
    }
    else
    {
        budget = "UPDATE SALEPROPOSAL SET "
                ":ID, :TYPE, :CODE, :TITLE, :VERSION, "
                ":CUSTOMER_CODE, :CUSTOMER_NAME, :PROJECT_CODE, :PROJECT_TITLE, "
                ":COST, :PRICE, :TAX, :STATE, :STATE_NUMBER, :DESCRIPTION, "
                ":CREATEDAT, :VALIDUNTILL, :DELIVERY_DATE, :CREATEDBY "
                "WHERE CODE = :CODE"
                ";";

        budgetdata = "UPDATE SALEPROPOSALDATA SET "
                ":ID, :SALEDOCUMENT_CODE, :VERSION, :NODEINDEX, "
                ":ELEMENT_CODE, :ELEMENT_TYPE, :ELEMENT_INDEX, :ELEMENT_TITLE, :ELEMENT_DESCRIPTION, "
                ":ELEMENT_UNIT_AMOUNT, :ELEMENT_TOTAL_AMOUNT, :ELEMENT_UNIT, :ELEMENT_PRICE, "
                ":BENEFIT, :DISCOUNT, :TAX, :PRINT, "
                ":CREATEDAT, :CREATEDBY "
                "WHERE CODE = :CODE"
                ";";
    }

    dApp->Enterprise().open();
    QSqlQuery qry = QSqlQuery(dApp->Enterprise());

    // 1. Guardar los datos:
    QAbstractItemModel *model = ui->treeView->model();

    // Borrar toda las filas al final que están vacias
    //  -- de momento se hace chequeando si la columna 13 está vacía
    /*
    int count = model->rowCount() - 1;
    for (int i = model->rowCount() - 1; i >= 0; i--)
    {
        count = i;

        QString dat = model->index(i, 13).data().toString();
        if(!dat.isEmpty())
            break;
    }

    for (int i = 0; i <= count; i++)
    {
        qry.prepare(budgetdata);
        qry.bindValue(":ID",                    i);
        qry.bindValue(":SALEDOCUMENT_CODE",     ui->editCode->text());
        qry.bindValue(":VERSION",               ui->editVersion->currentText());
        qry.bindValue(":NODEINDEX",             model->index(i, 0).data().toString());
        qry.bindValue(":ELEMENT_CODE",          model->index(i, 1).data().toString());
        qry.bindValue(":ELEMENT_TYPE",          model->index(i, 13).data().toString());
        qry.bindValue(":ELEMENT_TITLE",         model->index(i, 2).data().toString());
        qry.bindValue(":ELEMENT_DESCRIPTION",   model->index(i, 3).data().toString());
        qry.bindValue(":ELEMENT_UNIT_AMOUNT",   model->index(i, 4).data().toDouble());
        //qry.bindValue(":ELEMENT_TOTAL_AMOUNT",  model->index(i, 2).data().toDouble());
        qry.bindValue(":ELEMENT_UNIT",          model->index(i, 6).data().toString());
        qry.bindValue(":ELEMENT_PRICE",         model->index(i, 7).data().toString());
        qry.bindValue(":BENEFIT",               model->index(i, 9).data().toString());
        qry.bindValue(":DISCOUNT",              model->index(i, 10).data().toString());
        //qry.bindValue(":TAX",                   model->index(i, 10).data().toString());
        //qry.bindValue(":PRINT",                 model->index(i, 10).data().toBool());

        if(!qry.exec())
        {
            qDebug() << "" << qry.lastError().text();
            continue;
        }
    }
    */



    // 2. Si todo fue bien, guardar el documento:
    qry.prepare(budget);
    //qry.bindValue(":ID",);
    qry.bindValue(":TYPE", "");
    qry.bindValue(":CODE", ui->editCode->text());
    qry.bindValue(":TITLE", ui->editTitle->text());
    qry.bindValue(":VERSION", ui->editVersion->currentText());
    qry.bindValue(":CUSTOMER_CODE", ui->editClientCode->currentText());
    qry.bindValue(":CUSTOMER_NAME", ui->editClientName->text());
    qry.bindValue(":PROJECT_CODE", ui->editProjectCode->currentText());
    qry.bindValue(":PROJECT_TITLE", ui->editProjectName->text());
    qry.bindValue(":COST", ui->editCost->text());
    qry.bindValue(":PRICE", ui->editPrice->text());
    //qry.bindValue(":TAX", );
    qry.bindValue(":STATE", ui->editPrice->text());
    qry.bindValue(":STATE_NUMBER", ui->editPrice->text());
    //qry.bindValue(":DESCRIPTION", );
    QSqlQuery qrySave(dApp->Enterprise());
    qrySave.prepare(budget);
    //qrySave.bindValue(":ID",);
    qrySave.bindValue(":TYPE", "");
    qrySave.bindValue(":CODE", ui->editCode->text());
    qrySave.bindValue(":TITLE", ui->editTitle->text());
    qrySave.bindValue(":VERSION", ui->editVersion->currentText());
    qrySave.bindValue(":CUSTOMER_CODE", ui->editClientCode->currentText());
    qrySave.bindValue(":CUSTOMER_NAME", ui->editClientName->text());
    qrySave.bindValue(":PROJECT_CODE", ui->editProjectCode->currentText());
    qrySave.bindValue(":PROJECT_TITLE", ui->editProjectName->text());
    qrySave.bindValue(":COST", ui->editCost->text());
    qrySave.bindValue(":PRICE", ui->editPrice->text());
    //qrySave.bindValue(":TAX", );
    qrySave.bindValue(":STATE", ui->editPrice->text());
    qrySave.bindValue(":STATE_NUMBER", ui->editPrice->text());
    //qrySave.bindValue(":DESCRIPTION", );
    qrySave.bindValue(":CREATEDAT", ui->editdateCreated->text());
    qrySave.bindValue(":VALIDUNTILL", ui->editdateValidUntill->text());
    // No hay campo para creado por en la UI, dejamos vacío o NULL según la base de datos

    if(!qrySave.exec())
    {
        qDebug() << "" << qrySave.lastError().text();
        dApp->Enterprise().close();
        return;
    }

    // 3. Guardar los datos de las líneas:
    int rowCount = model->rowCount();
    for (int i = 0; i < rowCount; i++)
    {
        qry.prepare(budgetdata);
        qry.bindValue(":ID",                    i);
        qry.bindValue(":SALEDOCUMENT_CODE",     ui->editCode->text());
        qry.bindValue(":VERSION",               ui->editVersion->currentText());
        qry.bindValue(":NODEINDEX",             model->index(i, 0).data().toString());
        qry.bindValue(":ELEMENT_CODE",          model->index(i, 1).data().toString());
        qry.bindValue(":ELEMENT_TYPE",          model->index(i, 13).data().toString());
        qry.bindValue(":ELEMENT_TITLE",         model->index(i, 2).data().toString());
        qry.bindValue(":ELEMENT_DESCRIPTION",   model->index(i, 3).data().toString());
        qry.bindValue(":ELEMENT_UNIT_AMOUNT",   model->index(i, 4).data().toDouble());
        //qry.bindValue(":ELEMENT_TOTAL_AMOUNT",  model->index(i, 2).data().toDouble());
        qry.bindValue(":ELEMENT_UNIT",          model->index(i, 6).data().toString());
        qry.bindValue(":ELEMENT_PRICE",         model->index(i, 7).data().toString());
        qry.bindValue(":BENEFIT",               model->index(i, 9).data().toString());
        qry.bindValue(":DISCOUNT",              model->index(i, 10).data().toString());
        //qry.bindValue(":TAX",                   model->index(i, 10).data().toString());
        //qry.bindValue(":PRINT",                 model->index(i, 10).data().toBool());

        if(!qry.exec())
        {
            qDebug() << "" << qry.lastError().text();
            continue;
        }
    }

    dApp->Enterprise().close();
    m_changed = false;
}

bool formBudget::needsave()
{
    // Basic change tracker implemented via m_changed and UI connections
    return m_changed;
}

void formBudget::setEditMode(bool aMode)
{
    mEditMode = aMode;
}

void formBudget::closeDocument()
{
    // TODO: implementar lógica de cierre
    // Por ahora, solo limpiamos el flag de cambios
    m_changed = false;
}

void formBudget::setLineType(QString type, QModelIndex index)
{
    setCellText(type, index, 13);
}

void formBudget::setCellText(QString val, QModelIndex index, int col)
{
    QAbstractItemModel *model = ui->treeView->model();
    model->setData(model->index(index.row(), col, index.parent()), val);
}

bool formBudget::InsertElement(QString ID, QModelIndex index)
{
    QSqlQuery qry(dApp->Enterprise());
    if (qry.exec(QString("SELECT * FROM ELEMENT WHERE CODE = '%1';").arg(ID)))
    {
        qry.first();
        setCellText(qry.value(qry.record().indexOf("TITLE")).toString(), index, 2);         // TITLE
        setCellText(qry.value(qry.record().indexOf("DESCRIPTION")).toString(), index, 3);   // DESCRIPTION
        setCellText(qry.value(qry.record().indexOf("UNIT_ID")).toString(), index, 6);       // UNIT

        if (qry.value(qry.record().indexOf("TYPE1")).toInt() == 0)
        {
            QSqlQuery comp = QSqlQuery(dApp->Enterprise());
            QAbstractItemModel *treemodel = ui->treeView->model();

            if (comp.exec(QString("SELECT * FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
            {
                QList<QPair<QString, QString> > list;

                while(comp.next())
                {
                    list.append(qMakePair(comp.value(comp.record().indexOf("ELEMENT_CODE")).toString(),
                                          comp.value(comp.record().indexOf("ELEMENT_AMOUNT")).toString()));
                }

                int row = 0;
                while (row < list.size())
                {
                    if(!treemodel->insertRow(treemodel->rowCount(index), treemodel->index(index.row(), 0, index.parent())))
                        break;

                    qDebug() << treemodel->rowCount(index);

                    QModelIndex child = treemodel->index(row, 0, treemodel->index(index.row(), 0, index.parent()));
                    setCellText(list.at(row).first, child, 1);
                    setCellText(list.at(row).second, child, 4);   //AMOUNT*/
                    row++;

                }
            }
        }
        else
        {
            setCellText(qry.value(qry.record().indexOf("PURCHASE_PRICE")).toString(), index, 7);        //PRICE
        }

        // TODO: mirar de hacer esto con una enumeración o algo que automice el porceso:
        switch (static_cast<ElementType>(qry.value(qry.record().indexOf("TYPE1")).toInt()))
        {
            case ElementType::Composed:
                setLineType("CO", index);             // type
                break;
            case ElementType::Material:
                setLineType("MT", index);             // type
                break;
            case ElementType::ManPower:
                setLineType("MO", index);             // type
                break;
            case ElementType::Machinery:
                setLineType("MQ", index);             // type
                break;
            default:
                break;
        }
    }
    else
    {
        qDebug() << qry.lastError().text();
    }

    dApp->Enterprise().close();
    return false;
}

void formBudget::on_buttonValidate_released()
{
    // TODO: generar el código definitivo

    mDocumentID = ui->editCode->text();
    setWindowTitle(mDocumentID);

    QTabWidget * prt = static_cast<QTabWidget*>(parent()->parent());
    prt->setTabText(prt->currentIndex(), mDocumentID);
}

void formBudget::on_buttonSave_released()
{
    save();
}

void formBudget::onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    if(mEditMode)
        return;

    Q_UNUSED(bottomRight);

    if(topLeft.column() == 1)
    {
        qDebug() << topLeft.data().toString();
        InsertElement(topLeft.data().toString(), topLeft);
    }
}
void formBudget::insertRow()
{
    ui->treeView->insertRow();
}

void formBudget::insertChild()
{
    ui->treeView->insertChild();
}

void formBudget::removeRow()
{
    ui->treeView->removeRow();
}

void formBudget::focusInEvent(QFocusEvent *event)
{
    qDebug() << "focusInEvent";
}


void formBudget::focusOutEvent(QFocusEvent *event)
{
    qDebug() << "focusOutEvent";
}


void formBudget::on_tabWidget_currentChanged(int index)
{
    if (index == 1)
    {
        ui->ToolbarLines->setVisible(true);
    }
    else
    {
        ui->ToolbarLines->setVisible(false);
    }
}

void formBudget::on_buttonInsertRow_released()
{
    insertRow();
}

void formBudget::on_buttonInsertChild_released()
{
    insertChild();
}

void formBudget::on_buttonRemoveRow_released()
{
    removeRow();
}



void formBudget::on_buttonPercent_released()
{
    // TODO: implementar lógica para botón de porcentaje
}

void formBudget::on_buttonMaterials_released()
{
    // TODO: implementar lógica para botón de materiales
}

void formBudget::on_buttoMachinary_released()
{
    // TODO: implementar lógica para botón de maquinaria
}

void formBudget::on_buttonManpower_released()
{
    // TODO: implementar lógica para botón de mano de obra
}

void formBudget::onAnyChange()
{
    m_changed = true;
}

void formBudget::updateMargin()
{
    bool okCost, okPrice;
    double cost = ui->editCost->text().toDouble(&okCost);
    double price = ui->editPrice->text().toDouble(&okPrice);

    if (!okCost || !okPrice || price == 0.0) {
        ui->editProfit->setText("0.00");
        return;
    }

    double margin = (price - cost) / price * 100.0;
    // Block signals to prevent triggering textChanged on editProfit
    const bool block = ui->editProfit->blockSignals(true);
    ui->editProfit->setText(QString::number(margin, 'f', 2));
    ui->editProfit->blockSignals(block);
}