<?php

namespace App\Core\Payment\TBCBankGeorgia;

use App\Exceptions\ApiErrorException;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Log;
use Exception;

class TBCBankGeorgia
{

    private $requestUrl;
    private $clientId;
    private $clientSecret;
    private $apiKey;
    private $accessToken;

    public function __construct($paymentInitializeParam)
    {
        $this->restClient = new Client(['http_errors' => false]);

        $this->requestUrl = 'https://api.tbcbank.ge/v1';

        $this->clientId = $paymentInitializeParam['clientId'];
        $this->clientSecret = $paymentInitializeParam['clientSecret'];
        $this->apiKey = '3pkukzNSrBd5G7BbgG2ksu4gCzgZGkGy';

        $tbcBankTokenCacheKey = 'TBCBankGeorgia';
        $accessToken = Cache::get($tbcBankTokenCacheKey);
        if (empty($accessToken)) {
            $accessToken = $this->getAccessToken();
            if ($accessToken['status']) {
                $accessToken = $accessToken['token'];
            }
            Cache::put($tbcBankTokenCacheKey, $accessToken, 60 * 60 * 23); // 23h
        }

        $this->accessToken = $accessToken;

    }

    private function makeRequest($method, $payloadData, $methodType = 'POST')
    {

        $response = ['status' => false, 'message' => ''];

        try {

            $requestParams['headers']['apikey'] = $this->apiKey;
            $requestParams['headers']['Content-Type'] = 'application/json';
            $requestParams['headers']['Authorization'] = 'Bearer ' . $this->accessToken;
            $requestParams['body'] = json_encode($payloadData);

            $result = $this->restClient->request($methodType, $this->requestUrl . '/' . $method, $requestParams);

            $getResponseBody = $result->getBody()->getContents();
            $getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];

            if (isset($getResponseData['httpStatusCode']) && $getResponseData['httpStatusCode'] == 200) {

                $response = [
                    'status' => true,
                    'serviceResponse' => $getResponseData
                ];

            } else {
                throw new Exception($getResponseData['status'] . ': ' . $getResponseData['detail']);
            }


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

        }

        if (!$response['status']) {
            Log::error($method);
            Log::error($payloadData);
            Log::error($response);
        }

        return $response;

    }

    private function getAccessToken()
    {

        $getTokenData = null;
        $response = ['status' => false, 'message' => ''];

        try {

            $requestParams['headers']['apikey'] = $this->apiKey;
            $requestParams['headers']['Content-Type'] = 'application/x-www-form-urlencoded';

            $requestParams['form_params']['client_id'] = $this->clientId;
            $requestParams['form_params']['client_secret'] = $this->clientSecret;


            $result = $this->restClient->request('POST', $this->requestUrl . '/tpay/access-token', $requestParams);

            $getResponseBody = $result->getBody()->getContents();
            $getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];

            if (isset($getResponseData['error_code'])) {
                throw new ApiErrorException($getResponseData['error_message']);
            }

            $response['status'] = true;
            $response['token'] = $getResponseData['access_token'];

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

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

        return $response;

    }


    public function paymentInitialize($param)
    {

        $response = ['status' => false, 'message' => ''];
        try {

            //5, Pan (Payment with card)
            //7, Internet Bank Login
            //9, Apple Pay
            //14 Google Pay

            $localeLanguageCode = app('translator')->getLocale();
            $paymentInitializeParam = [
                'amount' => [
                    'currency' => $param['currencyCode'],
                    'total' => $param['amount']
                ],
                'returnurl' => $param['paymentCheckUrl'],
                'userIpAddress' => $param['ipAddress'],
                'expirationMinutes' => 5,
                'methods' => [5, 7, 9, 14],
                'preAuth' => false,
                'language' => $localeLanguageCode == 'ka' ? 'KA' : 'EN',
                'merchantPaymentId' => $param['orderId'],
            ];

            $paymentInitialize = $this->makeRequest('tpay/payments', $paymentInitializeParam);

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

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

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

        return $response;

    }

    public function checkoutOrderInfo($orderId)
    {

        $response = ['status' => false, 'message' => ''];
        try {

            $method = 'tpay/payments/' . $orderId;
            $payloadData = [];

            $checkoutOrderInfoRequest = $this->makeRequest($method, $payloadData, 'GET');

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

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

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

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

        return $response;

    }

}
