#include "shopservice.h"
#include "numberseriesservice.h"
#include "shop-odb.hxx"

ShopService::ShopService()
{
}

QSharedPointer<Voucher> ShopService::createVoucher()
{
    QSharedPointer<Voucher> voucher(new Voucher);
    voucher->setStatus(Voucher::NEW);
    return voucher;
}

void ShopService::addShopItem(QSharedPointer<Voucher> voucher, QSharedPointer<IShopItem> item, int count)
{
    QSharedPointer<VoucherItem> vItem(new VoucherItem);
    vItem->setName(item->name());
    vItem->setUnitPrice(item->unitPrice());
    vItem->setCount(count);
    vItem->setRefId(item->id());
    vItem->setItemPlugin(item->pluginId());
    vItem->setVatType(item->vatType());

    voucher->addItem(vItem);
}

void ShopService::calculate(QSharedPointer<Voucher> voucher)
{
    QDecDouble total;

    loadSettings();
    voucher->setVatRateHigh(m_gs->vatHigh());
    voucher->setVatRateFirstLower(m_gs->vatFirstLower());
    voucher->setVatRateSecondLower(m_gs->vatSecondLower());

    foreach (QSharedPointer<VoucherItem> item, voucher->items()) {
        calculateItem(item);

        QDecDouble priceWitouthWat = item->priceWitouthVat();
        switch (item->vatType()) {
        case Enums::NONE:
            voucher->setPriceNoVat(voucher->priceNoVat() + priceWitouthWat);
            break;
        case Enums::HIGH:
            voucher->setPriceVatHigh(voucher->priceVatHigh() + priceWitouthWat);
            break;
        case Enums::FIRST_LOWER:
            voucher->setPriceVatFirstLower(voucher->priceVatFirstLower() + priceWitouthWat);
            break;
        case Enums::SECOND_LOWER:
            voucher->setPriceVatSecondLower(voucher->priceVatSecondLower() + priceWitouthWat);
            break;
        default:
            break;
        }

        total += item->price();
    }

    voucher->setTotalPriceVatHigh(includeVat(voucher->priceVatHigh(), Enums::HIGH));
    voucher->setTotalPriceVatFirstLower(includeVat(voucher->priceVatFirstLower(), Enums::FIRST_LOWER));
    voucher->setTotalPriceVatSecondLower(includeVat(voucher->priceVatSecondLower(), Enums::SECOND_LOWER));
    voucher->setTotalPrice(total);
}

void ShopService::calculateItem(QSharedPointer<VoucherItem> item)
{
    loadSettings();
    if (m_gs->vatPayer())
    {
        item->setVatRate(vatRate(item->vatType()));
        item->setPriceWitouthVat(item->unitPrice() * item->count());
        item->setPrice(includeVat(item->priceWitouthVat(), item->vatType()));
    }
    else
    {
        item->setPrice(item->unitPrice() * item->count());
        item->setPriceWitouthVat(item->price());
    }
}

void ShopService::loadItems(QSharedPointer<Voucher> voucher)
{
    Service<VoucherItem> srv;
    voucher->setItems(srv.all(QString("voucher = %1").arg(voucher->id())));
}

void ShopService::pay(QSharedPointer<Voucher> voucher)
{
    Transaction tx;
    NumberSeriesService srvNs;

    NumberSeriesPtr numSer = srvNs.nextForPlugin("SHOP");
    QString numSerStr;
    numSerStr.sprintf("%s%05d", numSer->prefix().toStdString().c_str(), numSer->lastNumber());

    voucher->setNumSer(numSerStr);
    voucher->setStatus(Voucher::PAID);
    voucher->setPayDateTime(QDateTime::currentDateTime());

    this->update(voucher);

    tx.commit();
}

QList<QSharedPointer<Voucher> > ShopService::savedVouchers()
{
    return all(QString("status = %1").arg(QString::number(Voucher::NOT_PAID)));
}

QList<QSharedPointer<Voucher> > ShopService::tempVouchers()
{
    return all(QString("status = %1").arg(QString::number(Voucher::TEMPORARY)));
}

QList<QSharedPointer<Voucher> > ShopService::paiedVouchers()
{
    return all(QString("status = %1").arg(QString::number(Voucher::PAID)));
}

QDecDouble ShopService::includeVat(QDecDouble price, Enums::VatType vatType)
{
    return price * ((vatRate(vatType) / 100) + QDecDouble(1));
}

void ShopService::loadSettings()
{
    if (m_gs.isNull())
    {
        SettingsService settings("CORE");
        m_gs = settings.loadSettings<GlobalSettings>();
    }
}

QDecDouble ShopService::vatRate(Enums::VatType vatType)
{
    QDecDouble vatRate;

    loadSettings();
    switch (vatType) {
    case Enums::NONE:
        vatRate = 0;
        break;
    case Enums::HIGH:
        vatRate = m_gs->vatHigh();
        break;
    case Enums::FIRST_LOWER:
        vatRate = m_gs->vatFirstLower();
        break;
    case Enums::SECOND_LOWER:
        vatRate = m_gs->vatSecondLower();
        break;
    default:
        break;
    }

    return vatRate;
}

void ShopService::saveVoucher(QSharedPointer<Voucher> entity)
{
    Transaction tr;
    odb::database *db = Context::instance().db();

    db->persist(entity);

    foreach (QSharedPointer<VoucherItem> item, entity->items()) {
        item->setVoucher(entity.toWeakRef());
        db->persist(item);
    }

    tr.commit();
}

void ShopService::updateVoucher(QSharedPointer<Voucher> entity)
{
    Transaction tr;
    odb::database *db = Context::instance().db();

    db->execute(QString("DELETE FROM VoucherItem WHERE voucher = %1").arg(entity->id()).toStdString());

    foreach (QSharedPointer<VoucherItem> item, entity->items()) {
        item->setVoucher(entity.toWeakRef());
        db->persist(item);
    }

    db->update(entity);

    tr.commit();
}
