#include "formproduct.h"
#include "ui_formproduct.h"
#include "mapplication.h"
#include "treemodelcomposeelement.h"

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

#include "QtSql"


formProduct::formProduct(QString aID, int aEditMode, QWidget *parent) :
    formBase(aID, aEditMode, parent),
    ui(new Ui::formProduct),
    editMode(false)
{
    ui->setupUi(this);
    ui->editDischargeDate->setDate(QDate::currentDate());
    ui->editUpdateDate->setDate(QDate::currentDate());

    QStringList headers;
    headers << tr("Código")             //Código del elemento (editable)
            << tr("Título")             //Título del elemento (NO editable)
            << tr("Cantidad")           //Cantidad del elemento (editable)
            << tr("Cantidad total")     //Cantidad total del elemento (NO editable)
            << tr("Unidad")             //Unidad del elemento (editable)
            << tr("N. Precio Unitario") //Precio unitario del elemento (editable)
            << tr("N. Precio Total")    //Precio total del elemento (NO editable)
            << tr("Tipo")
            << ("");

    TreeModelComposeElement *model = new TreeModelComposeElement(headers, QByteArray());
    ui->treeView->setModel(model);

    // Texto con Popup
    ItemTextPopupDelegate *LineTextPopup = new ItemTextPopupDelegate(this);
    ui->treeView->setItemDelegateForColumn(0, LineTextPopup);

    // Texto:
    //ItemTextDelegate *LineTextEditor = new ItemTextDelegate(this);
    //ui->treeView->setItemDelegateForColumn(0, LineTextEditor);
    //ui->treeView->setItemDelegateForColumn(2, LineTextEditor);

    // Números:
    ItemNumberDelegate *doubleNumberEditor = new ItemNumberDelegate(0.0, 999999.99, 0.05, 2, this);
    ui->treeView->setItemDelegateForColumn(2, doubleNumberEditor);

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

    connect(model, &TreeModelComposeElement::dataChanged, this, &formProduct::on_ModelSetData);
    ui->treeView->setColumnWidth( 0, 150);
    ui->treeView->setColumnWidth( 1, 250);
    ui->treeView->setColumnWidth( 2, 80);
    ui->treeView->setColumnWidth( 3, 80);
    ui->treeView->setColumnWidth( 4, 50);
    ui->treeView->setColumnWidth( 5, 80);
    ui->treeView->setColumnWidth( 6, 80);



    //Arg1: the number
    //Arg2: how many 0 you want?
    //Arg3: The base (10 - decimal, 16 hexadecimal - if you don't understand, choose 10)
    //      It seems like only decimal can support negative numbers.
    ui->editCode->setText(QString("EL%1").arg(2, 10, 10, QChar('0')));

    // Unidades:
    dApp->Enterprise().open();
    QSqlQueryModel *unitModel = new QSqlQueryModel(this);
    unitModel->setQuery("SELECT * FROM UNIT", dApp->Enterprise());

    //ui->comboUnit->setModel(unitModel);
    QTableView* tableView = new QTableView( this );
    QHeaderView* header = tableView->verticalHeader();
    header->setDefaultSectionSize(20); // 20 px height
    header->sectionResizeMode(QHeaderView::Fixed);
    tableView->setModel( unitModel );
    tableView->verticalHeader()->setVisible(false);
    tableView->horizontalHeader()->setVisible(false);
    tableView->setColumnWidth ( 0, 60 );
    tableView->setColumnWidth ( 1, 160 );
    tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    tableView->setAutoScroll(false);
    ui->comboUnit->setModel( unitModel );
    ui->comboUnit->setView( tableView );
    ui->comboUnit->view()->setMinimumWidth(220);

    dApp->Enterprise().close();

}

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

void formProduct::openDocument(QString id)
{
    setEditMode();
    ui->editCode->setText(id);
    ui->editCode->setReadOnly(true);

    ui->treeView->model()->removeRows(0, ui->treeView->model()->rowCount());

    dApp->Enterprise().open();
    QSqlQuery qry = QSqlQuery(dApp->Enterprise());
    if(qry.exec(QString("SELECT * FROM ELEMENT WHERE CODE = '%1';").arg(id)))
    {
        qry.first();

        ui->comboType1->setCurrentIndex(qry.value(qry.record().indexOf("TYPE1")).toInt());
        ui->comboType2->setCurrentIndex(qry.value(qry.record().indexOf("TYPE2")).toInt());

        ui->editTitle->setText(qry.value(qry.record().indexOf("TITLE")).toString());
        ui->editDescription->setHtml(qry.value(qry.record().indexOf("DESCRIPTION")).toString());
        //ui->editTitle->setText(qry.value(4).toString());  // FAMILY_ID
        ui->comboUnit->setCurrentText(qry.value(qry.record().indexOf("UNIT_ID")).toString());  // UNIT_ID

        ui->editUpdateDate->setDate(qry.value(qry.record().indexOf("DATE_UPDATE")).toDate());
        //ui->editDischargeDate->setDate(qry.value().toDate());

        ui->editPVP->setValue(qry.value(qry.record().indexOf("REAL_PRICE")).toDouble());
        ui->editDiscount->setValue(qry.value(qry.record().indexOf("DISCOUNT")).toDouble());
        ui->editPC->setValue(qry.value(qry.record().indexOf("PURCHASE_PRICE")).toDouble());
        ui->editMargin->setValue(qry.value(qry.record().indexOf("BENEFIT")).toDouble());
        ui->editPV->setValue(qry.value(qry.record().indexOf("SALE_PRICE")).toDouble());
        ui->comboIVA->setCurrentText(qry.value(qry.record().indexOf("TAX")).toString());

        ui->checkState->setChecked(qry.value(qry.record().indexOf("STATE")).toBool());

        ui->editWeight->setValue(qry.value(qry.record().indexOf("WEIGHT")).toDouble());
        ui->editHeight->setValue(qry.value(qry.record().indexOf("HEIGHT")).toDouble());
        ui->editWidth->setValue(qry.value(qry.record().indexOf("WIDTH")).toDouble());
        ui->editLength->setValue(qry.value(qry.record().indexOf("LENGHT")).toDouble());

        if(qry.value(qry.record().indexOf("TYPE1")).toInt() == 0)
        {
            setComposeElement(true);

            QList<QPair<QString, QString> > list;

            if(qry.exec(QString("SELECT * FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(id)))
            {
                while(qry.next())
                {
                    list.append(qMakePair(qry.value(qry.record().indexOf("ELEMENT_CODE")).toString(),
                                          qry.value(qry.record().indexOf("ELEMENT_AMOUNT")).toString()));
                }

                int row = 0;

                while(row < list.size())
                {
                    ui->treeView->addRow();
                    QModelIndex index = ui->treeView->model()->index(row, 0);
                    setCellText(list.at(row).first, index, 0);      // CODE
                    setCellText(list.at(row).second, index, 2);    // AMOUNT
                    row ++;
                }
                ui->treeView->addRow();
            }
            else
            {
                qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
            }
        }
        else
        {
            setComposeElement(false);
        }
    }
    else
    {
        qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
    }

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

void formProduct::closeDocument()
{
    close();
}

void formProduct::setEditMode()
{
    editMode = true;
    ui->editCode->setReadOnly(true);// ->setEnabled(false);
}

void formProduct::on_editPC_valueChanged(double arg1)
{
    CalculatePrice();
}

void formProduct::on_editMargin_valueChanged(double arg1)
{
    CalculatePrice();
}

void formProduct::on_editPV_valueChanged(double arg1)
{

}

void formProduct::on_editPV_editingFinished()
{
    double pc = ui->editPC->value();
    if (pc == 0)
        return;

    double ma;
    double pv = ui->editPV->value();

    ma = (pv/pc - 1) * 100;
    if(ma != ui->editMargin->value())
        ui->editMargin->setValue(ma);
}

void formProduct::on_comboIVA_currentIndexChanged(const QString &arg1)
{
    CalculatePrice();
}

void formProduct::CalculatePrice()
{
    double pc = ui->editPC->value();
    double ma = ui->editMargin->value();
    QString ivatext = ui->comboIVA->currentText().replace("%", "");
    double iva = ivatext.toDouble();

    double pv = pc * (1 + ma / 100);
    ui->editPV->setValue(pv);
    ui->editPVIVA->setValue( pv * (1 + iva / 100));
}

void formProduct::save()
{
    // INSERT
    QString Element;
    QString ElementComp;


    if(editMode == false)
    {
        Element = "INSERT INTO ELEMENT ("
                  "CODE, TYPE1, TYPE2, TITLE, DESCRIPTION, FAMILY_ID, UNIT_ID, "
                  "DATE_UPDATE, REAL_PRICE, DISCOUNT, PURCHASE_PRICE, BENEFIT, TAX, SALE_PRICE, "
                  "BARCODE, IMAGE, STATE, MANUFACTURER, GAMMA, "
                  "WEIGHT, HEIGHT, WIDTH, LENGHT"
                  ") VALUES ("
                  ":CODE, :TYPE1, :TYPE2, :TITLE, :DESCRIPTION, :FAMILY_ID, :UNIT_ID, "
                  ":DATE_UPDATE, :REAL_PRICE, :DISCOUNT, :PURCHASE_PRICE, :BENEFIT, :TAX, :SALE_PRICE, "
                  ":BARCODE, :IMAGE, :STATE, :MANUFACTURER, :GAMMA, "
                  ":WEIGHT, :HEIGHT, :WIDTH, :LENGHT"
            ");";

        ElementComp = "INSERT INTO ELEMENTCOMPOSITION ("
            "CODE, ELEMENT_CODE, ELEMENT_AMOUNT"
            ") VALUES ("
            ":CODE, :ELEMENT_CODE, :ELEMENT_AMOUNT"
            ");";
    }
    // UPDATE
    else
    {
        Element = "UPDATE ELEMENT SET "
            "TYPE1 = :TYPE1, TYPE2 = :TYPE2, TITLE = :TITLE, DESCRIPTION = :DESCRIPTION, FAMILY_ID = :FAMILY_ID, "
            "UNIT_ID = :UNIT_ID, DATE_UPDATE = :DATE_UPDATE, REAL_PRICE = :REAL_PRICE, DISCOUNT = :DISCOUNT, "
            "PURCHASE_PRICE = :PURCHASE_PRICE, BENEFIT = :BENEFIT, TAX = :TAX, SALE_PRICE = :SALE_PRICE, BARCODE = :BARCODE, IMAGE = :IMAGE, "
            "STATE = :STATE, MANUFACTURER = :MANUFACTURER, GAMMA = :GAMMA, WEIGHT = :WEIGHT, HEIGHT = :HEIGHT, "
            "WIDTH = :WIDTH, LENGHT = :LENGHT "
            "WHERE CODE = :CODE"
            ";";

        ElementComp = "UPDATE ELEMENTCOMPOSITION SET "
                      "ELEMENT_AMOUNT = :ELEMENT_AMOUNT "
                      "WHERE CODE = :CODE AND ELEMENT_CODE = :ELEMENT_CODE";
    }


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

    // 1. Si es compuesto crear la lista de elementos que lo componen:
    if(ui->comboType1->currentIndex() == 0)
    {
        QAbstractItemModel *model = ui->treeView->model();

        for (int i = 0; i < model->rowCount(); i++)
        {
            // Obtiene los datos de la primera columna
            QString elementCode = model->index(i, 0).data().toString();

            // Verifica si los datos son válidos
            if (elementCode.isEmpty())
                continue;

            qry.prepare(ElementComp);
            qry.bindValue(":CODE", ui->editCode->text());
            qry.bindValue(":ELEMENT_CODE", elementCode);
            qry.bindValue(":ELEMENT_AMOUNT", model->index(i, 2).data().toDouble());

            if(!qry.exec())
            {
                // barrar lo creado: eliminar las composiciones ya insertadas para este producto
                if (!insertedElementCodes.isEmpty())
                {
                    QSqlQuery qryDel = QSqlQuery(dApp->Enterprise());
                    qryDel.prepare(QString("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = :CODE AND ELEMENT_CODE IN (%1)").arg(QString(insertedElementCodes.size(), '?').replace('?', ":ELEMENT_CODE")));
                    qryDel.bindValue(":CODE", ui->editCode->text());
                    for (int j = 0; j < insertedElementCodes.size(); ++j)
                    {
                        qryDel.bindValue(QString(":ELEMENT_CODE%1").arg(j), insertedElementCodes.at(j));
                    }
                    qryDel.exec();
                }
                qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
                dApp->Enterprise().close();
                return;
            }}
        }
    }

    // 2. Crear el elemento principal
    qry.prepare(Element);
    qry.bindValue(":CODE", ui->editCode->text());
    qry.bindValue(":TYPE1", ui->comboType1->currentIndex());
    qry.bindValue(":TYPE2", ui->comboType2->currentIndex());
    qry.bindValue(":TITLE", ui->editTitle->text());
    qry.bindValue(":DESCRIPTION", ui->editDescription->toHtml());
    //qry.bindValue(":FAMILY_ID", ui->editCode->text());
    qry.bindValue(":UNIT_ID", ui->comboUnit->currentText());
    qry.bindValue(":DATE_UPDATE", ui->editUpdateDate->date());
    qry.bindValue(":REAL_PRICE", ui->editPVP->value());
    qry.bindValue(":DISCOUNT", ui->editDiscount->value());
    qry.bindValue(":PURCHASE_PRICE", ui->editPC->value());
    qry.bindValue(":BENEFIT", ui->editMargin->value());
    qry.bindValue(":TAX", ui->comboIVA->currentText().replace("%", ""));
    qry.bindValue(":SALE_PRICE", ui->editPV->text());
    //qry.bindValue(":BARCODE", ui->edit->text());
    //qry.bindValue(":IMAGE", ui->editCode->text());
    qry.bindValue(":STATE", ui->checkState->isChecked());
    //qry.bindValue(":MANUFACTURER", ui->editCode->text());
    //qry.bindValue(":GAMMA", ui->editCode->text());
    qry.bindValue(":WEIGHT", ui->editWeight->text());
    qry.bindValue(":HEIGHT", ui->editHeight->text());
    qry.bindValue(":WIDTH", ui->editWidth->text());
    qry.bindValue(":LENGHT", ui->editLength->text());

    if(!qry.exec())
    {
        //goto error;
    }

    setWindowTitle(mDocumentID);

    QTabWidget * prt = static_cast<QTabWidget*>(parent()->parent());
    prt->setTabText(prt->currentIndex(), ui->editCode->text() + " - " + ui->editTitle->text());
    dApp->Enterprise().close();
    setEditMode();
    return;

error:
    dApp->Enterprise().close();
    qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
}

void formProduct::on_buttonSave_released()
{
    // Salvar
    save();
}

void formProduct::on_editPVIVA_valueChanged(const QString &arg1)
{
    ui->editUpdateDate->setDate(QDate::currentDate());
}

void formProduct::on_ModelSetData(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    Q_UNUSED(bottomRight);

    if(topLeft.column() == 0)
    {
        InsertElement(topLeft.data(roles.first()).toString(), topLeft);
    }
    else if(topLeft.column() == 2)
    {
        QAbstractItemModel /*TreeModelComposeElement*/ *aModel = ui->treeView->model();
        double pt = 0;
        for(int i = 0; i < aModel->rowCount(); i++)
        {
            QModelIndex idx = aModel->index(i, 6);
            pt += idx.data().toDouble();
        }
        ui->editPC->setValue(pt);
    }
}

void formProduct::setLineType(QString type, QModelIndex index)
{
    setCellText(type, index, 7);
}

void formProduct::setCellText(QString val, QModelIndex index, int col)
{
    //QModelIndex selindex = ui->treeView->selectionModel()->currentIndex();
    QAbstractItemModel *treemodel = ui->treeView->model();

    QModelIndex child = treemodel->index(index.row(), col, index.parent().isValid() ? index.parent() : QModelIndex());
    treemodel->setData(child, QVariant(val), Qt::EditRole);
}

bool formProduct::InsertElement(QString ID, QModelIndex index)
{
    if (ID.isEmpty())
        return false;

    dApp->Enterprise().open();
    QSqlQuery qry = QSqlQuery(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, 1);            // TITLE
        setCellText(qry.value(qry.record().indexOf("UNIT_ID")).toString(), index, 4);             // UNIT                    ----QSqlQuery::value: not positioned on a valid record

        /*
        if (qry.value(qry.record().indexOf("TYPE")).toInt() == 0)
        {
            on_buttonInsertChild_released();

            QSqlQuery comp = QSqlQuery(dApp->Enterprise());
            if (comp.exec(QString("SELECT * FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
            {
                while (comp.next())
                {
                    on_buttonInsertRow_released();
                    InsertElement(comp.value(1).toString());
                    setCellText(4, comp.value(comp.record().indexOf("ELEMENT_AMOUNT")).toString());  //AMOUNT
                }
            }
        }
        else*/
        {
            setCellText(qry.value(qry.record().indexOf("PURCHASE_PRICE")).toString(), index, 5);        //PRICE                         ----QSqlQuery::value: not positioned on a valid record
        }

        // TODO: mirar de hacer esto con una enumeración o algo que automice el porceso:
        // Use enumeration for element types
        switch (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;
            case ElementType::Subcontracted:
                setLineType("SC", index);             // type
                break;
            case ElementType::Other:
                setLineType("OT", index);             // type
                break;
            default:
                setLineType("UNKNOWN", index);        // type
                break;
        }
    }
    else
    {
        qDebug() << qry.lastError().text();
    }

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

void formProduct::on_comboType2_currentIndexChanged(int index)
{
    if(index == 0)
        setComposeElement(true);
    else
        setComposeElement(false);
}

void formProduct::setComposeElement(bool val)
{
    ui->editPVP->setEnabled(!val);
    ui->editDiscount->setEnabled(!val);
    ui->editPC->setReadOnly(val);
    ui->groupBox_6->setVisible(!val);

    //ui->tabCompose->setVisible(val);

    ui->comboType1->setEnabled(!val);
    //ui->comboType2->setEnabled(!val);
}
