<?php
declare(strict_types=1);
namespace Autogedal\Extend\Controller\Payment;

use Psr\Log\LoggerInterface;
use Monolog\Logger as MonoLogger;
use Monolog\Handler\StreamHandler;
use Monolog\Level;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Module\Dir\Reader;
use Magento\Framework\View\Result\PageFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface;
class Ipn extends \Netopia\Netcard\Controller\Payment\Ipn
{
    /**
     * @var Logger
     */
    private $logger;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;
    public function __construct(Context $context, PageFactory $resultPageFactory, Reader $reader, ScopeConfigInterface $scopeConfig, BuilderInterface $builderInterface, Order $orderFactory, LoggerInterface $logger)
    {
        $monolog = new MonoLogger('mobilpay');
        $monolog->pushHandler(new StreamHandler(BP . '/var/log/mobilpay.log', Level::Debug));
        $this->logger = $monolog;

        $this->orderRepository = ObjectManager::getInstance()->get(OrderRepositoryInterface::class);

        parent::__construct($context, $resultPageFactory, $reader, $scopeConfig, $builderInterface, $orderFactory);
    }

    /**
     * @return bool
     */
    private function isOrderClosed(): bool
    {
        $preventDuplicate = $this->_scopeConfig->isSetFlag('payment/net_card/prevent_duplicate');
        return $preventDuplicate &&
            in_array($this->_order->getState(), [
                ORDER::STATE_CLOSED,
                Order::STATE_COMPLETE,
                Order::STATE_CANCELED
            ], true);
    }

    /**
     * @param string $method
     * @param bool $underVerification
     *
     * @return void
     */
    private function saveOrder(string $method = '', bool $underVerification = true): void
    {
        try {
            $this->orderRepository->save($this->_order);
        } catch (\Exception $e) {
            $this->logger->error(
                $method . ' save failed' . ($underVerification === false ? ' [not underVerification]' : '') . ': ' . $e->getMessage()
            );
            $this->logger->error($e->getTraceAsString());
            throw $e;
        }
    }

    protected function _handleCancel()
    {
        $payment = $this->_order->getPayment();
        $payment->setPreparedMessage($this->_objPmReq->objPmNotify->errorMessage);
        $payment->setParentTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
        $payment->registerVoidNotification();
        $trans = $this->_builderInterface;
        $transaction = $trans->setPayment($payment)
            ->setOrder($this->_order)
            ->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))
            ->setAdditionalInformation(
                [\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS => array('id'=>$this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))]
            )
            ->setFailSafe(true)
            //build method creates the transaction and returns the object
            ->build(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND);
        $payment->addTransactionCommentsToOrder($transaction, $this->_objPmReq->objPmNotify->errorMessage. " - Tranzactie anulata - ");
        $this->_order->setState('pending')->setStatus('custom_neplatit');
        $this->saveOrder('_handleCancel');
    }

    protected function _handleAuthorization($underVerification = true)
    {
        $payment = $this->_order->getPayment();
        $payment->setPreparedMessage($this->_objPmReq->objPmNotify->errorMessage);
        $payment->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
        $trans = $this->_builderInterface;
        $transaction = $trans->setPayment($payment)
            ->setOrder($this->_order)
            ->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))
            ->setAdditionalInformation(
                [\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS => array('id'=>$this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))]
            )
            ->setFailSafe(true)
            //build method creates the transaction and returns the object
            ->build(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND);
        $payment->addTransactionCommentsToOrder($transaction, $this->_objPmReq->objPmNotify->errorMessage . " | ");
        $payment->setIsTransactionClosed(0);

        if (!$underVerification) {
            $payment->setIsTransactionPending(false);
            $payment->registerAuthorizationNotification($this->_objPmReq->objPmNotify->processedAmount);
            $this->_order->setState('pending')->setStatus('new');
            $this->_order->addStatusToHistory('new', $this->_objPmReq->objPmNotify->errorMessage);

            $this->saveOrder('_handleAuthorization', $underVerification);
        } else {
            $payment->setIsTransactionPending(true);
            $this->_order->setState('pending')->setStatus('custom_neplatit');
            $this->_order->sendNewOrderEmail();
        }
        $this->saveOrder('_handleAuthorization');
    }

    /**
     * Handeling such case like:
     * Card Expire
     * Cod CVV2/CCV incorect
     */
    protected function _handlePaymentDenial()
    {
        parent::_handlePaymentDenial();

        $this->_order->addStatusToHistory('custom_neplatit', $this->_objPmReq->objPmNotify->errorMessage);
        $this->_order->setState('pending');
        $this->saveOrder('_handlePaymentDenial');
    }

    protected function _handleRefund() {
        parent::_handleRefund();

        $this->_order->setState(Order::STATE_CLOSED);
        $this->_order->setStatus('creditata');
        $this->_order->addStatusToHistory($this->_order->getStatus(), 'Refunded from Netopia Portal', $notified = false);
        $this->saveOrder('_handleRefund');
    }

    protected function _handleCapturePending()
    {
        if ($this->_order->getStatus() === 'new') {
            $this->logger->info('_handleCapturePending skipped — order already captured (status: new), order: ' . $this->_order->getIncrementId());
            return;
        }

        $payment = $this->_order->getPayment();
        $payment->setPreparedMessage($this->_objPmReq->objPmNotify->errorMessage);
        $payment->setIsTransactionClosed(0);
        $payment->setIsTransactionPending(true);

        $payment->setAmount($this->_objPmReq->objPmNotify->processedAmount);

        $trans = $this->_builderInterface;
        $transaction = $trans->setPayment($payment)
            ->setOrder($this->_order)
            ->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))
            ->setAdditionalInformation(
                [\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS => array('id'=>$this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId))]
            )
            ->setFailSafe(true)
            ->build(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND);
        $payment->addTransactionCommentsToOrder($transaction, $this->_objPmReq->objPmNotify->errorMessage . " - tranzactie in curs de verificare - ");
        $this->_order->setStatus('custom_neplatit');
        $this->saveOrder('_handleCapturePending');
    }

    protected function _handleCapture()
    {
        if ($this->isOrderClosed()) {
            $formattedAmount = $this->_order->getBaseCurrency()->formatTxt($this->_objPmReq->objPmNotify->processedAmount ?? $this->_order->getBaseGrandTotal());
            $message = __('Order already closed, completed or canceled.') . ' ' . __('Authorized amount of %1 online', $formattedAmount);
            $this->_order->addStatusToHistory($this->_order->getStatus(), $message . '; ' . $this->_objPmReq->objPmNotify->errorMessage);
            $this->saveOrder('_handleCapture');
            $this->logger->info($message);
            return null;
        }

        $payment = $this->_order->getPayment();
        $payment->setPreparedMessage($this->_objPmReq->objPmNotify->errorMessage);
        $payment->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
        $payment->setIsTransactionClosed(0);
        $payment->setIsTransactionPending(false);
        /**
         *
         */
        $payment->setStoreCurrencyCode('RON');
        $payment->setBaseCurrencyCode('RON');
        $payment->setOrderCurrencyCode('RON');


        if ($this->_order->getStatus() == Order::STATE_PROCESSING) {
            $payment->setParentTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
            $payment->registerCaptureNotification($this->_objPmReq->objPmNotify->processedAmount);
            $payment->setAmount($this->_objPmReq->objPmNotify->processedAmount);

        } else {
            $payment->setAmount($this->_objPmReq->objPmNotify->processedAmount);
            $payment->setTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
            $payment->setParentTransactionId($this->getRealOrderId($this->_objPmReq->objPmNotify->purchaseId));
            $payment->registerCaptureNotification($this->_objPmReq->objPmNotify->processedAmount);
        }


        $this->_order->setState('pending');
        $this->_order->setStatus('new');
        $this->_order->addStatusToHistory('new', $this->_objPmReq->objPmNotify->errorMessage, $notified = false);
        $this->saveOrder('_handleCapture');
    }
}
