<?php

namespace App\Core\Payment\Moka;

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

use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Log;
use Exception;

class Moka
{

    private $restClient;
    private $userName;
    private $password;
    private $dealerCode;

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

        $this->requestUrl = 'https://service.moka.com';
        if ($paymentInitializeParam['env'] == 'test') {
            $this->requestUrl = 'https://service.refmoka.com';
        }

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

    }

    private function errorCodes($code)
    {
        $codes = [
            md5('PaymentDealer.CheckPaymentDealerAuthentication.InvalidRequest') => 'Hatalı hash bilgisi',
            md5('PaymentDealer.CheckPaymentDealerAuthentication.InvalidAccount') => 'Böyle bir bayi bulunamadı',
            md5('PaymentDealer.CheckPaymentDealerAuthentication.VirtualPosNotFound') => 'Bu bayi için sanal pos tanımı yapılmamış',
            md5('PaymentDealer.RequiredFields.AmountRequired') => 'Tutar girilmemiş',
            md5('PaymentDealer.DoCapture.DealerNotAuthorized') => 'Ön provizyonu provizyona çevirmek için yetkiniz yok',
            md5('PaymentDealer.DoDirectPayment3dRequest.CardTokenNotFound') => 'Tanımlı CardToken bulunamadı',
            md5('PaymentDealer.CheckCardInfo.InvalidCardInfo') => 'Geçersiz Kart Bilgisi',
            md5('PaymentDealer.DoDirectPayment3dRequest.VirtualPosNotAvailable') => 'Bu kredi kartı için ödeme desteklenmemektedir, lütfen farklı bir kart deneyiniz',
            md5('PaymentDealer.CheckDealerPaymentLimits.DailyDealerLimitExceeded') => 'Bu kredi kartı için günlük kullanım limiti dolmuştur, lütfen farklı bir kart deneyiniz',
            md5('PaymentDealer.DoDirectPayment3dRequest.ThisInstallmentNumberNotAvailableForDealer') => 'Bu taksit sayısı kullanılamaz',
            md5('EX') => 'Beklenmeyen bir hata oluştu'
        ];

        return fillOnUndefined($codes, md5($code), 'Bilinmeyen bir hata oluştu');
    }

    private function mokaServiceResponse($getResponse, $param)
    {
        $response = ['status' => false, 'message' => '', 'error' => '', 'data' => []];

        if ($getResponse['ResultCode'] != 'Success') {
            $response['message'] = $this->errorCodes($getResponse['ResultCode']);
            //Log::error($getResponse);
        } else {
            $response = [
                'status' => true,
                'data' => $getResponse['Data']
            ];
        }

        return $response;

    }

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

            $res = $this->restClient->post($this->requestUrl. $param['method'], [
                'verify' => false,
                'headers' => [
                    'Content-Type' => 'application/json',
                ],
                'body' => json_encode($param['param'])
            ]);

            $getResponseBody = $res->getBody();
            $getResponse = json_decode($getResponseBody, true);

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

            $getResponse = $this->mokaServiceResponse($getResponse, $param);

        } catch (Exception $e) {
            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
        }
        return $getResponse;

    }

    public function paymentDealerAuthentication()
    {
        return [
            'DealerCode' => $this->dealerCode,
            'Username' => $this->userName,
            'Password' => $this->password,
            'CheckKey' => hash('sha256', $this->dealerCode . 'MK' . $this->userName . 'PD' . $this->password)
        ];
    }

    public function DoDirectPaymentThreeD($param = [])
    {

        try {

            $doDirectPaymentThreeD['method'] = '/PaymentDealer/DoDirectPaymentThreeD';
            $doDirectPaymentThreeD['param']['PaymentDealerAuthentication'] = $this->paymentDealerAuthentication();
            $doDirectPaymentThreeD['param']['PaymentDealerRequest'] = [
                'CardHolderFullName' => fillOnUndefined($param, 'CardHolderFullName'),
                'CardNumber' => fillOnUndefined($param, 'CardNumber', ''),
                'ExpMonth' => fillOnUndefined($param, 'ExpMonth'),//12
                'ExpYear' => fillOnUndefined($param, 'ExpYear'),//2022
                'CvcNumber' => fillOnUndefined($param, 'CvcNumber'),
                'CardToken' => fillOnUndefined($param, 'CardToken'),
                'Amount' => fillOnUndefined($param, 'Amount'),//10.50
                'Currency' => fillOnUndefined($param, 'Currency', 'TL'),
                'InstallmentNumber' => fillOnUndefined($param, 'InstallmentNumber', 1),
                'ClientIP' => fillOnUndefined($param, 'ClientIP', Request::ip()),
                'OtherTrxCode' => fillOnUndefined($param, 'OtherTrxCode', ''),
                'IsPreAuth' => fillOnUndefined($param, 'IsPreAuth', 1),
                'Software' => fillOnUndefined($param, 'Software', ''),
                'Description' => fillOnUndefined($param, 'Description', ''),
                'RedirectUrl' => fillOnUndefined($param, 'RedirectUrl'),
            ];

            $response = $this->post($doDirectPaymentThreeD);

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

        return $response;
    }

    public function getPaymentDetail($param = [])
    {
        try {

            $getPaymentList['method'] = '/PaymentDealer/GetDealerPaymentTrxDetailList';
            $getPaymentList['param']['PaymentDealerAuthentication'] = $this->paymentDealerAuthentication();
            $getPaymentList['param']['PaymentDealerRequest'] = [
                'PaymentId' => fillOnUndefined($param, 'PaymentId', ''),
                'OtherTrxCode' => fillOnUndefined($param, 'OtherTrxCode', ''),
            ];

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

        return $response;
    }

}
