<?php

declare(strict_types=1);

namespace External\PompoBundle\DataGo\EventSubscriber;

use External\PompoBundle\DataGo\Synchronizer\OrderSynchronizer;
use External\PompoBundle\DataGo\Util\DataGoApi;
use External\PompoBundle\Util\PompoLogger;
use External\PompoBundle\Util\PompoUtil;
use KupShop\OrderingBundle\Event\OrderEvent;
use Query\Operator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class OrderSubscriber implements EventSubscriberInterface
{
    private DataGoApi $dataGoApi;
    private PompoUtil $pompoUtil;
    private OrderSynchronizer $orderSynchronizer;
    private PompoLogger $pompoLogger;

    public function __construct(DataGoApi $dataGoApi, PompoUtil $pompoUtil, OrderSynchronizer $orderSynchronizer, PompoLogger $pompoLogger)
    {
        $this->dataGoApi = $dataGoApi;
        $this->pompoUtil = $pompoUtil;
        $this->orderSynchronizer = $orderSynchronizer;
        $this->pompoLogger = $pompoLogger;
    }

    public static function getSubscribedEvents()
    {
        return [
            OrderEvent::ORDER_STORNO => [
                ['handleOrderStorno', 200],
            ],
        ];
    }

    public function handleOrderStorno(OrderEvent $event): void
    {
        $order = $event->getOrder();

        $dataGo = sqlQueryBuilder()
            ->select('id_datago, data')
            ->from('datago_orders')
            ->andWhere(Operator::equals(['id_order' => $order->id]))
            ->andWhere('JSON_VALUE(COALESCE(data, "{}"), "$.completed") IS NULL')
            ->execute()->fetchAssociative();

        // objednavka neni v DataGo nebo uz je oznacena jako completed
        if (!$dataGo) {
            return;
        }

        $drsId = sqlQueryBuilder()
            ->select('id_drs')
            ->from('drs_orders')
            ->where(Operator::equals(['id_order' => $order->id]))
            ->execute()->fetchOne();

        // Pokud je objednavka uz nahrana v DRSu, tak nepotrebuju v DataGo nic stornovat, protoze uz me DataGo nezajima
        if ($drsId) {
            return;
        }

        $data = json_decode($dataGo['data'] ?? '', true) ?? [];
        // Pokud je storno ze synchronizace - byla tedy stornovana v DataGo, tak uz to nechci sotrnovat v DataGo
        // protoze tam to je uz stornovany
        if ($data['stornoFromDataGo'] ?? false) {
            return;
        }

        // musim objednavku znovu nacist, protoze potrebuji polozky v nove strukture (objekty)
        $order = \Order::get((int) $order->id);

        [$user, $pass] = $this->pompoUtil->getDataGoCredentialsByOrder($order);

        try {
            // vynulovat objednavku v DataGo
            $this->dataGoApi->setCredentials($user, $pass)
                ->stornoOrder(
                    $this->orderSynchronizer->getOrderData($order)
                );
            // oznacit v mappingu jako completed
            $this->orderSynchronizer->setOrderCompleted($order);
            // zalogovat k objednavce
            $order->logHistory('[DataGo] Objednávka byla v DataGo vynulována');
        } catch (\Throwable $e) {
            if (isDevelopment()) {
                throw $e;
            }

            $this->pompoLogger->logException($e, sprintf('Objednávku "%s" se nepodařilo stornovat v DataGo!', $order->order_no));
        }
    }
}
