<?php

namespace KupShop\GraphQLBundle\ApiPos\Controller;

use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\GraphQLBundle\ApiPos\Types\Order\PosOrder;
use KupShop\GraphQLBundle\ApiPos\Types\Order\PosOrderFinish;
use KupShop\GraphQLBundle\ApiPos\Types\Purchase\PosPurchase;
use KupShop\GraphQLBundle\ApiPos\Types\User\PosUser;
use KupShop\POSBundle\Util\PosOrderUtil;
use Psr\Log\LoggerInterface;
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\GraphQLite\Annotations\UseInputType;

class PosOrderController
{
    public function __construct(
        protected ?PosOrderUtil $posOrderUtil,
        protected LoggerInterface $logger,
    ) {
    }

    #[Query]
    public function order(?int $id, ?string $code): PosOrder
    {
        return $this->posOrderUtil->getOrder($id, $code);
    }

    #[Mutation]
    public function posOrderUpdateAndRecalculate(
        #[UseInputType('[OrderItemInput!]!')] array $orderItems,
        #[UseInputType('POSUserInput')] ?PosUser $user = null,
        #[UseInputType('[OrderCouponItem]')] array $couponItems = [],
        #[UseInputType('[String]')] array $newProducts = [],
        #[UseInputType('[String]')] array $newCoupons = [],
        ?int $appliedBonusPoints = null,
        ?int $idOrder = null,
        string $methodPayment = 'UNDEFINED',
        string $paidPrice = '0',
        bool $savePurchase = false,
        bool $purchase = false,
    ): ?PosPurchase {
        $requestParameters = json_encode([
            'orderItems' => $orderItems,
            'user' => $user,
            'couponItems' => $couponItems,
            'newProducts' => $newProducts,
            'newCoupons' => $newCoupons,
            'appliedBonusPoints' => $appliedBonusPoints,
            'idOrder' => $idOrder,
            'methodPayment' => $methodPayment,
            'paidPrice' => $paidPrice,
            'savePurchase' => $savePurchase,
        ], JSON_PRETTY_PRINT);

        try {
            $response = $this->posOrderUtil->recalculateAndUpdateOrder(
                orderItems: $orderItems,
                couponItems: $couponItems,
                newProducts: $newProducts,
                newCoupons: $newCoupons,
                appliedBonusPoints: $appliedBonusPoints,
                user: $user,
                idOrder: $idOrder,
                savePurchase: $savePurchase,
                methodPayment: $methodPayment,
                paidPrice: $paidPrice,
                purchase: $purchase
            );
            $this->sendNotice($requestParameters, json_encode($response, JSON_PRETTY_PRINT));
        } catch (ValidationException $exception) {
            return new PosPurchase(
                items: [],
                discounts: [],
                usedDiscounts: [],
                charges: [],
                priceWithoutVat: '',
                priceWithVat: '',
                loadedProducts: [],
                loadedCoupons: [],
                posOrderResponse: null,
                exception: $exception->getMessage(),
            );
        } catch (\Exception $e) {
            isLocalDevelopment() ? throw $e : $this->sendNotice($requestParameters, $e->getMessage(), 'exception');

            return null;
        }

        return $response;
    }

    #[Mutation]
    public function posOrderFinish(int $id): PosOrderFinish
    {
        try {
            $response = $this->posOrderUtil->finishOrder($id);
            $this->logger->notice('POS API: posOrderFinish', ['data' => [
                'requestParams' => json_encode(['idOrder' => $id], JSON_PRETTY_PRINT),
                'response' => json_encode($response, JSON_PRETTY_PRINT),
            ]]);
        } catch (ValidationException $exception) {
            return new PosOrderFinish(
                idOrder: $id,
                status: -1,
                exception: $exception->getMessage(),
            );
        }

        return $response;
    }

    #[Mutation]
    public function posOrderStorno(int $id): PosOrderFinish
    {
        try {
            $response = $this->posOrderUtil->stornoOrder($id);
            $this->logger->notice('POS API: posOrderStorno', ['data' => [
                'requestParams' => json_encode(['idOrder' => $id], JSON_PRETTY_PRINT),
                'response' => json_encode($response, JSON_PRETTY_PRINT),
            ]]);
        } catch (ValidationException $exception) {
            return new PosOrderFinish(
                idOrder: $id,
                status: -1,
                exception: $exception->getMessage(),
            );
        }

        return $response;
    }

    private function sendNotice($params, $response, $type = 'response'): void
    {
        $this->logger->notice('POS API: posOrderCreate', ['data' => [
            'requestParams' => $params,
            'response' => $response,
            'type' => $type,
        ]]);
    }
}
