<?php
/**
 * Created by PhpStorm.
 * User => sunilkhorwal
 * Date => 2019-05-30
 * Time => 15 =>57
 */

namespace App\Avanse\DataModels;

use App\Avanse\Processes\AvanseProcesses;
use App\AvanseCreateCustomer;
use App\AvanseMasterData;
use App\Company;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\ConsumerApplicationFiles;
use App\NachSupportedBank;
use App\StateModel;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use App\Slack;
use Illuminate\Support\Facades\Storage;

class AvanseCustomer extends DataMapping
{

    private $request;
    public $error = null;

    public function __construct(Request $request)
    {

        $this->request = $request;
    }

    public function getPayload()
    {

        $this->dataInitialize();

        $Branch = Config::get('avanse')['Branches'];

        $emails = [];

        if ($this->request->get('email')){
            $emails = [
                [
                    "custEMailTypeCode" => "COMM",
                    "custEMail" => $this->request->get('email'),
                    "custEMailPriority" => 5
                ]
            ];
        }

        return [
            "baseCurrency" => "INR",
            "primaryRelationOfficer" => _env('AVANSE_ACCOUNTS_OFFICER'),
            "categoryCode" => "RETAIL",
            "defaultBranch" => $Branch['DELHI'],
            "personalInfo" => $this->getPersonalInfo(),
            "customerIncome" => "",
            "addresses" => $this->getAddresses(),
            "employments" => $this->getEmployments(),
            "phones" => [
                [
                    "phoneTypeCode" => "MOBILE1",
                    "phoneCountryCode" => "",
                    "phoneAreaCode" => "",
                    "phoneNumber" => $this->request->get('mobile_number'),
                    "priority" => 5
                ]
            ],
            "emails" => $emails,
            "documents" => $this->getDocuments(),
            "customersBankInfo" => $this->getBankInfo(),
            "extendedDetails" => $this->getExtendedDetails()
        ];
    }

    public function getExtendedDetails(){


        $co = '';
        if($this->request->has('applicant_type') && $this->request->get('applicant_type') == 2){
            $co = 'Co-Applicant ';
        }

        if (!$this->request->get('current_address_status')){
            $this->error[] = $co.'Address[Status] is missing';
        }
        if (!$this->request->get('designation')){
            $this->error[] = $co.'Designation is missing';
        }

        return [
            [
                "extendedFields" => [
                    [
                        "fieldName" => "AML",
                        "fieldValue" => "Low"
                    ],
                    [
                        "fieldName" => "PEP",
                        "fieldValue" => "No"
                    ],
                    [
                        "fieldName" => "QUALIFICATION",
                        "fieldValue" => "Doctor"//$this->request->get('designation')
                    ],
                    [
                        "fieldName" => "RESIDENCESTABILITY",
                        "fieldValue" => date('Y-m-d\TH:i:s', Carbon::now()->subYear(2)->timestamp)
                    ],
                    [
                        "fieldName" => "RESIDENCETYPE",
                        "fieldValue" => "Rented"//$this->request->get('current_address_status')
                    ]
                ]
            ]
        ];
    }

    public function getEmployments(){

        $company = Company::where('id', $this->request->get('company_id'))->first();


        $co = '';
        if($this->request->has('applicant_type') && $this->request->get('applicant_type') == 2){
            $co = 'Co-Applicant ';
        }

        if (!$this->request->get('experience')){
            $this->error[] = $co.'Experience is missing';
        }

        if (isset($company->id) && $this->request->get('designation')) {
            return [
                [
                    "employerId" => "3038",//$company->id,
                    "custEmpType" => "PVT",
                    "designation" => "OTH",
                    "department" => "",//$this->request->get('department'),
                    "startDate" => $this->request->get('experience') ? date('Y-m-d\TH:i:s', Carbon::now()->subMonth($this->request->get('experience'))->timestamp) : '',
                    "endDate" => ""
                ]
            ];
        }
    }

    private function getAddresses(){

        $addressees = [];


        $co = '';
        if($this->request->has('applicant_type') && $this->request->get('applicant_type') == 2){
            $co = 'Co-Applicant ';
        }


        if (!$this->request->get('addressees')){
            $this->error[] = $co.'Address is missing';
        }

        if ($this->request->get('addressees')) {
            foreach ($this->request->get('addressees') as $addressItem) {

                $address = $addressItem['current_address_line_1'];



                //-----
                $addrLine = [];
                $addressL1 = '';
                $ds = explode(' ',$address);
                foreach ($ds as $key => $ads){
                    if (!isset($F1Set)) {
                        $addressL1Temp = $addressL1;
                        $addressL1 .= $ads . ' ';
                        if (strlen($addressL1) > 49) {
                            $addrLine[] = $addressL1Temp;
                            $addressL1 = '';
                            $addressL1Temp = '';
                            $F1Set = true;
                        }
                    }

                    if(isset($F1Set)){
                        $addressL1Temp = $addressL1;
                        $addressL1 .= $ads.' ';
                        if (strlen($addressL1) > 49){
                            $addrLine[] = $addressL1Temp;
                            $addressL1Temp = '';
                            $addressL1 = '';
                            $F2Set = true;
                        }else if(!isset($ds[$key + 1])){
                            $addrLine[] = $addressL1;
                        }
                    }

                    if(isset($F2Set)){
                        $addressL1Temp = $addressL1;
                        $addressL1 .= $ads.' ';
                        if (strlen($addressL1) > 49){
                            $addrLine[] = $addressL1Temp;
                            $addressL1Temp = '';
                            $addressL1 = '';
                            $F3Set = true;
                        }else if(!isset($ds[$key + 1])){
                            $addrLine[] = $addressL1;
                        }
                    }
                }
                $adsLines = !empty($addrLine) ? $addrLine : $addressL1;

                if (is_array($adsLines)){
                    $addrLine1 = $adsLines[0] ?? '';
                    $addrLine2 = $adsLines[1] ?? '';
                    $addrLine3 = $adsLines[2] ?? '';
                    $addrLine4 = $adsLines[3] ?? '';
                }else{
                    $addrLine1 = $addressL1;
                    $addrLine2 = '';
                }
                //-----

                /*if($address_length > 40){
                    // We gonna look for the comma which is the more close to the center of the string
                    $address_equal_length = $address_length/2;
                    $comma_index_before = strrpos(substr($address, 0, $address_equal_length), ',');
                    $comma_index_after = strpos($address, ',', $address_equal_length);
                    if ($comma_index_before === false) {
                        $comma_index_before = 0;
                    }
                    if ($comma_index_after === false) {
                        $comma_index_after = $address_length;
                    }
                    $comma_index = $address_equal_length - $comma_index_before <= $comma_index_after - $address_equal_length ? $comma_index_before : $comma_index_after;

                    $addrLine1 = substr($address, 0, $comma_index);
                    $addrLine2 = substr($address, $comma_index + 1);
                }*/



                /*$address = explode(' ', str_replace("\n", ' ', $addressItem['current_address_line_1']));

                $addrLine1 = $address;
                $addrLine2 = '';
                if (count($address) > 2){
                    $addrLine1 = $address[0].' '.$address[1];
                    unset($address[0]); unset($address[1]);
                    $addrLine2 = implode(' ', $address);
                }else if (count($address) > 1){
                    $addrLine1 = $address[0];
                    $addrLine2 = $address[1];
                }*/


                /*$avanse = new AvanseMasterData();
                $avanse->setTable('BMTPinCodes');
                $cityPincodeData = $avanse->where('PinCode', $addressItem['current_address_pincode'])->first();

                if (isset($cityPincodeData->City)) {
                    $avanse->setTable('RMTProvinceVsCity');
                    $cityData = $avanse->where('PCCity', $cityPincodeData->City)->first();
                }*/

                $stateModel = StateModel::where('name', $addressItem['current_address_state'])->first(['code']);

                if (!$addressItem['current_address_city']){
                    $this->error[] = $co.'Address[City] is missing';
                }
                if (!$addrLine1){
                    $this->error[] = $co.'Address[Line1] is missing';
                }
                if (!$addrLine2){
                    $this->error[] = $co.'Address[Line2] is missing';
                }
                if (!isset($cityPincodeData->City)){
                    //$this->error[] = $co.'Address[City] is missing';
                }
                if (!isset($cityData->PCCountry)){
                    //$this->error[] = $co.'Address[PCCountry: Country] is missing';
                }
                if (!isset($cityData->PCProvince)){
                    //$this->error[] = $co.'Address[PCProvince: State] is missing';
                }
                if (!$addressItem['current_address_landmark']){
                    $this->error[] = $co.'Address[Landmark] is missing';
                }

                if (strlen($addrLine1) >= 50){
                    //$this->error[] = $co.'Address length should be less than 50';
                }

                if (strlen($addrLine2) >= 50){
                    //$this->error[] = $co.'Address length should be less than 50';
                }


                $addressees[] = [
                    "addrLine1" =>  trim(preg_replace( "/\r|\n/", " ", $addrLine1)),
                    "addrLine2" =>  $addrLine2 ? trim(preg_replace( "/\r|\n/", " ", $addrLine2)) : trim(preg_replace( "/\r|\n/", " ", $addrLine1)),
                    "addrLine3" =>  isset($addrLine3) ? trim(preg_replace( "/\r|\n/", " ", $addrLine3)) : '',
                    "addrLine4" =>  isset($addrLine4) ? trim(preg_replace( "/\r|\n/", " ", $addrLine4)) : '',
                    "addrType" =>  "CURRES",
                    "buildingNo" =>  "1",
                    "city" => $cityPincodeData->City ?? $addressItem['current_address_city'],
                    "country" => $cityData->PCCountry ?? 'IN',
                    "FlatNo" =>  "",
                    "pinCode" =>  $addressItem['current_address_pincode'],
                    "poBox" =>  "",
                    "priority" =>  5,
                    "residingFrom" =>  null,
                    "state" => $cityData->PCProvince ?? ($stateModel->code ?? ''),
                    "Street" =>  $addressItem['current_address_landmark'],
                    "typeOfResidence" =>  ""
                ];
            }
        }

        return $addressees;
    }

    private function getBankInfo(){

        $bankData = [];

        $bankDetails = [$this->request->get('bank')];
        if ($bankDetails && $this->request->get('bank')) {
            foreach ($bankDetails as $bank) {

                $bank_code = '';
                $nachSupportedBank = NachSupportedBank::where('bank', $bank->bank_name)->first(['bank_code']);
                if (isset($nachSupportedBank->bank_code)) {
                    $bank_code = $nachSupportedBank->bank_code;
                }

                $bankData[] = [
                    "bankBranch" => $bank->branch_name,
                    "bankName" => $bank_code,
                    "accountNumber" => $bank->account_number,
                    "accountType" => $this->AccountTypes[strtolower($bank->account_type)],
                    "salaryAccount" => false
                ];
            }
        }

        return $bankData;
    }

    private function getDocuments(){


        if($this->request->has('applicant_type') && $this->request->get('applicant_type') == 1) {
            $files = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->whereIn('file_type', ['pan_card', 'aadhar_card', 'aadhar_card_back'])->whereNull('deleted_at')->orderBy('created_at', 'desc')->get();
        }else{
            $files = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->whereIn('file_type', ['co_applicant_pan_card', 'co_applicant_aadhar_card', 'co_applicant_aadhar_card_back'])->whereNull('deleted_at')->orderBy('created_at', 'desc')->get();
        }

        $filesArray = [];

        if($files) {
            $avanseProcesses = new AvanseProcesses($this->request);
            $uploaded = [];
            foreach ($files as $file) {

                if (!in_array($file->file_type, $uploaded)) {

                    $uploaded[] = $file->file_type;

                    if (in_array($file->file_type, ['aadhar_card', 'aadhar_card_back', 'co_applicant_aadhar_card', 'co_applicant_aadhar_card_back'])) {
                        $s3 = Storage::disk('s3_temp');
                    } else {
                        $s3 = Storage::disk('s3');
                    }

                    if (isset($file->id)) {
                        $extension = explode('.', $file->file_path);
                        $type = $extension[count($extension) - 1];
                        $format = $type == 'pdf' ? 'PDF' : 'IMG';
                        try {
                            $data = $s3->get($file->file_path);

                            $custDocTitle = $file->file_type == 'pan_card' ? $this->request->get('pan_card') : ($file->file_type == 'co_applicant_pan_card' ? $this->request->get('pan_card') : ($file->file_type == 'aadhar_card' ? $this->request->get('aadhar_card') : ($file->file_type == 'co_applicant_aadhar_card' ? $this->request->get('aadhar_card') : $file->file_type)));


                            $filesArray[] = [
                                "custDocTitle" => $custDocTitle,
                                "docCategory" => $avanseProcesses->getMappedKey($file->file_type),
                                "custDocIssuedCountry" => "IN",
                                "custDocIssuedAuth" => $format,
                                "docFormat" => $format,
                                "docRefId" => $file->id,
                                "custDocIssuedOn" => null,
                                "custDocExpDate" => null,
                                "docContent" => base64_encode($data),
                                "docName" => $file->file_type . '.' . $type
                            ];
                        } catch (\Exception $exception) {
                            (new Slack(new Request(['title' => 'Request Error Doc Upload', 'fields' => ['file_id' => $file->id, 'file_type' => $file->file_type, 'message' => $exception->getMessage(), 'line' => $exception->getLine(), 'trace' => $exception->getTraceAsString()]])))->send();
                        }
                    }
                }
            }
        }

        return $filesArray;
    }

    private function getPersonalInfo(){
        $name = explode(' ', $this->request->get('name'));
        return [
            "shortName" => isset($name[0]) ? $name[0] : '',
            "firstName" => isset($name[0]) ? $name[0] : '',
            "middleName" => isset($name[1]) && isset($name[2]) ? $name[1] : '',
            "lastName" => !isset($name[2]) && isset($name[1]) ? $name[1] : (isset($name[1]) && isset($name[2]) ? $name[2].(isset($name[3]) ? $name[3] : $name[0]) : $name[0]),
            "salutation" => $this->request->get('salutation'),
            "fatherName" => 'NA',
            "motherName" => 'NA',
            "subsegment" => "",
            "language" => "",
            "dateofBirth" => date('Y-m-d\TH:i:s', strtotime($this->request->get('dob'))),
            "countryofBirth" => "IN",
            "nationality" => "IN",
            "gender" => $this->request->get('gender'),
            "maritalStatus" => $this->request->get('marital_status'),
            "numofDependents" => 0,
            "type" => 512,
            "sector" => 350,
            "segment" => "",
            "subSector" => "",
            "industry" => "OTHERS",
            "groupID" => 0,
            "parentCountry" => "",
            "riskCountry" => "",
            "staff" => false,
            "staffID" => "",
            "employmentStatus" => "",
            "saleAgent" => "",
            "saleAgentDept" => "",
            "emiCardEligibilityAmt" => ""
        ];
    }

    private function dataInitialize(){
        //$this->loadMasterData();
        $application = ConsumerApplication::with('bank_details')->where('id', $this->request->get('id'))->first();
        $companyData = ConsumerApplicationElement::where('application_id', $this->request->get('id'))->first(['id','application_id', 'designation','department','co_applicant_designation']);

        $isAadhaarMasked = false;
        if($this->request->has('applicant_type') && $this->request->get('applicant_type') == 2){
            $state = null;
            if($application->co_applicant_address_state == "Pondicherry/Puducherry"){
                $state = "PONDICHERRY";
            }elseif($application->co_applicant_address_state == "Uttaranchal/Uttarakhand"){
                $state = "UTTARAKHAND";
            }elseif($application->co_applicant_address_state == "Orissa"){
                $state = "ORISSA";
            }
            $co = 'Co-Applicant ';
            $name = $application->co_applicant_name;
            $dob = $application->co_applicant_dob;
            $gender = $application->co_applicant_gender;
            $marital_status = $application->co_applicant_marital_status;
            $email = $application->co_applicant_email;
            $mobile_number = $application->co_applicant_mobile_number;
            $pan_card = $application->co_applicant_pan_card;
            $aadhar_card = $application->co_applicant_aadhaar_card;
            $current_address_line_1 = $application->co_applicant_address_line_1;
            $current_address_landmark = $application->co_applicant_address_landmark;
            $current_address_city = $application->co_applicant_address_city;
            $current_address_pincode = $application->co_applicant_address_pincode;
            $current_address_state = $state ?? $application->co_applicant_address_state;
            $current_address_status = $application->co_applicant_address_status;
            $company_name = $application->co_applicant_company_name;
            $bank = '';
            $experience = $application->co_applicant_experience;
            $designation = $companyData->co_applicant_designation;
            $department = '';

            $files = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->whereIn('file_type', ['co_applicant_aadhar_card', 'co_applicant_aadhar_card_back'])->where('is_masked', 1)->orderBy('created_at', 'desc')->get();

            if (count($files) >= 2){
                $isAadhaarMasked = true;
            }

        }else{
            $state = null;
            if($application->current_address_state == "Pondicherry/Puducherry"){
                $state = "PONDICHERRY";
            }elseif($application->current_address_state == "Uttaranchal/Uttarakhand"){
                $state = "UTTARAKHAND";
            }elseif($application->current_address_state == "Orissa"){
                $state = "ORISSA";
            }
            $co = 'Applicant ';
            $name = $application->name;
            $dob = $application->dob;
            $gender = $application->gender;
            $marital_status = $application->marital_status;
            $email = $application->email;
            $mobile_number = $application->mobile_number;
            $pan_card = $application->pan_card;
            $aadhar_card = $application->aadhaar_card;
            $current_address_line_1 = $application->current_address_line_1;
            $current_address_landmark = $application->current_address_landmark;
            $current_address_city = $application->current_address_city;
            $current_address_state = $state ?? $application->current_address_state;
            $current_address_pincode = $application->current_address_pincode;
            $current_address_status = $application->current_address_status;
            $company_name = $application->company_name;
            $bank = $application->bank_details;
            $experience = $application->experience;
            $designation = isset($companyData->designation) ? $companyData->designation : '';
            $department = isset($companyData->department) ? $companyData->department : '';

            $files = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->whereIn('file_type', ['aadhar_card', 'aadhar_card_back'])->where('is_masked', 1)->orderBy('created_at', 'desc')->get();

            if (count($files) >= 2){
                $isAadhaarMasked = true;
            }

        }


        if (!$isAadhaarMasked){
            $this->error[] = 'Either applicant or co-applicant aadhaar is not masked/missing';
        }

        if (!$aadhar_card){
            $this->error[] = $co.' Aadhaar Number is missing';
        }

        return $this->request->merge([
            'name' => $name,
            'dob' => $dob,
            'gender' => $gender == 'MALE' ? 'M' : 'F',
            'marital_status' => $marital_status == 'MARRIED' ? 'M' : 'S',
            'salutation' => $gender == 'MALE' ? 'MR' : 'MS',
            'email' => $email,
            'mobile_number' => $mobile_number,
            'pan_card' => $pan_card,
            'aadhar_card' => $aadhar_card,
            'co_applicant_aadhar_card' => $pan_card,
            'addressees' => [
                'current' => [
                    'current_address_line_1' => $current_address_line_1,
                    'current_address_landmark' => $current_address_landmark,
                    'current_address_city' => $current_address_city,
                    'current_address_state' => $current_address_state,
                    'current_address_pincode' => $current_address_pincode,
                ]
            ],
            'bank' => $bank,
            'company_id' => $company_name,
            'experience' => $experience,
            'current_address_status' => ucfirst($current_address_status),
            'designation' => $designation,
            'department' => $department,
            'isAadhaarMasked' => $isAadhaarMasked
        ]);
    }

    public function saveResponse(AvanseCustomer $avanseCustomer, $response){
        if ($response){
            try {

                $avanse_customer_id = null;
                if (!isset($response->returnStatus->returnCode) || $response->returnStatus->returnCode != '0000'){
                    if(isset($response->returnStatus->returnText) && strpos($response->returnStatus->returnText, ' is Already Exists.') !== false) {
                        $searchCustomerId = (new AvanseProcesses($this->request))->searchCustomer();

                        if (!is_array($searchCustomerId) && is_int($searchCustomerId)){

                            $responseSearchCustomer = json_decode(json_encode(["cif" => $searchCustomerId,"primaryRelationOfficer" => 0,"dedupReq" => false, "returnStatus" => ["returnCode" => "0000","returnText" => "Success"]]));

                            $avanse_customer_id = $this->saveCustomer($responseSearchCustomer);

                            if ($avanse_customer_id) {
                                $this->request->merge(['avanse_customer_id' => $avanse_customer_id]);
                            }

                            return $responseSearchCustomer;
                        }

                        if (isset($searchCustomerId->customerSearchDetails) && $searchCustomerId->customerSearchDetails){
                            $this->request->merge(['customers' => $searchCustomerId->customerSearchDetails]);
                        }
                    }
                    $avanseCustomer->error[] = isset($response->returnStatus->returnText) ? $response->returnStatus->returnText : 'Avanse: Incomplete data found!';
                    if ($avanse_customer_id) {
                        array_push($avanseCustomer->error, $avanse_customer_id);
                    }
                    return false;
                }

                $avanse_customer_id = $this->saveCustomer($response);

                if ($avanse_customer_id) {
                    $this->request->merge(['avanse_customer_id' => $avanse_customer_id]);
                }
            }catch (\Exception $exception){
                (new Slack(new Request(['title' => 'Request Error', 'fields' => ['response' => $response, 'request' => json_encode($this->request->all()), 'message' => $exception->getMessage(), 'line' => $exception->getLine(), 'trace' => $exception->getTraceAsString()]])))->send();
                $avanseCustomer->error = $exception->getMessage();
                return false;
            }
        }

        return $response;
    }

    private function saveCustomer($response){
        return AvanseCreateCustomer::insertGetId([
            "application_id" => $this->request->get('id'),
            "applicant_id" => $this->request->get('applicant_id'),
            "cif" => $response->cif,
            "primaryRelationOfficer" => $response->primaryRelationOfficer,
            "dedupReq" => $response->dedupReq,
            "created_at" => Carbon::now()->toDateTimeString(),
        ]);
    }

}
