<?php
declare(strict_types=1);

namespace PayPo\Payment\Helper;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

/**
 * Read-only accessor for the PayPo payment method configuration.
 *
 * Kept in the Helper namespace for backwards compatibility with previous
 * module versions; it no longer extends AbstractHelper because none of the
 * helper context (request, url builder, module manager) is used here.
 */
class Data
{
    /**
     * Configuration path prefix shared by every PayPo setting.
     */
    public const XML_PATH_PAYPO = 'payment/paypo/';

    /**
     * Store scope used when no explicit store id is passed to a getter.
     *
     * @var int|string|null
     */
    private $storeId;

    /**
     * @param ScopeConfigInterface $scopeConfig
     */
    public function __construct(
        private readonly ScopeConfigInterface $scopeConfig
    ) {
    }

    /**
     * Read a single PayPo setting.
     *
     * @param string $field Field name without the `payment/paypo/` prefix
     * @param int|string|null $storeId Falls back to the store set with setStoreId(), then to the current store
     * @return mixed
     */
    public function getConfig(string $field, int|string|null $storeId = null): mixed
    {
        if ($storeId === null) {
            $storeId = $this->storeId;
        }

        return $this->scopeConfig->getValue(
            self::XML_PATH_PAYPO . $field,
            ScopeInterface::SCOPE_STORE,
            $storeId
        );
    }

    /**
     * Whether an invoice should be created right after a successful payment.
     *
     * @param int|string|null $storeId
     * @return bool
     */
    public function autoApprove(int|string|null $storeId = null): bool
    {
        return (bool)$this->getConfig('auto_approve', $storeId);
    }

    /**
     * Whether the transaction is confirmed on invoice instead of on shipment.
     *
     * @param int|string|null $storeId
     * @return bool
     */
    public function autoApproveInvoice(int|string|null $storeId = null): bool
    {
        return (bool)$this->getConfig('auto_approve_invoice', $storeId);
    }

    /**
     * Whether the order should be cancelled after a failed or rejected payment.
     *
     * @param int|string|null $storeId
     * @return bool
     */
    public function autoCancel(int|string|null $storeId = null): bool
    {
        return (bool)$this->getConfig('auto_cancel', $storeId);
    }

    /**
     * Whether the sandbox (test) API credentials should be used.
     *
     * @param int|string|null $storeId
     * @return bool
     */
    public function isSandbox(int|string|null $storeId = null): bool
    {
        return (bool)$this->getConfig('testmode', $storeId);
    }

    /**
     * Merchant id of the environment currently in use.
     *
     * @param int|string|null $storeId
     * @return string
     */
    public function getMerchantId(int|string|null $storeId = null): string
    {
        $field = $this->isSandbox($storeId) ? 'sandbox_api_key' : 'live_api_key';

        return (string)$this->getConfig($field, $storeId);
    }

    /**
     * Product type and instalment count sent with every transaction.
     *
     * CORE is always split into 4 instalments, PNX is configurable.
     *
     * @param int|string|null $storeId
     * @return array{0: string, 1: int}
     */
    public function getProductMode(int|string|null $storeId = null): array
    {
        if ($this->getConfig('product_mode', $storeId) === 'PNX') {
            return ['PNX', (int)$this->getConfig('product_pnx_installment_count', $storeId)];
        }

        return ['CORE', (int)($this->getConfig('product_core_installment_count', $storeId) ?: 4)];
    }

    /**
     * Minimum cart total the method is offered for, 0 when not limited.
     *
     * @param int|string|null $storeId
     * @return float
     */
    public function getMinOrderTotal(int|string|null $storeId = null): float
    {
        return (float)$this->getConfig('min_order_total', $storeId);
    }

    /**
     * @return int|string|null
     */
    public function getStoreId()
    {
        return $this->storeId;
    }

    /**
     * Pin the helper to a store scope.
     *
     * @deprecated Pass the store id directly to the getters instead, the helper is a singleton
     *             and the pinned scope leaks between requests handled by the same process.
     * @param int|string|null $storeId
     * @return void
     */
    public function setStoreId($storeId = null): void
    {
        $this->storeId = $storeId;
    }
}
