<?php
/**
 * Created by PhpStorm.
 * User: sunil
 * Date: 28/11/18
 * Time: 12:39 PM
 */

namespace App;


use App\Http\Controllers\Admin\ConsumerDocument;
use App\Http\Middleware\MongoMiddleware;
use App\MongoDB\Mongo;
use Carbon\Carbon;
use Dompdf\Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use App\Logging\CloudWatchLoggerFactory;

class OCRRecognition
{
    private $request;
    private $endPointDevelopment = '';
    private $fileURL = '';
    private $karza_key = '';
    private $production = 'SFXdlWrNYduYwxk';
    private $curl;
    private $link;
    private $s3 = null;
    private $filePath;
    const PUBLIC = 'public';
    const PRIVATE = 'private';
    private $response;
    private $payload;
    private $auto_mask = false;

    public function __construct(Request $request){
        $this->request = $request;
        $this->link = ($this->request->has('link')) ? $this->request->get('link') : false;
        $this->endPointDevelopment = (_env('KARZAURLV3', ''));
        $this->karza_key = (_env('KARZAKEY', ''));
        if($this->endPointDevelopment && $this->karza_key) {
            $this->setup();
        }
    }

    private function setup(){
        $this->OCRRecognition();
        if($this->request->has('file_object') && $this->request->get('file_object') == true){
            $this->payload = array(
                'file' => curl_file_create( $_FILES['document']['tmp_name'],  $_FILES['document']['type'], $_FILES['document']['name'])
            );
            $this->endPointDevelopment = $this->endPointDevelopment.'ocr/cheque';
            $header = array(
                'cache-control: no-cache',
                "content-type: multipart/form-data; boundary=----WebKitFormBoundaryjCwX08dH9rJ5rH8u",
                'x-karza-key: '.$this->karza_key,
            );
        }else{
            $this->payload = json_encode(['url' => $this->fileURL, 'maskAadhaar' => true]);
            $this->endPointDevelopment = $this->endPointDevelopment.'ocr/kyc';
            $header = array(
                'Content-Type: application/json',
                'cache-control: no-cache',
                'x-karza-key: '.$this->karza_key
            );
        }

        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $this->endPointDevelopment,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => $this->payload,
            CURLOPT_HTTPHEADER => $header,
        ));

        $this->curl = $curl;
    }

    private function OCRRecognition(){
        if(!$this->request->has('file_object') && $this->request->get('file_object') == false) {
            if (!$this->link) {
                $applicationFile = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->where('file_type', $this->request->get('file_type'))->first(['file_path']);
                if (isset($applicationFile->file_path)) {
                    $s3 = Storage::disk('s3');
                    $this->s3 = $s3;
                    $this->filePath = $applicationFile->file_path;
                    $s3->setVisibility($applicationFile->file_path, static::PUBLIC);
                    $this->fileURL = _env('AWS_ORIGIN') . _env('AWS_BUCKET') . str_replace('//', '/', '/' . $applicationFile->file_path);
                }
            } else {
                $this->fileURL = $this->request->get('file_type');
                $this->auto_mask = $this->request->has('auto_mask');
                if (strpos($this->fileURL, _env('AWS_ORIGIN')) !== false) {
                    $file = explode(_env('AWS_ORIGIN'), $this->fileURL);
                    if (count($file) > 1) {
                        $this->filePath = (isset($file[1])) ? $file[1] : '';
                        if(strpos($this->filePath, 'aadhar_card') !== false){
                            $this->s3 = Storage::disk('s3_temp');
                            if(!$this->s3->exists($this->filePath)){
                                $this->s3 = Storage::disk('s3');
                            }
                        } else{
                            $this->s3 = Storage::disk('s3');
                        }
                        $this->s3->setVisibility($this->filePath, static::PUBLIC);

                    }
                }
            }
        }
    }

    public function get(){
        $response = curl_exec($this->curl);

        if (curl_error($this->curl)) {
            $error = curl_error($this->curl);
        }
        $cwFactory = new CloudWatchLoggerFactory();
        $data = array('application_id'=>$this->request->get('id'), 'user_id'=> isset(Auth::user()->id) ? Auth::user()->id : '', 'vendor'=> 'Karza', 'api_url' => $this->endPointDevelopment,'Request'=> $this->payload ?? '{}', 'Response'=>json_decode($response, 1) ?? '', 'error_msg' => isset($error) ? json_decode($error, 1) : '');
        $cwFactory->logger(json_encode($data));

        $mongo = new MongoMiddleware();
        $mongo->toMongo($this->request, new Response(['data' => $response, 'error' => isset($error) ? $error : null]));

        //(new Slack(new Request(['title' => 'Masking Response', 'fields' => ['Res' => $response], 'group' => Slack::$STAGE_TESTING])))->send();

        if($this->s3){
            try{
                $this->s3->setVisibility($this->filePath, static::PRIVATE);
            } catch (\Exception $e) {
                $this->s3 = Storage::disk('s3_temp');
                $this->s3->setVisibility($this->filePath, static::PRIVATE);
            }

        }
        curl_close($this->curl);
        if(isset($error)){
            return $error;
        }
        $data = json_decode($response,1);
        if($response){
            $fileName = 'ocr_'.time();
            if($this->request->has('type')){
                $fileName .= '_'.$this->request->get('type');
            }
            if($this->request->has('id')){
                $fileName .= '_'.$this->request->get('id');
            }
            Storage::disk('s3_temp')->put('/partner/ocr/'.$fileName.'.json', $response);
            //Storage::disk('storage')->put('/ocr/'.$fileName.'.json', $response);
        }
        if(isset($data['result'])) {
            if(isset($data['result'][0]['type'])) {
                foreach ($data['result'] as $details) {
                    $this->setDocument($details);

                    if ($this->auto_mask && isset($details['details']) && isset($details['details']['imageUrl'])){
                        if(strpos($this->filePath, 'aadhar_card') !== false){
                            if(isset($details['details']['imageUrl']['value'])){
                                //(new Slack(new Request(['title' => 'Masking', 'fields' => ['Link' => $details['details']['imageUrl']['value'], 'Path' => ltrim($this->filePath,'/')], 'group' => Slack::$STAGE_TESTING])))->send();
                                $consumer_files = ConsumerApplicationFiles::where('file_path', ltrim($this->filePath,'/'))->first(['file_type', 'file_path', 'applicant_type']);
                                //(new Slack(new Request(['title' => 'Masking', 'fields' => ['CF' => json_encode($consumer_files)], 'group' => Slack::$STAGE_TESTING])))->send();
                                $masked = true;
                                if(!empty($consumer_files)) {
                                    $name = $consumer_files->file_type;
                                }else{
                                    $name = 'aadhaar_card';
                                }
                                $extension = explode('.',$this->filePath);
                                $ext = '.jpg';
                                if(isset($extention)){
                                    $extension = count($extension) > 1 ? $extension[count($extension) - 1] : '.jpeg';
                                    $ext = '.'.$extension;
                                }

                                if($this->request->get('id') !== 0){
                                    $document = new ConsumerDocument(new Request(['type_of_applicant' => isset($consumer_files->applicant_type) ? $consumer_files->applicant_type : 1]));
                                    $document->uploadToS3($name, $this->request->get('id'), file_get_contents($details['details']['imageUrl']['value']), $ext, $masked);
                                }
                                if(!empty($consumer_files)) {
                                    $s3_temp = Storage::disk('s3_temp');
                                    $s3_temp->delete($this->filePath);
                                    ConsumerApplicationFiles::where('file_path', ltrim($this->filePath,'/'))->update(['deleted_at' => Carbon::now()->toDateTimeString()]);
                                }
                            }
                        }
                    }else{
                        (new Slack(new Request(['title' => 'Masking Failed', 'fields' => ['info' => json_encode($details['details']), 'application_id'=>$this->request->get('id')], 'group' => Slack::$STAGE_TESTING])))->send();
                    }
                }
                if(!empty(array_keys($this->response)) && isset(array_keys($this->response)[0])) {
                    $x=[];
                    $y=[];
                    try{
                        foreach($this->response['details'] as $details=>$value){
                            if($details != 'addressSplit'){
                                $x[$details] = $value['value'];
                            }else{
                                $y=$value;
                            }

                            if (isset($this->response['type']) && $this->response['type'] == 'Pan' && isset($x['name']) && $x['name']){
                                $consumerApplication = new ConsumerApplication();
                                $nameSplitDetails = $consumerApplication->getNameSplitAttribute(1, $x['name']);
                            }
                        }

                        $responsedata=array_merge($x,$y);
                        $responsedata = array_merge($responsedata,['document' => $this->response[array_keys($this->response)[ 0]]]);
                        if (isset($nameSplitDetails)){
                            $responsedata = array_merge($responsedata,$nameSplitDetails);
                        }
                        if (isset($responsedata['pin']) && !empty($responsedata['pin']) && $responsedata['pin'] !== '') {
                            try{
                                $statecity = ''; //GooglePlaces::getCityFromPincodeV1($responsedata['pin']);
                                $datacitydata = ''; //$statecity->getData();
//                                if ($datacitydata->status == "OK") {
                                    $responsedata['city'] = ''; //$datacitydata->district ?? '';
                                    $responsedata['state'] = ''; //$datacitydata->state ?? '';
//                                }
                            } catch (Exception $e){
                                (new Slack(new Request(['title'=>'Error 2', 'fields'=>['Message' => $e->getMessage(), 'Line' => $e->getLine(), 'File' =>$e->getFile(), 'Trace' => $e->getTraceAsString()]])))->send();
                            }
                        }
                        return array_merge($responsedata);
                    } catch (Exception $e){
                        (new Slack(new Request(['title'=>'Error 2', 'fields'=>['Message' => $e->getMessage(), 'Line' => $e->getLine(), 'File' =>$e->getFile(), 'Trace' => $e->getTraceAsString()]])))->send();
                    }
                }
                return false;
            }else{
                return ($data['result']);
            }
        }else{
            return false;
        }
    }

    public function setDocument($data){
        if(isset($data['type'])) {
            switch ($data['type']) {
                case 'pan':
                    $this->response[$data['type']] = $data['details'];
                    break;
                case 'aadhaar_front_top':
                    if (!empty($this->response['aadhar_card'])) {
                        $this->response['aadhar_card'] = array_merge($this->response['aadhar_card'], $data['details']);
                    } else {
                        $this->response['aadhar_card'] = $data['details'];
                    }
                    break;
                case 'aadhaar_front_bottom':
                    if (!empty($this->response['aadhar_card'])) {
                        $this->response['aadhar_card'] = array_merge($this->response['aadhar_card'], $data['details']);
                    } else {
                        $this->response['aadhar_card'] = $data['details'];
                    }
                    break;
                case 'aadhaar_back':
                    if (!empty($this->response['aadhar_card'])) {
                        $this->response['aadhar_card'] = array_merge($this->response['aadhar_card'], $data['details']);
                    } else {
                        $this->response['aadhar_card'] = $data['details'];
                    }
                    break;
                case 'passport_front':
                    if (!empty($this->response['passport'])) {
                        $this->response['passport'] = array_merge($this->response['passport'], $data['details']);
                    } else {
                        $this->response['passport'] = $data['details'];
                    }
                    break;
                case 'passport_back':
                    if (!empty($this->response['passport'])) {
                        $this->response['passport'] = array_merge($this->response['passport'], $data['details']);
                    } else {
                        $this->response['passport'] = $data['details'];
                    }
                    break;
                default :
                    $this->response = $data;
            }
        }else{
            $this->response = $data;
        }
    }
}
