<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Hook\Front\Checkout;

use Gls\GlsPoland\AdePlus\ParcelShop\ParcelShop;
use Gls\GlsPoland\DataProvider\ParcelShopDataProvider;
use Gls\GlsPoland\Entity\OrderParcelShop;
use Gls\GlsPoland\Entity\ShopDeliveryCarrier;
use Gls\GlsPoland\PrestaShop\Checkout\Presenter\ParcelShopAddressPresenter;
use Gls\GlsPoland\PrestaShop\Helper\CarrierFinder;
use Gls\GlsPoland\PrestaShop\Hook\HookInterface;
use Gls\GlsPoland\PrestaShop\Templating\RendererInterface;
use Gls\GlsPoland\Repository\CheckoutSessionRepository;
use Gls\GlsPoland\Repository\OrderParcelShopRepository;

final class DisplayOrderConfirmation implements HookInterface
{
    public const HOOK_NAME = 'displayOrderConfirmation';

    private $carrierFinder;
    private $sessionRepository;
    private $orderParcelShopRepository;
    private $dataProvider;
    private $presenter;
    private $renderer;

    public function __construct(CarrierFinder $carrierFinder, CheckoutSessionRepository $sessionRepository, OrderParcelShopRepository $orderParcelShopRepository, ParcelShopDataProvider $dataProvider, ParcelShopAddressPresenter $presenter, RendererInterface $renderer)
    {
        $this->carrierFinder = $carrierFinder;
        $this->sessionRepository = $sessionRepository;
        $this->orderParcelShopRepository = $orderParcelShopRepository;
        $this->dataProvider = $dataProvider;
        $this->presenter = $presenter;
        $this->renderer = $renderer;
    }

    /**
     * @param array{order: \Order} $parameters
     */
    public function execute(array $parameters): string
    {
        $order = $parameters['order'] ?? null;

        if (!$order instanceof \Order) {
            return '';
        }

        $carrier = $this->carrierFinder->findOneByCarrierId((int) $order->id_carrier);

        if (!$carrier instanceof ShopDeliveryCarrier) {
            return '';
        }

        if (null === $parcelShop = $this->getParcelShopDetails($order, $carrier->getId()->getValue())) {
            return '';
        }

        return $this->renderer->render('module:glspoland/views/templates/hook/order_confirmation.tpl', [
            'parcel_shop' => $parcelShop,
        ]);
    }

    private function getParcelShopDetails(\Order $order, int $carrierId): ?array
    {
        $stored = $this->orderParcelShopRepository->find((int) $order->id);
        if ($stored instanceof OrderParcelShop) {
            return [
                'id' => $stored->getParcelShopId(),
                'name' => $stored->getName(),
                'address' => implode('<br/>', array_filter([
                    $stored->getStreet(),
                    trim(sprintf('%s %s', $stored->getPostalCode(), $stored->getCity())),
                ])),
            ];
        }

        if (null === $parcelShop = $this->getParcelShop($order, $carrierId)) {
            return null;
        }

        $entity = new OrderParcelShop((int) $order->id, $parcelShop);
        $this->orderParcelShopRepository->add($entity);

        return [
            'id' => $parcelShop->getId(),
            'name' => trim(sprintf('%s %s %s', $parcelShop->getName1(), $parcelShop->getName2(), $parcelShop->getName3())),
            'address' => $this->presenter->present($parcelShop),
        ];
    }

    private function getParcelShop(\Order $order, int $carrierId): ?ParcelShop
    {
        $checkoutSession = $this->sessionRepository->find((int) $order->id_cart);

        if (null === $checkoutSession) {
            return null;
        }

        $parcelShopId = $checkoutSession->getParcelShopId($carrierId);
        if (null === $parcelShopId) {
            $parcelShopId = $checkoutSession->getParcelShopId((int) $order->id_carrier);
        }

        if (null === $parcelShopId) {
            return null;
        }

        return $this->dataProvider->getParcelShop($parcelShopId);
    }
}
