<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Checkout;

use Gls\GlsPoland\Cart\CartId;
use Gls\GlsPoland\DataProvider\ParcelShopDataProvider;
use Gls\GlsPoland\Entity\CheckoutSession;
use Gls\GlsPoland\Entity\ShopDeliveryCarrier;
use Gls\GlsPoland\Repository\CheckoutSessionRepository;

final class DeliveryOptionDataPersister implements DeliveryOptionDataPersisterInterface
{
    private $repository;
    private $dataProvider;

    public function __construct(CheckoutSessionRepository $repository, ParcelShopDataProvider $dataProvider)
    {
        $this->repository = $repository;
        $this->dataProvider = $dataProvider;
    }

    public function save(\Cart $cart, array $carriers, array $data): void
    {
        $parcelShops = [];

        foreach ($carriers as $key => $carrier) {
            if (!$carrier instanceof ShopDeliveryCarrier) {
                continue;
            }

            $parcelShopId = $data[$key]['parcel_shop_id'] ?? null;

            if (null === $parcelShopId || null === $parcelShop = $this->dataProvider->getParcelShop($parcelShopId)) {
                throw new \RuntimeException('ParcelShop does not exist');
            }

            $parcelShops[] = [$carrier, $parcelShop];
        }

        if ([] === $parcelShops) {
            $this->removeSession((int) $cart->id);
        } else {
            $this->updateSession((int) $cart->id, $parcelShops);
        }
    }

    private function removeSession(int $cartId): void
    {
        if (null === $session = $this->repository->find($cartId)) {
            return;
        }

        $this->repository->remove($session);
    }

    private function updateSession(int $cartId, array $data): void
    {
        $session = $this->repository->find($cartId) ?? new CheckoutSession(CartId::from($cartId));

        $session->reset();
        foreach ($data as $datum) {
            $session->setParcelShop(...$datum);
        }

        $this->repository->add($session);
    }
}
