<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Model;

use Magento\Directory\Helper\Data as DirectoryHelper;
use Magento\Framework\Api\AttributeValueFactory;
use Magento\Framework\Api\ExtensionAttributesFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\DataObject;
use Magento\Framework\Model\Context;
use Magento\Framework\Registry;
use Magento\Payment\Helper\Data as PaymentData;
use Magento\Payment\Model\Method\AbstractMethod;
use Magento\Payment\Model\Method\Logger;
use Magento\Quote\Api\Data\CartInterface;
use Simplyin\Payment\Service\PaymentMethodAvailability;

/**
 * SimplyIN payment method model
 *
 * Handles payment method logic and data assignment
 */
class Payment extends AbstractMethod
{
    public const CODE = 'simplyin_payment';

    /**
     * Supported currencies for SimplyIN payment
     * BLIK only works with PLN, card payments work with other currencies
     */
    public const SUPPORTED_CURRENCIES = ['PLN'];

    /**
     * @var string
     */
    protected $_code = self::CODE;

    /**
     * Custom info block so the order Payment Information shows the SimplyIN payment details
     * (method e.g. BLIK/card, provider, status, transaction id), not just the method title.
     *
     * @var string
     */
    protected $_infoBlockType = \Simplyin\Payment\Block\Info\Simplyin::class;

    /**
     * @var bool
     */
    protected $_isGateway = true;

    /**
     * @var bool
     */
    protected $_canCapture = true;

    /**
     * @var bool
     */
    protected $_canCapturePartial = true;

    /**
     * @var bool
     */
    protected $_canRefund = true;

    /**
     * @var bool
     */
    protected $_canRefundInvoicePartial = true;

    /**
     * @var bool
     */
    protected $_canVoid = true;

    /**
     * @var bool
     */
    protected $_canAuthorize = true;

    /**
     * @var PaymentMethodAvailability
     */
    private PaymentMethodAvailability $paymentMethodAvailability;

    /**
     * Constructor
     *
     * Only the required AbstractMethod dependencies (plus the DirectoryHelper it
     * relies on) are declared; the optional resource/collection/data arguments are
     * left to their parent defaults, as this method is not configured with any of
     * them via DI.
     *
     * @param Context $context
     * @param Registry $registry
     * @param ExtensionAttributesFactory $extensionFactory
     * @param AttributeValueFactory $customAttributeFactory
     * @param PaymentData $paymentData
     * @param ScopeConfigInterface $scopeConfig
     * @param Logger $logger
     * @param PaymentMethodAvailability $paymentMethodAvailability
     * @param DirectoryHelper|null $directory
     */
    public function __construct(
        Context $context,
        Registry $registry,
        ExtensionAttributesFactory $extensionFactory,
        AttributeValueFactory $customAttributeFactory,
        PaymentData $paymentData,
        ScopeConfigInterface $scopeConfig,
        Logger $logger,
        PaymentMethodAvailability $paymentMethodAvailability,
        ?DirectoryHelper $directory = null
    ) {
        parent::__construct(
            $context,
            $registry,
            $extensionFactory,
            $customAttributeFactory,
            $paymentData,
            $scopeConfig,
            $logger,
            null,
            null,
            [],
            $directory
        );
        $this->paymentMethodAvailability = $paymentMethodAvailability;
    }

    /**
     * Check whether payment method can be used
     *
     * @param CartInterface|null $quote
     * @return bool
     */
    public function isAvailable(?CartInterface $quote = null): bool
    {
        if (!parent::isAvailable($quote)) {
            return false;
        }

        // Hide SimplyIN when the merchant has no payment method configured.
        // Fail-closed: a successful empty response, or any error/
        // exception/unauthenticated response, hides it; see PaymentMethodAvailability
        // for the full rule.
        return $this->paymentMethodAvailability->hasAvailablePaymentMethods();
    }

    /**
     * Check if currency is supported for BLIK payments
     *
     * BLIK only works with PLN currency
     *
     * @param string $currencyCode
     * @return bool
     */
    public function isBlikAvailableForCurrency(string $currencyCode): bool
    {
        return strtoupper($currencyCode) === 'PLN';
    }

    /**
     * Check if currency is fully supported (all payment methods)
     *
     * @param string $currencyCode
     * @return bool
     */
    public function isFullySupportedCurrency(string $currencyCode): bool
    {
        return in_array(strtoupper($currencyCode), self::SUPPORTED_CURRENCIES, true);
    }

    /**
     * Assign data to info model instance
     *
     * @param DataObject|mixed $data
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function assignData(DataObject $data): static
    {
        parent::assignData($data);

        $additionalData = $data->getAdditionalData();

        $fields = [
            'simplyin_order_id',
            'simplyin_payment_id',
            'simplyin_provider_payment_id',
            'simplyin_payment_status',
            'simplyin_registered_at',
            'simplyin_redirect_url',
            'simplyin_redirect_iframe_allowed',
        ];

        foreach ($fields as $field) {
            if (isset($additionalData[$field])) {
                $this->getInfoInstance()->setAdditionalInformation($field, $additionalData[$field]);
            }
        }

        return $this;
    }
}
