<?php

namespace KupShop\OrderingBundle\Util\Order;

use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Entity\EntityUtil;
use KupShop\OrderingBundle\Entity;
use KupShop\OrderingBundle\Event\OrderItemEvent;
use Query\Operator;

class OrderItemUtil
{
    /** @var EntityUtil */
    private $entityUtil;

    public function __construct(EntityUtil $entityUtil)
    {
        $this->entityUtil = $entityUtil;
    }

    /**
     * Saves item to db.
     *
     * @param Entity\OrderItem $orderItem Entity of order item
     */
    public function saveOrderItem(Entity\OrderItem $orderItem, \Order $order, \Product $product, $editMode = false, $dispatchEvent = true)
    {
        return sqlGetConnection()->transactional(function () use ($orderItem, $order, $product, $editMode, $dispatchEvent) {
            $orderItemArr = $this->entityUtil->createArray($orderItem);
            unset($orderItemArr['id'], $orderItemArr['date']);

            // serializer converts price to array
            $orderItemArr['piece_price'] = $orderItem->getPiecePrice();
            $orderItemArr['total_price'] = $orderItem->getTotalPrice();

            $qb = sqlQueryBuilder()
                ->insert($order->items_table)
                ->directValues($orderItemArr);

            $qb->execute();
            $item_id = sqlInsertId();
            $orderItemArr['id'] = $item_id;

            if ($dispatchEvent) {
                $dispatcher = ServiceContainer::getService('event_dispatcher');
                $dispatcher->dispatch(new OrderItemEvent(
                    $product, $orderItem->getIdVariation(), toDecimal($orderItem->getTotalPrice()), $orderItem->getPieces(), [
                        'row' => $orderItemArr,
                        'items_table' => $order->items_table,
                    ], $order),
                    OrderItemEvent::ITEM_CREATED
                );
            }

            if (!$editMode) {
                $reserved = $product->sell($orderItem->getIdVariation(), $orderItem->getPieces());

                sqlQueryBuilder()->update('orders')
                    ->set('date_updated', 'NOW()')
                    ->where('id=:id')
                    ->setParameter('id', $order->id)
                    ->execute();

                sqlQueryBuilder()->update('order_items')
                    ->directValues(['pieces_reserved' => $reserved])
                    ->where(Operator::equals(['id' => $item_id]))
                    ->execute();
            }

            return $item_id;
        });
    }

    public function updateOrderItem(Entity\OrderItem $orderItem, $editMode, $itemId, $order)
    {
        return sqlGetConnection()->transactional(function () use ($orderItem, $editMode, $itemId, $order) {
            $item = sqlQueryBuilder()
                ->select('oi.id_product, oi.id_variation, oi.pieces')
                ->from('order_items', 'oi')
                ->where('oi.id=:id')
                ->forUpdate()
                ->setParameter('id', $itemId)
                ->execute()
                ->fetch();

            if (!$editMode && $item['id_product'] > 0) {
                $prod = new \Product($item['id_product']);
                $prod->sell($item['id_variation'], $orderItem->getPieces() - $item['pieces']);
                $dispatcher = ServiceContainer::getService('event_dispatcher');
                $dispatcher->dispatch(
                    new OrderItemEvent($prod, $item['id_variation'], null, $orderItem->getPieces() - $item['pieces'], null, $order),
                    OrderItemEvent::ITEM_UPDATED
                );
            }

            sqlQueryBuilder()
                ->update('order_items')
                ->directValues([
                    'pieces' => "{$orderItem->getPieces()}",
                    'total_price' => "{$orderItem->getTotalPrice()}",
                    'piece_price' => "{$orderItem->getPiecePrice()}",
                    'note' => "{$orderItem->getNote()}",
                    'date' => 'NOW()',
                ])
                ->where('id=:id')
                ->setParameter('id', $itemId)
                ->execute();

            if (!$editMode) {
                sqlQueryBuilder()
                    ->update('orders')
                    ->set('date_updated', 'NOW()')
                    ->where('id=:id_order')
                    ->setParameter('id_order', $orderItem->getIdOrder())
                    ->execute();
            }

            return true;
        });
    }
}
