<?php

namespace App\Core\Payment\WeePay;

use App\Exceptions\ApiErrorException;
use App\Exceptions\ApplicationError;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
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 WeePay
{

    private $requestUrl;

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

        $this->requestUrl = 'https://api.weepay.co';
        if ($paymentInitializeParam['env'] == 'test') {
            $this->requestUrl = 'https://testapi.weepay.co';
        }


        $this->merchantId = $paymentInitializeParam['merchantId'];
        $this->apiKey = $paymentInitializeParam['apiKey'];
        $this->secretKey = $paymentInitializeParam['secretKey'];
        $this->ipAddress = isset($paymentInitializeParam['ipAddress']) ? $paymentInitializeParam['ipAddress'] : '185.137.215.118';

        $this->currencyMapping = [
            'TRY' => 'TL',
            'USD' => 'USD',
            'EUR' => 'EUR',
            'GBP' => 'GBP',
        ];

    }

    private function makeRequest($method, $payloadData)
    {

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

        try {

            $requestParams['headers']['Content-Type'] = 'application/json';

            $requestParams['body'] = json_encode($payloadData);

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

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

            if ($getResponseData['status'] == 'success') {
                $response = [
                    'status' => true,
                    'serviceResponse' => $getResponseData
                ];
            }

        } catch (ClientException  $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            $getResponseErrorBody = $e->getResponse()->getBody()->getContents();
            $getResponseError = $getResponseErrorBody ? json_decode($getResponseErrorBody, 1) : [];


            $errorList = [];
            if(is_array($getResponseError['message'])) {
                foreach ($getResponseError['message'] as $errorKey => $error) {
                    $errorList[] = implode(', ', $error);
                }
            } else {
                $errorList[] = $getResponseError['message'];
            }

            $message = implode(', ', $errorList);
            $response['message'] = $message;
            Log::debug($message);

        } catch (ServerException $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();
        }

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

        return $response;

    }


    public function generateHashKey($total, $installment, $currency_code, $invoice_id)
    {

        $data = $total . '|' . $installment . '|' . $currency_code . '|' . $this->merchantKey . '|' . $invoice_id;

        $iv = substr(sha1(mt_rand()), 0, 16);
        $password = sha1($this->appSecret);

        $salt = substr(sha1(mt_rand()), 0, 4);
        $saltWithPassword = hash('sha256', $password . $salt);

        $encrypted = openssl_encrypt("$data", 'aes-256-cbc', "$saltWithPassword", null, $iv);

        $msg_encrypted_bundle = "$iv:$salt:$encrypted";
        $msg_encrypted_bundle = str_replace('/', '__', $msg_encrypted_bundle);

        return $msg_encrypted_bundle;
    }

    public function generateRefundHashKey($invoice_id, $merchant_key, $app_secret)
    {
        $data = $invoice_id . '|' . $merchant_key;
        $iv = substr(sha1(mt_rand()), 0, 16);
        $password = sha1($app_secret);
        $salt = substr(sha1(mt_rand()), 0, 4);
        $saltWithPassword = hash('sha256', $password . $salt);
        $encrypted = openssl_encrypt(
            $data, 'aes-256-cbc', "$saltWithPassword", null, $iv
        );
        $msg_encrypted_bundle = "$iv:$salt:$encrypted";
        $hash_key = str_replace('/', '__', $msg_encrypted_bundle);
        return $hash_key;
    }

    public function paySmart3D($param)
    {

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

            $param['creditCard']['installment'] = $param['creditCard']['installment'] == 0 ? 1 : $param['creditCard']['installment'];

            $items = [];
            $items[] = [
                'productId' => $param['orderCode'],
                'name' => 'Booking',
                'productPrice' => $param['amount'],
                'itemType' => 'VIRTUAL',
            ];

            $method = 'Payment/PaymentRequestThreeD';
            $payloadData = [
                'Auth' => [
                    'bayiId' => $this->merchantId,
                    'apiKey' => $this->apiKey,
                    'secretKey' => $this->secretKey,
                ],
                'Data' => [
                    'orderId' => $param['orderId'],
                    'currency' => isset($this->currencyMapping[$param['currencyCode']]) ? $this->currencyMapping[$param['currencyCode']] : $param['currencyCode'],
                    'locale' => 'tr',
                    'paidPrice' => $param['amount'],
                    'ipAddress' => $this->ipAddress,
                    'cardHolderName' => $param['creditCard']['holderName'],
                    'cardNumber' => $param['creditCard']['number'],
                    'expireMonth' => $param['creditCard']['expiryMonth'],
                    'expireYear' => mb_substr($param['creditCard']['expiryYear'], 2, 2),
                    'cvcNumber' => $param['creditCard']['cvv'],
                    'installmentNumber' => $param['creditCard']['installment'],
                    'description' => $param['orderCode'],
                    'callBackUrl' => $param['paymentCheckUrl']
                ],
                'Customer' => [
                    'customerId' => $param['orderId'],
                    'customerName' => $param['orderId'],
                    'customerSurname' => $param['orderId'],
                    'gsmNumber' => $param['orderId'],
                    'email' => 'support@extranetwork.com',
                    'identityNumber' => '11111111111',
                    'city' => $param['orderId'],
                    'country' => $param['orderId'],
                ],
                'BillingAddress' => [
                    'contactName' => $param['orderId'],
                    'address' => $param['orderId'],
                    'city' => $param['orderId'],
                    'country' => $param['orderId'],
                ],
                'Products' => $items

            ];

            $checkRequest = $this->makeRequest($method, $payloadData);

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

            $response = [
                'status' => true,
                'data' => $checkRequest['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 checkPaymentStatus($orderId)
    {

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

            $method = 'GetPayment/Detail';
            $payloadData = [
                'Auth' => [
                    'bayiId' => $this->merchantId,
                    'apiKey' => $this->apiKey,
                    'secretKey' => $this->secretKey,
                ],
                'Data' => [
                    'ipAddress' => $this->ipAddress,
                    'orderId' => $orderId,
                    'locale' => 'tr'
                ]
            ];

            $checkStatusRequest = $this->makeRequest($method, $payloadData);

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

            if ($checkStatusRequest['serviceResponse']['paymentStatus'] != 'SUCCESS') {
                throw new ApiErrorException($checkStatusRequest['message']);
            }

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

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

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

        return $response;

    }

}
