<?php

namespace KupShop\ApiBundle\Api\Endpoints;

use KupShop\ApiBundle\Api\Auth;
use KupShop\ApiBundle\Api\Cart;
use KupShop\ApiBundle\Api\Errors;
use KupShop\ApiBundle\Exception\ApiErrorResponseException;
use Luracast\Restler\RestException;

class OrderEndpoint
{
    /**
     * Get order by order_number.
     *
     * Return:<br>
     * <pre>
     *{<br>
     *&nbsp;    "result": {<br>
     *&nbsp;&nbsp;       "items": [<br>
     *&nbsp;&nbsp;&nbsp;              { <br>
     *&nbsp;&nbsp;&nbsp;                'order_number' : 1,<br>
     *&nbsp;&nbsp;&nbsp;                'currency' : 'OK.',<br>
     *&nbsp;&nbsp;&nbsp;                'status_code' : 2,<br>
     *&nbsp;&nbsp;&nbsp;                'status_msg' : 2,<br>
     *&nbsp;&nbsp;&nbsp;                'order_items' : [<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    {<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'id_product' : 123,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'name' : 'Pretty item xy',<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'pieces' : 10,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'vat' : 21,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'piece_price_without_vat' : 10,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'total_price' : 100,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    },<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    {<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'id_product' : 321,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'name' : 'Pretty item xyz',<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'pieces' : 10,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'vat' : 21,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'piece_price_without_vat' : 10,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    'total_price' : 100,<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;                    }<br>
     *&nbsp;&nbsp;&nbsp;                ]<br>
     *&nbsp;&nbsp;&nbsp;              },</br
     *&nbsp;&nbsp;         ]<br>
     *&nbsp;    }<br>
     *}<br>
     *</pre>
     *
     * @param string $order_number code of order
     *
     * @return array
     *
     * @throws RestException
     *
     * @url GET :order_number
     */
    public function getOrderByID($order_number)
    {
        $sql = sqlQuery('SELECT * FROM orders
                      WHERE id_user=:id_user AND order_no=:order_no', ['id_user' => Auth::getUser(), 'order_no' => $order_number]);

        if (sqlNumRows($sql) < 1) {
            throw new RestException(404, 'Order with this ID does not exist.');
        }
        $order = sqlFetchArray($sql);

        $return = [
            'order_number' => $order['order_no'],
            'currency' => $order['currency'],
            'total_price' => $order['total_price'],
            'status_code' => $order['status'],
            'status_msg' => getOrderStatus($order['status'])['name'],
            'status_payed' => $order['status_payed'],
            'note' => $order['note_user'],

            'order_items' => [],
        ];

        $sql = sqlQuery('SELECT oi.*, p.code, p.title AS title, v.vat AS vat FROM order_items oi
                      LEFT JOIN products p ON p.id = oi.id_product
                      LEFT JOIN vats v ON v.id = p.vat
                      WHERE oi.id_order=:id_order', ['id_order' => $order['id']]);

        foreach ($sql as $order_item) {
            $return['order_items'][] = [
                'id_product' => $order_item['code'],
                'name' => $order_item['title'],
                'quantity' => $order_item['pieces'],
                'piece_price_without_vat' => $order_item['piece_price'],
                'total_price' => $order_item['total_price'],
                'vat' => $order_item['vat'],
            ];
        }

        return Errors::getResponse(0, ['order' => $return]);
    }

    /**
     * Get order codes.
     *
     * Return:<br>
     * <pre>
     *{<br>
     *&nbsp;  "error": 0,<br>
     *&nbsp;  "message": "OK",<br>
     *&nbsp;  "order_numbers": [<br>
     *&nbsp;&nbsp;    "3116985062",<br>
     *&nbsp;&nbsp;    "3416985064",<br>
     *&nbsp;&nbsp;    "3416985067",<br>
     *&nbsp;&nbsp;    "3416985068",<br>
     *&nbsp;&nbsp;    "3416985071"<br>
     *&nbsp;  ]<br>
     * }<br>
     * </pre>
     *
     * @url GET
     */
    public function getOrders()
    {
        $sql = sqlQuery('SELECT * FROM orders
                      WHERE id_user=:id_user', ['id_user' => Auth::getUser()]);

        $order_numbers = [];

        if (sqlNumRows($sql) < 1) {
            throw new RestException(404, 'You have no orders.');
        } else {
            foreach ($sql as $order) {
                $order_numbers[] = $order['order_no'];
            }
        }

        return Errors::getResponse(0, ['order_numbers' => $order_numbers]);
    }

    /**
     * Create order by inserted items.
     *
     * Return:<br>
     * <pre>
     * {<br>
     *&nbsp;   "error": 8,<br>
     *&nbsp;   "message": "Operation failed",<br>
     *&nbsp;   "items": {<br>
     *&nbsp;&nbsp;     "1": {<br>
     *&nbsp;&nbsp;&nbsp;        "error": 3,<br>
     *&nbsp;&nbsp;&nbsp;        "message": "Not enough pieces in stock. In store is 4 pcs",<br>
     *&nbsp;&nbsp;&nbsp;        "id_product": "1"<br>
     *&nbsp;&nbsp;     }<br>
     *&nbsp;   }<br>
     * }<br>
     *<br>
     * or
     * <br>
     * <br>
     *{<br>
     *&nbsp;  "error": 0,<br>
     *&nbsp;  "message": "Order was created", <br>
     *&nbsp;  "items": [ <br>
     *&nbsp;&nbsp;    { <br>
     *&nbsp;&nbsp;&nbsp;      "name": "Pretty product xyz",<br>
     *&nbsp;&nbsp;&nbsp;      "quantity": "2", <br>
     *&nbsp;&nbsp;&nbsp;      "id_product": "1", <br>
     *&nbsp;&nbsp;&nbsp;      "price_without_vat": 1.498, <br>
     *&nbsp;&nbsp;&nbsp;      "vat": "21" <br>
     *&nbsp;&nbsp;    } <br>
     *&nbsp;  ], <br>
     *&nbsp;  "order_number": "3416985071"<br>
     * }<br>
     * <br>
     *<br>
     * Statuses:<br>
     *    0 => 'OK.',<br>
     *    3 => 'There are not enough pieces in stock.', - see available_quantity field<br>
     *    8 => 'Operation failed',<br>
     *   1012 => 'Cart is empty',<br>
     *   1018 => 'Delivery into this country is not supported',<br>
     *   1005 => 'You have not choose delivery type',<br>
     *   1031 => 'You have not choose product variation',<br>
     *   1030 => 'This item is out of stock',<br>
     * </pre>
     *
     * @param mixed array insert object o
     * <pre>
     *   {<br>
     *&nbsp;      "products" : [<br>
     *&nbsp;&nbsp;&nbsp;    {<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;       "code" : "1",<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;       "quantity" : "2"<br>
     *&nbsp;&nbsp;&nbsp;    },<br>
     *&nbsp;&nbsp;&nbsp;    {<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;       "code" : "2",<br>
     *&nbsp;&nbsp;&nbsp;&nbsp;       "quantity" : "5"<br>
     *&nbsp;&nbsp;&nbsp;    }<br>
     *&nbsp;&nbsp;   ],<br>
     *&nbsp;      "note" : "acdsaca"<br>
     * }
     * </pre>
     *
     * @return array
     *
     * @throws RestException
     *
     * @url POST
     */
    public function createOrder($order)
    {
        try {
            $result = sqlGetConnection()->transactional(function () use ($order) {
                $userKey = Cart::getCartID();
                $userKey .= '_quick';
                Cart::setCartID($userKey);

                $cart = CartEndpoint::getCartObject();
                $cart->clear();

                $cart->createFromDB();

                if (empty($order['products'])) {
                    $products = $order;
                } else {
                    $products = $order['products'];
                }

                if (!empty($order['note'])) {
                    $cart->setNote($order['note']);
                }

                if (empty($products)) {
                    throw ApiErrorResponseException::fromResponse(
                        Errors::getResponse(9),
                    );
                }

                $items_result = CartEndpoint::insertProductsIntoCart($products);

                if (!CartEndpoint::checkIfItemsOK($items_result)) {
                    throw ApiErrorResponseException::fromResponse(
                        Errors::getResponse(8, ['items' => $items_result]),
                    );
                }

                CartEndpoint::checkCartItems($errors, $items_result);

                if (!CartEndpoint::checkIfItemsOK($items_result)) {
                    throw ApiErrorResponseException::fromResponse(
                        Errors::getResponse(8, ['items' => $items_result]),
                    );
                }

                $order = $cart->submitOrder();

                return CartEndpoint::createOrderSuccess($order, $items_result);
            });
        } catch (ApiErrorResponseException $e) {
            return $e->apiResponse;
        }

        return $result;
    }
}
