<?php
/**
 * Created by PhpStorm.
 * User: sarah z
 * Date: 26/02/18
 * Time: 11:00 PM
 */

namespace App;


use App\Http\Controllers\Admin\ConsumerDocument;
use Barryvdh\DomPDF\Facade as PDF;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use App\Logging\CloudWatchLoggerFactory;
use App\ConsumerApplication;

class ekycIntegration extends Model
{
    const UPLOAD_ESIGN_DOC_ENDPOINT = 'client/document/uploadpdf';
    const DOWNLOAD_AGREEMENT_ENDPOINT = 'client/document/download';
    const DOWNLOAD_DOCUMENT_DETAILS_ENDPOINT = 'client/document';

    private $digio_url = '';
    private $digio_id = '';
    private $digio_secret = '';
    private $digio_key = '';
    private $curl = '';
    const PUBLIC = 'public';
    const PRIVATE = 'private';
    private $start_time;
    private $payload;

//    protected $table = 'employment_verification';

    public function setup($lender_id){
        if($lender_id == KMGP2P::$lender_id){
            $this->digio_id = (_env('KMGP2P_DIGIO_CLIENT_ID', ''));
            $this->digio_secret = (_env('KMGP2P_DIGIO_CLIENT_SECRET', ''));
        } else {
            $this->digio_id = (_env('DIGIO_CLIENT_ID', ''));
            $this->digio_secret = (_env('DIGIO_CLIENT_SECRET', ''));
        }
        $this->digio_url = (_env('DIGIO_URL', ''));
        $this->digio_key = base64_encode($this->digio_id.':'.$this->digio_secret);
        $this->start_time = time();
    }

    public function requestKYC($identifier, $application_id, $applicant_type = 'Applicant'){
        $_applicant_type = $applicant_type == 'Applicant' ? 1 : 2;
        $isExist = KYCDetails::where('application_id', $application_id)->where('applicant_type', $_applicant_type)->first(['request_id']);
        if (isset($isExist->request_id)){
            return $isExist->request_id;
        }
        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        if($this->digio_url && $this->digio_key) {
            $url =$this->digio_url.'/client/digilocker/request';
            $this->payload = json_encode(['identifier' => $identifier, 'document_types' => ['pan', 'aadhaar'], 'send_document_fetch_link' => false]);

            $this->callCurl($url, "POST");

            $response = $this->get();

            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('application_id'=> $application_id,'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $url,'Request'=> $this->payload ?? '{}', 'Response'=>$response ?? '{}', 'error_msg' => $err ?? '');
            $cwFactory->logger(json_encode($data1));

            if(isset($response['id']) && $response['id'] != null){
                KYCDetails::insert([
                    'application_id' => isset($application_id) ? $application_id : 0,
                    'applicant_type' => $_applicant_type,
                    'request_id' => $response['id'],
                    'created_at' => Carbon::now()->toDateTimeString()
                ]);

                return $response['id'];
            }
        }

        return false;
    }

    public function getParsedInfo($request_id, $application_id, $doctype, $do_not_save = false){
        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        if($this->digio_url && $this->digio_key) {
            $url = $this->digio_url.'/client/digilocker/parsed_document_info?request_id='.$request_id.'&type='.trim($doctype);
            $this->callCurl($url, "GET");
            $response = $this->get();
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('application_id'=> $application_id,'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $url,'Request'=> '{}', 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($err) ? $err : '');
            $cwFactory->logger(json_encode($data1));
            $data = [];
            $identityDetails = '';
            if($do_not_save == false) {
                if ($doctype == "pan") {
                    $val = ['name' => $response['name'], 'dob' => Carbon::createFromFormat('d/m/Y', $response['dob'])->toDateString(), 'gender' => $response['gender'] == 'M' ? 'MALE' : 'FEMALE', 'pan_card' => $response['id_number']];
                    //ConsumerApplication::where('id', $application_id)->update($val);
                    $identityDetails = ['name' => $response['name'], 'pan' => $response['id_number'], 'dob' => $response['dob'],
                        'gender' => $response['gender'] == 'M' ? 'MALE' : 'FEMALE'];

                } elseif ($doctype == "aadhaar") {
                    //Permanent Address
                    $permanent_address = explode(',', trim($response['permanent_address']));
                    $permanent_address_line_1 = implode(',', array_slice($permanent_address, 0, count($permanent_address) - 2));
                    $permanent_pincode = trim(end($permanent_address));
                    $permanent_state = trim(prev($permanent_address));
                    //Current Address
                    $current_address = explode(',', $response['current_address']);
                    $current_address_line_1 = implode(',', array_slice($current_address, 0, count($current_address) - 2));
                    $current_pincode = trim(end($current_address));
                    $current_state = trim(prev($current_address));

                    $val = [
                        'permanent_address_line_1' => $permanent_address_line_1, 'permanent_address_state' => $permanent_state, 'permanent_address_pincode' => $permanent_pincode,
                        'current_address_line_1' => $current_address_line_1, 'current_address_state' => $current_state, 'current_address_pincode' => $current_pincode
                    ];

                    $identityDetails = ['flat_building' => $permanent_address_line_1, 'state_name' => $permanent_state, 'pincode' => $permanent_pincode,
                        'current_addr' => ($permanent_address_line_1 === $current_address_line_1 || $permanent_pincode === $current_pincode) ? 'yes' : 'no',
                        'curr_flat' => $current_address_line_1, 'curr_state_name' => $current_state, 'curr_pincode' => $current_pincode];

                    //ConsumerApplication::where('id', $application_id)->update($val);

                }
            }

            $KYCDetails = KYCDetails::where('request_id', $request_id)->first(['id','applicant_type', 'response']);

            $response['applicant_type'] = isset($KYCDetails->id) && $KYCDetails->applicant_type ? $KYCDetails->applicant_type : (isset($KYCDetails->id) ? 2 : ($application_id == 'Applicant' ? 1 : 2));
            if(!empty($KYCDetails->response)){
                $exiting_doc = json_decode($KYCDetails->response, 1);
                if($exiting_doc[0]['document_type'] != $response['document_type']){
                    $data [] = $exiting_doc[0];
                    $data [] = $response;
                }
            } else{
                $data [] = $response;
            }


            if(!empty($data)) {
                KYCDetails::where('request_id', $request_id)->where('application_id', $application_id)->update([
                    'response' => json_encode($data)
                ]);
            }

            if($do_not_save == false) {
                return $identityDetails;
            } else{
                return json_encode($data);
            }

        }

        return false;
    }

    public function generateReport($request_id, $application_id, $response){
        try{
            $application = ConsumerApplication::where('id', $application_id)->first(['name','co_applicant_name']);

            $digio_kyc =  KYCDetails::where('request_id', $request_id)->first();
            (new Slack(new Request(['title' => 'Digio before if', 'fields' => ['response' => $response, 'application_id' => $application_id]])))->send();
            if(!empty($digio_kyc) || !empty($response)){
                (new Slack(new Request(['title' => 'Digio before after if', 'fields' => ['response' => $response, 'application_id' => $application_id]])))->send();
                if(isset($response) && !empty($response)){
                    $digio_kyc->response = $response;
                }
                $name = $digio_kyc->applicant_type == 1 ? $application->name : $application->co_applicant_name;
                $type = $digio_kyc->applicant_type == 1 ? 'applicant' : 'coapplicant';

                $pdf = App::make('snappy.pdf.wrapper');
                $digio_kyc_report = $pdf->loadHTML(view('front.digio-report', ['digio_kyc' => $digio_kyc, 'name' => $name]));

                $document = new ConsumerDocument(new Request());
                (new Slack(new Request(['title' => 'Digio before uploading', 'fields' => ['application_id' => $application_id]])))->send();
                $document->uploadToS3('digio-report-'.$type, $application_id, $digio_kyc_report->output());
                (new Slack(new Request(['title' => 'Digio after uploading', 'fields' => ['application_id' => $application_id]])))->send();
            }
        }catch (\Exception $e){
            (new Slack(new Request(['title' => 'Digio report gen error', 'fields' => ['error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), 'application_id' => $application_id, 'id_type' => 'application_id', 'application_id' => $application_id]])))->send();
        }
    }

    public function getDocument($request_id, $doctype, $application_id){
        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        if($this->digio_url && $this->digio_key) {
            $url =$this->digio_url.'/client/digilocker/download?request_id='.$request_id.'&type='.$doctype;

            $this->callCurl($url, "GET");

            $doc = true;

            $response = $this->get($doc);
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('application_id'=> $application_id,'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $url,'Request'=> '{}', 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($err) ? $err : '');
            $cwFactory->logger(json_encode($data1));

            $document = new ConsumerDocument(new Request());
            $document->uploadToS3($doctype, $application_id, $response);

            return $response;
        }

        return false;
    }

    public function requestStatus($request_id, $application_id){
        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        if($this->digio_url && $this->digio_key) {
            $url =$this->digio_url.'/client/digilocker/request/'.$request_id;

            $this->callCurl($url, "GET");

            $response = $this->get();
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $url,'Request'=> '{}', 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($err) ? $err : '');
            $cwFactory->logger(json_encode($data1));

            if(isset($response) && $response != null){
                $doc_name = [];
                if(isset($response['document_list'])) {
                    foreach ($response['document_list'] as $docs){
                        if($docs['state'] == 'shared'){
                            $doc_name[] = $docs['type'];
                        }
                    }
                }
                //$data['doc_type'] = implode(',',$doc_name);
                $data['doc_type'] = $doc_name;
                return $data;
            }
            return $response;
        }

        return false;
    }

    public function get($doc=false){
        try {
            $response = curl_exec($this->curl);
            if (curl_error($this->curl)) {
                $error = curl_error($this->curl);
            }
            curl_close($this->curl);

            (new Services())->log('E-KYC', ['status' => true, 'service_count' => 0, 'start_time' => $this->start_time]);

            if (isset($error)) {
                return false;
            }

            if($doc){
                return $response;
            }else {
                return json_decode($response, 1);
            }

        }catch (\Exception $e){

        }
        return false;
    }

    public function callCurl($url, $method){
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_POSTFIELDS => $this->payload,
            CURLOPT_HTTPHEADER => array(
                'Content-Type: application/json',
                'cache-control: no-cache',
                'Authorization: Basic' . $this->digio_key
            ),
        ));

        return $this->curl = $curl;
    }

    public function resetCurl() {
        $this->curl = '';
    }

    public function uploadEsignDocument($signers, $doc_path, $path_type, $is_estamp = 0, $estamp_tag = '', $estamp_qty = 1, $application_id) {

        if($path_type != 's3') {
            if(!Storage::disk($path_type)->exists($doc_path)) {
                throw new \Exception("Agreement PDF not found at location");
            }
        }
        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        $payload = [
            "signers" => $signers,
            "expire_in_days" => 30,
            "display_on_page" => "all",
            "notify_signers" => false,
            "send_sign_link" => false,
            "file_name" => basename($doc_path),
            "file_data" => base64_encode(Storage::disk($path_type)->get($doc_path)),
            "generate_access_token" => true
        ];
        if($path_type != 's3') {
            $payload["file_data"] = base64_encode(Storage::disk($path_type)->get($doc_path));
        }

        if($is_estamp == 1 && !empty($estamp_tag)) {
            $payload["estamp_request"] = [
                "tags" => [
                  $estamp_tag => $estamp_qty
                ],
                "sign_on_page" => "all",
                "note_content" => "",
                "note_on_page" => "all"
            ];
        }
        $this->payload = json_encode($payload);
        $this->callCurl($this->digio_url.DIRECTORY_SEPARATOR.self::UPLOAD_ESIGN_DOC_ENDPOINT, "POST");
        if(!empty($this->curl)) {
            $response = curl_exec($this->curl);
            //\Log::info($response);
            $httpcode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
            $erro = '';
            if ($httpcode !== 200 && curl_error($this->curl)) {
                $error = curl_error($this->curl);
            }
            curl_close($this->curl);
            $this->resetCurl();
            if (!empty($error)) {
                throw new \Exception($error);
            }
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $this->digio_url.DIRECTORY_SEPARATOR.self::UPLOAD_ESIGN_DOC_ENDPOINT,'Request'=> $this->payload, 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($error) ? $error : '');
            $cwFactory->logger(json_encode($data1));
            return json_decode($response, 1);
        }
        throw new \Exception("Curl object undefined for agreement signing");

    }

    public function downloadEsignDocument($doc_id, $application_id) {

        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        $payload = [];
        $this->payload = json_encode($payload);
        $this->callCurl($this->digio_url.DIRECTORY_SEPARATOR.self::DOWNLOAD_AGREEMENT_ENDPOINT.'?document_id='.$doc_id, "GET");
        if(!empty($this->curl)) {
            $response = curl_exec($this->curl);
            //\Log::info($response);
            $httpcode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
            $erro = '';
            if ($httpcode !== 200 && curl_error($this->curl)) {
                $error = curl_error($this->curl);
            }
            curl_close($this->curl);
            $this->resetCurl();
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $this->digio_url.DIRECTORY_SEPARATOR.self::DOWNLOAD_AGREEMENT_ENDPOINT.'?document_id='.$doc_id,'Request'=> $this->payload, 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($error) ? $error : '');
            $cwFactory->logger(json_encode($data1));
            if (!empty($error)) {
                throw new \Exception($error);
            }
            return $response;
        }
        throw new \Exception("Curl object undefined for agreement details download");

    }

    public function downloadDocumentDetails($doc_id, $application_id) {

        $appln = ConsumerApplication::where('id', $application_id)->first(['lender_id']);
        $lender_id = isset($appln->lender_id) ? $appln->lender_id : 0;
        $this->setup($lender_id);
        $payload = [];
        $this->payload = json_encode($payload);
        $this->callCurl($this->digio_url.DIRECTORY_SEPARATOR.self::DOWNLOAD_DOCUMENT_DETAILS_ENDPOINT.DIRECTORY_SEPARATOR.$doc_id, "GET");
        if(!empty($this->curl)) {
            $response = curl_exec($this->curl);
            //\Log::info($response);
            $httpcode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
            $error = '';
            if ($httpcode !== 200 && curl_error($this->curl)) {
                $error = curl_error($this->curl);
            }
            curl_close($this->curl);
            $this->resetCurl();
            $cwFactory = new CloudWatchLoggerFactory();
            $data1 = array('user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Digio', 'api_url' => $this->digio_url.DIRECTORY_SEPARATOR.self::DOWNLOAD_DOCUMENT_DETAILS_ENDPOINT.DIRECTORY_SEPARATOR.$doc_id,'Request'=> $this->payload, 'Response'=>isset($response) ? $response : '{}', 'error_msg' => isset($error) ? $error : '');
            $cwFactory->logger(json_encode($data1));
            if (!empty($error)) {
                throw new \Exception($error);
            }
            return json_decode($response, 1);
        }
        throw new \Exception("Curl object undefined for agreement details download");

    }
}
