<?php

namespace Aman\AmanAccept\Model\Api;

use Aman\AmanAccept\Logger\Logger;
use Aman\AmanAccept\Api\Data\PayloadInterface;
use Aman\AmanAccept\Api\CustomInterface;

use Magento\Framework\View\Result\PageFactory;
use Magento\Checkout\Model\Session;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\OrderFactory;
use Aman\AmanAccept\Gateway\Config\AmanExpress\Config;
use Magento\Framework\App\Response\Http;
use Magento\Sales\Model\Order\Payment\Transaction\Builder as TransactionBuilder;
use Magento\Sales\Model\Order\Payment\Transaction;
use Magento\Sales\Api\OrderRepositoryInterface;

class Custom implements CustomInterface
{
    protected $_objectmanager;
    protected $_checkoutSession;
    protected $_orderFactory;
    protected $urlBuilder;
    private $logger;
    protected $response;
    protected $config;
    protected $messageManager;
    protected $transactionRepository;
    protected $cart;
    protected $inbox;

    public function __construct(
        Session $checkoutSession,
        OrderFactory $orderFactory,
        Logger $logger,
        Config $config,
        Http $response,
        TransactionBuilder $tb,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\AdminNotification\Model\Inbox $inbox,
        \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository,
        OrderRepositoryInterface $orderRepository,
        \Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
        \Aman\AmanAccept\Model\Adapter\AmanAdapterFactory $adapterFactory
    ) {

        $this->checkoutSession = $checkoutSession;
        $this->orderFactory = $orderFactory;
        $this->response = $response;
        $this->config = $config;
        $this->transactionBuilder = $tb;
        $this->logger = $logger;
        $this->cart = $cart;
        $this->inbox = $inbox;
        $this->transactionRepository = $transactionRepository;
        $this->urlBuilder = \Magento\Framework\App\ObjectManager::getInstance()
            ->get('Magento\Framework\UrlInterface');

        $this->orderRepository = $orderRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilderFactory->create();

        $this->adapterFactory = $adapterFactory;
    }

    /**
     * @param string $transactionReference
     * @param string $orderReference
     * @param string $merchantReference
     * @param string $paymentMethod
     * @param string $amount
     * @param string $currency
     * @param string $status
     * @param string $createdAt
     * @param string $updatedAt
     * @param string $transactionType
     * @param string $transactionFees
     * @param string $customerName
     * @param string $customerPhoneNumber
     * @param string $customerEmail
     * @param string $customerAddress
     * @param string $hmac
     * @return string|void
     */
    public function getPost(
        string $transactionReference,
        string $orderReference,
        string $merchantReference,
        string $paymentMethod,
        string $amount,
        string $currency,
        string $status,
        string $createdAt,
        string $updatedAt,
        string $transactionType,
        string $transactionFees,
        string $customerName,
        string $customerPhoneNumber,
        string $customerEmail,
        string $customerAddress,
        string $hmac
    )
    {
        $this->logger->info("Receiving response payload\n" .
            "TransactionReference " . $transactionReference . "\n" .
            "OrderReference " . $orderReference . "\n" .
            "PaymentMethod " . $paymentMethod . "\n" .
            "Amount " . $amount . "\n" .
            "Currency " . $currency . "\n" .
            "TransactionFees " . $transactionFees . "\n" .
            "Status " . $status . "\n" .
            "CreatedAt " . $createdAt . "\n" .
            "UpdatedAt " . $updatedAt);


        $transactionId_str = $orderReference ;
        $reference_arr = explode('-', $transactionId_str);
        $transactionId = $reference_arr[2];
        if ($transactionId != null) {
            try {
                # get transaction
                $this->logger->info("Magento transactionId: $transactionId");

                $this->searchCriteriaBuilder->addFilter('txn_id', $transactionId);
                $list = $this->transactionRepository->getList(
                    $this->searchCriteriaBuilder->create()
                );

                $transactions = $list->getItems();
                $transaction = reset($transactions);

                if ($transaction) {
                    $order_id = $transaction["order_id"];
                    $payment_id = $transaction["payment_id"];
                    $increment_id = $transaction["increment_id"];
                    $this->logger->info("order_id: $order_id | payment_id: $payment_id | increment_id: $increment_id");

                    # get order and payment objects
                    $order = $this->orderFactory->create()->loadByIncrementId((int)$increment_id);

                    if ($order) {
                        # get Client credentials from configurations.
                        $storeId = $order->getStoreId();
                        $this->logger->info("aman_result_auth_storeId: $storeId");
                        $secretKey = $this->config->getSecretKey($storeId);
                        $publicKey = $this->config->getPublicKey($storeId);
                        $authJson = sprintf("{Amount:\"%s\",Currency:\"%s\",TransactionReference:\"%s\",TransactionFees:\"%s\",TransactionType:\"%s\",OrderReference:\"%s\",PaymentMethod:\"%s\",Status:\"%s\",CreatedAt:\"%s\",UpdatedAt:\"%s\",MerchantReference:\"%s\",customerName:\"%s\",customerPhoneNumber:\"%s\",customerEmail:\"%s\",customerAddress:\"%s\"}",
                        $amount, $currency, $transactionReference, $transactionFees, $transactionType, $orderReference, $paymentMethod, $status, $createdAt, $updatedAt, $merchantReference, $customerName, $customerPhoneNumber, $customerEmail, $customerAddress);

                        $this->logger->info("aman_result_authJson: $authJson");
                        $auth = $this->authJson($authJson, $secretKey);
                        $this->logger->info("aman_result_auth_secretKey: $secretKey");
                        $this->logger->info("aman_result_auth: $auth");
                        $this->logger->info("aman_result_auth_sha512: $hmac");
                        if ($auth == $hmac) {
                            if ($status == "SUCCESS") {
                                $order->setState(Order::STATE_PROCESSING)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING));

                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "successful"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is completed successfully"
                                );

                                $payment->setParentTransactionId(null);
                                $payment->registerAuthorizationNotification($amount);
                                $payment->registerCaptureNotification($amount);
                                # send new email
                                $order->setCanSendNewEmailFlag(true);
                                $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                                $objectManager->create('Magento\Sales\Model\OrderNotifier')->notify($order);
                                $payment->save();
                                $order->save();
                                $this->logger->info("Payment for $payment_id was credited.");
                            } elseif ($status == "CANCELLED") {
                                $order->setState(Order::STATE_CANCELED)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CANCELED));
                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "canceled"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is canceled"
                                );
                                $payment->setParentTransactionId(null);
                                $payment->save();
                                $order->save();
                            } elseif ($status == "REFUNDED") {
                                $order->setState(Order::STATE_CANCELED)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CLOSED));
                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "refunded"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is refunded"
                                );
                                $payment->setParentTransactionId(null);
                                $payment->save();
                                $order->save();
                            } elseif ($status == "FAILED") {
                                $order->setState(Order::STATE_CANCELED)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CANCELED));
                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "canceled"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is failed to be paid from customer"
                                );
                                $payment->setParentTransactionId(null);
                                $payment->save();
                                $order->save();
                            } elseif ($status == "EXPIRED") {
                                $order->setState(Order::STATE_CANCELED)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CANCELED));
                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "canceled"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is expired as the customer did not pay"
                                );
                                $payment->setParentTransactionId(null);
                                $payment->save();
                                $order->save();
                            } elseif ($status == "PENDING") {
                                $res = $order->setState(Order::STATE_PENDING_PAYMENT)
                                    ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PENDING_PAYMENT));
                                $this->logger->info("aman_result_pending_update:$res");
                                $transaction->setTxnId($payment_id);
                                $transaction->setAdditionalInformation(
                                    "AmanPayment Transaction Id",
                                    $payment_id
                                );
                                $transaction->setAdditionalInformation(
                                    "status",
                                    "Pending Payment"
                                );
                                $transaction->setIsClosed(1);
                                $transaction->save();
                                # get payment data
                                $payment = $order->getPayment();
                                $payment->addTransactionCommentsToOrder(
                                    $transaction,
                                    "Transaction is Pending Payment"
                                );
                                $payment->setParentTransactionId(null);
                                $payment->save();
                                $order->save();
                            }
                            $message = [];
							$message['status'] = '200';
							$message['message'] = 'SUCCESS';
                            http_response_code(200);
							echo json_encode($message);
                        } else {
                            $this->logger->info("Signature verification failed $transactionId_str");
                        }
                    } else {
                        $this->logger->info("Order not found with order id $order_id");
                        $message = [];
						$message['status'] = '400';
						$message['message'] = 'Signature Failed';
                        http_response_code(400);
						echo json_encode($message);
                    }
                } else {
                    $this->logger->info("transaction not found with transaction id $transactionId");
                    $message = [];
				    $message['status'] = '400';
					$message['message'] = 'transaction not found';
                    http_response_code(400);
					echo json_encode($message);
                }
            } catch (Exception $e) {
                $this->logger->info($e->getMessage());
                $this->logger->info("Payment for $payment_id was not credited.");
                //$this->_redirect($this->urlBuilder->getBaseUrl());
                $message = [];
				$message['status'] = '400';
				$message['message'] = 'Payment was not credited';
                http_response_code(400);
				echo json_encode($message);
            }
        }
    }

    /**
     * @param string $data
     * @param string $secretKey
     * @return mixed
     */
    public function authJson($data, $secretKey)
    {
        return hash_hmac("sha3-512", $data, $secretKey);
    }
}
