<?php

namespace App\Core\Payment\KuveytTurk;

use App\Exceptions\ApiErrorException;
use GuzzleHttp\Client;

use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Log;
use Exception;

class KuveytTurk
{

    private $restClient;
    private $customerId;
    private $merchantId;
    private $userName;
    private $password;
    private $currencyCodeMapping;

    public function __construct
    (
        $paymentInitializeParam
    )
    {
        $this->restClient = new Client();

        $this->requestUrl = 'https://boa.kuveytturk.com.tr/sanalposservice/Home';
        if ($paymentInitializeParam['env'] == 'test') {
            $this->requestUrl = 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home';
        }

        $this->customerId = $paymentInitializeParam['customerId'];
        $this->merchantId = $paymentInitializeParam['merchantId'];
        $this->userName = $paymentInitializeParam['userName'];
        $this->password = $paymentInitializeParam['password'];

        $this->currencyCodeMapping = [
            'TRY' => '0949',
            'USD' => '0840',
            'EUR' => '0978',
        ];

    }

    protected function post($param)
    {
        $getResponse = [];
        $param['logDebug'] = fillOnUndefined($param, 'logDebug', false);
        try {

            $paymentRequest = $this->restClient->post($this->requestUrl . '/' . $param['method'], [
                'headers' => [
                    'Content-Type' => 'application/xml; charset=UTF8',
                ],
                'body' => $param['payload']
            ]);

            $getResponseBody = $paymentRequest->getBody();
            $getResponseXmlBase = $getResponseBody->getContents();

            if (!$getResponseXmlBase) {
                throw new ApiErrorException('Payment Initialize not processing.');
            } else {

                $response = [
                    'status' => true,
                    'data' => $getResponseXmlBase
                ];
            }

            if ($param['logDebug']) {
                Log::debug(json_encode($param['param']));
                Log::debug($param['param']);
                Log::debug($getResponse);
            }

        } catch (ApiErrorException | Exception | ClientException | ServerException $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::debug($message);
            $response['message'] = $e->getMessage();
        }

        return $response;

    }


    public function threeDModelPayGate($param = [])
    {

        try {

            $hashData = null;
            $param['amount'] = (int)(floatval($param['amount']) * 100);
            $hashedPassword = base64_encode(sha1($this->password, "ISO-8859-9"));
            $hashData = base64_encode(sha1($this->merchantId . $param['orderId'] . $param['amount'] . $param['paymentCheckUrl'] . $param['paymentCheckUrl'] . $this->userName . $hashedPassword, "ISO-8859-9"));

            $requestParam['method'] = 'ThreeDModelPayGate';
            $requestPayload = new \SimpleXMLElement('<KuveytTurkVPosMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></KuveytTurkVPosMessage>');

            $currencyCodeBank = isset($this->currencyCodeMapping[$param['currencyCode']]) ? $this->currencyCodeMapping[$param['currencyCode']] : '0949';

            $requestPayload->addChild('APIVersion', '1.0.0');
            $requestPayload->addChild('OkUrl', $param['paymentCheckUrl']);
            $requestPayload->addChild('FailUrl', $param['paymentCheckUrl']);
            $requestPayload->addChild('HashData', $hashData);
            $requestPayload->addChild('MerchantId', $this->merchantId);
            $requestPayload->addChild('CustomerId', $this->customerId);
            $requestPayload->addChild('UserName', $this->userName);
            $requestPayload->addChild('CardNumber', $param['creditCard']['number']);
            $requestPayload->addChild('CardExpireDateYear', mb_substr($param['creditCard']['expiryYear'], 2, 2));
            $requestPayload->addChild('CardExpireDateMonth', $param['creditCard']['expiryMonth']);
            $requestPayload->addChild('CardCVV2', $param['creditCard']['cvv']);
            $requestPayload->addChild('CardHolderName', $param['creditCard']['holderName']);
            //$requestPayload->addChild('CardType', null);
            $requestPayload->addChild('BatchID', 0);
            $requestPayload->addChild('TransactionType', 'Sale');
            $requestPayload->addChild('InstallmentCount', $param['creditCard']['installment']);
            $requestPayload->addChild('Amount', $param['amount']);
            $requestPayload->addChild('DisplayAmount', $param['amount']);
            $requestPayload->addChild('CurrencyCode', $currencyCodeBank);
            $requestPayload->addChild('MerchantOrderId', $param['orderId']);
            $requestPayload->addChild('TransactionSecurity', 3);

            $requestParam['payload'] = $requestPayload->asXML();

            $paymentRequest = $this->post($requestParam);

            if (!$paymentRequest['status']) {
                throw new ApiErrorException($paymentRequest['message']);
            }

            $response = [
                'status' => true,
                'data' => $paymentRequest['data']
            ];

        } catch (ApiErrorException | Exception $e) {
            $response = ['status' => false, 'message' => $e->getMessage()];
        }

        if (isset($getResponseData)) {
            $response['serviceResponse'] = $paymentRequest;
        }


        return $response;
    }

    public function checkPaymentStatus($paymentCode, $param = [])
    {
        $response = ['status' => false, 'message' => ''];

        $requestContent = null;
        $paymentRequest = [];

        try {

            $requestContent = urldecode($param["AuthenticationResponse"]);
            $requestContent = json_decode(json_encode(simplexml_load_string($requestContent)), 1);


            if ($requestContent['ResponseCode'] != "00") {
                $errorMessage = $requestContent['ResponseCode'] . ': ' . $requestContent['ResponseMessage'];
                $paymentRequest['serviceResponse'] = $requestContent;
                throw new ApiErrorException($errorMessage);
            }

            $paymentCheckParam = [
                'merchantOrderId' => isset($requestContent['VPosMessage']['MerchantOrderId']) ? $requestContent['VPosMessage']['MerchantOrderId'] : null,
                'amount' => isset($requestContent['VPosMessage']['Amount']) ? $requestContent['VPosMessage']['Amount'] : null,
                'md' => isset($requestContent['MD']) ? $requestContent['MD'] : null,
            ];

            $hashData = null;
            //$param['amount'] = (int)(floatval($param['amount']) * 100);
            $hashedPassword = base64_encode(sha1($this->password, "ISO-8859-9"));
            $hashData = base64_encode(sha1($this->merchantId . $paymentCheckParam['merchantOrderId'] . $paymentCheckParam['amount'] . $this->userName . $hashedPassword, "ISO-8859-9"));


            $requestParam['method'] = 'ThreeDModelProvisionGate';
            $requestPayload = new \SimpleXMLElement('<KuveytTurkVPosMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></KuveytTurkVPosMessage>');

            $requestPayload->addChild('APIVersion', '1.0.0');
            $requestPayload->addChild('HashData', $hashData);
            $requestPayload->addChild('MerchantId', $this->merchantId);
            $requestPayload->addChild('CustomerId', $this->customerId);
            $requestPayload->addChild('UserName', $this->userName);
            $requestPayload->addChild('TransactionType', 'Sale');
            $requestPayload->addChild('InstallmentCount', 1);
            $requestPayload->addChild('CurrencyCode', '0949');
            $requestPayload->addChild('Amount', $paymentCheckParam['amount']);
            $requestPayload->addChild('MerchantOrderId', $paymentCheckParam['merchantOrderId']);
            $requestPayload->addChild('TransactionSecurity', 3);

            $kuveytTurkVPosAdditionalData = $requestPayload->addChild('KuveytTurkVPosAdditionalData');
            $additionalData = $kuveytTurkVPosAdditionalData->addChild('AdditionalData');
            $additionalData->addChild('Key', 'MD');
            $additionalData->addChild('Data', $paymentCheckParam['md']);

            $requestParam['payload'] = $requestPayload->asXML();

            $paymentRequest = $this->post($requestParam);

            if (!$paymentRequest['status']) {
                throw new ApiErrorException($paymentRequest['message']);
            }

            $requestContent = simplexml_load_string($paymentRequest['data']);
            $requestContent = json_decode(json_encode($requestContent), 1);

            $paymentRequest['serviceResponse'] = $requestContent;

            if ($requestContent['ResponseCode'] != "00") {
                $errorMessage = $requestContent['ResponseCode'] . ': ' . $requestContent['ResponseMessage'];
                throw new ApiErrorException($errorMessage);
            }

            $response = [
                'status' => true,
                'data' => $requestContent
            ];

        } catch (ApiErrorException | Exception $e) {
            $response = ['status' => false, 'message' => $e->getMessage()];
        }

        if (isset($paymentRequest['serviceResponse'])) {
            $response['serviceResponse'] = $paymentRequest['serviceResponse'];
        }


        return $response;
    }

}
