<?php
declare(strict_types=1);

namespace PayPo\Payment\Model\Ui;

use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Framework\Escaper;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\UrlInterface;
use Magento\Payment\Helper\Data as PaymentHelper;
use Magento\Store\Model\StoreManagerInterface;
use PayPo\Payment\Model\Payment\PayPo;

/**
 * Exposes the PayPo instructions and logo to the checkout javascript config.
 */
class ConfigProvider implements ConfigProviderInterface
{
    /**
     * Media sub directory the admin logo upload writes to.
     */
    public const PAYMENT_MEDIA_DIRECTORY = 'sales/store/payments/';

    /**
     * @var PayPo|null
     */
    private ?PayPo $method = null;

    /**
     * @param PaymentHelper $paymentHelper
     * @param Escaper $escaper
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        private readonly PaymentHelper $paymentHelper,
        private readonly Escaper $escaper,
        private readonly StoreManagerInterface $storeManager
    ) {
    }

    /**
     * Checkout configuration for the PayPo method.
     *
     * @return array
     * @throws NoSuchEntityException
     */
    public function getConfig(): array
    {
        $method = $this->getMethod();

        if ($method === null || !$method->isAvailable()) {
            return [];
        }

        return [
            'payment' => [
                'instructions' => [PayPo::METHOD_CODE => $method->getInstructions()],
                'logo' => [PayPo::METHOD_CODE => $this->getLogoUrl($method)],
            ],
        ];
    }

    /**
     * Absolute url of the configured logo, empty string when none is uploaded.
     *
     * @param PayPo $method
     * @return string
     * @throws NoSuchEntityException
     */
    private function getLogoUrl(PayPo $method): string
    {
        $logo = $method->getLogo();

        return $logo === ''
            ? ''
            : $this->storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA)
                . self::PAYMENT_MEDIA_DIRECTORY
                . $this->escaper->escapeHtml($logo);
    }

    /**
     * Resolve the payment method instance lazily, so a misconfigured method
     * cannot break the whole checkout config.
     *
     * @return PayPo|null
     */
    private function getMethod(): ?PayPo
    {
        if ($this->method === null) {
            try {
                $instance = $this->paymentHelper->getMethodInstance(PayPo::METHOD_CODE);
            } catch (LocalizedException $e) {
                return null;
            }

            if (!$instance instanceof PayPo) {
                return null;
            }

            $this->method = $instance;
        }

        return $this->method;
    }
}
