<?php

declare(strict_types=1);

namespace External\PompoBundle\Admin\Actions;

use External\PompoBundle\DataGo\Exception\DataGoException;
use External\PompoBundle\DataGo\Synchronizer\OrderSynchronizer;
use External\PompoBundle\DataGo\Util\DataGoApi;
use External\PompoBundle\Util\PompoLogger;
use External\PompoBundle\Util\PompoUtil;
use KupShop\AdminBundle\Admin\Actions\AbstractAction;
use KupShop\AdminBundle\Admin\Actions\ActionResult;
use KupShop\AdminBundle\Admin\Actions\IAction;
use Query\Operator;

class UpdateDataGoOrderAction extends AbstractAction implements IAction
{
    /** @required */
    public DataGoApi $dataGoApi;
    /** @required */
    public PompoUtil $pompoUtil;
    /** @required */
    public PompoLogger $pompoLogger;
    /** @required */
    public OrderSynchronizer $orderSynchronizer;

    public function getTypes(): array
    {
        return ['orders'];
    }

    public function getName(): string
    {
        return '[DataGo] Vytvořit / aktualizovat objednávku';
    }

    public function execute(&$data, array $config, string $type): ActionResult
    {
        $dataGoId = sqlQueryBuilder()
            ->select('id_datago')
            ->from('datago_orders')
            ->where(Operator::equals(['id_order' => $this->getId()]))
            ->execute()->fetchOne();

        $order = \Order::get((int) $this->getId());

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

        // Zapsani objednavky do DataGo
        if (!$dataGoId) {
            return $this->getActionResult(function () use ($user, $pass, $order) {
                $result = $this->dataGoApi->setCredentials($user, $pass)
                    ->createOrder(
                        $this->orderSynchronizer->getOrderData($order)
                    );

                if (!($result['uniqueid'] ?? false)) {
                    throw new DataGoException('Order was not sent to DataGo!');
                }

                $order->changeStatus(
                    1,
                    sprintf('[DataGo] Objednávka byla úspěšně nahrána do DataGo: %s; zapsáno pod uživatele: %s', $result['uniqueid'], $user),
                    false
                );

                sqlQueryBuilder()
                    ->insert('datago_orders')
                    ->directValues(
                        [
                            'id_datago' => $result['uniqueid'],
                            'id_order' => $order->id,
                        ]
                    )->execute();
            });
        }

        // Aktualizace jiz existujici objednavky v DataGo
        return $this->getActionResult(function () use ($user, $pass, $order) {
            $this->dataGoApi->setCredentials($user, $pass)
                ->updateOrder(
                    $this->orderSynchronizer->getOrderData($order)
                );

            $order->logHistory('[DataGo] Objednávka byla úspěšně aktualizovaná v DataGo');
        });
    }

    private function getActionResult(callable $action): ActionResult
    {
        try {
            $action();
        } catch (DataGoException $e) {
            $this->pompoLogger->logException($e, 'Chyba přu ručním nahrávání / aktualizaci objednávky!');

            return new ActionResult(false, $e->getMessage());
        }

        return new ActionResult(true);
    }
}
