<?php

namespace App\APIWrapper\Server;

use App\ConsumerApplication;
use App\DynamoDB\DynamoDB;
use App\Slack;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use App\Logging\CloudWatchLoggerFactory;

class ServerCalls extends DynamoDB {

    public static $err = null;

    /**
     * @throws ValidationException
     */
    public static function start(Request $request, $func){
        $executeHandler = true;
        dynamodb::log($request->all(), 'api-request');
        $api = $request->get('apis')[$func] ?? null;
        $identifier = $request->get('identifier');
        $p = $request->get('payload');
        $applicationId = isset($p['appId']) ? $p['appId'] : (isset($p['applicationId']) ? $p['applicationId'] : '');
        $appData = ConsumerApplication::where('id',$applicationId)->first(['lender_id']);

        if (!$api)
            throw ValidationException::withMessages(['API method not found: '. $func]);

        $headers = array();
        if (isset($api['headers'])) {
            foreach (array_filter($api['headers']) as $key => $header) {
                $headers[$key] = $header;
            }
        }

        if ($request->has('headers') && $request->get('headers')) {
            foreach (array_filter($request->get('headers')) as $key => $header) {
                $headers[$key] = $header;
            }
        }

        if ((isset($p['isLbLsp']) && $p['isLbLsp'] == 'true') && (isset($appData) && $appData->lender_id == 7) && $request->has('headersLSP') && $request->get('headersLSP')) {
            foreach (array_filter($request->get('headersLSP')) as $key => $header) {
                $headers[$key] = $header;
            }
        }

        $headersItems = [];
        foreach($headers as $key => $header) {
            if($identifier == 'JM' && $func == 'uploadDocument' && $key == 'content-type') {
                $headersItems[] = 'Content-Type: multipart/form-data; boundary='.uniqid();
            }else{
                $headersItems[] = $key . ':' . $header;
            }
        }

        $url = ($api['host'] ?? $request->get('host')).$api['route'];
        if(isset($p['lbUserId']) && ($func == "createLoan" || $func == "uploadDocument")){
            $url = $url.$p['lbUserId'];
        }

        if(strpos($url,"<lead_id>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['jm_lead_id'])) {
                $url = str_replace('<lead_id>', $request->get('addPayload')['jm_lead_id'], $url);
            }else if (isset($request->get('addPayload')['lead_id'])) {
                $url = str_replace('<lead_id>', $request->get('addPayload')['lead_id'], $url);
            }
        }

        if(strpos($url,"<client_name>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['client_name'])) {
                $url = str_replace('<client_name>', $request->get('addPayload')['client_name'], $url);
            }
        }
        if(strpos($url,"<pincode>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['pincode'])) {
                $url = str_replace('<pincode>', $request->get('addPayload')['pincode'], $url);
            }
        }
        if(strpos($url,"<loan_id>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['loan_id'])) {
                $url = str_replace('<loan_id>', $request->get('addPayload')['loan_id'], $url);
            }
        }
        if(strpos($url,"<case_id>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['case_id'])) {
                $url = str_replace('<case_id>', $request->get('addPayload')['case_id'], $url);
            }
        }
        if(strpos($url,"<type_of_doc>") !== false && $request->get('addPayload')){
            if (isset($request->get('addPayload')['type_of_doc'])) {
                $url = str_replace('<type_of_doc>', $request->get('addPayload')['type_of_doc'], $url);
            }
        }

        if(strpos($url,"/upload/docs?lbUserId=") !== false){
            $d = $api['payload'] ?? $request->get('payload');
        }else{
            $d = json_encode($api['payload'] ?? $request->get('payload'));
        }
        if(isset($func) && $func == "walletOrder"){
            $payload = isset($p['payload']) ? $p['payload'] : '';
            $d = json_encode($payload);
        }
        if($identifier == 'JM' && $func == 'uploadDocument') {
            $d = $api['payload'] ?? $request->get('payload');
        }
        if($identifier == 'HV' && $func == 'uploadDocument') {
            $d = $api['payload'] ?? $request->get('payload');
        }


        $host_name = ($api['host'] ?? $request->get('host'));


        if($host_name == _env('HOMEVILLE_HOST') && $func == 'uploadDocument'){

            $auth = $request->get('addPayload')['auth_token'] ?? (base64_encode(_env('HOMEVILLE_CLIENT_ID').':'._env('HOMEVILLE_CLIENT_SECRET')));
            $auth_type = 'Bearer';

            $application_uuid = escapeshellarg($d['application_uuid'] ?? '');
            $applicant_id = escapeshellarg($d['applicant_id'] ?? '');
            $document_type = escapeshellarg($d['document_type']);
            $document = escapeshellarg($d['document']);
            $documentFor = escapeshellarg($d['documentFor']);

            $curlCommand = 'curl -X \'' . $api['method'] . '\' --location \''.$url.'\' --header \'Authorization: '.$auth_type.' '.$auth.'\' --form \'application_uuid='.$application_uuid.'\' --form \'applicant_id='.$applicant_id.'\' --form \'documentFor='.$documentFor.'\' --form \'document_type='.$document_type.'\' --form \'document=@"'.$document.'"\'';

            exec('export LD_LIBRARY_PATH=/usr/local/openssl-1.1.1g/lib:$LD_LIBRARY_PATH && '.$curlCommand, $output, $returnCode);

            if ($returnCode === 0) {
                // Command executed successfully, handle response
                $response = implode("\n", $output);
                (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','code' => $returnCode, 'res' => $response, 'U' => $url, 'p' => $d, 'curlCommand' => $curlCommand], 'group' => Slack::$PROD_TECH_BUG])))->send();
                $response = json_decode($response);
            } else {
                // Command failed, handle error
                (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','code' => $returnCode, 'U' => $url, 'p' => $d, 'curlCommand' => $curlCommand], 'group' => Slack::$PROD_TECH_BUG])))->send();
                $response = null;
            }

            $executeHandler = false;
        }


            if(in_array($host_name, [_env('JM_HOST'), _env('PRD_ONEFIN_HOST')])){
            try {

                $auth_type = 'Basic';
                if ($host_name == _env('JM_HOST')){
                    $auth = base64_encode(_env('JM_BAuth'));
                }elseif ($host_name == _env('PRD_ONEFIN_HOST')){
                    $auth = _env('PRD_ONEFIN_USRPASS');
                }else if($host_name == _env('HOMEVILLE_HOST')){
                    $auth = $request->get('addPayload')['auth_token'] ?? (base64_encode(_env('HOMEVILLE_CLIENT_ID').':'._env('HOMEVILLE_CLIENT_SECRET')));
                    $auth_type = 'Bearer';
                }


                if($identifier == 'JM' && $func == 'uploadDocument') {
//                    $curlCommand = 'curl -X \'' . $api['method'] . '\'  --location \'' . $url . '\' \
//--header \'Content-Type: application/json\' \
//--header \'Authorization: Basic SEFzc0k3YVpuOEp2dElnU3BWa3FyMU1ESkN2M1JZcHRvQTEyWFBlaTpXWHlmYW9oRHpqM0NTa0tJT1gxdGNLa3VCcGpMVVdnRHpkTkNvQ1Nvc3l1a3luRm5oSGlZNldiNlppTkNwUXVSbG1VRDJIcnJYNzVCRjJQSkdzcFlsS2hGajdVVThRcFVWdEFWdWJBZW1hSGR6NW5IV2ZJS1N1bEhacExTN29Eeg==\'  \
//--form "document_id=' . $escapedDocumentId . '"';

                    $escapedDocumentId = escapeshellarg($d['document_id']);
                    $escapedDocumentPath = escapeshellarg($d['document']);

                    //$headerFormData = 'Content-Type: multipart/form-data; boundary='.uniqid();

                    $curlCommand = 'curl -X \'' . $api['method'] . '\' --location \''.$url.'\' --header \'Authorization: Basic '.base64_encode(_env('JM_BAuth')).'\' --form \'document_id='.$escapedDocumentId.'\' --form \'document=@"'.$escapedDocumentPath.'"\'';


                }else {

                    $curl_path = 'curl';
                    if ($host_name == _env('PRD_ONEFIN_HOST')){
                        $curl_path = _env('CURL_LATEST');
                    }
                    $curlCommand = $curl_path.' -X \'' . $api['method'] . '\'  --location \'' . $url . '\' \
--header \'Content-Type: application/json\' \
--header \'Authorization: '.$auth_type.' '.$auth.'\' \
--data-raw \'' . $d . '\'';
                }

                exec('export LD_LIBRARY_PATH=/usr/local/openssl-1.1.1g/lib:$LD_LIBRARY_PATH && '.$curlCommand, $output, $returnCode);

                if ($returnCode === 0) {
                    // Command executed successfully, handle response
                    $response = implode("\n", $output);
                    (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','code' => $returnCode, 'res' => $response, 'U' => $url, 'p' => $d, 'curlCommand' => $curlCommand], 'group' => Slack::$PROD_TECH_BUG])))->send();
                    $response = json_decode($response);
                } else {
                    // Command failed, handle error
                    (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','code' => $returnCode, 'U' => $url, 'p' => $d, 'curlCommand' => $curlCommand], 'group' => Slack::$PROD_TECH_BUG])))->send();
                    $response = null;
                }


                /*$headersData = [];
                foreach($headersItems as $headersItem){
                    $hItem = explode(':', $headersItem);
                    $headersData[$hItem[0]] = $hItem[1];
                }

                $client = new Client();
                // Make POST request
                $response = $client->request($api['method'], $url, [
                    'headers' => $headersData,
                    'json' => json_decode($d, 1)
                ]);

                // Get response body
                $response = $response->getBody()->getContents();

                (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','code' => $response, 'U' => $url], 'group' => Slack::$PROD_TECH_BUG])))->send();

                $response = json_decode($response);*/

            } catch (RequestException $e) {
                // Handle exception
                /*if ($e->hasResponse()) {
                    $response = $e->getResponse();
                    $statusCode = $response->getStatusCode();
                    $errorBody = $response->getBody()->getContents();
                    $response = json_decode($errorBody);
                } else {
                    static::$err = "Error: " . $e->getMessage();
                }

                (new Slack(new Request(['title' => 'Server Calls Headers Error', 'fields' => ['Status' => 'API Logging','error' => static::$err,'code' => $statusCode?? 0,'P' => $d, 'H' => $errorBody ?? '', 'U' => $url], 'group' => Slack::$PROD_TECH_BUG])))->send();*/

                (new Slack(new Request(['title' => 'Server Calls Headers Error', 'fields' => ['Status' => 'API Logging','error' => $e->getMessage(),'code' => $e->getFile(),'P' => $d, 'H' => $e->getTraceAsString(), 'U' => $url], 'group' => Slack::$PROD_TECH_BUG])))->send();
                $response = null;
            }
        }else if($executeHandler){
            $curl = curl_init();
            //(new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','P' => $d, 'H' => json_encode($headersItems), 'U' => $url], 'group' => Slack::$STAGE_TESTING])))->send();
            curl_setopt_array($curl, array(
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_FOLLOWLOCATION => true,
                //CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => $api['method'],
                CURLOPT_POSTFIELDS => $d,
                CURLOPT_HTTPHEADER => $headersItems,
            ));
            $curlData = curl_exec($curl);
            (new Slack(new Request(['title' => 'Server Calls Headers', 'fields' => ['Status' => 'API Logging','P' => $d, 'H' => $curlData, 'U' => $url], 'group' => Slack::$PROD_TECH_BUG])))->send();
            $response = json_decode($curlData);
            $err = curl_error($curl);
            if(!empty($response)){
                $response->httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            }
            curl_close($curl);

            if ($err) {
                static::$err = $err;
                (new Slack(new Request(['title' => 'Server Calls Headers Error', 'fields' => ['Error' => json_encode(static::$err), 'Status' => 'API Logging','P' => $d, 'H' => $curlData, 'U' => $url], 'group' => Slack::$PROD_TECH_BUG])))->send();
            }
        }

        $vendor = '';
        if(strpos($request->get('vendor'),"ABFL") !== false){
            $applicationId = isset($request->get('payload')['accountId']) ? $request->get('payload')['accountId'] : '';
            $vendor = 'ABFL';
        }elseif(strpos($request->get('vendor'),"Decentro") !== false){
            $applicationId = isset($request->get('payload')['reference_id']) ? $request->get('payload')['reference_id'] : '';
            $vendor = 'Decentro';
        }

        $cwFactory = new CloudWatchLoggerFactory();
        if(is_string($d)){
            $len = strlen($d);
        }
        if(isset($len) && $len > 1000 && $func == "saveEMI") {
            $str = str_split($d,1000);
            foreach($str as $split){
                $data = array('application_id'=>$applicationId, 'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> $vendor, 'api_url' => $url,'part'=> $split ?? '{}', 'Response'=>$response, 'error_msg' => $err ?? '');
                $cwFactory->logger(json_encode($data));
            }
        }else{
            //To remove large data content to avoid cloudwatch bytes exceeds limit issue
            if($func == "uploadDocument") {
                if (!is_array($d)) {
                    $reqData = is_string($d) ? json_decode($d, true) : $d;
                    if (isset($reqData['docContent'])) {
                        unset($reqData['docContent']);
                    }
                }
                $d = isset($reqData) ? (is_array($reqData) ? json_encode($reqData) : $reqData) : $d;
            }

            $data = array('application_id'=>$applicationId, 'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> $vendor, 'api_url' => $url,'Request'=> json_encode($d) ?? '{}', 'Response'=>$response, 'error_msg' => $err ?? '');
            $cwFactory->logger(json_encode($data));
        }
        dynamodb::log(static::$err ?? $response, 'api-response', ['url' => $url]);
        self::after_response_handling($request);
        return static::$err ?? $response;
    }

    public static function after_response_handling(Request $request){
        if ($request->get('additional_data')){
            $additional_data = $request->get('additional_data');
            if (isset($additional_data['temp_files'])){
                foreach ($additional_data['temp_files'] as $file){
                    if (file_exists($file)) {
                        //unlink($file);
                    }
                }
            }
        }
    }
}