<?php
namespace App\Http\Services\Deposit\Bank;

use App\Http\Services\Deposit\Bank\Util\ResponseBankUtilDepositServices;
use App\Models\Gateway;
use Illuminate\Support\Facades\URL;

/**
 * Laravel/Symfony Developer
 * Name: Muongozo
 * Telegram: @muongozotrader
 * Hire me via Telegram: muongozotrader
 */
class ShpayBankDepositServices
{
    
    /**
     * Deposit Payment
     * 
     * @param string reference
     * @param string currency
     * @param string amount
     * @param string method
     */
    public function deposit(
        string $reference,
        string $currency,
        string $amount,
        string $method
    )
    {
        try {

            // Request Body
            $requestBody = array(
                'mchtId' => '****',
                'appId' => '****',
                'countryCode' => 'NG',
                'requestTime' => date('Y-m-d H:i:s'),
                'notifyUrl' => ''.URL::route('ipn.default').'',
                'signType' => 'MD5',
                'transAmt' => $amount,
                'mobile' => '',
                'email' => ''.time().'@gmail.com',
                'outTradeNo' => ''.$reference.'',
                'subject' => 'Order '.$reference.'',
                'body' => 'Order '.$reference.'',
                'extInfo' => ''
            );

            // Send Curl Request
            $sendRequest = $this->curlRequest('POST', 'trans/payIn', $requestBody);

            // Exception
            if($sendRequest instanceof \Exception) throw new \Exception($sendRequest->getMessage());

            // Format Response
            $response = ResponseBankUtilDepositServices::response(200, 2, true, $reference, $sendRequest['result']['transNo'], $currency, $amount, $method, $sendRequest['result']['link']);

            // Response
            return $response;

        } catch (\Exception $th) {
            //throw $th;
            return $th;
        }
    }


    /**
     * Verify Payment
     * 
     * @param string reference
     * @param string currency
     * @param string amount
     * @param string method
     */
    public function verify(
        string $reference,
        string $method
    )
    {
        try {

            // Request Body
            $requestBody = array(
                'mchtId' => '****',
                'appId' => '****',
                'signType' => 'MD5',
                'outTradeNo' => ''.$reference.''
            );

            // Send Curl Request
            $sendRequest = $this->curlRequest('POST', 'order/query', $requestBody);

            // Exception
            if($sendRequest instanceof \Exception) throw new \Exception($sendRequest->getMessage());

            // Response
            return $sendRequest;

        } catch (\Exception $th) {
            return $th;
        }
    }


    /**
     * Cur Request
     * send request
     * 
     * @param string method
     * @param string endpoint
     * @param string body
     */
    public function curlRequest(
        string $method,
        string $endpoint,
        array $body = []
    ){

        try {

			//throw new \Exception('Sorry service not available. User other channel to pay');

            // Find Setting
            $setting = Gateway::where(['code' => '101', 'status' => 1])->first();

            // Exception
            if(!$setting) throw new \Exception("Service not enabled at the moment");

            // Parse setting
            $setting = json_decode($setting->gateway_parameters);

            $body['mchtId'] = $setting->mchtId->value;
            $body['appId'] = $setting->appId->value;

            // Build Sign
            $sign = self::buildSignDigest($body, $setting->secret_key->value);
            $body['sign'] = $sign;

            // Convert request data to JSON
            $jsonData = json_encode($body);

            // Curl Request
            $curl = curl_init();
            curl_setopt_array($curl, array(
				CURLOPT_URL => 'https://transapi.shpays.com/v1/'.$endpoint,
				CURLOPT_SSL_VERIFYPEER => false,
				CURLOPT_RETURNTRANSFER => true,
				CURLOPT_ENCODING => '',
				CURLOPT_MAXREDIRS => 10,
				CURLOPT_TIMEOUT => 30,
				CURLOPT_FOLLOWLOCATION => true,
				CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
				CURLOPT_CUSTOMREQUEST => $method,
				CURLOPT_POSTFIELDS => $jsonData,
				CURLOPT_HTTPHEADER => array(
					'Content-Type: application/json'
				),
            ));
    
            $response = curl_exec($curl);
            $err = curl_error($curl);
            $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    
            // there was an error contacting
            if ($err) throw new \Exception('Curl returned error: ' . $err);

            // Convert Json to Json Array
            $response_array = json_decode($response,true);

            // Error message
            $errorMessage = (empty($response_array['message'])) ? 'Sorry service not available. User other channel to pay' : $response_array['message'];
            
            // Check status
            if(!in_array($httpcode, ['200'])) throw new \Exception($errorMessage );

            // Check if successful
            if($response_array['success'] != true) throw new \Exception($errorMessage );
            
    
            return $response_array;

        } catch (\Exception $th) {
            //throw $th;
            return $th;
        }
    }

    public static function buildSignDigest($params, $secret_key) {
        // Hold Data
        $data = $params;
    
        $sb = '';
        if (empty($params)) {
            return $sb;
        }
        $keyList = array_keys($params);
        sort($keyList);
        foreach ($keyList as $key) {
            $value = $params[$key];
            if (empty($value)) {
                continue;
            }
            $sb .= $key . "=" . strval($value) . "&";
        }
        $digestContent = $sb;
    
        // String data
        $digest = substr($digestContent, 0, -1);
    
        // Second step: Concatenate with signKey
        $signKey = $secret_key;
        $digest .= $signKey;
    
        // Third step: MD5 and convert to uppercase
        return strtoupper(md5($digest));
    }
}
