<?php

namespace Oney\ThreeByFour\Model\Method;

use Magento\Framework\DataObject;
use Magento\Payment\Model\InfoInterface;
use Magento\Payment\Model\Method\AbstractMethod;
use Magento\Payment\Model\Method\Adapter;
use Magento\Payment\Model\MethodInterface;
use Oney\ThreeByFour\Api\ThreeByFourMethodInterface;
use Oney\ThreeByFour\Helper\Config;
use Psr\Log\LoggerInterface;
use Oney\ThreeByFour\Logger\Logger as OneyLogger;

/**
 * ThreeByFour Payment Method
 * 
 * Main payment method class for Oney ThreeByFour payment solution.
 * Implements payment method interface and handles payment operations.
 * 
 * @package Oney\ThreeByFour\Model\Method
 * @version 1.0.0
 * @author Oney
 * @since 1.0.0
 */
class ThreeByFour extends DataObject implements MethodInterface, ThreeByFourMethodInterface
{
    /**
     * Payment method code
     * 
     * @const string
     * @version 1.0.0
     */
    const METHOD_CODE = "oney_threebyfour";

    /**
     * Payment status constants
     * 
     * @const string
     * @version 1.0.0
     */
    const STATUS_PENDING = "PENDING";
    const STATUS_FAVORABLE = "FAVORABLE";
    const STATUS_FUNDED = "FUNDED";
    const STATUS_CANCELLED = "CANCELLED";
    const STATUS_REFUSED = "REFUSED";
    const STATUS_ABORTED = "ABORTED";
    
    /**
     * Configuration helper instance
     * 
     * @var Config
     * @version 1.0.0
     */
    protected $_helperConfig;
    
    /**
     * Payment method code
     * 
     * @var string
     * @version 1.0.0
     */
    protected $code = self::METHOD_CODE;
    
    /**
     * Payment adapter instance
     * 
     * @var Adapter
     * @version 1.0.0
     */
    protected $_adapter;
    
    /**
     * Logger instance
     * 
     * @var OneyLogger
     * @version 1.0.0
     */
    protected $_logger;

    /**
     * Constructor
     * 
     * @param Adapter $adapter Payment adapter
     * @param Config $config Configuration helper
     * @param OneyLogger $logger Logger instance
     * @param array $data Additional data
     * @version 1.0.0
     */
    public function __construct(
        Adapter $adapter,
        Config $config,
        OneyLogger $logger,
        array $data = []
    ) {
        $this->_adapter = $adapter;
        $this->_helperConfig = $config;
        $this->_logger = $logger;
        parent::__construct($data);
    }

    /**
     * Get payment method code
     * 
     * @return string Payment method code
     * @version 1.0.0
     */
    public function getCode(): string
    {
        return $this->code;
    }

    /**
     * Get form block type
     * 
     * @return string Form block type
     * @version 1.0.0
     */
    public function getFormBlockType(): string
    {
        return $this->_adapter->getFormBlockType();
    }

    /**
     * Set store ID
     * 
     * @param int|string $storeId Store ID
     * @return void
     * @version 1.0.0
     */
    public function setStore($storeId): void
    {
        $this->setData("store", $storeId);
    }

    /**
     * Get store ID
     * 
     * @return int|string|null Store ID
     * @version 1.0.0
     */
    public function getStore()
    {
        return $this->getData("store");
    }

    /**
     * Check if order is allowed
     * 
     * @return bool True if order is allowed
     * @version 1.0.0
     */
    public function canOrder(): bool
    {
        return true;
    }

    /**
     * Check if authorization is allowed
     * 
     * @return bool True if authorization is allowed
     * @version 1.0.0
     */
    public function canAuthorize(): bool
    {
        return false;
    }

    /**
     * Check if capture is allowed
     * 
     * @return bool True if capture is allowed
     * @version 1.0.0
     */
    public function canCapture(): bool
    {
        return true;
    }

    /**
     * Check if partial capture is allowed
     * 
     * @return bool True if partial capture is allowed
     * @version 1.0.0
     */
    public function canCapturePartial(): bool
    {
        return false;
    }

    /**
     * Check if capture once is allowed
     * 
     * @return bool True if capture once is allowed
     * @version 1.0.0
     */
    public function canCaptureOnce(): bool
    {
        return true;
    }

    /**
     * Check if refund is allowed
     * 
     * @return bool True if refund is allowed
     * @version 1.0.0
     */
    public function canRefund(): bool
    {
        return true;
    }

    public function canRefundPartialPerInvoice()
    {
        return true;
    }

    public function canVoid()
    {
        return true;
    }

    public function canUseInternal()
    {
        return true;
    }

    public function canUseCheckout()
    {
        return true;
    }

    public function canEdit()
    {
        return false;
    }

    public function canFetchTransactionInfo()
    {
        return false;
    }

    public function fetchTransactionInfo(InfoInterface $payment, $transactionId)
    {
        return $this->_adapter->fetchTransactionInfo($payment, $transactionId);
    }

    public function isGateway()
    {
        return true;
    }

    public function isOffline()
    {
        return false;
    }

    public function isInitializeNeeded()
    {
        return false;
    }

    public function canUseForCountry($country)
    {
        return true;
    }

    public function canUseForCurrency($currencyCode)
    {
        return true;
    }

    public function getInfoBlockType()
    {
        return $this->_adapter->getInfoBlockType();
    }

    public function getInfoInstance()
    {
        return $this->_adapter->getInfoBlockType();
    }

    public function setInfoInstance(InfoInterface $info)
    {
        $this->_adapter->setInfoInstance($info);
    }

    public function validate()
    {
        $this->_adapter->validate();
        return $this;
    }

    public function order(InfoInterface $payment, $amount)
    {
        $this->_adapter->order($payment, $amount);
        return $this;
    }

    public function authorize(InfoInterface $payment, $amount)
    {
        $this->_adapter->authorize($payment, $amount);
        return $this;
    }

    public function capture(InfoInterface $payment, $amount)
    {
        $this->_adapter->capture($payment, $amount);
        $this->_logger->info('[SUCCESS] [ORDER] Order captured with amount: ', ['amount' => $amount]);
        return $this;
    }

    public function refund(InfoInterface $payment, $amount)
    {
        $this->_adapter->refund($payment, $amount);
        $this->_logger->info('[SUCCESS] [ORDER] Order refunded with amount: ', ['amount' => $amount]);
        return $this;
    }

    public function cancel(InfoInterface $payment)
    {
        $this->_adapter->cancel($payment);
        $this->_logger->info('[SUCCESS] [ORDER] Order cancelled');
        return $this;
    }

    public function void(InfoInterface $payment)
    {
        $this->_adapter->void($payment);
        return $this;
    }

    public function canReviewPayment()
    {
        return $this->_adapter->canReviewPayment();
    }

    public function acceptPayment(InfoInterface $payment)
    {
        $this->_adapter->acceptPayment($payment);
        return $this;
    }

    public function denyPayment(InfoInterface $payment)
    {
        $this->_adapter->denyPayment($payment);
        return $this;
    }

    public function getConfigData($field, $storeId = null)
    {
        return $this->getData($field);
    }

    public function assignData(\Magento\Framework\DataObject $data)
    {
        $this->setData($data->toArray());
    }

    public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)
    {
        if ($quote === null) {
            $this->_logger->debug("[INFO] quote is null: ", $quote);
            return false;
        }
        
        $this->_logger->debug("[INFO] method is available :", $this->toArray());
        return ($quote->getGrandTotal() >= $this->getMinOrderTotal() && $quote->getGrandTotal() <= $this->getMaxOrderTotal());
    }

    public function isActive($storeId = null)
    {
        return true;
    }

    public function initialize($paymentAction, $stateObject)
    {
        return $this->_adapter->initialize($paymentAction, $stateObject);
    }

    public function getConfigPaymentAction()
    {
        return AbstractMethod::ACTION_ORDER;
    }

    public function setCode($code)
    {
        $this->code = $code;
        return $this;
    }

    public function getMaxOrderTotal()
    {
        return $this->getData('max_order_total_oney');
    }

    public function getMinOrderTotal()
    {
        return $this->getData('min_order_total_oney');
    }

    public function getTitle()
    {
        return $this->getData('title');
    }
}


