<?php

namespace App\Http\Controllers;

use App\_Slack;
use App\ABFL\Services\Services;
use App\ApplicationEMICalculation;
use App\Bank;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\Http\Controllers\Admin\HomevilleController;
use App\PostApprovalFlow;
use App\MerchantCategoryKYCRules;
use App\DigitalSignDetails;
use App\EMICalculation;
use App\EmiPayment;
use App\Logging\CloudWatchLoggerFactory;
use App\Singularity\Singularity;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Admin\AccountingController;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\Http\Controllers\Admin\DisbursementController;
use App\KYCDetails;
use App\Lenders;
use App\LoanManagement;
use App\Mandate;
use App\Merchant;
use App\MerchantCategory;
use App\MerchantFiles;
use App\MerchantOffers;
use App\MerchantLocation;
use App\PaymentEmi;
use App\Slack;
use App\User;
use Carbon\Carbon;
use function Composer\Autoload\includeFile;
use Hashids\Hashids;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Input;
use App\ConsumerApplicationFiles;
use Illuminate\Support\Facades\App;
use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use App\Model\LoanAgreementVendor;
use App\KarzaVideo;
use App\KarzaVideoAttribute;
use App\KarzaVideoWebhook;
use App\LoanHypothecation\LoanHypothecation;
use App\Shortio;
use App\DigioVKYC;
use App\BankValidation;
use App\Http\Controllers\FrontController;
//use FuzzyWuzzy\Fuzz;
use FuzzyWuzzy\Process;
use App\ContentLogger;
use Illuminate\Support\Facades\Session;

class PostApprovalController extends Controller
{
    public $cloudwatchLogger;
    const BANK_NAME_MATCH_PERCENTAGE = 50;

    public function __construct() {
        $this->cloudwatchLogger = new CloudWatchLoggerFactory();
    }

    public function getKYCDone($app_id){
        try {
            $hashids = new Hashids('Creditfair by CS', 20);
            $frontController = new FrontController();
            $apiController = new ApiController();
            $id = $hashids->decode($app_id);
            if(isset($id[0])){
                $user_details = ConsumerApplication::where('id', $id[0])->first(['name', 'mobile_number', 'email', 'approved_amount', 'purpose', 'merchant_id', 'loan_amount', 'co_applicant_name','co_applicant_email','co_applicant_mobile_number','offer_id','lender_id','state']);
                $applicationElement = ConsumerApplicationElement::where('application_id', $id[0])
                    ->orderBy('created_at', 'desc')
                    ->first(['preferred_language','onfido_skip', 'agreement_resign', 'co_app_onfido_skip', 'is_consent', 'is_co_app_consent']);
                //$consumerAdditional = DB::selectOne("SELECT linked_status, co_linked_status FROM consumer_application_additional WHERE application_id = " . $id[0]);
                $offer_details = MerchantOffers::where('merchant_id', $user_details->merchant_id)->where('id', $user_details->offer_id)->where('status',1)->first();
                if(!isset($offer_details->id)){
                    (new Slack(new Request(['title' => 'Offer missing in loan agreement', 'fields' => ['application_id' => $id[0]]])))->send();
                    return redirect()->to('/404');
                }
                //$net_loan_amount = $frontController->checkNetLoanAmount($offer_details, $user_details->approved_amount);
                //$signed_data = DigitalSignDetails::where('application_id', $id[0])->where('applicant', 1)->first();
                //$co_app_signed_data = DigitalSignDetails::where('application_id', $id[0])->where('applicant', 2)->first();

                $kycStatus = $this->checkKYCStatus($id[0])->getData();
                // $data['app_kyc_completed'] = $kycStatus->applicant->kyc_completed ? true : false;
                $skipStatus = $this->checkSkipStatus($id[0]);
                $data['app_kyc_completed'] = $kycStatus->applicant->kyc_completed && $kycStatus->applicant->kyc_status!= "rejected" ? true : false;
                if (
                    (is_array($skipStatus->applicant) && isset($skipStatus->applicant['vkyc']) && $skipStatus->applicant['vkyc'] == 0) ||
                    (is_object($skipStatus->applicant) && isset($skipStatus->applicant->vkyc) && $skipStatus->applicant->vkyc == 0)
                ) {
                    $data['app_kyc_completed'] = true;
                }
                // $skipKyc = $this->checkSkipKYC($id[0]);
                if (isset($user_details->co_applicant_name)) {
                    $data['co_app_kyc_completed'] = $kycStatus->co_applicant->kyc_completed && $kycStatus->co_applicant->kyc_status!= "rejected" ? true : false;
                }
                else {
                    $data['co_app_kyc_completed'] = true;
                }
                if (
                    (is_array($skipStatus->co_applicant) && isset($skipStatus->co_applicant['vkyc']) && $skipStatus->co_applicant['vkyc'] == 0) ||
                    (is_object($skipStatus->co_applicant) && isset($skipStatus->co_applicant->vkyc) && $skipStatus->co_applicant->vkyc == 0)
                ) {
                    $data['co_app_kyc_completed'] = true;
                }
                $merchant = Merchant::where('id', $user_details->merchant_id)->first(['merchant_name', 'category_id']);
                $kycRules = MerchantCategoryKYCRules::where('category_id', $user_details->purpose)->where('lender_id', $user_details->lender_id)->get();
                $kycType = $frontController->checkKycCondition($user_details->approved_amount, $kycRules);
                $amount = isset($user_details->approved_amount) && !empty($user_details->approved_amount) && $user_details->approved_amount != 0 ? $user_details->approved_amount : $user_details->loan_amount;
                $content = 'Please complete the KYC and loan signing to receive disbursement of loan for ₹' . $amount;
                if ($merchant->category_id != 3) {
                    $content = 'Please complete the payment, KYC and loan agreement signing to receive disbursement of loan for purchase from ' . $merchant->merchant_name . ' for ₹' . $amount;
                }

                $data['status'] = 'success';
                $data['application_id'] = $id[0];
                $data['hashed_application_id']= $app_id;
                $data['consent_hashed_id'] = $hashids->encode($id[0]);
                $data['request_id'] = isset($request_id) ? $request_id : '';
                $data['identifier'] = isset($identifier) ? $identifier : '';
                $data['source'] = 'link';
                $data['text_content'] = isset($content) ? $content : '';
                $data['user_details'] = $user_details;
                $data['preferred_language'] = isset($applicationElement->preferred_language) ? $applicationElement->preferred_language : '';
                $isHypothecationActive = $apiController->canHypothecated($id[0]);
                $stepDetails = $frontController->getFeesData($id[0],false, true);
                if (isset($stepDetails['set_auto_debit'])) {
                    $data['mandate'] = 1;
                }
                if (isset($stepDetails['set_auto_debit_co_applicant'])) {
                    $data['mandate_co_applicant'] = 1;
                }
                if (isset($stepDetails['payment_details']['Total Payment']['amount']) && $stepDetails['payment_details']['Total Payment']['amount'] > 0) {
                    $data['payment'] = 1;
                }
                // if (!$stepDetails['bank']['validation']) {
                //     $data['bank'] = 1;
                // }
                // if (isset($stepDetails['co_applicant_bank']) && !$stepDetails['co_applicant_bank']) {
                //     $data['co_applicant_bank'] = 1;
                // }
                $data['isHypothecationActive'] = $isHypothecationActive;
                $data['consentGiven'] = $applicationElement->is_consent;
                $data['consentGivenCoApp'] = $applicationElement->is_co_app_consent;
                if ($kycType == 1 || $kycType == 3) {
                    $data['kyc_type'] = $kycType;
                    return view('admin.digio_vkyc_integration', $data);
                }
                return view('admin.karza_vkyc_integration', $data);
            }
        } catch (\Exception $e) {
            $this->cloudwatchLogger->logger(json_encode(['title' => 'Post Approval Link','application id' => $app_id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            return redirect()->to('/404');
        }
    }

    public function esign($id, $applicantType = 1){
        try {
            $hashids = new Hashids('Creditfair by CS', 20);
            $frontController = new FrontController();
            $hashed_application_id = $id;
            $application_ids = $hashids->decode($id);
            if (request()->has('type')) {
                $applicantType = request()->get('type');
            }
            if(!isset($application_ids[0])){
                $datasucess = array("application_ids" => 1,"failure"=>"");
                return view('front.esign-failure', $datasucess);
            }
            $application_id = $application_ids[0];
            $applicationDetails = ConsumerApplication::with('merchant')->where('id', $application_id)->first(['merchant_id', 'co_applicant_name', 'name', 'lender_id', 'approved_amount']);

            $apiController = new ApiController();
            $isHypothecationActive = $apiController->canHypothecated($application_id);
            if ($isHypothecationActive) {

                $kycDetails = $this->checkKYCStatus($application_id)->getData();
                $datasucess = array("application_ids" => $id,
                    "applicantType" => $applicantType,
                    "hashed_application_id" =>$hashed_application_id,
                    "user_details" => $applicationDetails,
                    "fees" => $frontController->getFeesData($application_id, false, true, $applicantType),
                    "kycDetails" => $kycDetails,
                    "text_content" => 'Please complete the payment, KYC and loan agreement signing to receive disbursement of loan for purchase from ' . $applicationDetails->merchant->merchant_name . ' for ₹' . $applicationDetails->approved_amount
                );
                if (isset($applicantType) && $applicantType == '2' && isset($kycDetails->co_applicant)) {
                    if ($kycDetails->co_applicant->kyc_completed && !in_array($kycDetails->co_applicant->kyc_status, ['approved', 'rejected'])) {
                        $coAppData['applicationId'] = $application_id;
                        $coAppData['applicantType'] = $applicantType;
                        $coAppData['hashed_application_id'] = $id;
                        $coAppData['reKYC'] = $kycDetails->co_applicant->kyc_status == 'rejected' ? true : false;
                        return view('admin.kyc_waiting_page', $coAppData);
                    }
                }
                if (!isset($datasucess['fees']['set_auto_debit']) && $datasucess['fees']['payment_details']['Total Payment']['amount']== 0) {
                    if ($kycDetails->applicant->kyc_completed && !in_array($kycDetails->applicant->kyc_status, ['approved', 'rejected'])) {
                        $bladeData['applicationId'] = $application_id;
                        $bladeData['applicantType'] = '1';
                        $bladeData['hashed_application_id'] = $id;
                        $bladeData['reKYC'] = $kycDetails->applicant->kyc_status == 'rejected' ? true : false;
                        return view('admin.kyc_waiting_page', $bladeData);
                    }
                }
                $skipSteps = $this->checkSkipStatus($application_id);
                $datasucess = array_merge($datasucess, ['skipSteps' => $skipSteps]);
                // Hypothecation agreement e-sign
                $consumerDocs = DB::select("select consumer_application_id from consumer_application_files caf where (caf.file_type = 'pro_forma_invoice' and ((caf.created_by is not null and caf.created_by != 107) or (caf.doc_ref_id = 'proforma by merchant') or (caf.file_type = 'proforma' && caf.created_by is null))) and consumer_application_id = ? and caf.deleted_at is null limit 1", [$application_id]);
                if (!empty($consumerDocs)) {
                    $request = new Request();
                    $request->merge(['id' => $application_id]);
                    $hypothecation = new LoanHypothecation($request);
                    $links_data = $hypothecation->getHypothecationLinks();
                    if (isset($links_data)) {
                        return view('front.esign-congrats', array_merge($datasucess, ['links_data' => $links_data]));
                    }
                }
                return view('front.esign-congrats', $datasucess);
            }
            $user_details = ConsumerApplication::where('id', $application_id)->first(['name', 'mobile_number', 'email', 'approved_amount', 'merchant_id', 'loan_amount', 'co_applicant_name','co_applicant_email','co_applicant_mobile_number','offer_id','lender_id','state']);

            if(isset($user_details->lender_id) && $user_details->lender_id == Singularity::$lender_id){
                $datasucess = array("application_ids" => $id,'lender_id'=>$user_details->lender_id);
                return view('front.esign-congrats', $datasucess);
            }

            # Click wrap sign agreement
            $type = "Loan Agreement Esign";
            $request = new Request();
            $request->request->add(['type'=>$type, 'esign' => true]);
            $consumerDocument = new ConsumerDocument($request);
            $viewParameter = ($consumerDocument->getDocument($application_id));

            if ($viewParameter instanceof RedirectResponse){
                $datasucess = array("application_ids" => 1,"failure"=>"");
                return view('front.esign-failure', $datasucess);
            }

            $mobile_number = $viewParameter['user']['customer_mobile'];
            $co_applicant_mobile_number = $viewParameter['user']['co_applicant_mobile'];
            $co_applicant_name = $viewParameter['user']['co_applicant_name'];
            $preferred_language = $viewParameter['user']['preferred_language'];
            $agreement_version = $viewParameter['user']['agreement_version'];

            $firstName = $viewParameter['user']['customer_name'];
            if($firstName != "") {
                $applicant = array("name" => $firstName, "value" => "1_" . $mobile_number);
            }else{
                $applicant = array();
            }
            if($co_applicant_name != ""){
                $co_applicant = array("name" => $co_applicant_name, "value" => "2_".$co_applicant_mobile_number);
            }else{
                $co_applicant = array();
            }
            $signed_data = DigitalSignDetails::where('application_id',$application_id)->get();
            if(count($signed_data) > 0) {
                foreach ($signed_data as $signdata) {
                    if ($signdata->applicant == 1) {
                        $applicant = array();
                    }
                    if ($signdata->applicant == 2) {
                        $co_applicant = array();
                    }
                }
            }

            if($viewParameter['user']['status'] == "rejected" || $viewParameter['user']['status'] == "aborted"){
                $datasucess = array("application_ids" => $id,"failure"=>$viewParameter['user']['status']);
                return view('front.esign-failure', $datasucess);
            }

            if(count($applicant) == 0 && count($co_applicant) == 0 ){
                return $frontController->digitalsignupdate($id);
            }

            $mandate = Mandate::where('consumer_application_id', $application_id)->whereNotNull('umrn')->where('status', 'active')->first(['umrn', 'status']);
            $kyc_digio =  KYCDetails::where('application_id', $application_id)->whereNull('deleted_at')->orderBy('id', 'desc')->first();
            $userVerified = User::where('mobile_number', $mobile_number)->first(['user_verified']);

            if($viewParameter['user']['merchant_skip_otp'] && (!empty($mandate) || (!empty($kyc_digio) && !empty($kyc_digio->response))  || (!empty($userVerified) && $userVerified->user_verified == 1))){
                $skipOtp = true;
            }else{
                $skipOtp = false;
            }

            $lastName = "";
            $callbackURL = asset("esignupdate/id/".$id);
            $opendatetime = date('Y-m-d H:i:s');
            return view('front.digitalpdf',['https' => 'http',
                                            'applicant'=>$applicant,
                                            'co_applicant'=>$co_applicant,
                                            'co_applicant_mobile_number'=>$co_applicant_mobile_number,
                                            'co_applicant_name'=>$co_applicant_name,
                                            'customer_mobile' => $mobile_number,
                                            'opendatetime'=>$opendatetime,
                                            'user'=>$viewParameter['user'],
                                            'lender' => $viewParameter['lender'],
                                            'id'=>$application_id,'hasdid'=>$id,'data'=>$viewParameter['data'],
                                            'pdf'=>0, 'is_pdf'=>1,'preferred_language'=>$preferred_language,
                                            'agreement_version'=>$agreement_version, 'skipOtp'=>$skipOtp, 
                                            'combined_sl_la'=>$viewParameter['combined_sl_la'],
                                            'is_bnpl'=>$viewParameter['application']->application_element->is_bnpl, 
                                            'application'=>$viewParameter['application']]);
        } catch (\Exception $e) {
            $this->cloudwatchLogger->logger(json_encode(['title' => 'Post Approval Link', 'application id' => $id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            return redirect()->to('/404');
        }
    }

    public function checkSkipStatus($applicationId) {
        $applicationElement = ConsumerApplicationElement::where('application_id', $applicationId)->orderBy('created_at', 'desc')->first(['type_of_customer', 'type_of_customer_sub_category','type_of_customer_application','type_of_entity']);
        $application = ConsumerApplication::find($applicationId, ['lender_id']);
        $lenderId = $application ? $application->lender_id : null;


        $postApprovalChanges = PostApprovalFlow::where('type_customer', $applicationElement->type_of_customer_application)
                    ->where('type_entity', $applicationElement->type_of_entity)
                    ->where('solar_for', $applicationElement->type_of_customer)
                    ->where('sub_category', $applicationElement->type_of_customer_sub_category)
                    ->where('lender_id', $lenderId)
                    ->first(['applicant', 'co_applicant']);

        // If no entry found, set default object
        if (!$postApprovalChanges) {
                $postApprovalChanges = (object)[
                    'applicant' => ["vkyc"=>"1","payment"=>"1","mandate"=>"1","loan_agreement"=>"1"],
                    'co_applicant' => ["vkyc"=>"1","payment"=>"1","mandate"=>"1","loan_agreement"=>"1"]
            ];

            // You can set default values as needed, e.g.:
            // 'applicant' => json_encode(['skip_kyc' => false])
        }
        $skipStatus = new \stdClass();
        $skipStatus->applicant = 0; // Default
        if (isset($postApprovalChanges->applicant) && is_array($postApprovalChanges->applicant)) {
            $skipStatus->applicant = $postApprovalChanges->applicant;
        }

        $skipStatus->co_applicant = 0; // Default
        if (isset($postApprovalChanges->co_applicant) && is_array($postApprovalChanges->co_applicant)) {
            $skipStatus->co_applicant = $postApprovalChanges->co_applicant;
        }

        return $skipStatus;
    }

    public function checkKYCStatus($applicationId) {
        $application = DB::selectOne("SELECT co_applicant_name FROM consumer_application WHERE id = " . $applicationId);
        $applicant = [
            'kyc_completed' => false,
            'kyc_status' => null
        ];
        if (!empty($application->co_applicant_name)) {
            $co_applicant = [
                'kyc_completed' => false,
                'kyc_status' => null
            ];
        }
        $karzaKYCRecords = KarzaVideoAttribute::where('application_id', $applicationId)
            ->whereNull('deleted_at')
            ->whereIn('applicant_type', [1, 2])
            ->orderBy('id', 'desc')
            ->get(['id']);
        $digioKYCDetails = DigioVKYC::where('application_id', $applicationId)->whereNull('deleted_at')->get(['id', 'kyc_journey', 'kyc_status', 'applicant_type']);
        $selfAttestedFiles = DB::select("SELECT id, doc_verify, file_type FROM (SELECT id, doc_verify, file_type, ROW_NUMBER() OVER (PARTITION BY file_type ORDER BY created_at DESC)
        AS rn FROM consumer_application_files WHERE consumer_application_id = $applicationId AND file_type IN ('self_attested_pan', 'self_attested_aadhar', 'self_attested_co_aadhar', 'self_attested_co_pan', 'co_app_self_attested_pan', 'co_app_self_attested_aadhar', 'self_attested_selfie','customer_photo','self_attested_co_selfie','co_applicant_customer_photo') AND deleted_at IS NULL) t WHERE rn = 1;");

        if (count($digioKYCDetails) > 0) {
            foreach ($digioKYCDetails as $digioRecord) {
                if ($digioRecord->kyc_journey == 'complete') {
                    if ($digioRecord->applicant_type == 1) {
                        $applicant['kyc_completed'] = true;
                    } else {
                        $co_applicant['kyc_completed'] = true;
                    }
                }
                if ($digioRecord->kyc_status == 'approved') {
                    if ($digioRecord->applicant_type == 1) {
                        $applicant['kyc_status'] = 'approved';
                    } else {
                        $co_applicant['kyc_status'] = 'approved';
                    }
                }
                if ($digioRecord->kyc_status == 'rejected') {
                    if ($digioRecord->applicant_type == 1) {
                        $applicant['kyc_status'] = 'rejected';
                    } else {
                        $co_applicant['kyc_status'] = 'rejected';
                    }
                }
            }
        }
        if (count($karzaKYCRecords) > 0) {
            foreach ($karzaKYCRecords as $karzaRecord) {
                $customer_webhook = KarzaVideoWebhook::where('karza_id', $karzaRecord->id)->get(['data', 'applicant_type']);
                if(!empty($customer_webhook)){
                    foreach ($customer_webhook as $key => $value) {
                        $kyc_data = json_decode($value->data);
                        if (isset($kyc_data->approvedByAgent) && $kyc_data->approvedByAgent == "ACCEPTED") {
                            // $applicantType = substr($kyc_data->customerId, -1);
                            if ($value->applicant_type == 1) {
                                $applicant['kyc_completed'] = true;
                            } else {
                                $co_applicant['kyc_completed'] = true;
                            }
                        }
                        if (isset($kyc_data->approvedByAuditor) && $kyc_data->approvedByAuditor == "ACCEPTED") {
                            // $applicantType = substr($kyc_data->customerId, -1);
                            if ($value->applicant_type == 1) {
                                $applicant['kyc_status'] = 'approved';
                            } else {
                                $co_applicant['kyc_status'] = 'approved';
                            }
                        }
                        if (isset($kyc_data->approvedByAuditor) && $kyc_data->approvedByAuditor == "REJECTED") {
                            // $applicantType = substr($kyc_data->customerId, -1);
                            if ($value->applicant_type == 1) {
                                $applicant['kyc_status'] = 'rejected';
                            } else {
                                $co_applicant['kyc_status'] = 'rejected';
                            }
                        }
                    }
                }
            }
        }
        if (count($selfAttestedFiles) > 0) {
            $applicantPANUploaded = $applicantAadharUploaded = $applicantSelfieUploaded = false;
            $coApplicantPANUploaded = $coApplicantAadharUploaded = $coApplicantSelfieUploaded = false;

            $applicantPANVerified = $applicantAadhaarVerified = $applicantSelfieVerified = null;
            $coApplicantPANVerified = $coApplicantAadhaarVerified = $coApplicantSelfieVerified = null;

            foreach ($selfAttestedFiles as $file) {
                switch ($file->file_type) {
                    case 'self_attested_pan':
                        $applicantPANUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $applicantPANVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $applicantPANVerified = 'rejected';
                            } else {
                                $applicantPANVerified = null;
                            }
                        }
                        break;
                    case 'self_attested_aadhar':
                        $applicantAadharUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $applicantAadhaarVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $applicantAadhaarVerified = 'rejected';
                            } else {
                                $applicantAadhaarVerified = null;
                            }
                        }
                        break;
                    case 'customer_photo':
                    case 'self_attested_selfie':
                        $applicantSelfieUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $applicantSelfieVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $applicantSelfieVerified = 'rejected';
                            } else {
                                $applicantSelfieVerified = null;
                            }
                        }
                        break;
                    case 'self_attested_co_pan':
                    case 'co_app_self_attested_pan':
                        $coApplicantPANUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $coApplicantPANVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $coApplicantPANVerified = 'rejected';
                            } else {
                                $coApplicantPANVerified = null;
                            }
                        }
                        break;
                    case 'self_attested_co_aadhar':
                    case 'co_app_self_attested_aadhar':
                        $coApplicantAadharUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $coApplicantAadhaarVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $coApplicantAadhaarVerified = 'rejected';
                            } else {
                                $coApplicantAadhaarVerified = null;
                            }
                        }
                        break;
                    case 'co_applicant_customer_photo':
                    case 'self_attested_co_selfie':
                        $coApplicantSelfieUploaded = true;
                        if (isset($file->doc_verify)) {
                            if ($file->doc_verify == 1) {
                                $coApplicantSelfieVerified = 'approved';
                            } elseif ($file->doc_verify == 0) {
                                $coApplicantSelfieVerified = 'rejected';
                            } else {
                                $coApplicantSelfieVerified = null;
                            }
                        }
                        break;
                }
            }

            if ($applicantPANUploaded && $applicantAadharUploaded && $applicantSelfieUploaded) {
                $applicant['kyc_completed'] = true;
                // Check if any document is explicitly rejected
                if ($applicantPANVerified === 'rejected' || $applicantAadhaarVerified === 'rejected' || $applicantSelfieVerified === 'rejected') {
                    $applicant['kyc_status'] = 'rejected';
                } elseif ($applicantPANVerified === 'approved' && $applicantAadhaarVerified === 'approved' && $applicantSelfieVerified === 'approved') {
                    $applicant['kyc_status'] = 'approved';
                } else {
                    // Some verifications pending or null -> set status as null (waiting)
                    $applicant['kyc_status'] = null;
                }
            }

            // Co-applicant: same rules
            if (isset($co_applicant) && $coApplicantPANUploaded && $coApplicantAadharUploaded && $coApplicantSelfieUploaded) {
                $co_applicant['kyc_completed'] = true;
                if ($coApplicantPANVerified === 'rejected' || $coApplicantAadhaarVerified === 'rejected' || $coApplicantSelfieVerified === 'rejected') {
                    $co_applicant['kyc_status'] = 'rejected';
                } elseif ($coApplicantPANVerified === 'approved' && $coApplicantAadhaarVerified === 'approved' && $coApplicantSelfieVerified === 'approved') {
                    $co_applicant['kyc_status'] = 'approved';
                } else {
                    $co_applicant['kyc_status'] = null;
                }
            }
        }
        if (isset($co_applicant)) {
            return \response()->json([
                'status' => 'OK',
                'applicant' => $applicant,
                'co_applicant' => $co_applicant
            ], 200);
        }
        return \response()->json([
            'status' => 'OK',
            'applicant' => $applicant
        ], 200);
    }

    public function fuzzyComparison($string1, $string2) {
        try {
            $name1_set = array_unique(array_map('strtolower', preg_split('/\s+/', $string1)));
            $name2_set = array_unique(array_map('strtolower', preg_split('/\s+/', $string2)));

            if (count(array_diff($name1_set, $name2_set)) === 0) {
                return ["name_match" => true, "percentage" => 100];
            }

            // Fuzzy match using fuzzywuzzy-php
            // $fuzz = new Fuzz();
            // $percentage_match = $fuzz->ratio(strtolower($string1), strtolower($string2));
            $percentage_match = 100; // set to 100 since composer package issue.

            return ["name_match" => false, "percentage" => $percentage_match];
        } catch (Exception $e) {
            $this->cloudwatchLogger->logger(json_encode(['title' => 'Fuzzy Comparison Error', 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            return ["name_match" => false, "percentage" => 0];
        }
    }

    public function bankValidation($requestBody) {
        // $nameMatchpercentage = 50; // Current threshold is 50 change this value to change the threshold
        $data = $requestBody;
        $app_type = isset($data['type']) ? $data['type'] : "1";
        $app_type = $app_type == 'Bank-Details' ? 1 : $app_type;
        $bank = Bank::where(['application_id' => $data['applicationid'], 'applicant_type' => $app_type])->first(['id', 'account_number', 'karza_response', 'name_match']);
        $bankSuccess = true;
        if (isset($bank->id)) {
            $resultPercentage = 0;
            if(isset($bank->name_match)){
                $resultPercentage = json_decode($bank->name_match);
                $resultPercentage = $resultPercentage->percentage;
            }

            $validation = isset($bank->karza_response) ? json_decode($bank->karza_response) : null;
            if ((isset($validation->result->bankResponse) && ($validation->result->bankResponse != 'SUCCESSFUL TRANSACTION') || $resultPercentage < self::BANK_NAME_MATCH_PERCENTAGE)) {
                Input::merge([
                    're_validate' => 'on',
                    'applicant_type' => $app_type,
                    'application_id' => $data['applicationid'],
                    'name' => $data['name'],
                    'account_type' => $data['accounttype'],
                    'bank_name' => $data['bankname'],
                    'branch_name' => $data['branch'],
                    'account_number' => $data['accountno'],
                    'ifsc_code' => $data['ifsccode']
                ]);
                $response = $this->storeBankDetails($data['applicationid'], false);
                $response = $response->getData();
                $resultPercentage = isset($response->match_percentage->percentage) ? $response->match_percentage->percentage : 0;
                if (isset($response) && ($response->message != 'SUCCESSFUL TRANSACTION' && isset($resultPercentage))) {
                    $bankSuccess = false;
                }
            }
        }
        if (!isset($bank->id)) {
            Input::merge([
                'applicant_type' => $app_type,
                'application_id' => $data['applicationid'],
                'name' => $data['name'],
                'account_type' => $data['accounttype'],
                'bank_name' => $data['bankname'],
                'branch_name' => $data['branch'],
                'account_number' => $data['accountno'],
                'ifsc_code' => $data['ifsccode']
            ]);
            $response = $this->storeBankDetails($data['applicationid'], false);
            $response = $response->getData();
            $resultPercentage = isset($response->match_percentage->percentage) ? $response->match_percentage->percentage : 0;
            if (isset($response) && ($response->message != 'SUCCESSFUL TRANSACTION')) {
                $bankSuccess = false;
            }
        }
        return ['result' => $bankSuccess, 'percentage' => $resultPercentage];
    }

    public function storeBankDetails($id, $redirect=true)
    {
        $customer_id = Input::has('applicant_type') ? Input::get('applicant_type') : 1;
        $data['consumer_applications'] = ConsumerApplication::find($id);
        $bankDetails = Bank::where('application_id', $id)->where('applicant_type',$customer_id)->first();
        $request['consent'] = "Y";
        $request['application_id'] = $id;
        if (isset($bankDetails->id)) {
            (new ContentLogger())->logger($bankDetails, 'bank');
            $bankDetails->fill(Input::all());
            $bankDetails->bank_name = Input::get('bank_name') == 'other' ? Input::get('bank_name_text') : Input::get('bank_name');

            if (Input::has('re_validate') && Input::get('re_validate') == 'on') {
                $request['ifsc'] = Input::get('ifsc_code');
                $request['accountNumber'] = Input::get('account_number');
                $request = new Request(['data' => $request]);
                $validation_response = (new BankValidation($request))->get();
                // $validation_response = json_decode('{"requestId":"5eb4f28d-3252-4067-ad33-1ed39f5a307d","result":{"data":{"source":[{"statusAsPerSource":"VALID","data":{"accountNumber":"087401509708","ifsc":"ICIC0000874","accountName":"creditcoapp mandate","bankResponse":"SUCCESSFUL TRANSACTION","bankTxnStatus":true,"bankRRN":"336111758317","statusCode":"KC01"},"isValid":true}]},"comparisionData":[]},"statusCode":101}', true);
                // $validation_response = json_decode('{"requestId":"60414401-d358-436d-a882-97dd6692180e","result":{"data":{"source":[{"statusAsPerSource":"INVALID","data":{"accountNumber":"8740150970","ifsc":"ICIC0000874","accountName":"","bankResponse":"INVALID BENEFICIARY ACCOUNT / IFSC","bankTxnStatus":false,"bankRRN":"336112799307","statusCode":"KC03"},"isValid":false}]},"comparisionData":[]},"statusCode":101}', true);
                if ((_env('KARZA_BANK_VERSION', '')) == '3') {

                    $validation_response1['result'] = isset($validation_response['result']['data']['source'][0]['data']) ? $validation_response['result']['data']['source'][0]['data'] : $validation_response;
                    $validation_response = $validation_response1;
                    $validationAccountName = $validation_response['result']['accountName'] ?? '';
                    $fuzzyResult = (new PostApprovalController())->fuzzyComparison($validationAccountName, $customer_id == 1 ? $data['consumer_applications']->name : $data['consumer_applications']->co_applicant_name);
                }
                $bankDetails->name_match = json_encode($fuzzyResult);
                $bankDetails->karza_response = json_encode($validation_response);
            }

            $bankDetails->save();

            if($data['consumer_applications']->lender_id == Singularity::$lender_id) {
                (new HomevilleController(new Request(['id' => $id])))->updateLoanApplication();
            }

            if (!$redirect) {
                return \response()->json(['message' => $validation_response['result']['bankResponse'] ?? '', 'status' => 'OK', 'match_percentage' => isset($fuzzyResult) ? $fuzzyResult : []]);
            }
            \Session::flash('success', 'Bank details are updated!');
            return redirect()->back();
        }
        $bank = new Bank();
        $bank->fill(Input::all());

        $bank->bank_name = Input::get('bank_name') == 'other' ? Input::get('bank_name_text') : Input::get('bank_name');
        $bank->user_id = $data['consumer_applications']->user_id;
        $bank->application_id = $id;

        $request['ifsc'] = $bank->ifsc_code;
        $request['accountNumber'] = $bank->account_number;
        $request = new Request(['data' => $request]);
        $validation_response = (new BankValidation($request))->get();
        // $validation_response = json_decode('{"requestId":"5eb4f28d-3252-4067-ad33-1ed39f5a307d","result":{"data":{"source":[{"statusAsPerSource":"VALID","data":{"accountNumber":"087401509708","ifsc":"ICIC0000874","accountName":"NAVEEN KUMAR GORAKHN","bankResponse":"SUCCESSFUL TRANSACTION","bankTxnStatus":true,"bankRRN":"336111758317","statusCode":"KC01"},"isValid":true}]},"comparisionData":[]},"statusCode":101}', true);
        // $validation_response = json_decode('{"requestId":"60414401-d358-436d-a882-97dd6692180e","result":{"data":{"source":[{"statusAsPerSource":"INVALID","data":{"accountNumber":"8740150970","ifsc":"ICIC0000874","accountName":"","bankResponse":"INVALID BENEFICIARY ACCOUNT / IFSC","bankTxnStatus":false,"bankRRN":"336112799307","statusCode":"KC03"},"isValid":false}]},"comparisionData":[]},"statusCode":101}', true);
        if ((_env('KARZA_BANK_VERSION', '')) == '3') {
            $validation_response1['result'] = isset($validation_response['result']['data']['source'][0]['data']) ? $validation_response['result']['data']['source'][0]['data'] : $validation_response;
            $validation_response = $validation_response1;
            $validationAccountName = $validation_response['result']['accountName'] ?? '';
            $fuzzyResult = (new PostApprovalController())->fuzzyComparison($validationAccountName, $customer_id == 1 ? $data['consumer_applications']->name : $data['consumer_applications']->co_applicant_name);
            $bank->name_match = json_encode($fuzzyResult);
            $bank->karza_response = json_encode($validation_response);
            $bank->save();

            if($data['consumer_applications']->lender_id == Singularity::$lender_id) {
                (new HomevilleController(new Request(['id' => $id])))->updateLoanApplication();
            }

            (new ContentLogger())->logger($bank, 'bank', true);
        }
        if (isset($validation_response['result']['bankTxnStatus']) && $validation_response['result']['bankTxnStatus'] == true) {
            if (!$redirect) {
                return \response()->json(['message' => $validation_response['result']['bankResponse'] ?? '', 'status' => 'OK', 'match_percentage' => $fuzzyResult]);
            }
            \Session::flash('success', 'Bank details are added!');
            return redirect()->back();
        } else {
            if (isset($validation_response['result'])) {
                if (!$redirect) {
                    return \response()->json(['message' => $validation_response['result']['bankResponse'] ?? '', 'status' => 'FAIL']);
                }
                \Session::flash('error', isset($validation_response['result']['bankResponse']) ? $validation_response['result']['bankResponse'] : 'Can\'t validate at this time.');
                return redirect()->back();
            }
            if (!$redirect) {
                return \response()->json(['message' => $validation_response->result->bankResponse ?? '', 'status' => 'FAIL']);
            }
            \Session::flash('error', 'Bank Validation Failed. Please check details again');
            return redirect()->back();
        }
        \Session::flash('success', 'Bank details are added!');
        return redirect()->back();
    }

    public function checkTFRCondition($id) {
        $consumerApplicationElement = DB::selectOne("SELECT id, type_of_customer, solar_power_type from consumer_application_element where application_id = $id");
        if (($consumerApplicationElement->solar_power_type == 1 && $consumerApplicationElement->type_of_customer == 1) || $consumerApplicationElement->type_of_customer == 4){
            return true;
        }
        return false;
    }

}