<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Delivery\Point\Presenter;

use InPost\International\Api\Point\Model\Address;
use InPost\International\Api\Point\Model\PointType;
use InPost\International\Country;
use InPost\International\Delivery\Point\PointInterface;
use InPost\International\PrestaShop\ObjectModel\Repository\CountryRepository;
use InPost\International\PrestaShop\ObjectModel\Repository\ObjectRepositoryInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class PointPresenter implements PointPresenterInterface
{
    /**
     * @var CountryRepository
     */
    private $countryRepository;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @param CountryRepository $countryRepository
     */
    public function __construct(ObjectRepositoryInterface $countryRepository, TranslatorInterface $translator)
    {
        $this->countryRepository = $countryRepository;
        $this->translator = $translator;
    }

    public function formatName(PointInterface $point, string $locale = null): string
    {
        $typeLabel = $point->getType();
        if (null !== $type = PointType::tryFrom($typeLabel)) {
            $typeLabel = $type->trans($this->translator, $locale);
        }

        return sprintf('%s %s', $typeLabel, $point->getId());
    }

    public function formatAddress(PointInterface $point, string $locale = null): string
    {
        $address = $this->createAddress($point, $locale);

        return \AddressFormat::generateAddress($address);
    }

    private function createAddress(PointInterface $point, ?string $locale): \Address
    {
        $pointAddress = $point->getAddress();

        $address = new \Address();
        $address->firstname = $this->formatName($point, $locale);
        $address->lastname = '';
        $address->address1 = $this->formatStreetAddress($pointAddress);
        $address->city = $pointAddress->getCity();
        $address->postcode = $pointAddress->getPostalCode();
        $address->id_country = $this->getCountryId($pointAddress->getCountry());

        return $address;
    }

    private function getCountryId(string $isoCode): ?int
    {
        if (null === $country = $this->countryRepository->findOneByIsoCode($isoCode)) {
            return null;
        }

        return (int) $country->id;
    }

    private function formatStreetAddress(Address $address): string
    {
        $country = Country::tryFrom($address->getCountry()) ?? Country::Poland();

        return $country->formatStreetAddress((string) $address->getStreet(), (string) $address->getBuildingNumber());
    }
}
