<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Checkout\Presenter;

use Gls\GlsPoland\AdePlus\ParcelShop\ParcelShop;
use Gls\GlsPoland\DataProvider\ParcelShopDataProvider;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\AddressRepository;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\CountryRepository;
use Gls\GlsPoland\Repository\CheckoutSessionRepository;

final class CheckoutConfigPresenter
{
    private $checkoutSessionRepository;
    private $addressRepository;
    private $countryRepository;
    private $parcelShopDataProvider;
    private $language;

    private $data = [];

    public function __construct(CheckoutSessionRepository $checkoutSessionRepository, AddressRepository $addressRepository, CountryRepository $countryRepository, ParcelShopDataProvider $parcelShopDataProvider, \Language $language)
    {
        $this->checkoutSessionRepository = $checkoutSessionRepository;
        $this->addressRepository = $addressRepository;
        $this->countryRepository = $countryRepository;
        $this->parcelShopDataProvider = $parcelShopDataProvider;
        $this->language = $language;
    }

    public function present(\Cart $cart): array
    {
        if (isset($this->data[$cart->id])) {
            return $this->data[$cart->id];
        }

        $address = $this->addressRepository->find((int) $cart->id_address_delivery);

        return $this->data[$cart->id] = [
            'cartId' => (int) $cart->id,
            'zipCode' => null !== $address ? $address->postcode : null,
            'country' => $this->getCountryIsoCode($address),
            'language' => 'pl' === strtolower($this->language->iso_code) ? 'PL' : 'EN',
            'weight' => $cart->getTotalWeight() ?: 0.01,
            'parcelShops' => $this->getSelectedParcelShops($cart),
        ];
    }

    private function getSelectedParcelShops(\Cart $cart): array
    {
        if (null === $checkoutSession = $this->checkoutSessionRepository->find((int) $cart->id)) {
            return [];
        }

        if ([] === $parcelShopIds = $checkoutSession->getParcelShopIds()) {
            return [];
        }

        $result = [];

        foreach ($parcelShopIds as $referenceId => $parcelShopId) {
            if (null !== $parcelShop = $this->parcelShopDataProvider->getParcelShop($parcelShopId)) {
                $result[$referenceId] = $this->presentParcelShop($parcelShop);
            }
        }

        return $result;
    }

    private function getCountryIsoCode(?\Address $address): string
    {
        if (null === $address || null === $country = $this->countryRepository->find((int) $address->id_country)) {
            return 'PL';
        }

        return $country->iso_code ?? 'PL';
    }

    private function presentParcelShop(ParcelShop $parcelShop): array
    {
        return [
            'id' => $parcelShop->getId(),
            'name' => $this->formatParcelShopName($parcelShop),
            'postal_code' => $parcelShop->getZipCode(),
            'city' => $parcelShop->getCity(),
            'street' => $parcelShop->getStreet(),
        ];
    }

    private function formatParcelShopName(ParcelShop $parcelShop): string
    {
        return trim(sprintf('%s %s %s', $parcelShop->getName1(), $parcelShop->getName2(), $parcelShop->getName3()));
    }
}
