<?php

namespace App\Model;

use App\ConsumerApplicationElement;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\ConsumerApplication;
use App\CreditReport;
use App\GSTPANData;
use App\Devices;
use App\EPFUANLookup;
use App\Http\Controllers\AnalyticsController;
use App\EmiPayment;
use App\Equifax;

class Prediction extends Model
{

	protected $table = 'predictions';

	const PARTNER = 'markytics';

	public static function apiCustomerPayload($appObj) {

	    $repayments = self::getRepayments($appObj->id);
	    if(!empty($repayments)) {
	    	$repayments = [$appObj->id => $repayments];
	    } else {
	    	$repayments = (object) [];
	    }
	    return [
	    	'consumer_application' => [
                    self::getApplictionData($appObj),
                ],
            'repayments' => $repayments
	    ];
	}

	public static function getApplictionData($appObj) {

		$crObj = self::getCreditReport($appObj->id);
		$insData = isset($appObj->user_id) ? self::getInstalledAppData($appObj->user_id) : null;
		$arr = [
			"id" =>  $appObj->id,
	        "Gender" => !empty($appObj->gender) ? strtoupper($appObj->gender) : '',
	        "tenure" =>  !empty($appObj->tenure) ? $appObj->tenure : '',
	        "Purpose" =>  !empty($appObj->purpose) ? $appObj->purpose : '',
	        "loan_amount" =>  !empty($appObj->loan_amount) ? $appObj->loan_amount : '',
	        "approved_amount" =>  !empty($appObj->approved_amount) ? $appObj->approved_amount : null,
	        "marital_status" =>  !empty($appObj->marital_status) ? $appObj->marital_status : null,
	        "employment_status" =>  !empty($appObj->employee_status) ? $appObj->employee_status : null,
	        "dob" =>  !empty($appObj->dob) ? $appObj->dob : null,
	        "employee_status" =>  !empty($appObj->employee_status) ? $appObj->employee_status : null,
	        "co_applicant_employee_status" =>  !empty($appObj->co_applicant_employee_status) ? $appObj->co_applicant_employee_status : null,
	        "monthly_income" =>  !empty($appObj->monthly_income) ? $appObj->monthly_income : null,
	        "updated_from" =>  !empty($appObj->updated_by) ? $appObj->updated_by : null,
	        "foir_including_cf_emi" => !empty($crObj->foirIncludingCFEMI) ? $crObj->foirIncludingCFEMI : null,
	        "foir_excluding_cf_emi" => !empty($crObj->foirNAIncludingCFEMI) ? $crObj->foirNAIncludingCFEMI : null,
	        "gst_pan_validation" => self::getGstPanData($appObj->id),
	        "epf_data" =>  self::getEpfData($appObj->id),
	        "sms_data" =>  !empty($insData['sms_data']) ? $insData['sms_data'] : null,
	        "contact_list" =>  !empty($appObj->user_id) ? self::getContactList($appObj->user_id) : null,
	        "installed_app" =>  !empty($insData['installed_app']) ? $insData['installed_app'] : null,
	        "device_data" =>  !empty($appObj->user_id) ? self::getDeviceData($appObj->user_id) : null,
	        "is_negative_location" =>  self::getNegativeLocation($appObj),
	        "state" =>  !empty($appObj->state) ? $appObj->state : '',
	        "is_repeat" =>  0,
	    ];
	    unset($crObj, $insData);
	    return $arr;
	}

	public static function getContactList($user_id) {
		try {
            $s3 = Storage::disk('s3');
            $userInfo = $s3->listContents("info/" . $user_id . '/');
            foreach ($userInfo as $userInfoItem) {
                $date = $userInfoItem['basename'];
                $userFile = $s3->listContents("info/" . $user_id . '/' . $date . '/');
                foreach ($userFile as $userFileItem) {
                    $file = $s3->get("info/" . $user_id . '/' . $date . '/' . $userFileItem['basename']);
                    $decrypted_file = wall_decrypt($file);
                    $report_data = json_decode($decrypted_file, true);
                    if (isset($report_data['data'])) {
                        $userData = json_decode($report_data['data'], true);
                        if (isset($userData) && isset($userData['contact'])) {
                            $contactCount = count($userData['contact']);
                            $applicant = ConsumerApplication::where('user_id', $user_id)->get(['applicant_id']);
                            foreach ($applicant as $applicantData) {
                                if (!empty($applicantData->applicant_id)) {
                                    return $contactCount;
                                }
                            }
                        }
                    }
                }
            }
            return 0;
        }catch (\Exception $exception){
            return  0;
        }
	}

	public static function getInstalledAppData($user_id) {

		$installed_app = $sms_data = false;

        $consumerApplicationController = new ConsumerApplicationController(); // Ensure the class exists in the imported namespace
        $userAppData = $consumerApplicationController->getUserFormattedData($user_id);
        if($userAppData){
            $installed_app = $userAppData['risky'] ? true : false;
            $sms_data = $userAppData['charges'] || $userAppData['salary'] ? true : false;
        }
        unset($consumerApplicationController);
        return ['installed_app' => $installed_app, 'sms_data' => $sms_data];
	}

	public static function getNegativeLocation($appObj) {

		$consumerApplicationController = new ConsumerApplicationController();
        $installationAddressPincode = ConsumerApplicationElement::where('application_id', $appObj->id)
            ->value('installation_address_pincode');
		$NegativeAreaResponse = $consumerApplicationController->getNegativeAreaList([
            // 'permanent_pincode' => $appObj->permanent_address_pincode,
            'current_pincode' => $appObj->current_address_pincode,
            // 'co_applicant_pincode' => $appObj->co_applicant_address_pincode,
            'installation_pincode' => $installationAddressPincode,
        ]);
        unset($consumerApplicationController);
        if ($NegativeAreaResponse && isset($NegativeAreaResponse->level) && $NegativeAreaResponse->level == 1) {
            return true;
        }
        return false;
	}

	public static function getCreditReport($id) {

		return CreditReport::where('application_id', $id)->first();
	}

	public static function getGstPanData($id) {

		$gst_pan_data = [];
		$gstObj = GSTPANData::where('application_id', $id)->get();
		if (!empty($gstObj)) {
            foreach ($gstObj as $gst_pan_item) {
                $gst_pan_data[] = [
                    'application_id' => $gst_pan_item->application_id,
                    'data' => $gst_pan_item->data,
                    'type' => $gst_pan_item->type,
                    'pan' => $gst_pan_item->pan,
                ];
            }
        }
        return $gst_pan_data;
	}

	public static function getDeviceData($user_id) {

		$devices = [];
		$devObj = Devices::where('user_id',$user_id)->get();

        if (!empty($devObj)) {
            foreach ($devObj as $device) {
                $devices[] = [
                    'model' => $device->model,
                    'brand' => $device->brand,
                    'product' => $device->product,
                    'device' => $device->device,
                    'fingerprint' => $device->fingerprint
                ];
            }
        }
        return $devices;
	}

	public static function getEpfData($id) {

		$epf_data = [];
		$epfObj = EPFUANLookup::where('application_id',$id)->get();

        if (!empty($epfObj)) {
            foreach ($epfObj as $epf_uan_lookup) {
                $epf_data[] = [
                    'application_id' => $epf_uan_lookup->application_id,
                    'entityID' => $epf_uan_lookup->entity_id,
                    'employerName' => $epf_uan_lookup->employerName,
                    'uan_no' => $epf_uan_lookup->uan_no,
                    'data' => $epf_uan_lookup->data
                ];
            }
        }
        return $epf_data;
	}

	public static function getRepayments($id) {
		$repayments = [];
		$emiPayments = EmiPayment::where('application_id', $id)->get();
        foreach ($emiPayments as $emiPayment) {
            $repayments[] = [
                'application_id' => $emiPayment->application_id,
                'emi_amount' => $emiPayment->emi_amount,
                'bounce_charges' => $emiPayment->bounce_charges,
                'delay_penalty' => $emiPayment->delay_penalty,
                'payment_mode' => $emiPayment->payment_mode,
                'payment_date' => $emiPayment->payment_date,
                'payment_status' => $emiPayment->payment_status,
//                'bounce_charge_igst' => $emiPayment->bounce_charge_igst,
//                'bounce_charge_cgst' => $emiPayment->bounce_charge_cgst,
//                'bounce_charge_sgst' => $emiPayment->bounce_charge_sgst,
//                'net_bounce_charge' => $emiPayment->net_bounce_charge,
//                'penal_interest_igst' => $emiPayment->penal_interest_igst,
//                'penal_interest_cgst' => $emiPayment->penal_interest_cgst,
//                'penal_interest_sgst' => $emiPayment->penal_interest_sgst,
//                'net_penal_interest' => $emiPayment->net_penal_interest,
//                'final_bounce_charge' => $emiPayment->final_bounce_charge,
//                'final_penal_interest' => $emiPayment->final_penal_interest,
                'due_date' => $emiPayment->due_date,
                'total_payable' => $emiPayment->total_payable,
                'amount_due' => $emiPayment->amount_due,
                'delay_days' => $emiPayment->delay_days,
                'moratorium' => $emiPayment->moratorium,
                'moratorium_amount' => $emiPayment->moratorium_amount,
                'dpd_reason' => $emiPayment->dpd_reason
            ];
        }
        return $repayments;
	}

	public static function getConfigParams() {
        return \Config::get(self::PARTNER);
    }

	public static function apiCustomerResponse($appObj) {
		$payload = json_encode(self::apiCustomerPayload($appObj));
		$config = self::getConfigParams();
		if(!empty($config['services']['api_customer']['API'])) {
			$url = $config['base'].$config['services']['api_customer']['API'];
			$headers = array('Content-Type: application/json');
			$response = self::sendRequest($url, 'POST', $payload, $headers);
			return self::logResponse($appObj, $payload, $response, __FUNCTION__);
		}
		return false;
	}

	public static function logResponse($appObj, $payload, $resp, $api_call) {
		$response = json_decode($resp, 1);
		$decision = 0; $reason = $error = '';
		if(!empty($response['status'])) {
			if(200 === (int)$response['status']) {
				// call success
				// check if approved or rejected
				if (isset($response['data'][0]['predicted_loan_decision'])) {
					$decision = $response['data'][0]['predicted_loan_decision'];
				}
				if (isset($response['data'][0]['Reason'][0])) {
					$reason = $response['data'][0]['Reason'][0];
				}
			} else if('failed' === strtolower($response['status'])) {
				// call failed
				if (!empty($response['message'])) {
					$error = $response['message'];
				}
			}
			$obj = new self;
			$obj->lid = $appObj->id;
			$obj->api_call = $api_call;
			$obj->decision = ($decision == 1) ?  1: 0;
			$obj->reason = !empty($reason) ? $reason : '';
			$obj->error = !empty($error) ? $error : '';
			$obj->payload = $payload;
			$obj->response = $resp;
			$obj->save();
			return $obj;
		}
		return false;
	}

	private static function sendRequest($url, $method, $payload, $headers = []) {
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $url,
            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 => $payload,
            CURLOPT_HTTPHEADER => $headers,
        ));

        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if (curl_errno($curl)) {
            $response['status'] = 400;
            $response['message'] = curl_error($curl);
            $response = json_encode($response);
        }
        if(!$response && $httpCode != 200){
            $response['status'] = $httpCode;
            $response['message'] = "Something went wrong in sendRequest prediction API call";
            $response = json_encode($response);
        }
        curl_close($curl);
        return $response;
    }

    public static function getBureauData($appObj) {

    	$at = ($appObj->applicant_type == 1 || !$appObj->applicant_type) ? '' : '_'.$appObj->applicant_type;
    	$filePath = $appObj->id. "/" . $appObj->id . "_response" . $at . ".json";
    	$accounts = $scoreData = $accountSummaryData = $recentActivitiesData = $otherKeyIndData = $enquirySummaryData =
        $accountDetailsData = [];
        if (false !== $file = Equifax::readFile($filePath)) {
            $resp =  json_decode($file, true);
            if(!empty($resp['soapenv:Envelope']['soapenv:Body']['sch:InquiryResponse']['sch:ReportData'])) {

        		$bureauData = $resp['soapenv:Envelope']['soapenv:Body']['sch:InquiryResponse']['sch:ReportData'];
                $scoreData = !empty($bureauData['sch:Score']) ? $bureauData['sch:Score'] : [];
                $accountSummaryData = !empty($bureauData['sch:AccountSummary']) ? $bureauData['sch:AccountSummary'] : [];
                $recentActivitiesData = !empty($bureauData['sch:RecentActivities']) ? $bureauData['sch:RecentActivities'] : [];
                $otherKeyIndData = !empty($bureauData['sch:OtherKeyInd']) ? $bureauData['sch:OtherKeyInd'] : [];
                $enquirySummaryData = !empty($bureauData['sch:EnquirySummary']) ? $bureauData['sch:EnquirySummary'] : [];
                $accountDetailsData = !empty($bureauData['sch:AccountDetails']['sch:Account']) ? $bureauData['sch:AccountDetails']['sch:Account'] : [];
            }
        }
        foreach ($accountDetailsData as $account) {
            $history = [];
            if(!empty($account['sch:History48Months']['sch:Month'])) {
            	foreach ($account['sch:History48Months']['sch:Month'] as $month) {
	                $history[] = $month;
	            }
            }
            $accounts[] = [
                'seq' => $account['@seq'],
                'AccountType' => $account['sch:AccountType'],
                'OwnershipType' => $account['sch:OwnershipType'],
                'history' => isset($history) ? $history : [],
            ];
        }
        $creditReport = self::getCreditReport($appObj->id);
        $bureau = [
            'id' => $creditReport->application_id,
            'applicant_type' => $creditReport->applicant_type,
            'extracted_date' => date('d-m-Y', strtotime($appObj->created_at)),
            'extracted_time' => date('G:i:s', strtotime($appObj->created_at)),
            'credit_score' => !empty($scoreData['sch:Value']) ? $scoreData['sch:Value'] : "",
            'average_open_balance' => !empty($accountSummaryData['sch:AverageOpenBalance']) ? $accountSummaryData['sch:AverageOpenBalance'] : 0,
            'most_severe_status_within_24_months' => !empty($accountSummaryData['sch:MostSevereStatusWithIn24Months']) ? $accountSummaryData['sch:MostSevereStatusWithIn24Months'] : '',
            'recent_account' => !empty($accountSummaryData['sch:RecentAccount']) ? $accountSummaryData['sch:RecentAccount'] : '',
            'no_of_accounts' => !empty($accountSummaryData['sch:NoOfAccounts']) ? $accountSummaryData['sch:NoOfAccounts'] : '',
            'no_of_active_accounts' => !empty($accountSummaryData['sch:NoOfActiveAccounts']) ? $accountSummaryData['sch:NoOfActiveAccounts'] : '',
            'no_of_past_due_accounts' => !empty($accountSummaryData['sch:NoOfPastDueAccounts']) ? $accountSummaryData['sch:NoOfPastDueAccounts'] : '',
            'no_of_write_offs' => !empty($accountSummaryData['sch:NoOfWriteOffs']) ? $accountSummaryData['sch:NoOfWriteOffs'] : '',
            'no_of_zero_balance_accounts' => !empty($creditReport->zeroBalanceAccount) ? $creditReport->zeroBalanceAccount : '',
            'total_past_due' => !empty($accountSummaryData['sch:TotalPastDue']) ? $accountSummaryData['sch:TotalPastDue'] : '',
            'account_deliquent' => !empty($recentActivitiesData['sch:AccountsDeliquent']) ? $recentActivitiesData['sch:AccountsDeliquent'] : '',
            'account_opened' => !empty($recentActivitiesData['sch:AccountsOpened']) ? $recentActivitiesData['sch:AccountsOpened'] : '',
            'total_inquiries' => !empty($recentActivitiesData['sch:TotalInquiries']) ? $recentActivitiesData['sch:TotalInquiries'] : '',
            'account_updated' => !empty($recentActivitiesData['sch:AccountsUpdated']) ? $recentActivitiesData['sch:AccountsUpdated'] : '',
            'age_of_oldest_trade' => !empty($otherKeyIndData['sch:AgeOfOldestTrade']) ? $otherKeyIndData['sch:AgeOfOldestTrade'] : '',
            'number_of_open_trades' => !empty($otherKeyIndData['sch:NumberOfOpenTrades']) ? $otherKeyIndData['sch:NumberOfOpenTrades'] : '',
            'past_12_months' => !empty($enquirySummaryData['sch:Past12Months']) ? $enquirySummaryData['sch:Past12Months'] : '',
            'past_24_months' => !empty($enquirySummaryData['sch:Past24Months']) ? $enquirySummaryData['sch:Past24Months'] : '',
            'past_30_days' => !empty($enquirySummaryData['sch:Past30Days']) ? $enquirySummaryData['sch:Past30Days'] : '',
            'purpose' => !empty($enquirySummaryData['sch:Purpose']) ? $enquirySummaryData['sch:Purpose']: '',
            'accounts' => $accounts
        ];
        unset($accounts, $scoreData, $accountSummaryData, $recentActivitiesData, $otherKeyIndData, $enquirySummaryData,
        $accountDetailsData, $creditReport);

        return $bureau;
    }

    public static function apiBureauPayload($appObj) {

	    $repayments = self::getRepayments($appObj->id);
	    if(!empty($repayments)) {
	    	$repayments = [$appObj->id => $repayments];
	    } else {
	    	$repayments = (object) [];
	    }
	    return [
            'bureau' => [self::getBureauData($appObj)],
            'consumer_application' => [self::getApplictionData($appObj)],
            'repayments' => $repayments
	    ];
	}

    public static function apiCustomerBureauBankPayload($appObj) {

        $repayments = self::getRepayments($appObj->id);
        if(!empty($repayments)) {
            $repayments = [$appObj->id => $repayments];
        } else {
            $repayments = (object) [];
        }
        $analyticsController = new AnalyticsController(new Request(['internal' => true]));
        return [
            'bureau' => [self::getBureauData($appObj)],
            'consumer_application' => [self::getApplictionData($appObj)],
            'repayments' => $repayments,
            'bank' => [$analyticsController->getFinbitDetails($appObj->id)]
        ];
    }

    public static function apiCSBureauBankResponse($appObj) {
        $payload = json_encode(self::apiCustomerBureauBankPayload($appObj));
        $config = self::getConfigParams();
        if(!empty($config['services']['combine_api']['API'])) {
            $url = $config['base'].$config['services']['combine_api']['API'];
            $headers = array('Content-Type: application/json');
            $response = self::sendRequest($url, 'POST', $payload, $headers);
            return self::logResponse($appObj, $payload, $response, __FUNCTION__);
        }
        return false;
    }

	public static function apiBureauResponse($appObj) {
		$payload = json_encode(self::apiBureauPayload($appObj));
		$config = self::getConfigParams();
		if(!empty($config['services']['bureau_cust_api']['API'])) {
			$url = $config['base'].$config['services']['bureau_cust_api']['API'];
			$headers = array('Content-Type: application/json');
			$response = self::sendRequest($url, 'POST', $payload, $headers);
			return self::logResponse($appObj, $payload, $response, __FUNCTION__);
		}
		return false;
	}
}
