<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Hook\Admin;

use Gls\GlsPoland\Configuration\Api;
use Gls\GlsPoland\PrestaShop\Grid\Filters\ConsignmentFilters;
use Gls\GlsPoland\PrestaShop\Helper\CarrierFinder;
use Gls\GlsPoland\PrestaShop\Order\ParcelShopDetailsProvider;
use Gls\GlsPoland\PrestaShop\Hook\PrestaShopVersionAwareHookInterface;
use Gls\GlsPoland\PrestaShop\Hook\VersionRange;
use PrestaShop\PrestaShop\Core\Grid\GridFactoryInterface;
use PrestaShopBundle\Security\Voter\PageVoter;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Twig\Environment;

final class DisplayAdminOrderTabLink implements PrestaShopVersionAwareHookInterface
{
    public const HOOK_NAME = 'displayAdminOrderTabLink';

    private $authorizationChecker;
    private $configuration;
    private $gridFactory;
    private $parcelShopDetailsProvider;
    private $carrierFinder;
    private $twig;

    public function __construct(
        AuthorizationCheckerInterface $authorizationChecker,
        Api\ConfigurationInterface $configuration,
        GridFactoryInterface $gridFactory,
        ParcelShopDetailsProvider $parcelShopDetailsProvider,
        CarrierFinder $carrierFinder,
        Environment $twig
    ) {
        $this->authorizationChecker = $authorizationChecker;
        $this->configuration = $configuration;
        $this->gridFactory = $gridFactory;
        $this->parcelShopDetailsProvider = $parcelShopDetailsProvider;
        $this->carrierFinder = $carrierFinder;
        $this->twig = $twig;
    }

    public static function getVersionRange(): VersionRange
    {
        return new VersionRange('1.7.7');
    }

    public function execute(array $parameters): string
    {
        $order = $this->getOrder($parameters);
        if (!$order instanceof \Order || 0 >= (int) $order->id) {
            return '';
        }

        if (!$this->shouldDisplay($order)) {
            return '';
        }

        return $this->twig->render('@Modules/glspoland/views/templates/hook/admin_order_tab_link.html.twig');
    }

    private function shouldDisplay(\Order $order): bool
    {
        if (null !== $this->carrierFinder->findOneByCarrierId((int) $order->id_carrier)) {
            return true;
        }

        if (null !== $this->parcelShopDetailsProvider->getForOrder($order)) {
            return true;
        }

        if (
            !$this->authorizationChecker->isGranted(PageVoter::READ, \Gls\GlsPoland\Controller\Admin\ConsignmentController::TAB_NAME)
            && !$this->authorizationChecker->isGranted(PageVoter::READ, 'AdminModules')
        ) {
            return false;
        }

        /** @var ConsignmentFilters $filters */
        $filters = ConsignmentFilters::buildDefaults();
        $filters->addFilter([
            'id_order' => (int) $order->id,
            'sandbox' => $this->configuration->isSandboxEnabled(),
        ]);

        return 0 < $this->gridFactory->getGrid($filters)->getData()->getRecordsTotal();
    }

    private function getOrder(array $parameters): ?\Order
    {
        $order = $parameters['order'] ?? null;
        if ($order instanceof \Order && \Validate::isLoadedObject($order)) {
            return $order;
        }

        $orderId = (int) ($parameters['id_order'] ?? 0);
        if (0 >= $orderId) {
            return null;
        }

        $order = new \Order($orderId);

        return \Validate::isLoadedObject($order) ? $order : null;
    }
}
