<?php
/**
 * Created by PhpStorm.
 * User: sunil
 * Date: 16/11/18
 * Time: 11:56 AM
 */

namespace App\Http\Controllers\Grade;


use App\ABFL\Services\Services;
use App\ApprovalRule;
use App\ApprovalRuleLog;
use App\ApprovalStatusLog;
use App\ApprovedPincodeLists;
use App\AutoReject;
use App\AutoRejectRule;
use App\AutoRejectLogs;
use App\Avanse\Processes\AvanseProcesses;
use App\Avanse\Services\AvanseServices;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\ConsumerApplicationFiles;
use App\ConsumerApplicationGrade;
use App\CreditReport;
use App\DecisionTable;
use App\DocumentRule;
use App\DocumentRuleLog;
use App\DocumentSets;
use App\EPFUANLookup;
use App\Events\V1\EventTableOfOffer;
use App\FOIR;
use App\GradeLock;
use App\Grades;
use App\GradesV1;
use App\GSTPANData;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\Http\Controllers\Admin\EMICalculation;
use App\Http\Controllers\ApiController;
use App\Http\Controllers\Controller;
use App\Imports\TestImport;
use App\LendBox;
use App\MerchantOffers;
use App\PreApproval;
use App\PreApprovalLog;
use App\Products;
use App\PWAApplicationForm;
use App\ScoreCard;
use App\Slack;
use App\Comments;
use App\StatusLogs;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
use App\PreApprovalLock;
use App\AutoRejectLock;
use App\DocumentRuleLock;
use App\ProductOffers;
use App\Events\V1\EventBreApiCall;
use App\EpfFailureLog;
use Illuminate\Support\Facades\Storage;
use App\Logging\CloudWatchLoggerFactory;
use App\BreLog;
use App\JsonBreApprovalStatusLog;
use App\JWTAccess;
use Hashids\Hashids;
use App\Http\Controllers\JsonBREController;
use App\Http\Controllers\Grade\AutoRejection;
use App\LoanDecisionApprovedAmount;
use App\Http\Controllers\Admin\autoBRE;


class GradeController extends Controller
{
    use TableOfOffersTrait;

    public $applicant_type = null;
    protected $request;
    public $appId;
    public $negativeProfile = 0;
    public $checkDuplicates = 0;
    public $loan_amount = 0;
    public $tenure = 0;
    public $Atenure = [];
    public $product_loan_amount = 0;
    public $monthly_income = 0;
    public $score = 0;
    public $ageAtLastEMI = 0;
    public $age = 0;
    public $aboveThreeYear = 0;
    public $threeYear = 0;
    public $reason = null;
    public $pastDues = 0;
    public $termLoan = 0;
    public $caseType = 0;
    public $credit_limit;
    public $total_existing_emi;
    public $foirIncludingCFEMI = 0;
    public $foirNAIncludingCFEMI = 0;
    public $cfFoir = 0;
    public $closestOffer = null;
    public $closestEmi = 0;
    public $emiData = [];
    private $cf_foir = 0;
    private $lastResponse;
    protected $Acf_foir = [];
    private $foir = 0;
    protected $Afoir = [];
    private $AccountType = '';
    private $credit_limit_five_times = 0;
    private $error = 0;
    private $is_credit_card = 0;
    private $rejected = 0;
    private $employee_status = 0;
    private $bank_validation = 0;
    private $epf_verification = 0;
    private $fetch_gst = 0;
    private $amount_paid = 0;
    private $track_record = 0;
    private $amount_paid_cr = 0;
    private $guarantor = 0;
    private $dpdCountRejection = 0;
    private $address_status;
    private $downpayment;
    private $negative_area;
    protected $autoDocumentation = array();
    private $autoPreApprovalLog = array();
    private $black_list = 0;
    private $last_payment_date = 0;
    private $approved_pin = 0;
    private $approvalLogs = [];
    private $isLatestRule = false;
    private $rejectRules;
    private $bre_rules_ignored = [];
    public $powerSavingPolicyPassed = [];
    public $bureauSurrogateLimits = [];
    public $bankingPolicyPassed = [];
    public $policyPassed = [];
    public $adjustedABBMultiplier = 0;
    public $tofFoirLimit = 0;
    public $tofCfFoirLimit = 0;

    public function __construct(Request $request)
    {

        $this->request = $request;
    }

    public function index()
    {
        $grades = GradesV1::paginate(10);
        return view('admin.grade.index_v1', ['grades' => $grades]);
    }


    public function edit($id)
    {
        return $this->edit_v1($id);
        $grade = Grades::find($id);
        $grade['documentLists'] = DocumentSets::get();
        $grade['docRules'] = DocumentRule::where('grade_id', $id)->get();
        $grade['docRules'][] = array();
        $grade['preApproval'] = PreApproval::where('grade_id', $id)->get();
        $grade['preApproval'][] = array();
        $consumer_app_rule = AutoReject::where('grade_id', $id)->where('for_consumer',1)->first();
        $except_consumer_app_rule = AutoReject::where('grade_id', $id)->where('for_consumer',0)->first();
        $grade['auto_reject'] = [
            'consumer' => $consumer_app_rule,
            'ex_consumer' => $except_consumer_app_rule
        ];
        $grade['fields'] = [
            ['key' => 'min_loan_amount', 'label' => 'Min Loan Amount', 'value' => '', 'placeholder' => 'Enter Min Loan Amount', 'required' => 1],
            ['key' => 'loan_amount', 'label' => 'Max Loan Amount', 'value' => '', 'placeholder' => 'Enter Max Loan Amount', 'required' => 1],
            ['key' => 'tenure', 'label' => 'Net Tenure', 'value' => '', 'placeholder' => 'Max Tenure', 'required' => 1],
            ['key' => 'score', 'label' => 'Credit Score', 'value' => '', 'placeholder' => 'Enter Min Credit Score', 'required' => 1],
            ['key' => 'foir', 'label' => 'FOIR', 'value' => '', 'placeholder' => 'Enter Max FOIR', 'required' => 1],
            ['key' => '', 'label' => '', 'value' => '', 'placeholder' => '', 'required' => 1],
            ['key' => '', 'label' => '', 'value' => '', 'placeholder' => '', 'required' => 1],
            ['key' => '', 'label' => '', 'value' => '', 'placeholder' => '', 'required' => 1],
            ['key' => '', 'label' => '', 'value' => '', 'placeholder' => '', 'required' => 1],
        ];

        return view('admin.grade.edit_v1', ['grade' => $grade]);
    }
    /* View the edit page of a specific Grade in the new format */
    public function edit_v1($id)
    {
        $grade = GradesV1::find($id);
        $grade['documentLists'] = DocumentSets::get();
        $grade['docRules'] = DocumentRule::where('grade_id', $id)->get();
        $grade['docRules'][] = array();
        $grade['preApproval'] = PreApproval::where('grade_id', $id)->get();
        $grade['preApproval'][] = array();
        $consumer_app_rule = AutoReject::where('grade_id', $id)->where('for_consumer',1)->first();
        $except_consumer_app_rule = AutoReject::where('grade_id', $id)->where('for_consumer',0)->first();
        $grade['auto_reject'] = [
            'consumer' => $consumer_app_rule,
            'ex_consumer' => $except_consumer_app_rule
        ];

        $rules = ApprovalRule::where('grade_id', $id)->get();

        $updateFields = [];
        $allFields = $this->gradeFields();
        // $temp = [];
        foreach($rules as $rule){
            // $updateFields['status'] = $rule->status;

            $rule_details = json_decode($rule->rules);
            // $rule_details = json_decode($str);
            // $temp[$rule->rule_name]['status'] = $rule->status;
            $updateFields[$rule->rule_name] = $allFields;
            $updateFields[$rule->rule_name]['status'] = $rule->status;
            $updateFields[$rule->rule_name]['rule_name'] = ['type' => 'text', 'key' => 'rule_name', 'label' => 'Rule Name', 'value' => $rule->rule_name, 'placeholder' => '', 'title' => ''];

            foreach($rule_details as $key => $val){
                if ($key == 'is_pincode_approved') {
                    $key = 'is_pincode_approved_or_risky';
                }
                $var = $this->selectedGradeFields($key, $val);
                // $temp[$rule->rule_name]['list'][$key] = $var;
                $updateFields[$rule->rule_name][$key] = $var;
            }
        }
        // $grade['selectedFields'] = $temp;
        $grade['fields'] = $allFields;
        $grade['updateFields'] = $updateFields;
        // $rejectionJson = '{"new_rejection_rules":{"MIN_AGE":18,"MAX_AGE":75,"MONTHLY_INCOME":20000,"MIN_SCORE":300,"MAX_SCORE":740,"DPD":[{"Ownership":["individual","joint"],"rules":[{"value":"30","months":"12","operator":">=","tradelines":"1"},{"value":"60","months":"12","operator":">=","tradelines":"1"},{"value":"90","months":"36","operator":">=","tradelines":"1"}]}],"KEYWORD":[{"Ownership":["joint","individual"],"rules":[{"value":"SMA","months":"24","operator":">=","tradelines":"1"},{"value":"SUB","months":"24","operator":">=","tradelines":"1"},{"value":"LOSS","months":"24","operator":">=","tradelines":"1"},{"value":"DBT","months":"24","operator":">=","tradelines":"1"},{"value":"WOF","months":"24","operator":">=","tradelines":"1"},{"value":"SET","months":"24","operator":">=","tradelines":"1"},{"value":"WDF","months":"24","operator":">=","tradelines":"1"},{"value":"SF","months":"24","operator":">=","tradelines":"1"},{"value":"B","months":"24","operator":">=","tradelines":"1"},{"value":"D","months":"24","operator":">=","tradelines":"1"},{"value":"L","months":"24","operator":">=","tradelines":"1"},{"value":"M","months":"24","operator":">=","tradelines":"1"}]}],"PRINCIPAL_WRITTEN_OFF_AMOUNT":[{"Ownership":["guarantor"],"rules":[{"value":5000,"months":12}]}],"ACCOUNT_STATUS":[{"Ownership":["individual","joint"],"rules":[{"value":"Default","months":"24"},{"value":"Restructured","months":"24"},{"value":"Suit filed","months":"*"},{"value":"Wilful Default","months":"*"},{"value":"Suit filed (Wilful Default)","months":"*"},{"value":"Written Off","months":"24"},{"value":"Suit Filed & Written Off","months":"*"},{"value":"Wilful Default & Written Off","months":"*"},{"value":"Suit Filed (Wilful Default) & Written Off","months":"*"},{"value":"Written Off","months":"24"},{"value":"Settled","months":"24"},{"value":"Post (WO) Settled","months":"24"},{"value":"Post Write Off Closed","months":"24"},{"value":"Post Written Off Settled","months":"24"},{"value":"Restructured due to COVID-19","months":"24"},{"value":"Written Off and Account Sold","months":"24"},{"value":"Account Purchased and Written Off","months":"24"},{"value":"Account Purchased and Settled","months":"24"},{"value":"Account Purchased and Restructured","months":"24"},{"value":"Restructured due to Natural Calamity","months":"24"},{"value":"Doubtful","months":"24"},{"value":"Loss","months":"24"},{"value":"Special Mention","months":"24"},{"value":"First Payment Default","months":"24"},{"value":"Charge Off/Written Off","months":"24"},{"value":"Loan Declined","months":"24"},{"value":"Closed Account/ Unpaid Final Bill","months":"24"},{"value":"Account is Inactive","months":"24"},{"value":"Loan Submitted","months":"24"},{"value":"Included in Bankruptcy","months":"24"}]}],"TOTAL_PAST_DUES":[{"Ownership":["individual","joint"],"rules":[{"value":"300","account_type":"Credit Card","months":"3"},{"value":"300","account_type":"Auto Loan","months":"3"},{"value":"300","account_type":"Housing Loan","months":"3"},{"value":"300","account_type":"Property Loan","months":"3"},{"value":"300","account_type":"Loan Against Shares / Securities","months":"3"},{"value":"300","account_type":"Personal Loan","months":"3"},{"value":"300","account_type":"Consumer Loan","months":"3"},{"value":"300","account_type":"Gold Loan","months":"3"},{"value":"300","account_type":"Education Loan","months":"3"},{"value":"300","account_type":"Loan to Professional","months":"3"},{"value":"300","account_type":"Credit Card","months":"3"},{"value":"300","account_type":"Leasing","months":"3"},{"value":"300","account_type":"Overdraft","months":"3"},{"value":"300","account_type":"Two-wheeler Loan","months":"3"},{"value":"300","account_type":"Non-Funded Credit Facility","months":"3"},{"value":"300","account_type":"Loan against Bank Deposits","months":"3"},{"value":"300","account_type":"Fleet Card","months":"3"},{"value":"300","account_type":"Commercial Vehicle Loan","months":"3"},{"value":"300","account_type":"Telco - Wireless","months":"3"},{"value":"300","account_type":"Telco - Broadband","months":"3"},{"value":"300","account_type":"Telco - Landline","months":"3"},{"value":"300","account_type":"Seller Financing","months":"3"},{"value":"300","account_type":"Seller Financing Soft Enquiry","months":"3"},{"value":"300","account_type":"GECL Loan Secured","months":"3"},{"value":"300","account_type":"GECL Loan UnSecured","months":"3"},{"value":"300","account_type":"Loan on Credit Card","months":"3"},{"value":"300","account_type":"Prime Minister Jaan Dhan Yojana - Overdraft","months":"3"},{"value":"300","account_type":"Mudra Loans – Shishu / Kishor / Tarun","months":"3"},{"value":"300","account_type":"Insurance","months":"3"},{"value":"300","account_type":"Short Term Personal Loan [Unsecured]","months":"3"},{"value":"300","account_type":"Priority Sector- Gold Loan [Secured]","months":"3"},{"value":"300","account_type":"Secured Credit Card","months":"3"},{"value":"300","account_type":"Used Car Loan","months":"3"},{"value":"300","account_type":"Construction Equipment Loan","months":"3"},{"value":"300","account_type":"Tractor Loan","months":"3"},{"value":"300","account_type":"Corporate Credit Card","months":"3"},{"value":"300","account_type":"Kisan Credit Card","months":"3"},{"value":"300","account_type":"Microfinance – Business Loan","months":"3"},{"value":"300","account_type":"Microfinance – Personal Loan","months":"3"},{"value":"300","account_type":"Microfinance – Housing Loan","months":"3"},{"value":"300","account_type":"Microfinance – Others","months":"3"},{"value":"300","account_type":"Pradhan Mantri Awas Yojana - Credit Link Subsidy Scheme MAY CLSS","months":"3"},{"value":"300","account_type":"P2P Personal Loan","months":"3"},{"value":"300","account_type":"P2P Auto Loan","months":"3"},{"value":"300","account_type":"P2P Education Loan","months":"3"},{"value":"300","account_type":"Business Loan – Secured","months":"3"},{"value":"300","account_type":"Business Loan – General","months":"3"},{"value":"300","account_type":"Business Loan - Unsecured","months":"3"},{"value":"300","account_type":"Temporary Overdraft [Unsecured]","months":"3"},{"value":"300","account_type":"Business Loan-Priority Sector-Small Business","months":"3"},{"value":"300","account_type":"Business Loan - Priority Sector- Agriculture","months":"3"},{"value":"300","account_type":"Business Loan - Priority Sector- Others","months":"3"},{"value":"300","account_type":"Business Non-Funded Credit Facility – General","months":"3"},{"value":"300","account_type":"Business Non-Funded Credit Facility - Priority Sector - Small Business","months":"3"},{"value":"300","account_type":"Business Non-Funded Credit Facility - Priority Sector - Agriculture","months":"3"},{"value":"300","account_type":"Business Non-Funded Credit Facility - Priority Sector - Other","months":"3"},{"value":"300","account_type":"Business Loan Against Bank Deposits","months":"3"},{"value":"300","account_type":"Working Capital Loan","months":"3"},{"value":"300","account_type":"Agriculture Loan","months":"3"},{"value":"300","account_type":"Commercial Equipment Loan","months":"3"},{"value":"300","account_type":"Auto Overdraft","months":"3"},{"value":"300","account_type":"Loan against Card","months":"3"},{"value":"300","account_type":"Auto Lease","months":"3"},{"value":"300","account_type":"BUSINESS LOAN - DIRECTOR SEARCH-Soft Enquiry - Score Unaffected","months":"3"},{"value":"300","account_type":"Dispute Resolution - CIR","months":"3"}]}],"NACH_BOUNCE":[{"Ownership":[],"rules":[{"operator":">","value":"1","months":"3"}]}],"APPROVED_PINCODE":true,"NEGATIVE_AREA":true}}';
        $applicantRules = AutoRejectRule::where(['grade_id' => $id, 'applicant_type' => 1, 'status' => 1])->orderBy('created_at', 'desc')->first(['modifications']);
        $coApplicantRules = AutoRejectRule::where(['grade_id' => $id, 'applicant_type' => 2, 'status' => 1])->orderBy('created_at', 'desc')->first(['modifications']);

        // Backward compatibility: If no applicant type rules found, check for the old flat records
        if (!$applicantRules) {
            $applicantRules = AutoRejectRule::where(['grade_id' => $id, 'status' => 1])->whereNull('applicant_type')->orderBy('created_at', 'desc')->first(['modifications']);
        }

        $defaultJson = '{"new_rejection_rules":{"MIN_AGE":null,"MAX_AGE":null,"MONTHLY_INCOME":null,"MIN_SCORE":null,"MAX_SCORE":null,"DPD":[{"ownership":[],"rules":[{"value":"","months":"","operator":"","tradelines":""}]}],"KEYWORD":[{"ownership":[],"rules":[{"value":"","months":"","operator":"","tradelines":""}]}],"PRINCIPAL_WRITTEN_OFF_AMOUNT":[{"ownership":[],"rules":[{"value":null,"months":null}]}],"ACCOUNT_STATUS":[{"ownership":[],"rules":[{"value":"","months":""}]}],"TOTAL_PAST_DUES":[{"ownership":[],"rules":[{"value":"","account_type":"","months":""}]}],"NACH_BOUNCE":[{"ownership":[],"rules":[{"operator":"","value":"","months":""}]}],"APPROVED_PINCODE":false,"NEGATIVE_AREA":false}}';
        
        $coApplicantIncomeJson = $defaultJson;
        $coApplicantSigningJson = $defaultJson;

        if (isset($coApplicantRules->modifications)) {
            $modData = json_decode($coApplicantRules->modifications, true);
            $coApplicantIncomeJson = isset($modData['co_applicant_for_income']) ? json_encode($modData['co_applicant_for_income']) : $defaultJson;
            $coApplicantSigningJson = isset($modData['co_applicant_for_signing']) ? json_encode($modData['co_applicant_for_signing']) : $defaultJson;
            
            // Backward compatibility: if it's the old flat structure, put it in income
            if (!isset($modData['co_applicant_for_income']) && !isset($modData['co_applicant_for_signing'])) {
                $coApplicantIncomeJson = $coApplicantRules->modifications;
            }
        }

        return view('admin.grade.edit_v1', [
            'grade' => $grade, 
            'applicant_rejection_json' => isset($applicantRules->modifications) ? $applicantRules->modifications : $defaultJson,
            'co_applicant_income_rejection_json' => $coApplicantIncomeJson,
            'co_applicant_signing_rejection_json' => $coApplicantSigningJson
        ]);
    }
    /* Dynamic population of fields for existing rules */
    public function selectedGradeFields($key, $val){
        switch($key){
            case 'thin_file':
                return ['type' => 'checkbox', 'key' => 'thin_file', 'label' => 'Thin File', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'All the applications with bureau scores between -1 and 10 are to be considered as thin file and pass, else fail'];
            case 'min_net_loan_amount':
                return ['type' => 'text', 'key' => 'min_net_loan_amount', 'label' => 'Min Net Loan Amount', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s net loan amount >= Min net loan amount, then the rule has passed, else fail'];
            case 'max_net_loan_amount':
                return ['type' => 'text', 'key' => 'max_net_loan_amount', 'label' => 'Max Net Loan Amount', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s net loan amount <= Max net loan amount, then the rule has passed, else fail'];
            case 'foir':
                return ['type' => 'text', 'key' => 'foir', 'label' => 'FOIR', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s FOIR > max FOIR, then the rule has failed, else pass'];
            case 'cf_foir':
                return ['type' => 'text', 'key' => 'cf_foir', 'label' => 'CF FOIR', 'value' => $val ?? '', 'placeholder' => '',
                    'title'=> 'If the application’s CF FOIR > max CF FOIR, then the rule has failed, else pass'];
            case 'min_net_tenure':
                return ['type' => 'text', 'key' => 'min_net_tenure', 'label' => 'Min Net Tenure', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s net tenure <= Min Net Tenure, then the rule has passed, else fail'];
            case 'max_net_tenure':
                return ['type' => 'text', 'key' => 'max_net_tenure', 'label' => 'Max Net Tenure', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s net tenure <= Max Net Tenure, then the rule has passed, else fail'];
            case 'score':
                return ['type' => 'text', 'key' => 'score', 'label' => 'Credit Score', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s bureau score >= Min Credit Score, then pass else fail. If the value is null, then the rule is to be skipped'];
            case 'employee_status':
                return ['type' => 'select', 'key' => 'employee_status', 'label' => 'Employee Status', 'value' => $val, 'placeholder' => '',
                    'title' => 'If the application’s employment is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'];
            case 'solar_financing_for':
                return ['type' => 'select', 'key' => 'solar_financing_for', 'label' => 'Solar Financing For', 'value' => $val, 'placeholder' => '',
                    'title' => 'If the application’s solar financing for is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'];
            case 'solar_power_type':
                return ['type' => 'select', 'key' => 'solar_power_type', 'label' => 'Solar Power Type', 'value' => $val, 'placeholder' => '',
                    'title' => 'If the application’s solar power type is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'];
            case 'monthly_income':
                return ['type' => 'text', 'key' => 'monthly_income', 'label' => 'Monthly Income', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s monthly income >= Monthly Income, then the rule has passed, else fail'];
            case 'age':
                return ['type' => 'text', 'key' => 'age', 'label' => 'Minimum Age', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'];
            case 'age_salaried':
                return ['type' => 'range', 'key' => 'age_salaried', 'label' => 'Age (Salaried)', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application with employment type salaried has age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'];
            case 'age_self_employed':
                return ['type' => 'range', 'key' => 'age_self_employed', 'label' => 'Age (Self Employed & Business)', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application with employment type self employed has age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'];
            case 'ageAtLastEMI':
                return ['type' => 'text', 'key' => 'ageAtLastEMI', 'label' => 'Age at Last EMI', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If this age is > input then fail, else pass. If the field is blank, then the rule is to be skipped'];
            case 'term_loan_amount_paid':
                return ['type' => 'text', 'key' => 'term_loan_amount_paid', 'label' => '(Term Loan) Amount Should be Paid (%)', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Loan period is > 0 Years. Loan is either [Auto Loan, Housing Loan, Personal Loan, Consumer Loan, Education Loan, Loan to Professional, Two-wheeler Loan, Commercial Vehicle Loan, Used Car Loan, Business Loan-Priority Sector-Small Business, Business Loan - Priority Sector- Agriculture, Business Loan - Priority Sector- Others, Business Non-Funded Credit Facility, Business Non-Funded Credit Facility - Priority, Staff Loan]. The loan should be active/open. If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail. If the input in the field is not present, then the rule is to be skipped'];
            case 'credit_card_amount_paid':
                return ['type' => 'text', 'key' => 'credit_card_amount_paid', 'label' => '(Credit Card) Amount Should be Paid (%)', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail. If the input in the field is not present, then the rule is to be skipped'];
            case 'epf_verification':
                return ['type' => 'checkbox', 'key' => 'epf_verification', 'label' => 'EPF Employment Verification', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If EPF verification is checked then in the EPF-report check if all the below conditions are true as per current employer data. 1) Is Employed 2) Is Recent; then the application has passed, else fail. If the field is not checked then the rule is to be skipped.'];
            case 'fetch_gst':
                return ['type' => 'checkbox', 'key' => 'fetch_gst', 'label' => 'Fetch GST Number using PAN', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If GST verification is checked then if both of the below conditions is true: 1] If applicant’s employment type is business, self employed - business, self employed - professional. 2] GST authStatus is ‘Inactive’; then the case has failed, else pass. If the field is not checked, then the rule is to be skipped'];
            case 'is_pincode_approved_or_risky':
                return ['type' => 'checkbox', 'key' => 'is_pincode_approved_or_risky', 'label' => 'Pincode Approval / Risky Pincode', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the Pincode approval is checked, then if both the condition is true: 1] If current address pincode is part of the approved or risky pincode list. 2] If permanent address pincode is past of the approved or risky pincode list; Then the case has passed, else failed. If the field is not checked, then the rule is to be skipped'];
            case 'negative_area':
                return ['type' => 'checkbox', 'key' => 'negative_area', 'label' => 'Negative Area', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If application’s current address / applications permanent address / co-applications address is part of the level 1 negative area list, then fail else pass. If the field is not checked, then the rule is to be skipped.'];
            case 'rejected':
                return ['type' => 'checkbox', 'key' => 'rejected', 'label' => 'Rejected', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application is ever aborted or rejected, then case has failed, else pass. If the field is not checked, then the rule is to be skipped'];
            case 'guarantor':
                return ['type' => 'checkbox', 'key' => 'guarantor', 'label' => 'Guarantor', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application has zero loans, then pass. If the application has at least 1 non-guarantor loan then pass else fail. If the field is not checked, then the rule is to be skipped'];
            case 'check_duplicates':
                return ['type' => 'checkbox', 'key' => 'check_duplicates', 'label' => 'De-Dupe Check', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s PAN card / Mobile Number / Email ID is present previously then the case has failed, else pass. If the field is not checked, then the rule is to be skipped'];
            case 'accountType':
                return ['type' => 'checkbox', 'key' => 'accountType', 'label' => 'AccountType', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If >= 3 open gold loans are present then fail, else pass. If the field is not checked, then the rule is to be skipped'];

            case 'no_owned_house':
                return ['type' => 'checkbox', 'key' => 'no_owned_house', 'label' => 'No Owned House', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If current address is not present OR Else If current address is present but isn’t: 1] OWNED 2] PARENTS HOUSE 3] Self Owned 4] Parent Owned; Then fail, else pass. If the field is not checked, then the rule is to be skipped'];
            case 'zero_downpayment':
                return ['type' => 'checkbox', 'key' => 'zero_downpayment', 'label' => 'Zero Downpayment', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If EMI is not generated, then mention reason as “EMI not generated” and fail Else if EMI is generated and upfront from customer is <= 0, then fail as “zero downpayment” Else Pass. If the field is not checked, then the rule is to be skipped'];
            case 'e_bill_fuzzy_match':
                return ['type' => 'text', 'key' => 'e_bill_fuzzy_match', 'label' => 'E-Bill Fuzzy Match', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Fuzzy match percentage for E-Bill'];
            case 'kw_capping':
                return ['type' => 'checkbox', 'key' => 'kw_capping', 'label' => 'KW Capping', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'KW Capping amount'];
            case 'caseType':
                return ['type' => 'text', 'key' => 'caseType', 'label' => 'Case Type', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If any of the mentioned values are present in the DPD of the tradeline then fail, else pass. If the field is blank, then the rule is to be skipped. Eg. Inputs -> PWOS,SET'];
            case 'bureau_surrogate':
                return ['type' => 'popup', 'key' => 'bureau_surrogate', 'label' => 'Surrogate', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => ''];
            case 'dpd_years_above_zero':
                return ['type' => 'number', 'key' => 'dpd_years_above_zero', 'label' => 'Years in 0+ DPD', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Number of years to count 0+ DPD'];
            case 'dpd_count_above_zero':
                return ['type' => 'number', 'key' => 'dpd_count_above_zero', 'label' => 'Count of 0+ DPD', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Count of the number of times DPD > 0 in last[years]. If the fields are blank, then the rule is to be skipped'];
            case 'pre_dpd_years':
                return ['type' => 'number', 'key' => 'pre_dpd_years', 'label' => 'Pre-DPD Years', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Number of years within which DPD is to be counted'];
            case 'pre_dpd_count':
                return ['type' => 'number', 'key' => 'pre_dpd_count', 'label' => 'Pre-DPD Count', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Count of DPD within the mentioned years'];
            case 'post_dpd_year':
                return ['type' => 'number', 'key' => 'post_dpd_year', 'label' => 'Post-DPD Years', 'value' => $val ?? '', 'placeholder' => '',
                'title' => 'Number of years above which DPD is to be counted'];
            case 'post_dpd_count':
                return ['type' => 'number', 'key' => 'post_dpd_count', 'label' => 'Post-DPD Count', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'Count of DPD above the mentioned years'];
            case 'pre_dpd_keywords':
                return ['type' => 'text', 'key' => 'pre_dpd_keywords', 'label' => 'Pre-DPD Keywords', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'List of keywords to exclude while counting dpd within the specified number of years'];
            case 'power_savings':
                return ['type' => 'checkbox', 'key' => 'power_savings', 'label' => 'Power Savings', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'EMI should be less than or equal to the power saving'];
            case 'min_banking_months':
                return [
                    'type' => 'text', 
                    'key' => 'min_banking_months', 
                    'label' => 'Min Banking Months', 
                    'value' => $val ?? '', 
                    'placeholder' => 'e.g. 6',
                    'title' => 'Configure no. of months to evaluate minimum banking history. If Banking months >= configured value then rule will Pass, If Banking months < configured value then rule will Fail'
                ];
            case 'name_match_threshold_pct':
                return [
                    'type' => 'text', 
                    'key' => 'name_match_threshold_pct', 
                    'label' => 'A/c Name Match %', 
                    'value' => $val ?? '', 
                    'placeholder' => 'e.g. 80',
                    'title' => 'Fuzzy match percentage between bank account holder name and applicant name. If Match% >= threshold then rule will Pass, if Match% < threshold then rule will Fail'
                ];
            case 'emi_bounce_rule':
                $values = is_string($val) ? json_decode($val, true) : (array)$val;
                
                return [
                    'type' => 'double_input', 
                    'key' => 'emi_bounce_rule',
                    'label' => 'EMI Bounce Rule',
                    'value' => [
                        'max_emi_bounces' => $values['max_emi_bounces'] ?? '',
                        'emi_bounce_lookback_months' => $values['emi_bounce_lookback_months'] ?? ''
                    ],
                    'placeholder' => '',
                    'title' => 'Checks the Number of EMI bounces in the defined period. If EMI bounces <= configured limit then rule will Pass, If EMI bounces > configured limit then rule will Fail'
                ];
            case 'speculative_txn_cap_pct':
                return [
                    'type' => 'text', 
                    'key' => 'speculative_txn_cap_pct', 
                    'label' => 'Speculative Txn Cap (%)', 
                    'value' => $val ?? '', 
                    'placeholder' => 'e.g. 10%',
                    'title' => 'Checks if there is any speculative transaction. If Speculative % <= cap then the rule is Pass, if Speculative % > cap then the rule is Fail'
                ];
            case 'emi_multiplier_on_abb':
                return [
                    'type' => 'text', 
                    'key' => 'emi_multiplier_on_abb', 
                    'label' => 'EMI Multiplier on ABB', 
                    'value' => $val ?? '', 
                    'placeholder' => 'e.g. 0.5x',
                    'title' => 'Eligible loan amount derived based on EMI & tenure'
                ];
            case 'post_dpd_keywords':
                return ['type' => 'text', 'key' => 'post_dpd_keywords', 'label' => 'Post-DPD Keywords', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'List of keywords to exclude while counting dpd within the specified number of years'];
            case 'track_record':
                return ['type' => 'popup', 'key' => 'track_record', 'label' => 'Track Record', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => '1] Loans with Ownership as Individual which are not closed OR the loan is closed in the last 3 year. 2] No open loan in the last 6 months with account type Credit card OR Gold Loan OR Loan against Shares/Securities; If the field is not checked, then the rule is to be skipped.'];
            case 'bank_validation':
                return ['type' => 'text', 'key' => 'bank_validation', 'label' => 'Bank Validation', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => ''];
            case 'dpd_rules':
                return ['type' => 'module', 'key' => 'dpd_rules', 'label' => 'DPD', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the module is active then the set of rules are checked else skipped'];
            case 'keyword_rules':
                return ['type' => 'module', 'key' => 'keyword_rules', 'label' => 'Keyword', 'value' => $val ?? '', 'placeholder' => '',
                        'title' => 'If the module is active then the set of rules are checked else skipped'];
            case 'account_status_rules':
                return ['type' => 'module', 'key' => 'account_status_rules', 'label' => 'Account Status', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the module is active then the set of rules are checked else skipped'];
            case 'principal_written_off_rules':
                return ['type' => 'module', 'key' => 'principal_written_off_rules', 'label' => 'Principal Written Off', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the module is active then the set of rules are checked else skipped'];
            case 'past_dues_rules':
                return ['type' => 'module', 'key' => 'past_dues_rules', 'label' => 'Past Dues', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the module is active then the set of rules are checked else skipped'];
            default:
                return 'true';
        }
    }
    public function gradeFields(){
        $list = [
            'rule_name' => ['type' => 'text', 'key' => 'rule_name', 'label' => 'Rule Name', 'value' => '', 'placeholder' => '', 'title' => ''],
            'thin_file' => ['type' => 'checkbox', 'key' => 'thin_file', 'label' => 'Thin File', 'value' => '', 'placeholder' => '',
                    'title' => 'All the applications with bureau scores between -1 and 10 are to be considered as thin file and pass, else fail'],
            'min_net_loan_amount' => ['type' => 'text', 'key' => 'min_net_loan_amount', 'label' => 'Min Net Loan Amount', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s loan amount >= Min loan amount, then the rule has passed, else fail'],
            'max_net_loan_amount' => ['type' => 'text', 'key' => 'max_net_loan_amount', 'label' => 'Max Net Loan Amount', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s loan amount <= Max loan amount, then the rule has passed, else fail'],
            'foir' => ['type' => 'text', 'key' => 'foir', 'label' => 'FOIR', 'value' => '', 'placeholder' => '', 'title' =>
                'If the application’s FOIR > max FOIR, then the rule has failed, else pass'],
            'cf_foir' => ['type' => 'text', 'key' => 'cf_foir', 'label' => 'CF FOIR', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s CF FOIR > max CF FOIR, then the rule has failed, else pass'],
            'min_net_tenure' => ['type' => 'text', 'key' => 'min_net_tenure', 'label' => 'Min Net Tenure', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s net tenure <= net tenure field, then the rule has passed, else fail'],
            'max_net_tenure' => ['type' => 'text', 'key' => 'max_net_tenure', 'label' => 'Max Net Tenure', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s net tenure <= Max Net Tenure, then the rule has passed, else fail'],
            'score' => ['type' => 'text', 'key' => 'score', 'label' => 'Credit Score', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s bureau score >= Min Credit Score, then pass else fail. If the value is null, then the rule is to be skipped'],
            'employee_status' => ['type' => 'select', 'key' => 'employee_status', 'label' => 'Employee Status', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s employment is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'],
            'solar_financing_for' => ['type' => 'select', 'key' => 'solar_financing_for', 'label' => 'Solar Financing For', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s solar financing for is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'],
            'solar_power_type' => ['type' => 'select', 'key' => 'solar_power_type', 'label' => 'Solar Power Type', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s solar power type is present in the selected dropdown, then the rule is passed else fail. If none are selected in the dropdown, then this rule is to be skipped'],
            'monthly_income' => ['type' => 'text', 'key' => 'monthly_income', 'label' => 'Monthly Income', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s monthly income >= Monthly Income, then the rule has passed, else fail'],
            'age' => ['type' => 'text', 'key' => 'age', 'label' => 'Minimum Age', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'],
            'age_salaried' => ['type' => 'range', 'key' => 'age_salaried', 'label' => 'Age (Salaried)', 'value' => '', 'placeholder' => '',
                'title' => 'If the application with employment type salaried has age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'],
            'age_self_employed' => ['type' => 'range', 'key' => 'age_self_employed', 'label' => 'Age (Self Employed & Business)', 'value' => '', 'placeholder' => '',
                'title' => 'If the application with employment type self employed has age >= Min Age, then pass else fail. If the value is null, then the rule is to be skipped'],
            'e_bill_fuzzy_match' => ['type' => 'text', 'key' => 'e_bill_fuzzy_match', 'label' => 'E-Bill Fuzzy Match', 'value' => '', 'placeholder' => '',
                'title' => 'Fuzzy match percentage for E-Bill'],
            'kw_capping' => ['type' => 'checkbox', 'key' => 'kw_capping', 'label' => 'KW Capping', 'value' => '', 'placeholder' => '',
                'title' => 'KW Capping amount'],
            'ageAtLastEMI' => ['type' => 'text', 'key' => 'ageAtLastEMI', 'label' => 'Age at Last EMI', 'value' => '', 'placeholder' => '',
                'title' => 'If this age is > input then fail, else pass. If the field is blank, then the rule is to be skipped'],
            'term_loan_amount_paid' => ['type' => 'text', 'key' => 'term_loan_amount_paid', 'label' => '(Term Loan) Amount Should be Paid (%)', 'value' => '', 'placeholder' => '',
                'title' => 'Loan period is > 0 Years. Loan is either [Auto Loan, Housing Loan, Personal Loan, Consumer Loan, Education Loan, Loan to Professional, Two-wheeler Loan, Commercial Vehicle Loan, Used Car Loan, Business Loan-Priority Sector-Small Business, Business Loan - Priority Sector- Agriculture, Business Loan - Priority Sector- Others, Business Non-Funded Credit Facility, Business Non-Funded Credit Facility - Priority, Staff Loan]. The loan should be active/open. If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail. If the input in the field is not present, then the rule is to be skipped'],
            'credit_card_amount_paid' => ['type' => 'text', 'key' => 'credit_card_amount_paid', 'label' => '(Credit Card) Amount Should be Paid (%)', 'value' => '', 'placeholder' => '',
                'title' => 'If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail. If the input in the field is not present, then the rule is to be skipped'],
            'epf_verification' => ['type' => 'checkbox', 'key' => 'epf_verification', 'label' => 'EPF Employment Verification', 'value' => '', 'placeholder' => '',
                'title' => 'If EPF verification is checked then in the EPF-report check if all the below conditions are true as per current employer data. 1) Is Employed 2) Is Recent; then the application has passed, else fail. If the field is not checked then the rule is to be skipped.'],
            'fetch_gst' => ['type' => 'checkbox', 'key' => 'fetch_gst', 'label' => 'Fetch GST Number using PAN', 'value' => '', 'placeholder' => '',
                'title' => 'If GST verification is checked then if both of the below conditions is true: 1] If applicant’s employment type is business, self employed - business, self employed - professional. 2] GST authStatus is ‘Inactive’; then the case has failed, else pass. If the field is not checked, then the rule is to be skipped'],
            'is_pincode_approved_or_risky' => ['type' => 'checkbox', 'key' => 'is_pincode_approved_or_risky', 'label' => 'Pincode Approval / Risky Pincode', 'value' => '', 'placeholder' => '',
                'title' => 'If the Pincode approval is checked, then if both the condition is true: 1] If current address pincode is part of the approved or risky pincode list. 2] If permanent address pincode is past of the approved or risky pincode list; Then the case has passed, else failed. If the field is not checked, then the rule is to be skipped'],
            'negative_area' => ['type' => 'checkbox', 'key' => 'negative_area', 'label' => 'Negative Area', 'value' => '', 'placeholder' => '',
                'title' => 'If application’s current address / applications permanent address / co-applications address is part of the level 1 negative area list, then fail else pass. If the field is not checked, then the rule is to be skipped'],
            'rejected' => ['type' => 'checkbox', 'key' => 'rejected', 'label' => 'Rejected', 'value' => '', 'placeholder' => '',
                'title' => 'If the application is ever aborted or rejected, then case has failed, else pass. If the field is not checked, then the rule is to be skipped'],
            'guarantor' => ['type' => 'checkbox', 'key' => 'guarantor', 'label' => 'Guarantor', 'value' => '', 'placeholder' => '',
                'title' => 'If the application has zero loans, then pass. If the application has at least 1 non-guarantor loan then pass else fail. If the field is not checked, then the rule is to be skipped'],
            'check_duplicates' => ['type' => 'checkbox', 'key' => 'check_duplicates', 'label' => 'De-Dupe Check', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s PAN card / Mobile Number / Email ID is present previously then the case has failed, else pass. If the field is not checked, then the rule is to be skipped'],
            'accountType' => ['type' => 'checkbox', 'key' => 'accountType', 'label' => 'AccountType', 'value' => '', 'placeholder' => '',
                'title' => 'If >= 3 open gold loans are present then fail, else pass. If the field is not checked, then the rule is to be skipped'],
            'no_owned_house' => ['type' => 'checkbox', 'key' => 'no_owned_house', 'label' => 'No Owned House', 'value' => '', 'placeholder' => '',
                'title' => 'If current address is not present OR Else If current address is present but isn’t: 1] OWNED 2] PARENTS HOUSE 3] Self Owned 4] Parent Owned; Then fail, else pass. If the field is not checked, then the rule is to be skipped' ],
            'zero_downpayment' => ['type' => 'checkbox', 'key' => 'zero_downpayment', 'label' => 'Zero Downpayment', 'value' => '', 'placeholder' => '',
                'title' => 'If EMI is not generated, then mention reason as “EMI not generated” and fail Else if EMI is generated and upfront from customer is <= 0, then fail as “zero downpayment” Else Pass. If the field is not checked, then the rule is to be skipped'],
            'caseType' => ['type' => 'text', 'key' => 'caseType', 'label' => 'Case Type', 'value' => '', 'placeholder' => '',
                'title' => 'If any of the mentioned values are present in the DPD of the tradeline then fail, else pass. If the field is blank, then the rule is to be skipped. Eg. Inputs -> PWOS,SET'],
            'bureau_surrogate' => ['type' => 'popup', 'key' => 'bureau_surrogate', 'label' => 'Surrogate', 'value' => '', 'placeholder' => '',
                'title' => 'Requested amount <= x% of the sanctioned amount for any HL, AL, & BL opened in L12M or closed in L60M'],
            'dpd_years_above_zero' => ['type' => 'number', 'key' => 'dpd_years_above_zero', 'label' => 'Years in 0+ DPD', 'value' => '', 'placeholder' => '',
                'title' => 'Number of years to count 0+ DPD'],
            'dpd_count_above_zero' => ['type' => 'number', 'key' => 'dpd_count_above_zero', 'label' => 'Count of 0+ DPD', 'value' => '', 'placeholder' => '',
                'title' => 'Count of the number of times DPD > 0 in last[years]. If the fields are blank, then the rule is to be skipped'],
            'pre_dpd_years' => ['type' => 'number', 'key' => 'pre_dpd_years', 'label' => 'Pre-DPD Years', 'value' => '', 'placeholder' => '',
                'title' => 'Number of years within which DPD is to be counted'],
            'pre_dpd_count' => ['type' => 'number', 'key' => 'pre_dpd_count', 'label' => 'Pre-DPD Count', 'value' => '', 'placeholder' => '',
                'title' => 'Count of DPD within the mentioned years'],
            'post_dpd_year' => ['type' => 'number', 'key' => 'post_dpd_year', 'label' => 'Post-DPD Years', 'value' => '', 'placeholder' => '',
                'title' => 'Number of years above which DPD is to be counted'],
            'post_dpd_count' => ['type' => 'number', 'key' => 'post_dpd_count', 'label' => 'Post-DPD Count', 'value' => '', 'placeholder' => '',
                'title' => 'Count of DPD above the mentioned years'],
            'pre_dpd_keywords' => ['type' => 'text', 'key' => 'pre_dpd_keywords', 'label' => 'Pre-DPD Keywords', 'value' => '', 'placeholder' => '',
                'title' => 'List of keywords to exclude while counting dpd within the specified number of years'],
            'post_dpd_keywords' => ['type' => 'text', 'key' => 'post_dpd_keywords', 'label' => 'Post-DPD Keywords', 'value' => '', 'placeholder' => '',
                'title' => 'List of keywords to exclude while counting dpd within the specified number of years'],
            'power_savings' => ['type' => 'checkbox', 'key' => 'power_savings', 'label' => 'Power Savings', 'value' => '', 'placeholder' => '',
                'title' => 'EMI should be less than or equal to the power saving'],
            'track_record' => ['type' => 'popup', 'key' => 'track_record', 'label' => 'Track Record', 'value' => '', 'placeholder' => '',
                'title' => '1] Loans with Ownership as Individual which are not closed OR the loan is closed in the last 3 year. 2] No open loan in the last 6 months with account type Credit card OR Gold Loan OR Loan against Shares/Securities; If the field is not checked, then the rule is to be skipped.'],
            'bank_validation' => ['type' => 'text', 'key' => 'bank_validation', 'label' => 'Bank Validation', 'value' => '', 'placeholder' => '',
                'title' => ''],
            'min_banking_months' => [
                    'type' => 'text', 
                    'key' => 'min_banking_months', 
                    'label' => 'Min Banking Months', 
                    'value' => '', 
                    'placeholder' => 'e.g. 6', 
                    'title' => 'Configure no. of months to evaluate minimum banking history. If Banking months >= configured value then rule will Pass, If Banking months < configured value then rule will Fail'
                ],
            'name_match_threshold_pct' => [
                    'type' => 'text', 
                    'key' => 'name_match_threshold_pct', 
                    'label' => 'A/c Name Match %', 
                    'value' => '', 
                    'placeholder' => 'e.g. 80', 
                    'title' => 'Fuzzy match percentage between bank account holder name and applicant name. If Match% >= threshold then rule will Pass, if Match% < threshold then rule will Fail'
                ],
            'speculative_txn_cap_pct' => [
                    'type' => 'text', 
                    'key' => 'speculative_txn_cap_pct', 
                    'label' => 'Speculative Txn Cap (%)', 
                    'value' => '', 
                    'placeholder' => 'e.g. 10', 
                    'title' => 'Checks if there is any speculative transaction. If Speculative % <= cap then the rule is Pass, if Speculative % > cap then the rule is Fail'
                ],
            'emi_bounce_rule' => [
                    'type' => 'double_input', 
                    'key' => 'emi_bounce_rule',
                    'label' => 'EMI Bounce Rule',
                    'value' => [
                        'max_emi_bounces' => '',           
                        'emi_bounce_lookback_months' => ''
                    ], 
                    'placeholder' => '', 
                    'title' => 'Checks the Number of EMI bounces in the defined period. If EMI bounces <= configured limit then rule will Pass, If EMI bounces > configured limit then rule will Fail'
                ],
            'emi_multiplier_on_abb' => [
                    'type' => 'text', 
                    'key' => 'emi_multiplier_on_abb', 
                    'label' => 'EMI Multiplier on ABB', 
                    'value' => '', 
                    'placeholder' => 'e.g. 0.5', 
                    'title' => 'Eligible loan amount derived based on EMI & tenure'
                ],
            'dpd_rules' => ['type' => 'module', 'key' => 'dpd_rules', 'label' => 'DPD', 'value' => '', 'placeholder' => '',
                'title' => 'If the module is active then the set of rules are checked else skipped'],
            'keyword_rules' => ['type' => 'module', 'key' => 'keyword_rules', 'label' => 'Keyword', 'value' => '', 'placeholder' => '',
                'title' => 'If the module is active then the set of rules are checked else skipped'],
            'account_status_rules' => ['type' => 'module', 'key' => 'account_status_rules', 'label' => 'Account Status', 'value' => '', 'placeholder' => '',
                'title' => 'If the module is active then the set of rules are checked else skipped'],
            'principal_written_off_rules' => ['type' => 'module', 'key' => 'principal_written_off_rules', 'label' => 'Principal Written Off', 'value' => '', 'placeholder' => '',
                'title' => 'If the module is active then the set of rules are checked else skipped'],
            'past_dues_rules' => ['type' => 'module', 'key' => 'past_dues_rules', 'label' => 'Past Dues', 'value' => '', 'placeholder' => '',
                'title' => 'If total past due amount >= input, then fail else pass. If the field is blank, then the rule is to be skipped'],
           ];
        return $list;
    }

    public function add()
    {
        if ($this->request->has('grade') && $this->request->has('clone')) {
            $gradeIdToClone = $this->request->get('grade');
            $originalGrade = GradesV1::find($gradeIdToClone);
            
            if ($originalGrade) {
                // Clone the grade
                $newGrade = $originalGrade->replicate();
                $newGrade->grade_alias = $originalGrade->grade_alias . ' (Clone)';
                $newGrade->save();
                
                // Clone DocumentRule
                $docRules = DocumentRule::where('grade_id', $gradeIdToClone)->get();
                foreach($docRules as $docRule) {
                    $newDocRule = $docRule->replicate();
                    $newDocRule->grade_id = $newGrade->id;
                    $newDocRule->save();
                }

                // Clone PreApproval
                $preApprovals = PreApproval::where('grade_id', $gradeIdToClone)->get();
                foreach($preApprovals as $preApproval) {
                    $newPreApproval = $preApproval->replicate();
                    $newPreApproval->grade_id = $newGrade->id;
                    $newPreApproval->save();
                }

                // Clone AutoReject
                $autoRejects = AutoReject::where('grade_id', $gradeIdToClone)->get();
                foreach($autoRejects as $autoReject) {
                    $newAutoReject = $autoReject->replicate();
                    $newAutoReject->grade_id = $newGrade->id;
                    $newAutoReject->save();
                }

                // Clone ApprovalRule
                $approvalRules = ApprovalRule::where('grade_id', $gradeIdToClone)->get();
                foreach($approvalRules as $approvalRule) {
                    $newApprovalRule = $approvalRule->replicate();
                    $newApprovalRule->grade_id = $newGrade->id;
                    $newApprovalRule->save();
                }

                // Clone AutoRejectRule
                $autoRejectRules = AutoRejectRule::where('grade_id', $gradeIdToClone)->get();
                foreach($autoRejectRules as $autoRejectRule) {
                    $newAutoRejectRule = $autoRejectRule->replicate();
                    $newAutoRejectRule->grade_id = $newGrade->id;
                    $newAutoRejectRule->save();
                }

                Session::flash('success', 'Grade cloned successfully.');
                return redirect('admin/grade/edit/' . $newGrade->id);
            }
        }
        return view('admin.grade.edit_v1');
    }


    public function save()
    {
        return $this->save_v1();
        $status = 'success';
        $message = 'Grade Add Successfully';
        try {
            $_grade = Grades::where('grade_alice', trim($this->request->get('grade_alice')))->first(['id']);
            if (isset($_grade->id)) {
                Session::flash('error', 'Duplicate Alias');
                return redirect()->back();
            }
            $this->request->request->remove('_token');
            $grade = new Grades();
            $grade->fill($this->request->all());
            if($this->request->request->has('is_pincode_approved')) {
                $grade->is_pincode_approved = 1;
            }else{
                $grade->is_pincode_approved = 0;
            }

            if($this->request->request->has('track_record')) {
                $grade->track_record = 1;
            }else{
                $grade->track_record = 0;
            }

            if($this->request->request->has('epf_verification')) {
                $grade->epf_verification = 1;
            }else{
                $grade->epf_verification = 0;
            }
            if($this->request->request->has('rejected')) {
                $grade->rejected = 1;
            }else{
                $grade->rejected = 0;
            }
            if($this->request->request->has('checkDuplicates')) {
                $grade->checkDuplicates = 1;
            }else{
                $grade->checkDuplicates = 0;
            }
            if($this->request->request->has('negative_area')) {
                $grade->negative_area = 1;
            }else{
                $grade->negative_area = 0;
            }
            if($this->request->request->has('guarantor')) {
                $grade->guarantor = 1;
            }else{
                $grade->guarantor = 0;
            }
            if($this->request->request->has('accountType')) {
                $grade->accountType = 1;
            }else{
                $grade->accountType = 0;
            }
            if($this->request->request->has('no_owned_house')) {
                $grade->no_owned_house = 1;
            }else{
                $grade->no_owned_house = 0;
            }
            if($this->request->request->has('zero_downpayment')) {
                $grade->zero_downpayment = 1;
            }else{
                $grade->zero_downpayment = 0;
            }
            if($this->request->request->has('caseType')) {
                $grade->caseType = 1;
            }else{
                $grade->caseType = 0;
            }
            if($this->request->request->has('ageAtLastEMI')) {
                $grade->ageAtLastEMI = 1;
            }else{
                $grade->ageAtLastEMI = 0;
            }
            if($this->request->request->has('dpdCountRejection')) {
                $grade->dpdCountRejection = 1;
            }else{
                $grade->dpdCountRejection = 0;
            }
            if($this->request->request->has('pastDues')) {
                $grade->pastDues = 1;
            }else{
                $grade->pastDues = 0;
            }
            if($this->request->request->has('threeYear')) {
                $grade->threeYear = 1;
            }else{
                $grade->threeYear = 0;
            }
            if($this->request->request->has('aboveThreeYear')) {
                $grade->aboveThreeYear = 1;
            }else{
                $grade->aboveThreeYear = 0;
            }
            if(!empty($this->request->get('case_type_value'))) {
                $grade->case_type_value = $this->request->get('case_type_value');
            }
            if(!empty($this->request->get('ageAtLastEMI_age'))) {
                $grade->ageAtLastEMI_age = $this->request->get('ageAtLastEMI_age');
            }
            if(!empty($this->request->get('dpdCountRejection_years'))) {
                $grade->dpdCountRejection_years = $this->request->get('dpdCountRejection_years');
            }
            if(!empty($this->request->get('dpdCountRejection_dpds'))) {
                $grade->dpdCountRejection_dpds = $this->request->get('dpdCountRejection_dpds');
            }
            if(!empty($this->request->get('pastDues_value'))) {
                $grade->pastDues_value = $this->request->get('pastDues_value');
            }
            if(!empty($this->request->get('threeYear_years'))) {
                $grade->threeYear_years = $this->request->get('threeYear_years');
            }
            if(!empty($this->request->get('dpd_keywords'))) {
                $grade->dpd_keywords = $this->request->get('dpd_keywords');
            }
            if(!empty($this->request->get('threeYear_dpds'))) {
                $grade->threeYear_dpds = $this->request->get('threeYear_dpds');
            }
            if(!empty($this->request->get('above_dpd_keywords'))) {
                $grade->above_dpd_keywords = $this->request->get('above_dpd_keywords');
            }
            if(!empty($this->request->get('aboveThreeYear_years'))) {
                $grade->aboveThreeYear_years = $this->request->get('aboveThreeYear_years');
            }
            if(!empty($this->request->get('aboveThreeYear_dpds'))) {
                $grade->aboveThreeYear_dpds = $this->request->get('aboveThreeYear_dpds');
            }
            if($this->request->request->has('fetch_gst')) {
                $grade->fetch_gst = 1;
            }else{
                $grade->fetch_gst = 0;
            }
            if($this->request->request->has('thin_file_epf_verification')) {
                $grade->thin_file_epf_verification = 1;
            }else{
                $grade->thin_file_epf_verification = 0;
            }
            if($this->request->request->has('thin_file_fetch_gst')) {
                $grade->thin_file_fetch_gst = 1;
            }else{
                $grade->thin_file_fetch_gst = 0;
            }
            if(empty($this->request->get('min_loan_amount'))) {
                $grade->min_loan_amount = 0;
            }
            if(empty($this->request->get('thin_file_min_loan_amount'))) {
                $grade->thin_file_min_loan_amount = 0;
            }
            if(!empty($this->request->get('power_savings'))) {
                $grade->power_savings = $this->request->get('power_savings');
            }
            $grade->employee_status = $this->request->get('employee_status') ? implode(',',$this->request->get('employee_status')) : '';
            $grade->thin_file_employee_status = $this->request->get('thin_file_employee_status') ? implode(',',$this->request->get('thin_file_employee_status')) : '';
            $grade->created_at = Carbon::now()->toDateTimeString();
            $grade->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Exception occurred while saving grade';
        }
        Session::flash($status, $message);
        return redirect()->to('/admin/grades');
    }
    /* Save grade name changes */
    public function save_grade_name()
    {
        $status = 'success';
        try {
            if($this->request->get('grade_id') != '' && gettype($this->request->get('grade_id')) != 'undefined' && $this->request->get('grade_id') != 'undefined'){
                $grade = GradesV1::find($this->request->get('grade_id'));
                $grade->grade_alias = trim($this->request->get('grade_alias'));
                $grade->updated_by = Auth::user() ? Auth::user()->id : 107;
                $grade->updated_at = Carbon::now()->toDateTimeString();
                $grade->save();

                $message = 'Grade Name Modified Successfully';
            }else{
                $_grade = GradesV1::where('grade_alias', trim($this->request->get('grade_alias')))->first(['id']);
                if (isset($_grade->id)) {
                    Session::flash('error', 'Duplicate Alias');
                    return redirect()->back();
                }
                $this->request->request->remove('_token');

                // Save the grade name
                $grade = new GradesV1();
                $grade->grade_alias = trim($this->request->get('grade_alias'));
                $grade->updated_by = Auth::user() ? Auth::user()->id : 107;
                $grade->created_at = Carbon::now()->toDateTimeString();
                $grade->save();
                $message = 'Grade Added Successfully';
            }
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Exception occurred while saving grade name';
        }

        return response()->json(['status' => $status, 'message' => $message]);
    }
    /* Save details of a Grade in the new format */
    public function save_v1()
    {
        parse_str($this->request->get('formData'), $formData);
        $this->request->request->remove('_token');
        $is_update = $this->request->get('is_update');
        $status = 'success';
        try {
            if($this->request->get('grade_id') != '' && GradesV1::where('id', $this->request->get('grade_id'))->exists()){
                $grade_id = $this->request->get('grade_id') ?? '';
            }else if (GradesV1::where('grade_alias', trim($this->request->get('grade_alias')))->exists()) {
                $grade_id = $grade->id ?? '';
            }else {
                // Save the grade name
                $grade = new GradesV1();
                $grade->grade_alias = trim($this->request->get('grade_alias'));
                $grade->updated_by = Auth::user() ? Auth::user()->id : 107;
                $grade->created_at = Carbon::now()->toDateTimeString();
                $grade->save();
                $grade_id = $grade->id ?? '';
            }
            foreach($formData as $key=>$val){
                if($val == 'on'){
                    $formData[$key] = true;
                }elseif($val == ''){
                    unset($formData[$key]);
                }elseif ($key == 'emi_bounce_rule' && is_array($val)) {
                    $nonEmptyValues = array_filter($val, function($v) {
                        return $v !== null && $v !== ''; 
                    });
                    
                    if (empty($nonEmptyValues)) {
                        unset($formData[$key]);
                    }
                }elseif ($key == 'bureau_surrogate' || $key == 'track_record') {
                    $formData[$key] = json_decode($val);
                }
            }

            if (isset($formData['__PREFIX__'])) {
                unset($formData['__PREFIX__']);
            }
            if (isset($formData['dpd_rules']) && is_array($formData['dpd_rules'])) {
                $dpdRules    = array_values($formData['dpd_rules']); // reindex 0..n
                $dpdOwnership = isset($formData['dpd_ownership']) ? (array)$formData['dpd_ownership'] : [];
                $dpdStatus    = !empty($formData['dpd_status']) ? 1 : 0;
                $dpdAccountTypes = isset($formData['dpd_exclude_account_types']) ? $formData['dpd_exclude_account_types'] : [];

                $formData['dpd_rules'] = [
                    'status'    => $dpdStatus,
                    'ownership' => $dpdOwnership,
                    'rules'     => $dpdRules,
                    'account_types' => $dpdAccountTypes,
                ];

                unset($formData['dpd_ownership'], $formData['dpd_status'], $formData['dpd_exclude_account_types']);
            }

            if (isset($formData['keyword_rules']) && is_array($formData['keyword_rules'])) {
                $keywordRules    = array_values($formData['keyword_rules']); // reindex 0..n
                $keywordOwnership = isset($formData['keyword_ownership']) ? (array)$formData['keyword_ownership'] : [];
                $keywordStatus    = !empty($formData['keyword_status']) ? 1 : 0;
                $keywordAccountTypes = isset($formData['keyword_exclude_account_types']) ? $formData['keyword_exclude_account_types'] : [];

                $formData['keyword_rules'] = [
                    'status'    => $keywordStatus,
                    'ownership' => $keywordOwnership,
                    'rules'     => $keywordRules,
                    'account_types' => $keywordAccountTypes,
                ];

                unset($formData['keyword_ownership'], $formData['keyword_status'], $formData['keyword_exclude_account_types']);
            }

            if (isset($formData['past_dues_rules']) && is_array($formData['past_dues_rules'])) {
                $pastDuesRules    = array_values($formData['past_dues_rules']); // reindex 0..n
                $pastDuesOwnership = isset($formData['past_dues_ownership']) ? (array)$formData['past_dues_ownership'] : [];
                $pastDuesStatus    = !empty($formData['past_dues_status']) ? 1 : 0;

                $formData['past_dues_rules'] = [
                    'status'    => $pastDuesStatus,
                    'ownership' => $pastDuesOwnership,
                    'rules'     => $pastDuesRules,
                ];

                unset($formData['past_dues_ownership'], $formData['past_dues_status']);
            }

            if (isset($formData['principal_written_off_rules']) && is_array($formData['principal_written_off_rules'])) {
                $principalWrittenOffRules    = array_values($formData['principal_written_off_rules']); // reindex 0..n
                $principalWrittenOffOwnership = isset($formData['principal_written_off_ownership']) ? (array)$formData['principal_written_off_ownership'] : [];
                $principalWrittenOffStatus    = !empty($formData['principal_written_off_status']) ? 1 : 0;

                $formData['principal_written_off_rules'] = [
                    'status'    => $principalWrittenOffStatus,
                    'ownership' => $principalWrittenOffOwnership,
                    'rules'     => $principalWrittenOffRules,
                ];

                unset($formData['principal_written_off_ownership'], $formData['principal_written_off_status']);
            }

            if (isset($formData['account_status_rules']) && is_array($formData['account_status_rules'])) {
                $accountStatusRules    = array_values($formData['account_status_rules']); // reindex 0..n
                $accountStatusOwnership = isset($formData['account_status_ownership']) ? (array)$formData['account_status_ownership'] : [];
                $accountStatusStatus    = !empty($formData['account_status_status']) ? 1 : 0;

                $formData['account_status_rules'] = [
                    'status'    => $accountStatusStatus,
                    'ownership' => $accountStatusOwnership,
                    'rules'     => $accountStatusRules,
                ];

                unset($formData['account_status_ownership'], $formData['account_status_status']);
            }

            $rule_name = $formData['rule_name'];
            unset($formData['rule_name']);

            $original_rule_name = isset($formData['original_rule_name']) ? $formData['original_rule_name'] : $rule_name;
            unset($formData['original_rule_name']);

            if(isset($formData['employee_status'])){
                $formData['employee_status'] = implode(',', $formData['employee_status']);
            }
            if(isset($formData['solar_financing_for'])){
                $formData['solar_financing_for'] = implode(',', $formData['solar_financing_for']);
            }
            if(isset($formData['solar_power_type'])){
                $formData['solar_power_type'] = implode(',', $formData['solar_power_type']);
            }

            $_formData = $formData;

            if(isset($formData['rule_status'])){
                $rule_status = (int)$formData['rule_status'];
                unset($formData['rule_status']);
            }

            if($is_update){
                $current_rule = ApprovalRule::where('grade_id', $grade_id)->where('rule_name', $original_rule_name)->first(['id','status', 'rules']);
                $new_rule = $old_rule = '';
                if(isset($current_rule->id)){
                    $old_rule = json_decode($current_rule->rules, 1);
                    $new_rule = $formData;
                    ksort($old_rule);
                    ksort($new_rule);
                }

                if($new_rule !== $old_rule || $rule_name !== $original_rule_name) {
                    ApprovalRule::where('grade_id', $grade_id)->where('rule_name', $original_rule_name)->update([
                        'rule_name' => $rule_name,
                        'rules' => json_encode($formData),
                        'status' => $rule_status,
                        'updated_by' => Auth::user() ? Auth::user()->id : 107,
                    ]);

                    // Rule Log saved
                    $rule = new ApprovalRuleLog();
                    $rule->grade_id = $grade_id;
                    $rule->rule_id = $current_rule->id;
                    $rule->modifications = $current_rule->status == $rule_status ? json_encode($formData) : json_encode($_formData);
                    $rule->created_at = Carbon::now()->toDateTimeString();
                    $rule->updated_by = Auth::user() ? Auth::user()->id : 107;
                    $rule->save();

                    $message = 'Grade Rule Updated Successfully';
                }else{
                    if($current_rule->status != $rule_status){
                        ApprovalRule::where('grade_id', $grade_id)->where('rule_name', $original_rule_name)->update([
                            'status' => $rule_status,
                            'updated_by' => Auth::user() ? Auth::user()->id : 107,
                        ]);
                    }
                    $message = '';

                }
            }else {
                // Save the rule
                $rule = new ApprovalRule();
                $rule->grade_id = $grade_id;
                $rule->rule_name = $rule_name;
                $rule->rules = json_encode($formData);
                $rule->status = 1; // Always saved as active, since we don't have a maker checker feature yet!
                $rule->created_at = Carbon::now()->toDateTimeString();
                $rule->updated_by = Auth::user() ? Auth::user()->id : 107;
                $rule->save();

                $lastInsertId = $rule->id;

                // Rule Log saved
                $rule = new ApprovalRuleLog();
                $rule->grade_id = $grade_id;
                $rule->rule_id = $lastInsertId;
                $rule->modifications = json_encode($formData);
                $rule->created_at = Carbon::now()->toDateTimeString();
                $rule->updated_by = Auth::user() ? Auth::user()->id : 107;
                $rule->save();

                $message = 'Grade Rule Added Successfully';
            }
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Exception occurred while saving approval rule logs';
        }

        return response()->json(['status' => $status, 'message' => $message]);
    }


    public function update($id)
    {
        $status = 'success';
        $message = 'Grade Updated Successfully';
        try {
            $this->request->request->remove('_token');
            $grade = Grades::find($id);

            $grade->fill($this->request->all());
            if($this->request->request->has('is_pincode_approved_or_risky')) {
                $grade->is_pincode_approved = 1;
            }else{
                $grade->is_pincode_approved = 0;
            }

            if($this->request->request->has('track_record')) {
                $grade->track_record = 1;
            }else{
                $grade->track_record = 0;
            }

            if($this->request->request->has('epf_verification')) {
                $grade->epf_verification = 1;
            }else{
                $grade->epf_verification = 0;
            }
            if($this->request->request->has('rejected')) {
                $grade->rejected = 1;
            }else{
                $grade->rejected = 0;
            }
            if($this->request->request->has('checkDuplicates')) {
                $grade->checkDuplicates = 1;
            }else{
                $grade->checkDuplicates = 0;
            }
            if($this->request->request->has('negative_area')) {
                $grade->negative_area = 1;
            }else{
                $grade->negative_area = 0;
            }
            if($this->request->request->has('guarantor')) {
                $grade->guarantor = 1;
            }else{
                $grade->guarantor = 0;
            }
            if($this->request->request->has('accountType')) {
                $grade->accountType = 1;
            }else{
                $grade->accountType = 0;
            }
            if($this->request->request->has('no_owned_house')) {
                $grade->no_owned_house = 1;
            }else{
                $grade->no_owned_house = 0;
            }
            if($this->request->request->has('zero_downpayment')) {
                $grade->zero_downpayment = 1;
            }else{
                $grade->zero_downpayment = 0;
            }
            if($this->request->request->has('caseType')) {
                $grade->caseType = 1;
            }else{
                $grade->caseType = 0;
            }
            if($this->request->request->has('ageAtLastEMI')) {
                $grade->ageAtLastEMI = 1;
            }else{
                $grade->ageAtLastEMI = 0;
            }
            if($this->request->request->has('dpdCountRejection')) {
                $grade->dpdCountRejection = 1;
            }else{
                $grade->dpdCountRejection = 0;
            }
            if($this->request->request->has('pastDues')) {
                $grade->pastDues = 1;
            }else{
                $grade->pastDues = 0;
            }
            if($this->request->request->has('threeYear')) {
                $grade->threeYear = 1;
            }else{
                $grade->threeYear = 0;
            }
            if($this->request->request->has('aboveThreeYear')) {
                $grade->aboveThreeYear = 1;
            }else{
                $grade->aboveThreeYear = 0;
            }
            if(!empty($this->request->get('case_type_value'))) {
                $grade->case_type_value = $this->request->get('case_type_value');
            }
            if(!empty($this->request->get('ageAtLastEMI_age'))) {
                $grade->ageAtLastEMI_age = $this->request->get('ageAtLastEMI_age');
            }
            if(!empty($this->request->get('dpdCountRejection_years'))) {
                $grade->dpdCountRejection_years = $this->request->get('dpdCountRejection_years');
            }
            if(!empty($this->request->get('dpdCountRejection_dpds'))) {
                $grade->dpdCountRejection_dpds = $this->request->get('dpdCountRejection_dpds');
            }
            if(!empty($this->request->get('pastDues_value'))) {
                $grade->pastDues_value = $this->request->get('pastDues_value');
            }
            if(!empty($this->request->get('threeYear_years'))) {
                $grade->threeYear_years = $this->request->get('threeYear_years');
            }
            if(!empty($this->request->get('dpd_keywords'))) {
                $grade->dpd_keywords = $this->request->get('dpd_keywords');
            }
            if(!empty($this->request->get('threeYear_dpds'))) {
                $grade->threeYear_dpds = $this->request->get('threeYear_dpds');
            }
            if(!empty($this->request->get('above_dpd_keywords'))) {
                $grade->above_dpd_keywords = $this->request->get('above_dpd_keywords');
            }
            if(!empty($this->request->get('aboveThreeYear_years'))) {
                $grade->aboveThreeYear_years = $this->request->get('aboveThreeYear_years');
            }
            if(!empty($this->request->get('aboveThreeYear_dpds'))) {
                $grade->aboveThreeYear_dpds = $this->request->get('aboveThreeYear_dpds');
            }
            if($this->request->request->has('fetch_gst')) {
                $grade->fetch_gst = 1;
            }else{
                $grade->fetch_gst = 0;
            }
            if($this->request->request->has('thin_file_epf_verification')) {
                $grade->thin_file_epf_verification = 1;
            }else{
                $grade->thin_file_epf_verification = 0;
            }
            if($this->request->request->has('thin_file_fetch_gst')) {
                $grade->thin_file_fetch_gst = 1;
            }else{
                $grade->thin_file_fetch_gst = 0;
            }
            if(empty($this->request->get('min_loan_amount'))) {
                $grade->min_loan_amount = 0;
            }
            if(empty($this->request->get('thin_file_min_loan_amount'))) {
                $grade->thin_file_min_loan_amount = 0;
            }
            if(!empty($this->request->get('power_savings'))) {
                $grade->power_savings = $this->request->get('power_savings');
            }
            $grade->employee_status = $this->request->get('employee_status') ? implode(',',$this->request->get('employee_status')) : '';
            $grade->thin_file_employee_status = $this->request->get('thin_file_employee_status') ? implode(',',$this->request->get('thin_file_employee_status')) : '';
            $grade->created_at = Carbon::now()->toDateTimeString();
            $grade->save();
            $data = $grade->toArray();
            $gradelock = new GradeLock();
            $gradelock->fill($data);
            $gradelock->grade_id = $grade->id;
            $gradelock->created_at = Carbon::now()->toDateTimeString();
            $gradelock->update_by = Auth::user()->id;
            $gradelock->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Exception occurred while updating grade';
        }
        Session::flash($status, $message);
        return redirect()->back();
    }

    public function CalculateFOIRbeforeAutoDecision($application_id, $application, $tableOfOffers = false){
        // Check if the FOIR calculation is incomplete
        $checkCreditReportDetails = CreditReport::with('incompleteFoir')->where('application_id', $application_id)->first(['id']);
        if (isset($checkCreditReportDetails->id) || isset($checkCreditReportDetails->incompleteFoir->id)) {
            $cwFactory = new CloudWatchLoggerFactory();
            $cwFactory->logger(json_encode(['title' => 'Auto Decision: refreshScoreCardData', 'application_id' => $application_id]));
            // (new Slack(new Request(['title' => 'Auto Decision: refreshScoreCardData', 'fields' => ['id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
            //realculating foir without coapp refreshing scorecard
            (new ConsumerApplicationController())->refreshScoreCardData($application_id);
            //making offers
            $offers = false;
            foreach ($application->foir as $foir) {
                if ($foir->AccountType == 'Credit Fair EMI'){
                    continue;
                }
                $this->setFOIRAttributes($foir);
            }
            if(isset($application->emi->emi) && $application->emi->emi) {
                $this->getFOIRCalculation($application);
            }
        }
    }


    public function ApprovalCheck($application_id)
    {
        $epf = EPFUANLookup::where('application_id', $application_id)->first();
        if (!isset($epf)){
            $this->CallEPFKarza($application_id);
        }
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.offer')->where('id', $application_id)->first();
        $this->CalculateFOIRbeforeAutoDecision($application_id, $application);

        return $this->MultiApprovalCheck($application_id);
        $checkLogs = $this->ApprovalCheckV1($application_id);
        //(new Slack(new Request(['title' => 'Auto Decision - Ended', 'fields' => ['id' => $application_id, 'time' => Carbon::now()->toDateTimeString()], 'group' => Slack::$STAGE_TESTING])))->send();
        return $checkLogs;
        $status = true;
        $threeYear = [];
        $accounts = [];
        $aboveThreeYear = [];
        ConsumerApplication::$isCFFoirNotInclude = true;
        $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.offer')->where('id', $application_id)->first();
        if (!$application->merchant || (isset($application->merchant) && !$application->merchant->grade)) {
            $this->error = 1;
            return $this;
        }
        if (isset($application->merchant->grade->id)) {
            $grade_date = $application->merchant->grade->toarray();
            $consumer_grade = new ConsumerApplicationGrade();
            $consumer_grade->fill($grade_date);
            $consumer_grade->grade_id = $application->merchant->grade->id;
            $consumer_grade->application_id = $application_id;
            $consumer_grade->created_at = Carbon::now()->toDateTimeString();
            $consumer_grade->save();
        }
        /*$f = Grades::first();
        $y = new \stdClass();
        $y->loan_amount = $f->loan_amount;
        $y->tenure = $f->tenure;
        $y->monthly_income = $f->monthly_income;
        $y->score = $f->score;
        $t = new \stdClass();
        $t->grade = $y;
        $application['merchant'] = $t;*/
        $status_array = ['aborted', 'rejected'];
        $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->get();
        if (isset($status_log[0])) {
            $this->rejected = true;
            return $this;
        }
        if (isset($application->application_element->negative_profile) && $application->application_element->negative_profile > 0) {
            $this->negativeProfile = true;
            return $this;
        }
        if ($checkDuplicates = $this->checkDuplicates($application)) {
            $this->checkDuplicates = $checkDuplicates;
            return $this;
        }

        if (isset($application->creditReport[0]) && isset($application->creditReport[0]->Score)) {
            if ($application->creditReport[0]->Score < $application->merchant->grade->score && $application->creditReport[0]->Score > 10) {
                $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
                return $this;
            } elseif ($application->creditReport[0]->Score < 10) {
                $loan_amount = (isset($application->merchant->grade->loan_amount) && !empty($application->merchant->grade->loan_amount)) ? $application->merchant->grade->loan_amount : 0;
                $tenure = (isset($application->merchant->grade->tenure) && !empty($application->merchant->grade->tenure)) ? $application->merchant->grade->tenure : 0;
                $monthly_income = (isset($application->merchant->grade->monthly_income) && !empty($application->merchant->grade->monthly_income)) ? $application->merchant->grade->monthly_income : 0;
                $grade_age = (isset($application->merchant->grade->age) && !empty($application->merchant->grade->age)) ? $application->merchant->grade->age : 0;
                $foir = (isset($application->merchant->grade->foir) && !empty($application->merchant->grade->foir)) ? $application->merchant->grade->foir : 0;
                $cf_foir = (isset($application->merchant->grade->cf_foir) && !empty($application->merchant->grade->cf_foir)) ? $application->merchant->grade->cf_foir : 0;
                $threeYearDPD = 0;
                $aboveThreeYearDPD = 0;

                if (empty((isset($application->current_address_status)) || (isset($application->current_address_status) && !in_array($application->emi->current_address_status, array('OWNED', 'PARENTS HOUSE', 'Self Owned', 'Parent Owned'))))) {
                    $this->address_status = "No Owned House";
                    return $this;
                }
                if (!$application->emi || (isset($application->emi) && $application->emi->upfront_from_customer <= 0)) {
                    if($application->merchant_id != 5803) {
                        $this->downpayment = isset($application->emi->upfront_from_customer) ? "Zero Downpayment" : 'emi_not_generated';
                        return $this;
                    }
                }

                if (((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) || ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode))) {
                    $data['current_pincode'] = ((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) ? $application->current_address_pincode : "";
                    $data['installation_pincode'] = ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode)) ? $application->application_element->installation_address_pincode : "";
                    $consumerApplicationConreoller = new ConsumerApplicationController();
                    $NegativeArearesponse = $consumerApplicationConreoller->getNegativeAreaList($data);
                    if ($NegativeArearesponse && isset($NegativeArearesponse->level) && $NegativeArearesponse->level == 1) {
                        $this->negative_area = "Negative Area";
                        return $this;
                    }
                }

            } else {
                $loan_amount = (isset($application->merchant->grade->loan_amount) && !empty($application->merchant->grade->loan_amount)) ? $application->merchant->grade->loan_amount : 0;
                $tenure = (isset($application->merchant->grade->tenure) && !empty($application->merchant->grade->tenure)) ? $application->merchant->grade->tenure : 0;
                $monthly_income = (isset($application->merchant->grade->monthly_income) && !empty($application->merchant->grade->monthly_income)) ? $application->merchant->grade->monthly_income : 0;
                $grade_age = (isset($application->merchant->grade->age) && !empty($application->merchant->grade->age)) ? $application->merchant->grade->age : 0;
                $foir = (isset($application->merchant->grade->foir) && !empty($application->merchant->grade->foir)) ? $application->merchant->grade->foir : 0;
                $cf_foir = (isset($application->merchant->grade->cf_foir) && !empty($application->merchant->grade->cf_foir)) ? $application->merchant->grade->cf_foir : 0;
                $threeYearDPD = 10;
                $aboveThreeYearDPD = 15;
            }
        } else {
            $this->score = 'no_equifax';
            return $this;
        }

        if ($application->loan_amount == 0 || $application->loan_amount > $loan_amount || $loan_amount == 0) {
            $this->loan_amount = $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount;
            return $this;
        }
        if (!$application->emi || $tenure == 0 || (isset($application->emi) && $application->emi->remaining_emi > $tenure)) {
            $this->tenure = isset($application->emi->remaining_emi) ? $application->emi->remaining_emi : 'emi_not_generated';
            return $this;
        }
        if (!$application->monthly_income || $monthly_income == 0 || ($application->monthly_income < $monthly_income)) {
            $this->monthly_income = ($application->monthly_income == 0 || $application->monthly_income == Null || $application->monthly_income == '') ? 1 : $application->monthly_income;
            return $this;
        }

        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
        if (isset($application->tenure)) {
            $last_emi_date = Carbon::now()->addMonths($application->tenure)->toDateString();
            $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
        }
        if ($grade_age == 0 || $age < $grade_age) {
            $this->age = $age;
            return $this;
        }
        if (isset($ageAtLastEMI)) {
            if ($ageAtLastEMI > 60) {
                $this->ageAtLastEMI = $ageAtLastEMI;
                return $this;
            }
        }

        $creditCardAmount = 0;
        if (isset($application->creditReport[0])) {
            $creditReport = $application->creditReport[0];
            if ($creditReport->TotalPastDue > 0) {
                $this->pastDues = $creditReport->TotalPastDue;
                return $this;
            }
            if ($status) {
                $oldloan = 1;
                $unsecuredloan = 1;
                $termloanarray = ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan',
                    'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility',
                    'Business Non-Funded Credit Facility - Priority', 'Staff Loan'];
                if ($application->foir) {
                    foreach ($application->foir as $foir) {

                        $accounts[] = $foir->AccountType;

                        if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                            $this->AccountType = $foir->AccountType;
                            break;
                        }

                        if ($foir->AccountType == 'Credit Card' && $foir->DateClosed == '') {
                            $creditCardAmount += $foir->InstallmentAmount;
                        }

                        if ($foir->DateOpened) {
                            if (!$foir->DateClosed) {
                                $foir->DateClosed = "";
                            }
                            if ($foir->DateClosed) {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened, $foir->DateClosed);
                            } else {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened);
                            }
//                            if ($foir->DateClosed) {
//                                $date = date('Y', strtotime($foir->DateClosed));
//                            } else {
//                                $date = date('Y', time());
//                            }
//
//                            $termLoan = (date('Y', strtotime($foir->DateOpened)) - $date);
                            if ($termLoan > 0 && $oldloan != 0) {
                                $oldloan = 0;
                            }

                            if ((in_array($foir->AccountType, $termloanarray)) && $unsecuredloan != 0) {
                                $unsecuredloan = 0;
                            }
                        }

                        $this->setFOIRAttributes($foir);
                    }

                    if (!empty($this->AccountType)) {
                        return $this;
                    }


//                    $request = new Request();
//                    $offer = MerchantOffers::where('merchant_id',$application->merchant_id)->where('tenure',$application->tenure)->first(['interest_type_id','id']);
//                    if($offer) {
//                        $request->attributes->add(['merchant_id' => $application->merchant_id, 'loan_amount' => $application->loan_amount, 'merchant_offer_id' => $offer->id, 'category_id' => $application->purpose, 'interest_type_id' => $offer->interest_type_id]);
//                        $calculation = new \App\Http\Controllers\Admin\EMICalculation($request);
//                        $calculation = $calculation->prepareCalculation();
//                        $calculation = $calculation->getData();
//
//                        if (isset($calculation->emi) && ($creditCardAmount * 0.05) > ($calculation->emi * 5)) {
//                            $this->credit_limit_five_times = ($calculation->emi * 5);
//                            return $this;
//                        }
//                    }

                    if (count($accounts) == 1) {
                        if (in_array('Guarantor', $accounts)) {
                            $this->guarantor = 1;
                            return $this;
                        }
                    }

                    $this->getFOIRCalculation($application);
                    //$this->getFOIRCalculation($application, 1);


                    if ($foir == 0 || $this->cfFoir > $foir) {
                        $this->foir = $this->cfFoir;
                        return $this;
                    }
                    if ($cf_foir == 0 || $this->foirIncludingCFEMI > cf_foir) {
                        $this->cf_foir = $this->foirIncludingCFEMI;
                        return $this;
                    }

                    foreach ($application->foir as $foir) {

                        $foirData = json_decode($foir->dpd, 1);


                        if ($foirData) {
                            $caseType = array_keys($foirData);
                            if ($caseType) {
                                foreach ($caseType as $type) {
                                    if (in_array($type, ['PWOS', 'SET'])) {
                                        $this->caseType = $type;
                                        return $this;
                                    }
                                }
                            }
                        }


                        $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                        if ($foirClean) {
                            if (strtotime($foir->DateOpened) <= strtotime($foirDateRange)) {
                                if (isset($foirData[2])) {
                                    $threeYear[] = $foirData[2];
                                }
                            }
                            if (strtotime($foir->DateOpened) >= strtotime($foirDateRange)) {
                                if (isset($foirData[2])) {
                                    $aboveThreeYear[] = $foirData[2];
                                }
                            }
                        }
                    }

                    if ($threeYear) {
                        if (max($threeYear) > $threeYearDPD) {
                            $this->threeYear = max($threeYear);
                            return $this;
                        }
                        if (max($aboveThreeYear) > $aboveThreeYearDPD) {
                            $this->aboveThreeYear = max($aboveThreeYear);
                            return $this;
                        }
                    }
                }

                if ($oldloan == 0 && $unsecuredloan == 0) {
                    $this->termLoan = 0;
                } else {
                    $this->termLoan = 1;
                }
            }
        }

        return $this;

    }

    public function setLastResponse($response) {
        $this->lastResponse = $response;
    }
    public function getLastResponse() {
        return $this->lastResponse;
    }

    public function processRule($grade_rule, $application, $application_id, $req_id, $tableOfOffers) {
        $rule_details = json_decode($grade_rule->rules);
        $rule_details = (array)$rule_details;
        ksort($rule_details);
        $rule_details = (object)$rule_details;

        $response = '';
        $this->Atenure = [];
        $this->Afoir = [];
        $this->Acf_foir = [];
        $status = 'success';

        $priority_keys = ['tenure', 'foir', 'cf_foir'];  // Example priority keys

        $rule_details = (array) $rule_details; // Ensure it's an array

        $sorted_rules = array_merge(
            array_intersect_key($rule_details, array_flip($priority_keys)),
            array_diff_key($rule_details, array_flip($priority_keys))
        );

        foreach ($sorted_rules as $key => $value) {
            $response = $this->ruleBasedCheck($application, $application_id, $key, $value, (object) $rule_details, $tableOfOffers);
            $this->setLastResponse($response);
            if ($response['failed_condition'] != "") { // Check for failure condition
                return false;
            }
        }

        if ($response['failed_condition'] == '' && $response['reason'] == '') {
            return true;
        }

        return false;
    }

    public function MultiApprovalCheck($application_id, $req_id='', $tableOfOffers = false)
    {
        if (_env('JSON_BRE_ACTIVE')) {
            return $this->MultiApprovalCheckJSONBRE($application_id, '', true);
        }
        $cwFactory = new CloudWatchLoggerFactory();
        $jsonBRE = new JsonBREController();
        $cwFactory->logger(json_encode(['title' => 'Auto Decision: MultiApprovalCheck', 'application_id' => $application_id]));
        //The unique generated random key to identify the rules and decisions that ran for a case at a given time.
        $req_id = $req_id != '' ? $req_id : ($this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : 0);
        $this->appId = $application_id;

        if ($req_id == 0) {
            $testImport = new TestImport(new Request());
            $requestID = $testImport->random_strings(8);
            $req_id = $requestID;
        }

        // Check if the FOIR calculation is incomplete
        // $checkCreditReportDetails = CreditReport::with('incompleteFoir')->where('application_id', $application_id)->first(['id']);
        // if (isset($checkCreditReportDetails->id) || isset($checkCreditReportDetails->incompleteFoir->id)) {
        //     (new Slack(new Request(['title' => 'Auto Decision: refreshScoreCardData', 'fields' => ['id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
        //     (new ConsumerApplicationController())->refreshScoreCardData($application_id);
        // }

        // Fetch application details
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade_v1', 'merchant.custom_grade', 'merchant.offer', 'products', 'bank_details')->where('id', $application_id)->first();
        $tableOfOffers = (isset($application->merchant->table_of_offers) && $application->merchant->table_of_offers) ? true : false;

        // Run basic checks on grades before running the approval rules
        $gradeChecks = $this->gradeChecks($application, $application_id, $tableOfOffers);

        if ($gradeChecks['status'] == 'failed' && $gradeChecks['reason'] != '') {
            $this->saveApprovalStatus(0, $application_id, $req_id, $gradeChecks['status'], $gradeChecks);
            return false;
        }


        // Custom grade conditions added in list
        if ($this->request->has('custom_grade_id')) { //$this->request->has('custom_grade_id')
            $f = Grades::find($this->request->get('custom_grade_id'));//$this->request->get('custom_grade_id')
            $t = new \stdClass();
            $t->grade = $f;
            $application['merchant'] = $t;
        }

        // ## Rule based checks:
        $grade_rules = ApprovalRule::where('grade_id', $application->merchant->grade_v1->id)->where('status', 1)->get();
        $auto_reject_rule = DB::selectOne("SELECT modifications from auto_reject_rule where grade_id = ? order by created_at desc", [$application->merchant->grade_v1->id]);
        $reject_rules = json_decode($auto_reject_rule->modifications);

        //json bre code
        $mode = (isset($application->updated_by)) ? $application->updated_by : "";
        $other_sources = ['consumer_app', 'EMI CHECKOUT', 'No touch', 'Partner Link', 'Solar form via Merchant admin panel'];
        if($mode && !in_array($mode, $other_sources)){
            try{
                $bre_api_payload = $jsonBRE->createBrePayload($application_id);
                try{
                    $file_path = _env('JSON_BRE_EXHAUSTIVE_JSON');
                    $exhaustive_criteria_json = $jsonBRE->get_exhaustive_criteria_json($file_path, $application_id);
                    $exhaustive_criteria_json = json_decode($exhaustive_criteria_json, 1);
                }
                catch(\Exception $e){
                    $cwFactory->logger(json_encode(['application_id'=> $application_id, 'title' => 'couldnt create rule list', 'exhaustive_criteria_json' => $exhaustive_criteria_json ?? '', 'error' =>$e]));
                }
                foreach ($grade_rules as $grade_rule) {
                    $rule = json_decode($grade_rule->rules, 1);
                    $policy = [];
                    $policy_name = "policy-".$grade_rule->id;
                    $rule_list = $this->create_rule_list($application_id, $grade_rule, $req_id, $tableOfOffers, $exhaustive_criteria_json);
                    if($rule_list){
                        $policy['rule'] = $rule_list;
                    }
                    else{
                        $policy['rule'] = [];
                    }
                    $policy['payload'] = array( 'identifier' => $application_id
                                                    , 'applicant_type' => 1
                                                    , 'rule_name' => $grade_rule->rule_name
                                                    , 'loan_amount' => isset($application->approved_amount) ? (int)($application->approved_amount) : null
                                                    , 'max_loan_amount' => isset($rule['max_loan_amount']) ? (int)($rule['max_loan_amount']) : null
                                                    , 'min_loan_amount' => isset($rule['min_loan_amount']) ? (int)($rule['min_loan_amount']) : null
                                                    , 'employee_status' => isset($rule['employee_status']) ? ($rule['employee_status']) : null
                                                    , 'past_dues' => isset($rule['past_dues']) ? (int)($rule['past_dues']) : null
                                                    , 'credit_card_percentage' => isset($rule['credit_card_amount_paid']) ? (int)($rule['credit_card_amount_paid']) : null
                                                    , 'age' => isset($rule['age']) ? (int)($rule['age']) : null
                                                    , 'ageAtLastEMI' => isset($rule['ageAtLastEMI']) ? (int)($rule['ageAtLastEMI']) : null
                                                    , 'monthly_income' => isset($rule['monthly_income']) ? (int)($rule['monthly_income']) : null
                                                    , 'score' => isset($rule['score']) ? (int)($rule['score']) : null
                                                    , 'tenure' => isset($rule['tenure']) ? (int)($rule['tenure']) : null
                                                    , 'cf_foir' => isset($rule['cf_foir']) ? (int)($rule['cf_foir']) : null
                                                    , 'foir' => isset($rule['foir']) ? (int)($rule['foir']) : null
                                                    , 'caseType' => isset($rule['caseType']) ? ($rule['caseType']) : null
                                                    , 'dpd_years_above_0' => isset($rule['dpd_years_above_zero']) ? (int)($rule['dpd_years_above_zero']) : null
                                                    , 'dpd_count_above_0' => isset($rule['dpd_count_above_zero']) ? (int)($rule['dpd_count_above_zero']) : null
                                                    , 'pre_dpd_years' => isset($rule['pre_dpd_years']) ? (int)($rule['pre_dpd_years']) : null
                                                    , 'pre_dpd_count' => isset($rule['pre_dpd_count']) ? (int)($rule['pre_dpd_count']) : null
                                                    , 'pre_dpd_keywords' => isset($rule['pre_dpd_keywords']) ? ($rule['pre_dpd_keywords']) : null
                                                    , 'post_dpd_year' => isset($rule['post_dpd_year']) ? (int)($rule['post_dpd_year']) : null
                                                    , 'post_dpd_count' => isset($rule['post_dpd_count']) ? (int)($rule['post_dpd_count']) : null
                                                    , 'post_dpd_keywords' => isset($rule['post_dpd_keywords']) ? ($rule['post_dpd_keywords']) : null
                                                    , 'surrogate_percentage' => isset($rule['bureau_surrogate']) ? (int)($rule['bureau_surrogate']) : null
                                                    , 'term_loan_amount_paid_percentage' => isset($rule['term_loan_amount_paid']) ? (int)($rule['term_loan_amount_paid']) : null
                                                    , 'power_savings' => isset($application->application_element->inverter_power_savings) ? (float)($application->application_element->inverter_power_savings) : null
                                                    , 'emi' => isset($application->emi->emi) ? (int)($application->emi->emi) : null
                                                    , 'zero_downpayment' => 0
                                                    , 'bank_validation' => isset($rule['bank_validation']) ? (int)($rule['bank_validation']) : null);
                    $cwFactory->logger(json_encode(['title' => 'BRE_API payload addition attempted', 'application_id' => $application_id, 'rule'=>$grade_rule->id]));
                    if (isset($policy)){
                        $bre_api_payload['grade']['rules'][$policy_name] = $policy;
                    }
                }
                // Rejection rules for JSON BRE
                $rejectionPolicy = [];
                $rejectionPolicy['payload'] = array(
                    'identifier' => $application_id,
                    'applicant_type' => 1,
                    'rule_name' => 'auto-rejection-rule',
                    'age_range' => [(int)$reject_rules->new_rejection_rules->MIN_AGE, (int)$reject_rules->new_rejection_rules->MAX_AGE],
                    'monthly_income' => isset($rule['monthly_income']) ? (int)($rule['monthly_income']) : null,
                    'credit_score_range' => [(int)$reject_rules->new_rejection_rules->MIN_SCORE, (int)$reject_rules->new_rejection_rules->MAX_SCORE],
                    'bureau_type' => $application->creditReport[0]->bureau,
                    'dpd_rejection_rules' => $reject_rules->new_rejection_rules->DPD[0],
                    'keyword_rejection_rules' => $reject_rules->new_rejection_rules->KEYWORD[0],
                    'account_status_rejection_rules' => $reject_rules->new_rejection_rules->ACCOUNT_STATUS[0],
                    'principal_write_off_rules' => $reject_rules->new_rejection_rules->PRINCIPAL_WRITTEN_OFF_AMOUNT[0],
                    'total_past_dues_rules' => $reject_rules->new_rejection_rules->TOTAL_PAST_DUES[0],
                    'nach_bounce_rule' => $reject_rules->new_rejection_rules->NACH_BOUNCE
                );
                $pirimidAnalysisAvailable = DB::selectOne("SELECT id, response from pirimid_bank_analysis where application_id = ?", [$application_id]);
                if (isset($pirimidAnalysisAvailable->id)) {
                    $response = json_decode($pirimidAnalysisAvailable->response, 1);
                    $bre_api_payload['pirimid_tracking_id'] = $response['trackingId'];
                }
                $policy_name = "policy-rejection";
                $rule_list = $jsonBRE->create_rejection_rule_list($application_id, $reject_rules, $exhaustive_criteria_json);
                if($rule_list){
                    $rejectionPolicy['rule'] = $rule_list;
                }
                $bre_api_payload['grade']['rules'][$policy_name] = $rejectionPolicy;
                try{
                    $response = $jsonBRE->runAutoDecisionBRE($bre_api_payload);
                    if($this->request->has('json_bre_for_log')){
                        return $response;
                    }
                    $jsonBRE->store_jsonbre_response($response, $req_id);
                }
                catch(\Exception $e) {
                    $cwFactory->logger(json_encode(['title' => 'BRE_API run Failed', 'application_id' => $application_id, 'req_id'=> $req_id]));
                }
            }
            catch(\Exception $e) {
                $cwFactory->logger(json_encode(['title' => 'Create BRE Payload failed', 'application_id' => $application_id, 'error'=>$e]));
            }
        }
        //json bre code end

        // Separate power-saving rule from others
        $power_saving_rules = $grade_rules->filter(function ($rule) {
            $rule_details = json_decode($rule->rules);
            return isset($rule_details->power_savings) && $rule_details->power_savings === true;
        });

        $other_rules = $grade_rules->filter(function ($rule) use ($power_saving_rules) {
            return !$power_saving_rules->contains('id', $rule->id);
        });

        $allFailed = true;
        $response = null;
        $allSuccess = true;
        $success = false;
        // Run all non-power-saving rules first
        foreach ($other_rules as $grade_rule) {
            $result = $this->processRule($grade_rule, $application, $application_id, $req_id, $tableOfOffers);
            $response = $this->getLastResponse();

            $this->saveApprovalStatus($grade_rule, $application_id, $req_id, $result ? 'success' : 'failed', $response);

            if ($result) {
                $allFailed = false;
                $success = true;
                break;
            }elseif(!$result) {
                $allSuccess = false;
            }
        }
        $cwFactory->logger(json_encode(['title' => 'Auto Decision: Non Power Saving Rule done', 'application_id' => $application_id, 'allFailed' => $allFailed, 'success' => $success]));

        $is_sub_category_allowed = (isset($application->application_element->type_of_customer) && in_array($application->application_element->type_of_customer, explode(',',_env('SOLAR_SUB_CATEGORIES')))) ? true : false;
        $is_solar_on_grid = (isset($application->application_element->solar_power_type) && $application->application_element->solar_power_type == 1) ? true : false;

        $is_solar_case = ($application->purpose == _env('SOLAR_CATEGORY_ID')) ? true : false;

        $is_power_saving_grade = count($power_saving_rules) > 0 ? true : false;
        // If all other rules fail, run the power-saving rule

        if ($allFailed && $is_power_saving_grade) {
            foreach ($power_saving_rules as $power_saving_rule) {

                $result = $this->processRule($power_saving_rule, $application, $application_id, $req_id, $tableOfOffers);
                $response = $this->getLastResponse();

                $this->saveApprovalStatus($power_saving_rule, $application_id, $req_id, $result ? 'success' : 'failed', $response);

                if ($result) {
                    $allFailed = false;
                    $success = true;
                    break;
                }elseif(!$result) {
                    $allSuccess = false;
                }
            }
        }

        $cwFactory->logger(json_encode(['title' => 'Auto Decision: Power Saving Rule done', 'application_id' => $application_id, 'allFailed' => $allFailed, 'success' => $success]));

        $status = ($success) ? true : false;

        if ($tableOfOffers && (!$is_solar_case || ($is_solar_case && $is_sub_category_allowed && $is_solar_on_grid))) {
            // Call saveDecisionInTable if all rules fail including the power saving rule
            $cwFactory->logger(json_encode(['title' => 'AutoDecision: SavetoDecisionTable', 'application_id' => $application_id]));
            $decisionTableResult = $this->saveDecisionInTable($application, $status, true, $req_id);
            $cwFactory->logger(json_encode(['title' => 'Auto Decision: Power Saving Rule done', 'application_id' => $application_id, 'decisionTableResult' => $decisionTableResult]));
            return $decisionTableResult;
        }

        return !$allFailed;
    }

    /* New Multi Approval Logic */
    public function MultiApprovalCheckJSONBRE($application_id, $req_id='', $tableOfOffers = false)
    {
        $cwFactory = new CloudWatchLoggerFactory();
        $jsonBRE = new JsonBREController();
        $cwFactory->logger(json_encode(['title' => 'Auto Decision: MultiApprovalCheck', 'application_id' => $application_id]));
        //The unique generated random key to identify the rules and decisions that ran for a case at a given time.
        $req_id = $req_id != '' ? $req_id : ($this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : 0);
        $this->appId = $application_id;

        if ($req_id == 0) {
            $testImport = new TestImport(new Request());
            $requestID = $testImport->random_strings(8);
            $req_id = $requestID;
        }

        // Fetch application details
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade_v1', 'merchant.custom_grade', 'merchant.offer', 'products', 'bank_details', 'activeOffer')->where('id', $application_id)->first();
        $tableOfOffers = (isset($application->merchant->table_of_offers) && $application->merchant->table_of_offers) ? true : false;

        // Run basic checks on grades before running the approval rules
        $gradeChecks = $this->gradeChecks($application, $application_id, $tableOfOffers);

        if ($gradeChecks['status'] == 'failed' && $gradeChecks['reason'] != '') {
            $this->saveApprovalStatus(0, $application_id, $req_id, $gradeChecks['status'], $gradeChecks);
            return false;
        }


        // Custom grade conditions added in list
        if ($this->request->has('custom_grade_id')) { //$this->request->has('custom_grade_id')
            $f = Grades::find($this->request->get('custom_grade_id'));//$this->request->get('custom_grade_id')
            $t = new \stdClass();
            $t->grade = $f;
            $application['merchant'] = $t;
        }

        // ## Rule based checks:
        $grade_rules = ApprovalRule::where('grade_id', $application->merchant->grade_v1->id)->where('status', 1)->get();

        //json bre code
        $json_bre_for_log = $this->request->has('json_bre_for_log') && $this->request->get('json_bre_for_log') == 1 ? true : false;
        $jsonBREResponse = $jsonBRE->runJsonBreApproval($application->id, $req_id, $application->merchant->grade_v1->id, $tableOfOffers, $json_bre_for_log, $this->request);
        $this->adjustedABBMultiplier = $jsonBRE->adjustedABBMultiplier;
        if ($json_bre_for_log) {
            return $jsonBREResponse;
        }
        $jsonBREResponse = $jsonBREResponse->getData();
        $jsonBREresult = isset($jsonBREResponse->res) ? (array)json_decode($jsonBREResponse->res) : false;
        // $jsonBREresult = json_decode('{"policy-29":{"failed_condition":{"key":"rejected","reason":"Application was aborted or rejected in the past"},"policy_status":false,"rules":[{"against":[0,"equal"],"key":"account_status_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[33,"greaterThanEqual"],"key":"age","log":[],"reason":"Passed: 33.0 greaterThanEqual 21","result":true,"source":21},{"against":[33,"lessThanEqual"],"key":"ageAtLastEMI","log":[],"reason":"Passed: 33.0 lessThanEqual 65","result":true,"source":65},{"against":[1,"equal"],"key":"check_duplicates","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"dpd_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[1,"greaterThanEqual"],"key":"e_bill_fuzzy_match","log":[],"reason":"Passed: 1.0 greaterThanEqual 1","result":true,"source":1},{"against":["SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","inList"],"key":"employee_status","log":[],"reason":"Passed:  SALARIED inList SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","result":true,"source":"SALARIED"},{"against":[1,"equal"],"key":"guarantor","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[1,"equal"],"key":"is_pincode_approved","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"keyword_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[225000,"lessThanEqual"],"key":"max_net_loan_amount","log":[],"reason":"Passed: 225000.0 lessThanEqual 300000","result":true,"source":300000},{"against":[6,"lessThanEqual"],"key":"max_net_tenure","log":[],"reason":"Passed: 6.0 lessThanEqual 60","result":true,"source":60},{"against":[225000,"greaterThanEqual"],"key":"min_net_loan_amount","log":[],"reason":"Passed: 225000.0 greaterThanEqual 50000","result":true,"source":50000},{"against":[6,"greaterThanEqual"],"key":"min_net_tenure","log":[],"reason":"Passed: 6.0 greaterThanEqual 3","result":true,"source":3},{"against":[300000,"greaterThanEqual"],"key":"monthly_income","log":[],"reason":"Passed: 300000.0 greaterThanEqual 20000","result":true,"source":20000},{"against":[1,"equal"],"key":"negative_area","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"past_dues_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"equal"],"key":"principal_written_off_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[["rejected","aborted"],"notInList"],"key":"rejected","log":[],"reason":"Application was aborted or rejected in the past","result":false,"source":"aborted"},{"against":["812","greaterThanEqual"],"key":"score","log":[],"reason":"Passed: 812.0 greaterThanEqual 625","result":true,"source":625},{"against":["1","inList"],"key":"solar_financing_for","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1},{"against":["1","inList"],"key":"solar_power_type","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1}]},"policy-30":{"failed_condition":{"key":"rejected","reason":"Application was aborted or rejected in the past"},"policy_status":false,"rules":[{"against":[0,"equal"],"key":"account_status_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[33,"greaterThanEqual"],"key":"age","log":[],"reason":"Passed: 33.0 greaterThanEqual 21","result":true,"source":21},{"against":[33,"lessThanEqual"],"key":"ageAtLastEMI","log":[],"reason":"Passed: 33.0 lessThanEqual 65","result":true,"source":65},{"against":[1,"equal"],"key":"check_duplicates","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"dpd_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":["SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","inList"],"key":"employee_status","log":[],"reason":"Passed:  SALARIED inList SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","result":true,"source":"SALARIED"},{"against":[1,"equal"],"key":"guarantor","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[1,"equal"],"key":"is_pincode_approved","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"keyword_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[225000,"lessThanEqual"],"key":"max_net_loan_amount","log":[],"reason":"Passed: 225000.0 lessThanEqual 500000","result":true,"source":500000},{"against":[6,"lessThanEqual"],"key":"max_net_tenure","log":[],"reason":"Passed: 6.0 lessThanEqual 60","result":true,"source":60},{"against":[225000,"greaterThanEqual"],"key":"min_net_loan_amount","log":[],"reason":"Passed: 225000.0 greaterThanEqual 50000","result":true,"source":50000},{"against":[6,"greaterThanEqual"],"key":"min_net_tenure","log":[],"reason":"Passed: 6.0 greaterThanEqual 3","result":true,"source":3},{"against":[300000,"greaterThanEqual"],"key":"monthly_income","log":[],"reason":"Passed: 300000.0 greaterThanEqual 20000","result":true,"source":20000},{"against":[1,"equal"],"key":"negative_area","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"past_dues_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"equal"],"key":"principal_written_off_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[["rejected","aborted"],"notInList"],"key":"rejected","log":[],"reason":"Application was aborted or rejected in the past","result":false,"source":"aborted"},{"against":["812","greaterThanEqual"],"key":"score","log":[],"reason":"Passed: 812.0 greaterThanEqual 625","result":true,"source":625},{"against":["1","inList"],"key":"solar_financing_for","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1},{"against":["1","inList"],"key":"solar_power_type","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1},{"against":[1,"equal"],"key":"track_record","log":["XXXXXXXXXXXX8054"],"reason":"Passed: 1 equal 1","result":true,"source":1}]},"policy-31":{"failed_condition":{"key":"rejected","reason":"Application was aborted or rejected in the past"},"policy_status":false,"rules":[{"against":[0,"equal"],"key":"account_status_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[33,"greaterThanEqual"],"key":"age","log":[],"reason":"Passed: 33.0 greaterThanEqual 21","result":true,"source":21},{"against":[33,"lessThanEqual"],"key":"ageAtLastEMI","log":[],"reason":"Passed: 33.0 lessThanEqual 65","result":true,"source":65},{"against":[0,"equal"],"key":"bureau_surrogate","log":[{"Auto Loan,Used Car Loan":180000}],"reason":"Surrogate policy check failed","result":false,"source":1},{"against":[1,"equal"],"key":"check_duplicates","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"dpd_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":["SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","inList"],"key":"employee_status","log":[],"reason":"Passed:  SALARIED inList SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","result":true,"source":"SALARIED"},{"against":[1,"equal"],"key":"guarantor","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[1,"equal"],"key":"is_pincode_approved","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"keyword_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[225000,"lessThanEqual"],"key":"max_net_loan_amount","log":[],"reason":"Passed: 225000.0 lessThanEqual 500000","result":true,"source":500000},{"against":[6,"lessThanEqual"],"key":"max_net_tenure","log":[],"reason":"Passed: 6.0 lessThanEqual 60","result":true,"source":60},{"against":[225000,"greaterThanEqual"],"key":"min_net_loan_amount","log":[],"reason":"Passed: 225000.0 greaterThanEqual 50000","result":true,"source":50000},{"against":[6,"greaterThanEqual"],"key":"min_net_tenure","log":[],"reason":"Passed: 6.0 greaterThanEqual 3","result":true,"source":3},{"against":[300000,"greaterThanEqual"],"key":"monthly_income","log":[],"reason":"Passed: 300000.0 greaterThanEqual 30000","result":true,"source":30000},{"against":[1,"equal"],"key":"negative_area","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"past_dues_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"equal"],"key":"principal_written_off_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[["rejected","aborted"],"notInList"],"key":"rejected","log":[],"reason":"Application was aborted or rejected in the past","result":false,"source":"aborted"},{"against":["812","greaterThanEqual"],"key":"score","log":[],"reason":"Passed: 812.0 greaterThanEqual 700","result":true,"source":700},{"against":["1,3","inList"],"key":"solar_financing_for","log":[],"reason":"Passed:  1 inList 1,3","result":true,"source":1},{"against":["1","inList"],"key":"solar_power_type","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1}]},"policy-adjusted-abb-33":{"failed_condition":{"key":"thin_file_score","reason":"Applicant does not satisfy the thin file criteria"},"policy_status":false,"rules":[{"against":[0,"equal"],"key":"account_status_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[33,"greaterThanEqual"],"key":"age","log":[],"reason":"Passed: 33.0 greaterThanEqual 21","result":true,"source":21},{"against":[33,"lessThanEqual"],"key":"ageAtLastEMI","log":[],"reason":"Passed: 33.0 lessThanEqual 65","result":true,"source":65},{"against":[1,"equal"],"key":"check_duplicates","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"dpd_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"lessThanEqual"],"key":"emi_bounce_rule","log":[],"reason":"Passed: 0.0 lessThanEqual 1","result":true,"source":1},{"against":["SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","inList"],"key":"employee_status","log":[],"reason":"Passed:  SALARIED inList SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","result":true,"source":"SALARIED"},{"against":[1,"equal"],"key":"guarantor","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[1,"equal"],"key":"is_pincode_approved","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"keyword_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[225000,"lessThanEqual"],"key":"max_net_loan_amount","log":[],"reason":"Passed: 225000.0 lessThanEqual 500000","result":true,"source":500000},{"against":[6,"lessThanEqual"],"key":"max_net_tenure","log":[],"reason":"Passed: 6.0 lessThanEqual 60","result":true,"source":60},{"against":[7,"greaterThanEqual"],"key":"min_banking_months","log":[],"reason":"Passed: 7.0 greaterThanEqual 6","result":true,"source":6},{"against":[225000,"greaterThanEqual"],"key":"min_net_loan_amount","log":[],"reason":"Passed: 225000.0 greaterThanEqual 50000","result":true,"source":50000},{"against":[6,"greaterThanEqual"],"key":"min_net_tenure","log":[],"reason":"Passed: 6.0 greaterThanEqual 3","result":true,"source":3},{"against":[300000,"greaterThanEqual"],"key":"monthly_income","log":[],"reason":"Passed: 300000.0 greaterThanEqual 30000","result":true,"source":30000},{"against":[100,"greaterThanEqual"],"key":"name_match_threshold_pct","log":[],"reason":"Passed: 100.0 greaterThanEqual 80","result":true,"source":80},{"against":[1,"equal"],"key":"negative_area","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"past_dues_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"equal"],"key":"principal_written_off_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[["rejected","aborted"],"notInList"],"key":"rejected","log":[],"reason":"Application was aborted or rejected in the past","result":false,"source":"aborted"},{"against":["812","greaterThanEqual"],"key":"score","log":[],"reason":"Failed: [None,812]","result":null,"source":null},{"against":["1,3","inList"],"key":"solar_financing_for","log":[],"reason":"Passed:  1 inList 1,3","result":true,"source":1},{"against":["1","inList"],"key":"solar_power_type","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1},{"against":[0,"lessThanEqual"],"key":"speculative_txn_cap_pct","log":[],"reason":"Passed: 0.0 lessThanEqual 10","result":true,"source":10},{"against":["812","inBetween"],"key":"thin_file_score","log":[],"reason":"Applicant does not satisfy the thin file criteria","result":false,"source":[-1,10]}]},"policy-power-savings-32":{"failed_condition":{"key":"thin_file_score","reason":"Applicant does not satisfy the thin file criteria"},"policy_status":false,"rules":[{"against":[0,"equal"],"key":"account_status_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[33,"greaterThanEqual"],"key":"age","log":[],"reason":"Passed: 33.0 greaterThanEqual 21","result":true,"source":21},{"against":[33,"lessThanEqual"],"key":"ageAtLastEMI","log":[],"reason":"Passed: 33.0 lessThanEqual 65","result":true,"source":65},{"against":[1,"equal"],"key":"check_duplicates","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"dpd_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[1,"greaterThanEqual"],"key":"e_bill_fuzzy_match","log":[],"reason":"Passed: 1.0 greaterThanEqual 1","result":true,"source":1},{"against":["SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","inList"],"key":"employee_status","log":[],"reason":"Passed:  SALARIED inList SALARIED,BUSINESS,Self Employed - Business,Self Employed - Professional","result":true,"source":"SALARIED"},{"against":[1,"equal"],"key":"guarantor","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[1,"equal"],"key":"is_pincode_approved","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"keyword_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[225000,"lessThanEqual"],"key":"max_net_loan_amount","log":[],"reason":"Passed: 225000.0 lessThanEqual 500000","result":true,"source":500000},{"against":[6,"lessThanEqual"],"key":"max_net_tenure","log":[],"reason":"Passed: 6.0 lessThanEqual 60","result":true,"source":60},{"against":[225000,"greaterThanEqual"],"key":"min_net_loan_amount","log":[],"reason":"Passed: 225000.0 greaterThanEqual 50000","result":true,"source":50000},{"against":[6,"greaterThanEqual"],"key":"min_net_tenure","log":[],"reason":"Passed: 6.0 greaterThanEqual 3","result":true,"source":3},{"against":[300000,"greaterThanEqual"],"key":"monthly_income","log":[],"reason":"Passed: 300000.0 greaterThanEqual 30000","result":true,"source":30000},{"against":[1,"equal"],"key":"negative_area","log":[],"reason":"Passed: 1 equal 1","result":true,"source":1},{"against":[0,"equal"],"key":"past_dues_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[0,"equal"],"key":"principal_written_off_rules","log":[],"reason":"Passed: 0 equal 0","result":true,"source":0},{"against":[["rejected","aborted"],"notInList"],"key":"rejected","log":[],"reason":"Application was aborted or rejected in the past","result":false,"source":"aborted"},{"against":["812","greaterThanEqual"],"key":"score","log":[],"reason":"Failed: [None,812]","result":null,"source":null},{"against":["1,3","inList"],"key":"solar_financing_for","log":[],"reason":"Passed:  1 inList 1,3","result":true,"source":1},{"against":["1","inList"],"key":"solar_power_type","log":[],"reason":"Passed:  1 inList 1","result":true,"source":1},{"against":["812","inBetween"],"key":"thin_file_score","log":[],"reason":"Applicant does not satisfy the thin file criteria","result":false,"source":[-1,10]}]},"status":false}', 1);

        // Variables defined after the JSON BRE response success
        $allFailed = true;
        $response = null;
        $allSuccess = true;
        $success = false;
        $is_sub_category_allowed = (isset($application->application_element->type_of_customer) && in_array($application->application_element->type_of_customer, explode(',',_env('SOLAR_SUB_CATEGORIES')))) ? true : false;
        $is_solar_on_grid = (isset($application->application_element->solar_power_type) && $application->application_element->solar_power_type == 1) ? true : false;
        $is_solar_case = ($application->purpose == _env('SOLAR_CATEGORY_ID')) ? true : false;

        if ($jsonBREresult) {
            $power_saving_policies = array_filter(
                $jsonBREresult,
                function ($key) {
                    return (str_contains($key, 'power-savings') && !str_contains($key, 'status'));
                }, ARRAY_FILTER_USE_KEY // This flag tells array_filter to pass the KEY to the callback
            );

            $banking_policies = array_filter(
                $jsonBREresult,
                function ($key) {
                    return (str_contains($key, 'adjusted-abb') && !str_contains($key, 'status'));
                }, ARRAY_FILTER_USE_KEY // This flag tells array_filter to pass the KEY to the callback
            );

            $bureau_surrogate_policies = array_filter(
                $jsonBREresult,
                function ($key) {
                    return (str_contains($key, 'bureau-surrogate') && !str_contains($key, 'status'));
                }, ARRAY_FILTER_USE_KEY // This flag tells array_filter to pass the KEY to the callback
            );

            $other_policies = array_filter(
                $jsonBREresult,
                function ($key) {
                    $excluded_keys = ['power-savings', 'adjusted-abb', 'bureau-surrogate', 'status'];
                    foreach ($excluded_keys as $excluded) {
                        if (str_contains($key, $excluded)) return false;
                    }
                    return true;
                }, ARRAY_FILTER_USE_KEY
            );
        }

        if (isset($other_policies)) {
            $passedPolicies = array_reduce(array_keys($other_policies), function ($carry, $key) use ($other_policies) {
                $item = $other_policies[$key];
                if (is_object($item) && $item->policy_status && preg_match('/policy-(\d+)/', $key, $matches)) {
                    $carry[(int)$matches[1]] = $item;
                }
                return $carry;
            }, []);
            $filteredGradeRules = count($passedPolicies) > 0
                ? $grade_rules->whereIn('id', array_keys($passedPolicies))
                : collect([]);
            if (count($passedPolicies) > 0) {
                $this->policyPassed = $passedPolicies;
                $allFailed = false;
                $success = true;
            }else {
                $allSuccess = false;
            }

            $is_power_saving_grade = isset($power_saving_policies) && count($power_saving_policies) > 0 ? true : false;
            $is_banking_grade = isset($banking_policies) && count($banking_policies) > 0 ? true : false;
            $is_bureau_surrogate_grade = isset($bureau_surrogate_policies) && count($bureau_surrogate_policies) > 0 ? true : false;

            if ($is_power_saving_grade) {
                foreach ($power_saving_policies as $policy_name => $power_saving_rule) {
                    if ($power_saving_rule->policy_status) {
                        $rule_id = array_map( function ($policy_name) {preg_match('/policy-power-savings-(\d+)/', $policy_name, $matches); return isset($matches[1]) ? (int)$matches[1] : null;}, [$policy_name]);
                        $this->powerSavingPolicyPassed[] = $grade_rules->filter(function ($rule) use ($rule_id) {return $rule->id == $rule_id[0];})->first();
                        $allFailed = false;
                        $success = true;
                        break;
                    }elseif(!$power_saving_rule->policy_status) {
                        $allSuccess = false;
                    }
                }
            }

            if ($is_banking_grade){
                foreach ($banking_policies as $policy_name => $banking_rule) {
                    if ($banking_rule->policy_status){
                        $rule_id = array_map( function ($policy_name) {preg_match('/policy-adjusted-abb-(\d+)/', $policy_name, $matches); return isset($matches[1]) ? (int)$matches[1] : null;}, [$policy_name]);
                        $this->bankingPolicyPassed[] = $grade_rules->filter(function ($rule) use ($rule_id) {return $rule->id == $rule_id[0];})->first();
                        $allFailed = false;
                        $success = true;
                    }elseif(!$banking_rule->policy_status) {
                        $allSuccess = false;
                    }
                }
            }

            if ($is_bureau_surrogate_grade) {
                foreach ($bureau_surrogate_policies as $policy_name => $bureau_policy_rule) {
                    if ($bureau_policy_rule->policy_status){
                        $rule_id = array_map( function ($policy_name) {preg_match('/policy-bureau-surrogate-(\d+)/', $policy_name, $matches); return isset($matches[1]) ? (int)$matches[1] : null;}, [$policy_name]);
                        $this->bureauSurrogatePolicyPassed[] = $grade_rules->filter(function ($rule) use ($rule_id) {return $rule->id == $rule_id[0];})->first();
                        $allFailed = false;
                        $success = true;
                    }elseif(!$bureau_policy_rule->policy_status) {
                        $allSuccess = false;
                    }
                }
            }

            if (isset($this->bureauSurrogatePolicyPassed) && count($this->bureauSurrogatePolicyPassed) > 0) {
                $this->bureauSurrogateLimits = $this->extractBureauSurrogateLimits($bureau_policy_rule);
            }

            $cwFactory->logger(json_encode(['title' => 'Auto Decision: TOF prep', 'application_id' => $application_id, 'allFailed' => $allFailed, 'success' => $success]));
            $status = ($success) ? true : false;
            $netLoanAmount = (new autoBRE())->calculateNetLoanAmount($application->loan_amount, $application->activeOffer);

            if ($tableOfOffers && (!$is_solar_case || ($is_solar_case && $is_sub_category_allowed && $is_solar_on_grid)) && $netLoanAmount < 500000 && $status) {
                return $this->initiateTableOfOffers($application, $status, $req_id, $application_id, $filteredGradeRules);
            }
        }

        return !$allFailed;
    }


    /**
     * Extract bureau_surrogate limits from a single passed policy.
     *
     * Finds the bureau_surrogate rule inside $policy->rules, then flattens
     * the log array (each entry is an object whose key is one or more
     * comma-separated loan-type names and whose value is the limit amount)
     * into a plain associative array: [ 'Auto Loan' => 180000, ... ]
     *
     * @param  object  $policy  A single policy object from the JSON-BRE result
     * @return array            [ loanType => limitAmount, ... ] or [] if not present
     */
    public function extractBureauSurrogateLimits($policy): array
    {

        foreach ($policy->rules as $rule) {
            if (isset($rule->key) && $rule->key === 'bureau_surrogate' && !empty($rule->log)) {
                $bureauSurrogateRules[] = $rule;
                break;
            }
        }

        if (!isset($bureauSurrogateRules)) {
            return [];
        }

        $limits = [];
        foreach ($bureauSurrogateRules as $bureauSurrogateRule) {
            foreach ($bureauSurrogateRule->log as $logEntry) {
                // Each log entry is an object/array with one or more loan type keys
                $logEntry = (array) $logEntry;
                foreach ($logEntry as $loanTypes => $limitAmount) {                    
                    $limits[] = $limitAmount;
                }
            }
        }

        return $limits;
    }



    /* Basic condition checks */
    public function gradeChecks($application, $application_id, $tableOfOffers){
        $status = $reason = $failed_condition = '';
        // Check if all details are fetched appropriately
        if(!$application || (!$tableOfOffers && !$application->emi) || !$application->application_element || (isset($application->creditReport[0]) && !$application->creditReport[0]) || !$application->foir || !$application->merchant->offer || !$application->products){
            $status = 'failed';
            $reason = 'Failed to fetch data from tables and relations';
        }

        // Check the bureau report exists for the case
        if ($status == '' && (!isset($application->creditReport[0]) || !isset($application->creditReport[0]->Score))) {
            $status = 'failed';
            $reason = 'Bureau not pulled';
            $failed_condition = json_encode(['score' => "no_equifax"]);
        }

        // Handle incorrect Merchant details or linking
        if ($status == '' && (!$application->merchant || (isset($application->merchant) && !$application->merchant->grade_v1))) {
            $status = 'failed';
            if(!$application->merchant){
                $reason = "Merchant not set";
            }
            if(isset($application->merchant) && !$application->merchant->grade_v1){
                $reason = "Merchant grade not set";
            }
            if(isset($application->merchant) && !$application->merchant->custom_grade_id){
                $reason = "Custom grade is not set properly";
            }
        }

        // Check for merchant status
        if ($status == '' && $application->merchant->status == 'inactive' /*&& $application->merchant->pre_status == 1*/) {
            $status = 'failed';
            $reason = "Merchant is not eligible for auto approval";
        }

        // Check if the merchant has auto approval enabled
        if ($status == '' && !$application->merchant->is_auto_approve) {
            $status = 'failed';
            $reason = "Merchant does not have auto-approval enabled";
        }

        // Check if the applicant is blacklisted by the RBI
        if($status == '') {
            $rbiBlack = (new ConsumerApplicationController())->getBlacklistData($application);
            if ($rbiBlack['status']) {
                $status = 'failed';
                $failed_condition = json_encode(['black_list' => true]);
                $reason = "The RBI has blacklisted this applicant";
            }
        }

        if(!$tableOfOffers) {
            // Handle Table of offers
            if ($status == '' && $application->merchant->table_of_offers) {
                event(new EventTableOfOffer(['id' => $application_id]));
            }
        }

        // Handle merchant's eligibility for max approval
        if($status == '') {
            $total = DB::table('consumer_application')->select(DB::raw('count(*) as app_count'), DB::raw('SUM(approved_amount) as total_approved_amount'))->where('merchant_id', $application->merchant_id)->whereIn('state', ['approved', 'disbursement checklist done', 'disbursement query', 'ready for disbursement', 'disbursed', 'nach registered', 'closed'])->first();
            $total_remaining_amount = $application->merchant->max_approval_value - $total->total_approved_amount;
            if ($application->loan_amount > $total_remaining_amount || $total->total_approved_amount > $application->merchant->max_approval_value || $total->app_count >= $application->merchant->max_no_cases) {
                $status = 'failed';
                if ($application->loan_amount > $total_remaining_amount) {
                    $reason = "Application loan amount greater than total remaining amount";
                    $failed_condition = json_encode(['total_remaining_amount' => $total_remaining_amount]);
                } elseif ($total->total_approved_amount > $application->merchant->max_approval_value) {
                    $reason = "Total approved amount greater than max approval limit";
                    $failed_condition = json_encode(['max_approval_value' => $application->merchant->max_approval_value]);
                } elseif ($total->app_count >= $application->merchant->max_no_cases) {
                    $reason = "Total application count limit reached";
                    $failed_condition = json_encode(['max_no_cases' => $application->merchant->max_no_cases]);
                }
            }
        }

        // Check if loan amount is not more than product value
        if($status == '' && !empty($application->application_element->product_name) && $application->products && count($application->products) > 0){
            $appl_prod = explode(',', $application->application_element->product_name);
            $products = Products::whereIn('id', $appl_prod)->get();
            $amount = 0;
            foreach($products as $product){
                $amount += $product->amount;
            }
            if($amount != 0 && $amount < $application['loan_amount']){
                $failed_condition = json_encode(['product_loan_amount' => $application['loan_amount'] - $amount]);
                $reason = "Loan amount is greater than the product amount";
                $status = 'failed';
            }
        }


        return ['status' => $status, 'failed_condition' => $failed_condition, 'reason' => $reason];
    }
    /* Rule based condition checks */
    public function ruleBasedCheck($application, $application_id, $key, $value, $rule_details, $tableOfOffers){
        $termloanarray = ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan',
            'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility',
            'Business Non-Funded Credit Facility - Priority', 'Staff Loan'];
        if ($application->creditReport[0]->Score < 10) {
            $oldloan = 0;
            $unsecuredloan = 0;
        } else {
            $oldloan = 1;
            $unsecuredloan = 1;
        }

        if(($key == 'foir' || $key == 'cf_foir') && $this->foirIncludingCFEMI < 1 && $this->cfFoir < 1){

            foreach ($application->foir as $foir) {
                $this->setFOIRAttributes($foir);
            }
            $this->getFOIRCalculation($application);
        }

        $offers = false;
        if($tableOfOffers) {
            $products = array_map('intval', array_map('trim', explode(',', $application->application_element->product_name)));
            $productOffers = ProductOffers::whereIn('product_id', $products)->whereNull('deleted_at')->pluck('offer_id');
            if (!$productOffers->isEmpty()) {
                $offers = MerchantOffers::whereIn('id', $productOffers)->where('status', 1)->whereNull('deleted_at')->get();
            } else {
                $offers = MerchantOffers::where('merchant_id', $application->merchant_id)->whereNull('deleted_at')->where('status', 1)->get();
            }
        }

        $failed_condition = $reason = '';
        // $key = 'epf_verification';
        switch($key){
            case 'thin_file':
                if ($application->creditReport[0]->Score > 10 || $application->creditReport[0]->Score < -1) {
                    $failed_condition = json_encode(['score' => $application->creditReport[0]->Score]);
                    $reason = "Applicant does not satisfy the thin file criteria";
                }
                break;
            case 'min_loan_amount':
                // Check if the requested loan amount meets the expected criteria
                $min_loan_amount = (isset($value) && !empty($value)) ? $value : 0;
                if ($application->loan_amount == 0 || $application->loan_amount < $min_loan_amount || $min_loan_amount == 0 || empty($min_loan_amount)) {
                    $failed_condition = json_encode(['min_loan_amount' => $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount]);
                    $reason = "Requested loan amount does not match the grade criteria";
                }
                break;
            case 'max_loan_amount':
                // Check if the requested loan amount meets the expected criteria
                $max_loan_amount = (isset($value) && !empty($value)) ? $value : 0;
                if ($application->loan_amount == 0 || $application->loan_amount > $max_loan_amount || $max_loan_amount == 0 || empty($max_loan_amount)) {
                    $failed_condition = json_encode(['max_loan_amount' => $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount]);
                    $reason = "Requested loan amount does not match the grade criteria";
                }
                break;
            case 'foir':
            case 'cf_foir':
                if($offers && $tableOfOffers) {
                    foreach ($offers as $offer) {

                        $this->request->merge(['merchant_id' => $application->merchant_id, 'loan_amount' => $application->loan_amount, 'merchant_offer_id' => $offer->id, 'category_id' => $application->purpose, 'interest_type_id' => $offer->interest_type_id, 'application_id' => $application->id, 'offer_obj' => $offer, 'charge_subvention_remaining_amount' => $application->merchant->charge_subvention_remaining_amount ?? 0]);

                        $_grade_ = new GradeController($this->request);

                        $emi = new EMICalculation($this->request);
                        $res = $emi->prepareCalculation();

                        $res = $res->getData();

                        $this->cfFoir = 0;
                        $this->foirIncludingCFEMI = 0;
                        foreach ($application->foir as $foir) {
                            if($foir->applicant_type != 2) {
                                $_grade_->setFOIRAttributes($foir);
                            }
                        }
                        $_grade_->getFOIRCalculation($application, $res->emi);
                        $this->emiData[$offer->id] = ['emi' => $res->emi, 'payable' => $res->payable, 'interest_rate' => $res->flat_annual_interest, 'processing_fee' => $res->processing_fee, 'upfront_from_customer' => $res->up_front_from_customer,'tenure'=> $res->emi_remaining];

                        if($key == 'foir') {
                            $_foir = (isset($value) && !empty($value)) ? $value : 0;
                            if ($_grade_->foirIncludingCFEMI > $_foir) {
//                                $this->foir = $this->foirIncludingCFEMI;
                                $this->Afoir[] = ['offer_id' => $offer->id, 'foirIncludingCFEMI' => $_grade_->foirIncludingCFEMI, 'status' => 1];
                                //return $this;
                            } else {
                                $this->Afoir[] = ['offer_id' => $offer->id, 'foirIncludingCFEMI' => $_grade_->foirIncludingCFEMI, 'status' => 0];
                            }
                        }

                        if($key == 'cf_foir') {
                            $_cf_foir = (isset($value) && !empty($value)) ? $value : 0;
                            if ($_grade_->cfFoir > $_cf_foir) {
//                                $this->cf_foir = $this->cfFoir;
                                $this->Acf_foir[] = ['offer_id' => $offer->id, 'cfFoir' => $_grade_->cfFoir, 'status' => 1];
                                //return $this;
                            } else {
                                $this->Acf_foir[] = ['offer_id' => $offer->id, 'cfFoir' => $_grade_->cfFoir, 'status' => 0];
                            }
                        }
                    }
                }else {
                    if($key == 'foir') {
                        $_foir = (isset($value) && !empty($value)) ? $value : 0;
                        if ($this->foirIncludingCFEMI > $_foir) {
                            $failed_condition = json_encode(['foir' => $this->foirIncludingCFEMI]);
                            $reason = "Applicant\'s FOIR does not match the grade criteria";
                        }
                    }

                    if($key == 'cf_foir'){
                        $_cf_foir = (isset($value) && !empty($value)) ? $value : 0;
                        if ($this->cfFoir > $_cf_foir) {
                            $failed_condition = json_encode(['cf_foir' => $this->cfFoir]);
                            $reason = "Applicant's CF FOIR does not match the grade criteria";
                        }
                    }
                }
                break;
            case 'tenure':
                if($offers && $tableOfOffers) {
                    foreach ($offers as $offer) {

                        $_tenure = $offer->tenure;
                        if ($offer->advance_type == 'emi') {
                            $_tenure = $offer->tenure - $offer->advance_emi;
                        }

                        // if (!$application->emi || $tenure == 0 || empty($tenure) || (isset($application->emi) && $_tenure > $tenure))
                        if ($value == 0 || empty($value) || (isset($application->emi) && $_tenure > $value)){
                            $this->tenure = !$_tenure ? 'no offer found' : $_tenure;
                            $this->Atenure[] = ['tenure' => !$_tenure ? 'no offer found' : $_tenure, 'offer_id' => $offer->id, 'status' => 1];
                            //return $this;
                        }else{
                            $this->Atenure[] = ['tenure' => !$_tenure ? 'no offer found' : $_tenure, 'offer_id' => $offer->id, 'status' => 0];
                        }
                    }
                }else{
                    // Check if the requested tenure meets the expected criteria
                    $tenure = (isset($value) && !empty($value)) ? $value : 0;
                    if (!$application->emi || $tenure == 0 || empty($tenure) || (isset($application->emi) && $application->emi->remaining_emi > $tenure)) {
                        $failed_condition = json_encode(['tenure' => !isset($application->emi->remaining_emi) ? 'emi not generated' : $application->emi->remaining_emi]);
                        $reason = "Requested tenure does not match the grade criteria";
                    }
                }
                break;
            case 'score':
                // Check if the applicant's score meets the grade criteria
                if ($application->creditReport[0]->Score < $value) {
                    $failed_condition = json_encode(['score' => $application->creditReport[0]->Score]);
                    $reason = "Applicant score does not match the grade criteria";
                }
                break;
            case 'power_savings':
                    // Check if the EMI should be less than or equal to the power saving.
                if($application->purpose == _env('SOLAR_CATEGORY_ID')){
                    $power_saving_value = isset($application->application_element->inverter_power_savings) ? (float)$application->application_element->inverter_power_savings : 0;

                    if ($application->emi->emi > $power_saving_value) {
                        $failed_condition = json_encode(['power_saving' => $power_saving_value]);
                        $reason = "EMI should be less than or equal to the power saving";
                        break;
                    }
                }
                break;
            case 'employee_status':
                // Check if the employee status meets the grade criteria
                if(isset($application->employee_status) && $value){
                    $value = explode(',',$value);
                    if(!in_array($application->employee_status, $value)) {
                        $failed_condition = json_encode(['employee_status' => true]);
                        $reason = "Employee's current status does not match the grade criteria";
                    }
                }
                break;
            case 'monthly_income':
                // Check if the monthly income meets the expected criteria
                $monthly_income = (isset($value) && !empty($value)) ? $value : 0;
                if (!$application->monthly_income || $monthly_income == 0 || empty($monthly_income) || ($application->monthly_income < $monthly_income)) {
                    $failed_condition = json_encode(['monthly_income' => $application->monthly_income]);
                    $reason = "Applicants monthly income does not match the grade criteria";
                }
                break;
            case 'age':
                // Check the age of the applicant at the time of application
                $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
                $grade_age = (isset($value) && !empty($value)) ? $value : 0;
                if ($grade_age == 0 || empty($grade_age) || $age < $grade_age) {
                    $failed_condition = json_encode(['age' => $age]);
                    $reason = "Applicant age does not match the grade criteria";
                }
                break;
            case 'ageAtLastEMI':
                // Check the age of the applicant at the end of his tenure
                if($application->emi) {
                    $last_emi_date = Carbon::now()->addMonths($application->emi->remaining_emi)->toDateString();
                    $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
                    $ageLimit = $value ?? 60;
                    if (isset($ageAtLastEMI)) {
                        if ($ageAtLastEMI > $ageLimit) {
                            $failed_condition = json_encode(['ageAtLastEMI' => $ageAtLastEMI]);
                            $reason = "Applicant's age at the end of tenure does not match the grade criteria";
                        }
                    }
                }
                break;
            case 'term_loan_amount_paid':
                $maxSanctioned = [];
                foreach ($application->foir as $foir) {
                    if ($foir->applicant_type == 1) {
                        if ($foir->DateOpened && !$foir->DateClosed) {
                            if (!$foir->DateClosed) {
                                $foir->DateClosed = "";
                            }
                            $termLoan = self::calculatedifferenceindate($foir->DateOpened);

                            if ($termLoan > 0) {
                                $oldloan = 0;
                            }

                            if ((in_array($foir->AccountType, $termloanarray))) {
                                $unsecuredloan = 0;
                            }

                            if (in_array($foir->AccountType, $termloanarray) && $oldloan == 0 && $unsecuredloan == 0 && $foir->DateClosed == '') {
                                $maxSanctioned[] = $foir->ApprovedAmount - $foir->Balance;
                            }
                        }
                    }
                }
                if($value && $application->loan_amount && $maxSanctioned){
                    $crLimitShould = $application->loan_amount * $value / 100;
                    if(max($maxSanctioned) < $crLimitShould){
                        $failed_condition = json_encode(['amount_paid' => $crLimitShould]);
                        $reason = "Due amount for old and open unsecure loans does not match the grade criteria";
                    }
                }
                break;
            case 'credit_card_amount_paid':
                $creditCardAmount = 0;
                $creditCardLimit = [];
                foreach ($application->foir as $foir) {
                    if ($foir->AccountType == 'Credit Card' && $foir->DateClosed == '') {
                        $creditCardAmount += $foir->InstallmentAmount;
                        $creditCardLimit[] = $foir->ApprovedAmount - $foir->Balance;
                    }
                }
                if($value && $application->loan_amount && $creditCardLimit){
                    $crLimitShould = $application->loan_amount * $value / 100;
                    if(max($creditCardLimit) < $crLimitShould){
                        $failed_condition = json_encode(['amount_paid_cr' => $crLimitShould]);
                        $reason = "Credit Card tradeline due amount does not match the grade criteria";
                    }
                }
                // if(!$creditCardLimit){
                //     $failed_condition = json_encode(['amount_paid_cr' => 'No Acive CC Tradeline']);
                //         $reason = "Active Credit Card tradeline does not exist in the grade criteria";
                // }
                break;
            // case 'epf_verification':
            //     // Verify EPF details of salaried applicants
            //     if($value && strtolower($application->employee_status) == 'salaried') {
            //         $epf = EPFUANLookup::where('application_id', $application->id)->first();
            //         if(isset($epf['data'])){
            //             $epf_data = json_decode($epf['data'], 1);
            //             $isEmployed = $uanNameMatch = false;
            //             if($epf_data['result']['uan'] && is_array($epf_data['result']['uan'])) {
            //                 foreach ($epf_data['result']['uan'] as $uanData) {
            //                     foreach ($uanData['employer'] as $uanDataEmployer) {
            //                         if(strtolower($uanDataEmployer['name']) == strtolower($epf->employerName)){
            //                             $isEmployed = $uanDataEmployer['isEmployed'] ?? false;
            //                             $uanNameMatch = $uanDataEmployer['uanNameMatch'] ?? false;
            //                             // $isRecent = $uanDataEmployer['uanNameMatch'] ?? false;
            //                         }
            //                     }
            //                 }
            //             }
            //             if(!$isEmployed || $isEmployed == false || !$uanNameMatch || $uanNameMatch == false || (strtolower($application->company->company) != strtolower($epf->employerName))){
            //                 if(!$isEmployed || $isEmployed == false){
            //                     $reason = "epf employement verification failed - epf";
            //                 // }else if(!$uanNameMatch || $uanNameMatch == false){
            //                 //     $reason = "Uan name not matched - epf";
            //                 }else if(strtolower($application->company->company) != strtolower($epf->employerName)){
            //                     $reason = "Employee name not matched - epf";
            //                 }

            //                 $failed_condition = json_encode(['epf_verification' => true]);
            //             }
            //         }
            //         else {
            //             $reason = "No EPF Data Found";
            //             $failed_condition = json_encode(['epf_verification' => true]);

            //         }
            //     }
            //     break;
            case 'epf_verification':
                // Verify EPF details of salaried applicants
                if($value && strtolower($application->employee_status) == 'salaried') {
                    $epf = EPFUANLookup::where('application_id', $application->id)->first();
                    if(isset($epf['data'])){
                        $epf_data = json_decode($epf['data'], 1);
                        $summary = $epf_data['result']['summary'];
                        if (isset($summary)){
                            $current_employer = $summary['uanLookup']['currentEmployer'];
                            if($current_employer){
                                $uan_data = $epf_data['result']['uan'][0]['employer'];
                                $current_employer_details = array_filter($uan_data, function($employer) use ($current_employer) {
                                    return $employer['name'] === $current_employer;
                                });
                                if($current_employer_details){
                                    $isEmployed = $current_employer_details[0]['isEmployed'];
                                    $isRecent = $current_employer_details[0]['isRecent'];
                                }
                            }
                        }
                        if(!$isEmployed || $isEmployed == false || !$isRecent || $isRecent == false){
                            $failed_condition = json_encode(['epf_verification' => true]);
                            if(!$isEmployed || $isEmployed == false){
                                $reason = "epf employment verification failed - epf";
                            }else if(!$isRecent || $isRecent == false){
                                $reason = "PF Filing not Recent - epf";
                            }
                        }
                    }
                    else {
                        $reason = "No EPF Data Found";
                        $failed_condition = json_encode(['epf_verification' => true]);

                    }
                }
                break;
            case 'fetch_gst':
                // Verify GST details of self-employed applicants
                if($value) {
                    $emp_status = ['business', 'self employed - business', 'self employed - professional'];
                    if(in_array(strtolower($application->employee_status), $emp_status)) {
                        $gst_pan_data = GSTPANData::where('application_id', $application->id)->orderBy('created_at', 'desc')->first();
                        $gst_data = json_decode($gst_pan_data['data']);
                        if(!isset($gst_data->result[0]->authStatus) || (isset($gst_data->result[0]->authStatus) && $gst_data->result[0]->authStatus == 'Inactive')){
                            $failed_condition = json_encode(['fetch_gst' => true]);
                            $reason = "GST verification failed";
                        }
                    }
                }
                break;
            case 'is_pincode_approved_or_risky':
                // Check if the applicant's address pincode is approved and matches the grade criteria
                $is_installation_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->application_element->installation_address_pincode)->first();
                $is_current_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->current_address_pincode)->first();
                if((!isset($is_current_address_pin_approved)) && (empty($is_current_address_pin_approved)) || ((!isset($is_installation_address_pin_approved)) && empty($is_installation_address_pin_approved))){
                    $failed_condition = json_encode(['approved_pin' => true]);
                    $reason = "Applicant's address pincode is not approved";
                }
                break;
            case 'negative_area':
                // Check if the applicant lives in negative location
                if (((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) || ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode))) {
                    $data['current_pincode'] = ((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) ? $application->current_address_pincode : "";
                    $data['installation_pincode'] = ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode)) ? $application->application_element->installation_address_pincode : "";
                    $consumerApplicationConreoller = new ConsumerApplicationController();
                    $NegativeArearesponse = $consumerApplicationConreoller->getNegativeAreaList($data);
                    if ($NegativeArearesponse && isset($NegativeArearesponse->level) && $NegativeArearesponse->level == 1) {
                        $failed_condition = json_encode(['negative_area' => "Negative Area"]);
                        $reason = "Applicant's address is considered in negative area";
                    }
                }
                break;
            case 'rejected':
                // Check if the application was aborted or rejected in the past
                $status_array = ['aborted', 'rejected'];
                $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->first(['id']);
                if (isset($status_log->id)) {
                    $failed_condition = json_encode(['rejected' => true]);
                    $reason = "Application was aborted or rejected in the past";
                }
                break;
            case 'guarantor':
                $flag = 0;
                foreach ($application->foir as $foir) {
                    if ($foir->applicant_type == 1) {
                        $ownership_types[] = $foir->OwnershipType;
                    }
                }
                if (isset($ownership_types) && count($ownership_types) != 0 ) {
                    foreach($ownership_types as $ownership_type) {
                        if ($ownership_type != 'Guarantor') {
                            $flag = 1;
                        }
                    }
                    if($flag == 0){
                        $failed_condition = json_encode(['guarantor' => true]);
                        $reason = "Applicant has a tradeline as a Guarantor";
                    }
                }
                break;
            case 'check_duplicates':
                // De-dupe Check
                $checkDuplicates = $this->checkDuplicates($application);
                if($checkDuplicates == false){
                    $failed_condition = json_encode(['checkDuplicates' => true]);
                    $reason = "Repeat applicant";
                }
                break;
            case 'accountType':
                $gold_loan = 0;
                $accountType = '';
                foreach ($application->foir as $foir) {
                    if ($foir->applicant_type == 1) {
                        if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                            $gold_loan++;
                            if ($gold_loan >= 3) {
                                $accountType = $foir->AccountType;
                                break;
                            }
                        }
                    }
                }
                if($accountType != ''){
                    $failed_condition = json_encode(['accountType' => $accountType]);
                    $reason = "Gold Loan tradeline count does not match the grade criteria";
                }
                break;
            case 'no_owned_house':
                // Check if the applicant owns a house to meet the grade criteria
                if ((!isset($application->current_address_status)) || empty($application->current_address_status) || (isset($application->current_address_status) && !in_array($application->current_address_status, array('OWNED', 'PARENTS HOUSE', 'Self Owned', 'Parent Owned')))) {
                    $failed_condition = json_encode(['address_status' => "No Owned House"]);
                    $reason = "No house is owned to match the grade criteria";
                }
                break;
            case 'zero_downpayment':
                // Check if the down payments details are present to meet the grade criteria
                if($application->emi) {
                    if (!$application->emi || (isset($application->emi) && $application->emi->upfront_from_customer <= 0)) {
                        if (!in_array($application->merchant_id, [5983, 5984, 5980, 5803])) {
                            $failed_condition = json_encode(['downpayment' => isset($application->emi->upfront_from_customer) ? "Zero Downpayment" : 'emi_not_generated']);
                            $reason = "No down-payment amount present to match the grade criteria";
                        }
                    }
                }
                break;
            case 'caseType':
                $case_exist = '';
                foreach ($application->foir as $foir) {
                    if ($foir->applicant_type == 1) {
                        $foirData = json_decode($foir->dpd, 1);
                        $casetypeValues = $value ?? null;
                        if ($casetypeValues != '') {
                            $keywords = [];
                            $array = explode(",", $casetypeValues);
                            foreach ($array as $item) {
                                array_push($keywords, $item);
                            }

                            if ($foirData) {
                                $caseType = array_keys($foirData);
                                if ($caseType) {
                                    foreach ($caseType as $type) {
                                        if (in_array($type, $keywords)) {
                                        $case_exist = $type;
                                        break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if($case_exist != '') {
                    $failed_condition = json_encode(['caseType' => $case_exist]);
                    $reason = "DPD case type does not match the grade criteria";
                }
                break;
            case 'dpd_years_above_zero':
            case 'dpd_count_above_zero':
                $dpdCountRejection = 0;
                if(isset($rule_details->dpd_years_above_zero) && isset($rule_details->dpd_count_above_zero)) {
                    foreach ($application->foir as $foir) {
                        if ($foir->applicant_type == 1) {
                            $foirData = json_decode($foir->dpd, 1);
                            $yearsLimit = $rule_details->dpd_years_above_zero; // ?? 2;
                            $countLimit = $rule_details->dpd_count_above_zero; // ?? 6;
                            $noDPDDateRange = Carbon::now()->subYear($yearsLimit)->startOfDay()->toDateTimeString(); //no of dpd’s greater than 6 which is more the 1-15 days in last 2 year)
                            if (strtotime($foir->DateOpened) >= strtotime($noDPDDateRange)) {
                                $dpdCount = 0;
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $dpdCount += $item;
                                        if ($dpdCount > $countLimit) {
                                            $dpdCountRejection = 1;
                                            break;
                                        }
                                    }
                                }
                            }
                            if ($dpdCountRejection > 0) {
                                break;
                            }
                        }
                    }
                } else{
                    $failed_condition = json_encode(['dpdCountRejection' => 1]);
                    $reason = "DPD count not configured properly";
                }
                if($key == 'dpd_count_above_zero'){
                    if(isset($rule_details->dpd_years_above_zero)) { unset($rule_details->dpd_years_above_zero); }
                }elseif($key == 'dpd_years_above_zero'){
                    if(isset($rule_details->dpd_count_above_zero)) { unset($rule_details->dpd_count_above_zero); }
                }
                if($dpdCountRejection > 0) {
                    $failed_condition = json_encode(['dpdCountRejection' => 1]);
                    $reason = "DPD count does not not match the grade criteria";
                }
                break;
            case 'pre_dpd_years':
            case 'pre_dpd_count':
            case 'pre_dpd_keywords':
                $dpdRange = 0;
                $dpdSumAllTradeline = 0;
                if(isset($rule_details->pre_dpd_count) && isset($rule_details->pre_dpd_years) && isset($rule_details->pre_dpd_keywords)) {
                    foreach ($application->foir as $foir) {
                        if ($foir->applicant_type == 1) {
                            $foirData = json_decode($foir->dpd, 1);
                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                            $dpdRange = $rule_details->pre_dpd_count; // ?? 0;
                            $dateRange = $rule_details->pre_dpd_years; // ?? 3;
                            $created_at = Carbon::parse($foir->created_at);
                            $diff_days = $foir->DateOpened ? $created_at->diffInDays($foir->DateOpened) : 0;
                            $dpdkeywords = $rule_details->pre_dpd_keywords; // ?? null;
                            $all_keywords = [];
                            $years = ($diff_days) / 365;
                            if (isset($dpdkeywords) && $dpdkeywords != '') {
                                $keywords = explode(",", $dpdkeywords);
                                foreach ($keywords as $key) {
                                    $keyword = trim($key);
                                    $keyword = trim($keyword, '"');
                                    array_push($all_keywords, $keyword);
                                }
                            }
                            if ($foirClean) {
                                if ($years <= $dateRange) {
                                    foreach ($foirData as $key => $item) {
                                        if (!in_array($key, $all_keywords)) {
                                            $dpdSumAllTradeline += $item;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else{
                    $failed_condition = json_encode(['pre_dpd' => $dpdSumAllTradeline]);
                    $reason = "Pre DPD count not configured properly";
                }
                if($key == 'pre_dpd_years'){
                    if(isset($rule_details->pre_dpd_count)) { unset($rule_details->pre_dpd_count); }
                    if(isset($rule_details->pre_dpd_keywords)) { unset($rule_details->pre_dpd_keywords); }
                }elseif($key == 'pre_dpd_count'){
                    if(isset($rule_details->pre_dpd_years)) { unset($rule_details->pre_dpd_years); }
                    if(isset($rule_details->pre_dpd_keywords)) { unset($rule_details->pre_dpd_keywords); }
                }elseif($key == 'pre_dpd_keywords'){
                    if(isset($rule_details->pre_dpd_years)) { unset($rule_details->pre_dpd_years); }
                    if(isset($rule_details->pre_dpd_count)) { unset($rule_details->pre_dpd_count); }
                }
                if ($dpdSumAllTradeline > $dpdRange) {
                    $failed_condition = json_encode(['pre_dpd' => $dpdSumAllTradeline]);
                    $reason = "Pre DPD count (within a certain period) does not not match the grade criteria";
                }
                break;
            case 'post_dpd_year':
            case 'post_dpd_count':
            case 'post_dpd_keywords':
                $dpdRangeAbove = 0;
                $dpdSumAllTradelineAbove = 0;
                if(isset($rule_details->post_dpd_count) && isset($rule_details->post_dpd_year) && isset($rule_details->post_dpd_keywords)) {
                    foreach ($application->foir as $foir) {
                        if ($foir->applicant_type == 1) {
                            $foirData = json_decode($foir->dpd, 1);
                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                            $dpdRangeAbove = $rule_details->post_dpd_count; // ?? 15;
                            $dateRange = $rule_details->post_dpd_year; // ?? 3;
                            $foirDateRange = Carbon::now()->subYear($dateRange)->startOfDay()->toDateTimeString();
                            $created_at = Carbon::parse($foir->created_at);
                            $diff_days = $foir->DateOpened ? $created_at->diffInDays($foir->DateOpened) : 0;
                            $aboveDpdKeywords = $rule_details->post_dpd_keywords; // ?? null;
                            $all_keywords_above = [];
                            $years = ($diff_days) / 365;
                            if (isset($aboveDpdKeywords) && $aboveDpdKeywords != '') {
                                $keywords = explode(",", $aboveDpdKeywords);
                                foreach ($keywords as $_key) {
                                    $keyword = trim($_key);
                                    $keyword = trim($keyword, '"');
                                    array_push($all_keywords_above, $keyword);
                                }
                            }
                            if ($foirClean) {
                                if ($years >= $dateRange) {
                                    foreach ($foirData as $key => $item) {
                                        if (!in_array($key, $all_keywords_above)) {
                                            $dpdSumAllTradelineAbove += $item;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else{
                    $failed_condition = json_encode(['post_dpd' => $dpdSumAllTradelineAbove]);
                    $reason = "Post DPD count not configured properly";
                }
                if($key == 'post_dpd_year'){
                    if(isset($rule_details->post_dpd_count)) { unset($rule_details->post_dpd_count); }
                    if(isset($rule_details->post_dpd_keywords)) { unset($rule_details->post_dpd_keywords); }
                }elseif($key == 'post_dpd_count'){
                    if(isset($rule_details->post_dpd_year)) { unset($rule_details->post_dpd_year); }
                    if(isset($rule_details->post_dpd_keywords)) { unset($rule_details->post_dpd_keywords); }
                }elseif($key == 'post_dpd_keywords'){
                    if(isset($rule_details->post_dpd_year)) { unset($rule_details->post_dpd_year); }
                    if(isset($rule_details->post_dpd_count)) { unset($rule_details->post_dpd_count); }
                }

                if ($dpdSumAllTradelineAbove > $dpdRangeAbove) {
                    $failed_condition = json_encode(['post_dpd' => $dpdSumAllTradelineAbove]);
                    $reason = "Post DPD count (above a certain period) does not not match the grade criteria";
                }

            break;
            case 'past_dues':
                $creditReport = $application->creditReport[0];
                $pastDueLimit = (int)$value;
                if ($creditReport->TotalPastDue > $pastDueLimit) {
                    $failed_condition = json_encode(['pastDues' => $creditReport->TotalPastDue]);
                    $reason = "Past due count does not not match the grade criteria";

                }
                break;
            case 'track_record':
                // Check if the applicant's track record matches the grade criteria
                $track_record = 1;
                $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();
                $vintage6Month = Carbon::now()->subMonth(6)->startOfDay()->toDateTimeString();
                if($value == 1){
                    $minAmount = min([$application->approved_amount * 50 / 100 , 50000]);
                    foreach ($application->foir as $foir) {
                        if ($foir->applicant_type == 1) {
                            if ($foir->OwnershipType == 'Individual' && ($foir->DateClosed == '' || (strtotime($foir->DateClosed) >= strtotime($foirDateRange))) && strtotime($foir->DateOpened) <= strtotime($vintage6Month) && ($foir->AccountType == 'Credit Card' || !in_array($foir->AccountType, ['Gold Loan', 'Loan against Shares/Securities']))) {
                                /*if (($application->approved_amount * 50 / 100 <= $foir->ApprovedAmount) || $application->approved_amount * 50 / 100 <= 50000) {
                                    $track_record = 0;
                                    break;
                                }*/
                                if($minAmount <= $foir->ApprovedAmount){
                                    $track_record = 0;
                                    break;
                                }
                            }
                        }
                    }

                    if($track_record) {
                        $failed_condition = json_encode(['track_record' => $track_record]);
                        $reason = "Applicant's track record does not match the grade criteria";
                    }
                }
                break;
            case 'bank_validation':
                if(isset($application->bank_details)){
                    if(isset($value) && $value > 0 && $value != ""){
                        $item = isset($application->bank_details) && isset($application->bank_details->karza_response) ? json_decode($application->bank_details->karza_response) : [];
                        if(isset($item->result)){
                            $item = $item->result;
                            $percentage = 0; $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
                            if(round($percentage,0) < $application->merchant->grade->bank_validation){
                                $failed_condition = json_encode(['bank_validation' => round($percentage,0)]);
                                $reason = "Bank validation percentage does not match the grade criteria";
                            }
                        }
                    }
                } else{
                    $failed_condition = json_encode(['bank_validation' => null]);
                    $reason = "Bank details not present in the application";
                }
                break;
            case 'bureau_surrogate':
                $surrogateChecks = [];
                foreach ($application->foir as $foir) {
                    $this->setFOIRAttributes($foir);
                    $surrogateChecks[] = $this->checkSurrogateRule($application, $value, $foir);
                }
                if(array_sum($surrogateChecks) == 0){
                    //surrogate_rule failed,  break the BRE
                    $failed_condition = json_encode(['surrogate' => 1]);
                    $reason = "Surrogate policy check failed";
                }
                break;
            default:
                break;
        }

        return ['failed_condition' => $failed_condition, 'reason' => $reason];
    }

    public function checkSurrogateRule($application, $surrogate_percentage, $foir){

        $surrogate_loans = [
            'Auto Loan',
            'Used Car Loan',
            'P2p Auto Loan',
            'Business Loan – General',
            'Business Loan',
            'Business Loan - Unsecured',
            'Business Loan –priority Sector – Small Business',
            'Business Loan - Priority Sector- Small Business',
            'Business Loan –priority Sector – Others',
            'Business Loan - Priority Sector- Others',
            'Microfinance – Business Loan',
            'Business Loan - Secured',
            'MicroFinance Business Loan',
            'Housing Loan',
            'Home Loan',
            'Microfinance – Housing Loan',
            'MicroFinance Housing Loan'
        ];

        $requested_loan_amount = $application->approved_amount;
        $bureau_pull_date = Carbon::parse($application->creditReport[0]->created_at);
        $loan_type = $foir->AccountType;
        $loan_open_date = Carbon::parse($foir->DateOpened);
        $loan_closed_date = Carbon::parse($foir->DateClosed);
        $sanctioned_amount = $foir->ApprovedAmount - $foir->Balance;
        $bureau_open =  $loan_open_date->diffInMonths($bureau_pull_date);
        $bureau_close = $loan_closed_date->diffInMonths($bureau_pull_date);
        $sanctioned_percentage = $sanctioned_amount * $surrogate_percentage / 100;

        $loan_type_check = in_array($loan_type, $surrogate_loans) ? 1 : 0;
        $open_date_check = $bureau_open >= 12 ? 1 : 0;
        $close_date_check = $bureau_close <= 60 ? 1 : 0;
        $amount_check = $sanctioned_percentage >= $requested_loan_amount ? 1 : 0;

        $combined_check = 0;
        if($loan_type_check && $open_date_check && $close_date_check && $amount_check){
            $combined_check = 1;
        }
        return $combined_check;
    }
    public function saveApprovalStatus($grade_rule, $application_id, $req_id, $status, $response) {
        $cwFactory = new CloudWatchLoggerFactory();
        $cwFactory->logger(json_encode(['title' => 'Auto Decision: saveApprovalStatus', 'application_id' => $application_id]));
        if (_env('JSON_BRE_ACTIVE')) {
            $response['application_id'] = $application_id;
            (new JsonBREController())->store_jsonbre_response(null, $req_id, false, $response);
            return;
        }
        $save_logs = new ApprovalStatusLog();
        $save_logs->rule_id = $grade_rule->id ?? 0;
        $save_logs->application_id = $application_id ?? 0;

        if ($response && isset($response['failed_condition'])) {
            $save_logs->failed_condition = $response['failed_condition'];
        }

        if ($response && isset($response['reason'])) {
            $save_logs->reason = $response['reason'];
        }
        $save_logs->request_batch_id = $req_id ?? 0;
        $save_logs->status = $status == 'success' ? 1 : 0;
        $save_logs->created_at = Carbon::now()->toDateTimeString();
        $save_logs->save();
    }

    public function getFOIRByID($id, $status = false, $applicant_type = null)
    {
        ConsumerApplication::$isCFFoirNotInclude = true;
        $application = ConsumerApplication::with('foir')->where('id', $id)->first();

        if ($application->foir && isset($application->foir[0])) {
            foreach ($application->foir as $foir) {
                if(($applicant_type == 1 && $foir->applicant_type == 1) || ($applicant_type == 2 && $foir->applicant_type == 2)){
                    $this->setFOIRAttributes($foir);
                    $this->getFOIRCalculation($application);
                }else{
                    $this->setFOIRAttributes($foir);
                    $this->getFOIRCalculation($application);
                }
            }
        } else {
            ConsumerApplication::$isCFFoirNotInclude = false;
            $application = ConsumerApplication::with('foir')->where('id', $id)->first();
            if ($application->foir && isset($application->foir[0]) && $application->foir[0]->InstallmentAmount) {
                $total_monthly_payment = $application->foir[0]->InstallmentAmount;
                $monthly_income = $application->monthly_income > 0 ? $application->monthly_income : 0;
                if($powerSavingIncome = $this->getPowerSavingIncome($id)){
                    $monthly_income += $powerSavingIncome;
                }
                $this->foirIncludingCFEMI = ($monthly_income) ? ($total_monthly_payment / $monthly_income) * 100 : 0;
            }
        }

        return ($status) ? $this : $this->foirIncludingCFEMI;
    }

    public function setFOIRAttributes($item, ScoreCard $scoreCard = null)
    {
        if ($item->isOpened == 1) {
            //(new Slack(new Request(['title' => 'Auto Decision: setFOIRAttributes', 'fields' => ['id' => $item->application_id, 'InstallmentAmount' => $item->InstallmentAmount, 'type' => $item->AccountType, 'cc' => $item->cc_loan ?? '00'], 'group' => Slack::$STAGE_TESTING])))->send();
            if ($item->cc_loan === 0) {
                $this->credit_limit += $item->Balance;
            } else if ($item->Balance > 0 || $item->created_by > 0) {
                if ($scoreCard && $item->AccountType == 'Gold Loan') {
                    $gold_loan_amount = 0;
                    if ($item->InstallmentAmount > 0) {
                        $repaymentTenure = ($item->RepaymentTenure > 0) ? $item->RepaymentTenure : 12;
                        $gold_loan_amount = $item->InstallmentAmount / $repaymentTenure;
                    } else {
                        $amount = $scoreCard->getEmiTenure($item->AccountType, $item->ApprovedAmount, $item->Balance, $item->DateOpened, $item->LastPaymentDate);
                        if ($amount > 0) {
                            $gold_loan_amount = $amount;
                        }
                    }
                    $this->total_existing_emi += $gold_loan_amount;
                } else if($item->OwnershipType != 'Guarantor'){
                    $this->total_existing_emi += $item->InstallmentAmount;
                }
            }
        }
    }

    public function getFOIRCalculation($application, $InstallmentAmount = 0)
    {
        if($InstallmentAmount == 0) {
            $creditFairEMI = FOIR::where('application_id', $application->id)->where('AccountType', 'Credit Fair EMI')->where('InstallmentAmount', '>', 0)->first(['InstallmentAmount']);
        }
        
        $total_credit_card_limit_five = ($this->credit_limit * 5) / 100;
        $total_monthly_payment = $this->total_existing_emi + $total_credit_card_limit_five;
        /* Code fixes to resolve conflicting logic of scorecard foir and edit blade foir */
        $cfInstallAmount = (isset($creditFairEMI->InstallmentAmount) && $creditFairEMI->InstallmentAmount > 0 ? $creditFairEMI->InstallmentAmount : ($InstallmentAmount > 0 ? $InstallmentAmount : 0));
        if ($InstallmentAmount || isset($creditFairEMI->InstallmentAmount)) {
            $total_monthly_payment += $cfInstallAmount;
        }

        $monthly_income = $application->monthly_income;
        if(isset($application->co_applicant_monthly_income) && !empty($application->co_applicant_monthly_income)){
            $monthly_income = $application->monthly_income + $application->co_applicant_monthly_income;
        }

        if($powerSavingIncome = $this->getPowerSavingIncome($application->id)){
            $monthly_income += $powerSavingIncome;
        }

        $this->foirIncludingCFEMI = ($application->monthly_income) ? ($total_monthly_payment / $monthly_income) * 100 : 0;
        if ($InstallmentAmount || isset($creditFairEMI->InstallmentAmount)) {
            $this->foirNAIncludingCFEMI = ($application->monthly_income) ? (($total_monthly_payment - ($cfInstallAmount)) / $monthly_income) * 100 : 0;
            $this->cfFoir = ($application->monthly_income) ? (($cfInstallAmount) / $monthly_income) * 100 : 0;
        }

        $applicant_type = 1;
        if ($this->applicant_type){
            $applicant_type = $this->applicant_type;
        }
        CreditReport::where('application_id', $application->id)->where('applicant_type', $applicant_type)->update(['foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'foirNAIncludingCFEMI' => $this->foirNAIncludingCFEMI, 'cfFoir' => $this->cfFoir]);
        //(new Slack(new Request(['title' => 'Auto Decision: FOIR Updated', 'fields' => ['id' => $application->id, 'total_monthly_payment' => $total_monthly_payment, 'total_existing_emi' => $this->total_existing_emi, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'foirNAIncludingCFEMI' => $this->foirNAIncludingCFEMI, 'cfFoir' => $this->cfFoir], 'group' => Slack::$STAGE_TESTING])))->send();
    }

    public function getPowerSavingIncome($id){
        $application = ConsumerApplicationElement::where('application_id', $id)->first(['inverter_power_savings']);
        if(isset($application->inverter_power_savings) && $application->inverter_power_savings > 0){
            return $application->inverter_power_savings;
        }
        return 0;
    }

    public function checkDuplicates($application)
    {
        (new Slack(new Request(['title' => 'Table of Offers: Inside check-dup', 'fields' => ['id' => $application->id,'status' => 'Entered checkDuplicate'], 'group' => Slack::$STAGE_TESTING])))->send();
        $consumerAppController = new ConsumerApplicationController();
        $repeatPeriod = Carbon::now()->subMonth(3)->toDateTimeString();
        if (isset($application->pan_card)) {
            $consumerApplication_pan = ConsumerApplication::where('pan_card', $application->pan_card)->where('id','!=',$application->id)->where('created_at', '>=', $repeatPeriod)->whereNull('is_deleted')->orderBy('created_at', 'desc')->first(['id', 'merchant_id']);
            if (isset($consumerApplication_pan->merchant_id) && !$consumerAppController->isNonBreMerchant($consumerApplication_pan->merchant_id)) { // checking for merchant status to not be bre
                $consumerApplication_pan = null;
            }
        }
        if (isset($application->email)) {
            if (isset($application->id)) {
                $consumerApplication_email = ConsumerApplication::where('email', $application->email)->where('id','!=',$application->id)->where('created_at', '>=', $repeatPeriod)->whereNull('is_deleted')->orderBy('created_at', 'desc')->first(['id', 'merchant_id']);
                if (isset($consumerApplication_email->merchant_id) && !$consumerAppController->isNonBreMerchant($consumerApplication_email->merchant_id)) {
                    $consumerApplication_email = null;
                }
            }
        }
        if (isset($application->mobile_number)) {
            if (isset($application->id)) {
                $consumerApplication_mobile = ConsumerApplication::where('mobile_number', $application->mobile_number)->where('id','!=',$application->id)->where('created_at', '>=', $repeatPeriod)->whereNull('is_deleted')->orderBy('created_at', 'desc')->first(['id', 'merchant_id']);
                if (isset($consumerApplication_mobile->merchant_id) && !$consumerAppController->isNonBreMerchant($consumerApplication_mobile->merchant_id)) {
                    $consumerApplication_mobile = null;
                }
            }
        }

        if (isset($consumerApplication_pan->id) || isset($consumerApplication_email->id) || isset($consumerApplication_mobile->id)) {
            (new Slack(new Request(['title' => 'Table of Offers: Inside check-dup', 'fields' => ['id' => $application->id,'status' => 'failed'], 'group' => Slack::$STAGE_TESTING])))->send();
            return false;
        }
        (new Slack(new Request(['title' => 'Table of Offers: Inside check-dup', 'fields' => ['id' => $application->id,'status' => 'success'], 'group' => Slack::$STAGE_TESTING])))->send();
        return true;
    }

    public static function calculatedifferenceindate($openDate, $closedDate = '')
    {
        if ($closedDate == '') {
            $closedDate = date('Y-m-d');
        }

        $date = Carbon::parse($openDate);
        $now = ($closedDate) ? Carbon::parse($closedDate) : Carbon::now();

        $month_diff = $date->diffInMonths($now);
        $year_diff = $date->diffInYears($now);

        return $month_diff >= 6 ? $month_diff : 0;
    }


    public function addComment($app_id,$user_id,$comment, $showMerchant=0, $isOffer = false){
        Comments::insert([
            'application_id' => $app_id,
            'user_id' => $user_id,
            'comment' => $comment,
            'show_consumer' => 0,
            'show_merchant' => $showMerchant,
            'created_at' => Carbon::now()->toDateTimeString(),
            'updated_at' => Carbon::now()->toDateTimeString(),
            'type' =>'consumer',
                ]);

        $consumerApplication = ConsumerApplication::where('id', $app_id)->first(['merchant_id']);
        if ($consumerApplication->merchant_id == env('SSE_MERCHANT_ID')) {
            if ($isOffer) {
                try {
                    $appController = new ConsumerApplicationController();
                    $status = 'Merchant-Comment';
                    $payload = $appController->getMConnectPayload($app_id,$status,['comment' => $comment]);
                    $appController->webhook($app_id, [
                        'type'   => 'Application-Webhook',
                        'status' => $status,
                        'data'   => $payload
                    ]);
                } catch (\Exception $e) {
                    (new CloudWatchLoggerFactory())->logger(json_encode(['title' => 'Failed to call webhook','application_id' => $app_id,'error' => $e->getMessage(),'line'  => $e->getLine(),'trace' => $e->getTraceAsString()]));
                }
            }
        }
    }

    public function getClosestOffer($application){
        $power_savings_value = isset($application->application_element->inverter_power_savings) ? $application->application_element->inverter_power_savings : '';
        foreach ($this->emiData as $offerId => $emiDetails) {
            if ($emiDetails['emi'] <= $power_savings_value && $emiDetails['emi'] > $this->closestEmi) {
                $this->closestOffer = $offerId;
                $this->closestEmi = $emiDetails['emi'];
            }
        }
    }




    public function addNegativeResidualLog($application_id, $policies=[], $reason){
        if (_env('JSON_BRE_ACTIVE')){
            $latestBatch = JsonBreApprovalStatusLog::where('application_id', $application_id)
                ->orderBy('created_at', 'desc')
                ->first(['request_batch_id']);
            if ($latestBatch && $latestBatch->request_batch_id) {
                if ($policies) {
                    JsonBreApprovalStatusLog::where('application_id', $application_id)
                        ->where('request_batch_id', $latestBatch->request_batch_id)
                        ->whereIn('rule_id', $policies)
                        ->update(['status' => 0, 'reason' => $reason]);
                } else {
                    JsonBreApprovalStatusLog::where('application_id', $application_id)
                        ->where('request_batch_id', $latestBatch->request_batch_id)
                        ->where('status', 1)
                        ->update(['status' => 0, 'reason' => $reason]);
                }
            }
        }else{
            $latestBatch = ApprovalStatusLog::where('application_id', $application_id)
                ->orderBy('created_at', 'desc')
                ->first(['request_batch_id']);
            if ($latestBatch && $latestBatch->request_batch_id) {
                if ($policies) {
                    ApprovalStatusLog::where('application_id', $application_id)
                        ->where('request_batch_id', $latestBatch->request_batch_id)
                        ->whereIn('rule_id', $policies)
                        ->update(['status' => 0, 'reason' => 'Residual EMI is zero or negative.']);
                } else {
                    ApprovalStatusLog::where('application_id', $application_id)
                        ->where('request_batch_id', $latestBatch->request_batch_id)
                        ->where('status', 1)
                        ->update(['status' => 0, 'reason' => 'Residual EMI is zero or negative.']);
                }
            }
        }
    }


    public function updateStatus($id, $status){
        $consumer_application = ConsumerApplication::find($id);
        $consumer_application->state = $status;
        if($status == 'rejected') {
            $consumer_application->approved_amount = 0;
        }
        $consumer_application->save();
        StatusLogs::insert([
            'application_id' => $id,
            'user_id' => 107,
            'status' => $status,
            'created_at' => Carbon::now()->toDateTimeString()
        ]);
    }

    public function getOutput()
    {
        if($this->isLatestRule){
            return $this->approvalLogs;
        }else {
            return [
                'error' => $this->error,
                'negativeProfile' => $this->negativeProfile,
                'guarantor' => $this->guarantor,
                'checkDuplicates' => $this->checkDuplicates,
                'loan_amount' => $this->loan_amount,
                'tenure' => $this->tenure,
                'monthly_income' => $this->monthly_income,
                'score' => $this->score,
                'product_loan_amount' => $this->product_loan_amount,
                'is_credit_card' => $this->is_credit_card,
                'ageAtLastEMI' => $this->ageAtLastEMI,
                'age' => $this->age,
                'credit_limit_five_times' => $this->credit_limit_five_times,
                'AccountType' => $this->AccountType,
                'foir' => $this->foir,
                'cf_foir' => $this->cf_foir,
                'aboveThreeYear' => $this->aboveThreeYear, //DPD < 15 days in CLOSED tracks with closure date > 3 years prior
                'threeYear' => $this->threeYear, //DPD < 10 days across all LIVE loan tracks (including credit cards) and tracks closed within last 3 years
                'pastDues' => $this->pastDues, //No current overdues as per CIR
                'termLoan' => $this->termLoan, //Loan tracks should contain ATLEAST 1 TERM LOAN with vintage > 12 months
                'caseType' => $this->caseType, //No write off/ Settled (Principal or interest) / Bankrupt cases,
                'rejected' => $this->rejected, // if the application is rejected or aborted once
                'downpayment' => $this->downpayment, // this is for thin file customer
                'address_status' => $this->address_status, // this is for thin file customer
                'negative_area' => $this->negative_area, // this is for thin file
                'black_list' => $this->black_list,
                'last_payment_date' => $this->last_payment_date, // this is for comparing last_payment_date input in grades with difference between login and last payment date
                'approved_pin' => $this->approved_pin, // this is for checking if the application has pincodes approved(current and permanent addresses only)
                'employee_status' => $this->employee_status,
                'bank_validation' => $this->bank_validation,
                'epf_verification' => $this->epf_verification,
                'fetch_gst' => $this->fetch_gst,
                'amount_paid' => $this->amount_paid,
                'amount_paid_cr' => $this->amount_paid_cr,
                'track_record' => $this->track_record,
                'reason' => $this->reason,
                'dpdCountRejection' => $this->dpdCountRejection
            ];
        }
    }

    public function ApprovalCheckV1($application_id, $req_id = '')
    {
        $epf = EPFUANLookup::where('application_id', $application_id)->first();
        if (!isset($epf)){
            $this->CallEPFKarza($application_id);
        }
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.offer')->where('id', $application_id)->first();
        $this->CalculateFOIRbeforeAutoDecision($application_id, $application);


        return $this->MultiApprovalCheck($application_id, $req_id);
        (new Slack(new Request(['title' => 'Auto Decision - Started', 'fields' => ['id' => $application_id, 'time' => Carbon::now()->toDateTimeString()], 'group' => Slack::$STAGE_TESTING])))->send();

        /*if((new AvanseProcesses(new Request(['id' => $application_id])))->checkEligibility()){
            $this->error = 1;
            return $this;
        }

        if((new Services())->checkEligibility($application_id)){
            $this->error = 1;
            return $this;
        }

        if((new LendBox())->checkEligibility($application_id)){
            $this->error = 1;
            return $this;
        }*/

        $status = true;
        $threeYear = [];
        $accounts = [];
        $aboveThreeYear = [];
        ConsumerApplication::$isCFFoirNotInclude = true;
        $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();
        $vintage6Month = Carbon::now()->subMonth(6)->startOfDay()->toDateTimeString();
        $noDPDDateRange = Carbon::now()->subYear(2)->startOfDay()->toDateTimeString(); //no of dpd’s greater than 6 which is more the 1-15 days in last 2 year)

        $creReport = CreditReport::with('incompleteFoir')->where('application_id', $application_id)->first(['id']);
        if(isset($creReport->id) || isset($creReport->incompleteFoir->id)) {
            //(new Slack(new Request(['title' => 'Auto Decision: refreshScoreCardData', 'fields' => ['id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
            (new ConsumerApplicationController())->refreshScoreCardData($application_id);
        }

        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.custom_grade', 'merchant.offer', 'products', 'bank_details')->where('id', $application_id)->first();

        if($application->merchant->table_of_offers){
            event(new EventTableOfOffer(['id' => $application_id]));
        }


        if (!$application->merchant || (isset($application->merchant) && !$application->merchant->grade)) {
            if(!$application->merchant){
                $this->reason = "Merchant not set";
            }
            if(isset($application->merchant) && !$application->merchant->grade){
                $this->reason = "Merchant grade not set";
            }
            $this->error = 1;
            if(isset($application->merchant) && !$application->merchant->custom_grade_id){
                $this->reason = "Custom grade is not set properly";
            }
            if (isset($application->merchant) && $application->merchant->custom_grade_id && $application->merchant->custom_grade) {
                return $this->ApprovalCheckCustomV1($application_id);
            }
            return $this;
        }

        if (!$application->merchant->is_auto_approve) {
            $this->reason = "Merchant doesn’t have auto-approval enabled";
            $this->error = 1;
            return $this;
        }

        $total = DB::table('consumer_application')->select(DB::raw('count(*) as app_count'), DB::raw('SUM(approved_amount) as total_approved_amount'))->where('merchant_id', $application->merchant_id)->whereIn('state', ['approved', 'disbursement checklist done','ready for disbursement','disbursed','nach registered','closed'])->first();
        $total_remaining_amount = $application->merchant->max_approval_value - $total->total_approved_amount;
        if ($application->merchant->status == 'active' && $application->merchant->pre_status == 1 && ($application->loan_amount > $total_remaining_amount || $total->total_approved_amount > $application->merchant->max_approval_value || $total->app_count >= $application->merchant->max_no_cases)) {
            if($application->loan_amount > $total_remaining_amount){
                $this->reason = "Application loan amount greater than total remaining amount";
            }elseif($total->total_approved_amount > $application->merchant->max_approval_value){
                $this->reason = "Total approved amount greater than max approval limit";
            }elseif($total->app_count >= $application->merchant->max_no_cases){
                $this->reason = "Total application count limit reached";
            }
            $this->error = 1;
            return $this;
        }


        if($application && $application->application_element && !empty($application->application_element->product_name) &&
            $application->products && count($application->products) > 0){
            $appl_prod = explode(',', $application->application_element->product_name);
            $products = Products::whereIn('id', $appl_prod)->get();
            $amount = 0;
            foreach($products as $product){
                $amount += $product->amount;
            }
            if($amount != 0 && $amount < $application['loan_amount']){
                $this->product_loan_amount = $application['loan_amount'] - $amount;
                return $this;
            }
        }

        if ($this->request->has('custom_grade_id')) { //$this->request->has('custom_grade_id')
            $f = Grades::find($this->request->get('custom_grade_id'));//$this->request->get('custom_grade_id')
            $t = new \stdClass();
            $t->grade = $f;
            $application['merchant'] = $t;
        }

        $status_array = ['aborted', 'rejected'];
        if($application->merchant->grade->rejected == 1){
            $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->get();
            if (isset($status_log[0])) {
                $this->rejected = true;
                return $this;
            }
        }

        /*if(isset($application->application_element->negative_profile) && $application->application_element->negative_profile > 0){
            $this->negativeProfile = true;
            return $this;
        }*/

        if($application->merchant->grade->checkDuplicates == 1){
            $checkDuplicates = $this->checkDuplicates($application);
            if($checkDuplicates == false){
                $this->checkDuplicates = 1;
                (new Slack(new Request(['title' => 'Table of Offers: After check-dup', 'fields' => ['id' => $application_id,'status' => 'failed'], 'group' => Slack::$STAGE_TESTING])))->send();
                return $this;
            }
            (new Slack(new Request(['title' => 'Table of Offers: After check-dup', 'fields' => ['id' => $application_id,'status' => 'success'], 'group' => Slack::$STAGE_TESTING])))->send();
        }
        if (isset($application->creditReport[0]) && isset($application->creditReport[0]->Score)) {
            if ($application->creditReport[0]->Score < $application->merchant->grade->score && $application->creditReport[0]->Score > 10) {
                $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
                return $this;
            } elseif ($application->creditReport[0]->Score < 10) {

                if ((isset($application->merchant->grade->thin_file_loan_amount) && empty($application->merchant->grade->thin_file_loan_amount)) || (!isset($application->merchant->grade->thin_file_loan_amount))) {
                    $this->reason = "Thin_file_loan_amount is not set in grade";
                    $this->error = 1;
                    return $this;
                }

                $min_loan_amount = ((isset($application->merchant->grade->thin_file_min_loan_amount) && !empty($application->merchant->grade->thin_file_min_loan_amount))) ? $application->merchant->grade->thin_file_min_loan_amount : 0;
                $loan_amount = ((isset($application->merchant->grade->thin_file_loan_amount) && !empty($application->merchant->grade->thin_file_loan_amount))) ? $application->merchant->grade->thin_file_loan_amount : 0;
                $tenure = ((isset($application->merchant->grade->thin_file_tenure) && !empty($application->merchant->grade->thin_file_tenure))) ? $application->merchant->grade->thin_file_tenure : 0;
                $monthly_income = ((isset($application->merchant->grade->thin_file_monthly_income) && !empty($application->merchant->grade->thin_file_monthly_income))) ? $application->merchant->grade->thin_file_monthly_income : 0;
                $grade_age = ((isset($application->merchant->grade->thin_file_age) && !empty($application->merchant->grade->thin_file_age))) ? $application->merchant->grade->thin_file_age : 0;
                $_foir = ((isset($application->merchant->grade->thin_file_foir) && !empty($application->merchant->grade->thin_file_foir))) ? $application->merchant->grade->thin_file_foir : 0;
                $_cf_foir = ((isset($application->merchant->grade->thin_file_cf_foir) && !empty($application->merchant->grade->thin_file_cf_foir))) ? $application->merchant->grade->thin_file_cf_foir : 0;
                $threeYearDPD = 0;
                $aboveThreeYearDPD = 0;
                if($application->merchant->grade->no_owned_house == 1){
                    if ((!isset($application->current_address_status)) || empty($application->current_address_status) || (isset($application->current_address_status) && !in_array($application->current_address_status, array('OWNED', 'PARENTS HOUSE', 'Self Owned', 'Parent Owned')))) {
                        $this->address_status = "No Owned House";
                        return $this;
                    }
                }
                if($application->merchant->grade->zero_downpayment == 1){
                    if (!$application->emi || (isset($application->emi) && $application->emi->upfront_from_customer <= 0)) {
                        if(!in_array($application->merchant_id, [5983, 5984, 5980, 5803])) {
                            $this->downpayment = isset($application->emi->upfront_from_customer) ? "Zero Downpayment" : 'emi_not_generated';
                            return $this;
                        }
                    }
                }
                if($application->merchant->grade->negative_area == 1){
                    if (((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) || ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode))) {
                        $data['current_pincode'] = ((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) ? $application->current_address_pincode : "";
                        $data['installation_pincode'] = ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode)) ? $application->application_element->installation_address_pincode : "";
                        $consumerApplicationConreoller = new ConsumerApplicationController();
                        $NegativeArearesponse = $consumerApplicationConreoller->getNegativeAreaList($data);
                        if ($NegativeArearesponse && isset($NegativeArearesponse->level) && $NegativeArearesponse->level == 1) {
                            $this->negative_area = "Negative Area";
                            return $this;
                        }
                    }
                }

                if(isset($application->employee_status)){
                    if($application->merchant->grade->thin_file_employee_status) {
                        $employee_status_array = explode(',',$application->merchant->grade->thin_file_employee_status);
                        if(!in_array($application->employee_status, $employee_status_array)) {
                            $this->employee_status = true;
                            return $this;
                        }
                    }
                }
                if(isset($application->merchant->grade->thin_file_bank_validation)){
                    if($application->merchant->grade->thin_file_bank_validation > 0){
                        $item = isset($application->bank_details) && isset($application->bank_details->karza_response) ? json_decode($application->bank_details->karza_response) : [];
                        if(isset($item->result)){
                            $item = $item->result;
                            $percentage = 0; $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
                            if(round($percentage,0) < $application->merchant->grade->thin_file_bank_validation){
                                $this->bank_validation = round($percentage,0);
                                return $this;
                            }
                        }
                    }
                }

                /* Required EPF Employment Verification for Thin File */
                if($application->merchant->grade->thin_file_epf_verification) {
                    if(strtolower($application->employee_status) == 'salaried'){
                        $epf = EPFUANLookup::where('application_id', $application->id)->first();
                        if(isset($epf) && !empty($epf)) {
                            $epf_data = json_decode($epf->data, 1);
                            $isEmployed = $uanNameMatch = false;
                            if ($epf_data['result']['uan'] && is_array($epf_data['result']['uan'])) {
                                foreach ($epf_data['result']['uan'] as $uanData) {
                                    foreach ($uanData['employer'] as $uanDataEmployer) {
                                        if (strtolower($uanDataEmployer['name']) == strtolower($epf->employerName)) {
                                            $isEmployed = $uanDataEmployer['isEmployed'] ?? false;
                                            $uanNameMatch = $uanDataEmployer['uanNameMatch'] ?? false;
                                        }
                                    }
                                }
                            }
                            if (!$isEmployed || $isEmployed == false || !$uanNameMatch || $uanNameMatch == false || (strtolower($application->company->company) != strtolower($epf->employerName))) {
                                $this->epf_verification = 1;
                                return $this;
                            }
                        }
                    }
                }
                /* Fetch GST Number using PAN for Thin File */
                if($application->merchant->grade->thin_file_fetch_gst) {
                    $emp_status = ['business', 'self employed - business', 'self employed - professional'];
                    if(in_array(strtolower($application->employee_status), $emp_status)) {
                        $gst_pan_data = GSTPANData::where('application_id', $application->id)->orderBy('created_at', 'desc')->first();
                        $gst_data = json_decode($gst_pan_data['data']);
                        if(!isset($gst_data->result[0]->authStatus) || (isset($gst_data->result[0]->authStatus) && $gst_data->result[0]->authStatus == 'Inactive')){
                            $this->fetch_gst = 1;
                            return $this;
                        }
                    }
                }

                $oldloan = 0;
                $unsecuredloan = 0;

            } else {
                $min_loan_amount = (isset($application->merchant->grade->min_loan_amount) && !empty($application->merchant->grade->min_loan_amount)) ? $application->merchant->grade->min_loan_amount : 0;
                $loan_amount = (isset($application->merchant->grade->loan_amount) && !empty($application->merchant->grade->loan_amount)) ? $application->merchant->grade->loan_amount : 0;
                $tenure = (isset($application->merchant->grade->tenure) && !empty($application->merchant->grade->tenure)) ? $application->merchant->grade->tenure : 0;
                $monthly_income = (isset($application->merchant->grade->monthly_income) && !empty($application->merchant->grade->monthly_income)) ? $application->merchant->grade->monthly_income : 0;
                $grade_age = (isset($application->merchant->grade->age) && !empty($application->merchant->grade->age)) ? $application->merchant->grade->age : 0;
                $_foir = (isset($application->merchant->grade->foir) && !empty($application->merchant->grade->foir)) ? $application->merchant->grade->foir : 0;
                $_cf_foir = (isset($application->merchant->grade->cf_foir) && !empty($application->merchant->grade->cf_foir)) ? $application->merchant->grade->cf_foir : 0;
                $threeYearDPD = 10;
                $aboveThreeYearDPD = 15;
                $oldloan = 1;
                $unsecuredloan = 1;

                if(isset($application->employee_status)){
                    if($application->merchant->grade->employee_status) {
                        $employee_status_array = explode(',',$application->merchant->grade->employee_status);
                        if(!in_array($application->employee_status, $employee_status_array)) {
                            $this->employee_status = true;
                            return $this;
                        }
                    }
                }
                if(isset($application->merchant->grade->bank_validation)){
                    if($application->merchant->grade->bank_validation > 0){

                        $item = isset($application->bank_details) && isset($application->bank_details->karza_response) ? json_decode($application->bank_details->karza_response) : [];
                        if(isset($item->result)){
                            $item = $item->result;
                            $percentage = 0; $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
                            if(round($percentage,0) < $application->merchant->grade->bank_validation){
                                $this->bank_validation = round($percentage,0);
                                return $this;
                            }
                        }
                    }
                }

                /* Required EPF Employment Verification */
                if($application->merchant->grade->epf_verification) {
                    if(strtolower($application->employee_status) == 'salaried'){
                        $epf = EPFUANLookup::where('application_id', $application->id)->first();
                        if(isset($epf['data'])){
                            $epf_data = json_decode($epf['data'], 1);
                            $isEmployed = $uanNameMatch = false;
                            if($epf_data['result']['uan'] && is_array($epf_data['result']['uan'])) {
                                foreach ($epf_data['result']['uan'] as $uanData) {
                                    foreach ($uanData['employer'] as $uanDataEmployer) {
                                        if(strtolower($uanDataEmployer['name']) == strtolower($epf->employerName)){
                                            $isEmployed = $uanDataEmployer['isEmployed'] ?? false;
                                            $uanNameMatch = $uanDataEmployer['uanNameMatch'] ?? false;
                                        }
                                    }
                                }
                            }
                            if(!$isEmployed || $isEmployed == false || !$uanNameMatch || $uanNameMatch == false || (strtolower($application->company->company) != strtolower($epf->employerName))){
                                if(!$isEmployed || $isEmployed == false){
                                    $this->reason = "epf employement verification failed - epf";
                                }
                                if(!$uanNameMatch || $uanNameMatch == false){
                                    $this->reason = "Uan name not matched - epf";
                                }
                                if(strtolower($application->company->company) != strtolower($epf->employerName)){
                                    $this->reason = "Employee name not matched - epf";
                                }
                                $this->epf_verification = 1;
                                return $this;
                            }
                        }
                    }
                }
                /* Fetch GST Number using PAN */
                if($application->merchant->grade->fetch_gst) {
                    $emp_status = ['business', 'self employed - business', 'self employed - professional'];
                    if(in_array(strtolower($application->employee_status), $emp_status)) {
                        $gst_pan_data = GSTPANData::where('application_id', $application->id)->orderBy('created_at', 'desc')->first();
                        $gst_data = json_decode($gst_pan_data['data']);
                        if(!isset($gst_data->result[0]->authStatus) || (isset($gst_data->result[0]->authStatus) && $gst_data->result[0]->authStatus == 'Inactive')){
                            $this->fetch_gst = 1;
                            return $this;
                        }
                    }
                }

            }
        } else {
            $this->score = 'no_equifax';
            return $this;
        }

        if ($application->loan_amount == 0 || $application->loan_amount > $loan_amount || $application->loan_amount < $min_loan_amount || $loan_amount == 0 || empty($loan_amount)) {
            $this->loan_amount = $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount;
            return $this;
        }
        if (!$application->emi || $tenure == 0 || empty($tenure) || (isset($application->emi) && $application->emi->remaining_emi > $tenure)) {
            $this->tenure = !isset($application->emi->remaining_emi) ? 'emi not generated' : $application->emi->remaining_emi;
            return $this;
        }
        if (!$application->monthly_income || $monthly_income == 0 || empty($monthly_income) || ($application->monthly_income < $monthly_income)) {
            $this->monthly_income = $application->monthly_income;
            return $this;
        }



//        if(!isset($application->creditReport[0]) || isset($application->creditReport[0]) && isset($application->creditReport[0]->Score) && $application->creditReport[0]->Score < $application->merchant->grade->score){
//            $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
//            return $this;
//        }
        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
        if (isset($application->emi)) {
            $last_emi_date = Carbon::now()->addMonths($application->emi->remaining_emi)->toDateString();
            $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
        }
        if ($grade_age == 0 || empty($grade_age) || $age < $grade_age) {
            $this->age = $age;
            return $this;
        }
        if($application->merchant->grade->ageAtLastEMI == 1){
            $ageLimit = isset($application->merchant->grade->ageAtLastEMI_age) ? $application->merchant->grade->ageAtLastEMI_age : 60;
            if (isset($ageAtLastEMI)) {
                if ($ageAtLastEMI > $ageLimit) {
                    $this->ageAtLastEMI = $ageAtLastEMI;
                    return $this;
                }
            }
        }
        $creditCardAmount = 0;
        $creditCardLimit = [];
        $maxSanctioned = [];
        if (isset($application->creditReport[0])) {
            $creditReport = $application->creditReport[0];
            if($application->merchant->grade->pastDues == 1){
                $pastDueLimit = isset($application->merchant->grade->pastDues_value) ? (int)$application->merchant->grade->pastDues_value : 500;
                if ($creditReport->TotalPastDue > $pastDueLimit) {
                    $this->pastDues = $creditReport->TotalPastDue;
                    return $this;
                }
            }
            if ($status) {
                $termloanarray = ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan',
                    'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility',
                    'Business Non-Funded Credit Facility - Priority', 'Staff Loan'];
                if ($application->foir) {
                    $gold_loan = 0;
                    //(new Slack(new Request(['title' => 'Auto Decision: foir', 'fields' => ['id' => $application_id,'state' => json_encode($application->foir)], 'group' => Slack::$STAGE_TESTING])))->send();
                    foreach ($application->foir as $foir) {

                        $accounts[] = $foir->AccountType;
                        $ownership_types[] = $foir->OwnershipType;
                        if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                            $gold_loan++;
                            if ($gold_loan >= 3) {
                                $this->AccountType = $foir->AccountType;
                                break;
                            }
                        }

                        if ($foir->AccountType == 'Credit Card' && $foir->DateClosed == '') {
                            $creditCardAmount += $foir->InstallmentAmount;
                            $creditCardLimit[] = $foir->ApprovedAmount - $foir->Balance;
                        }

                        if ($foir->DateOpened) {
                            if (!$foir->DateClosed) {
                                $foir->DateClosed = "";
                            }
                            if ($foir->DateClosed) {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened, $foir->DateClosed);
                            } else {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened);
                            }
//                            if ($foir->DateClosed) {
//                                $date = date('Y', strtotime($foir->DateClosed));
//                            } else {
//                                $date = date('Y', time());
//                            }
//
//                            $termLoan = (date('Y', strtotime($foir->DateOpened)) - $date);
                            if ($termLoan > 0 && $oldloan != 0) {
                                $oldloan = 0;
                            }

                            if ((in_array($foir->AccountType, $termloanarray)) && $unsecuredloan != 0) {
                                $unsecuredloan = 0;
                            }

                            if (in_array($foir->AccountType, $termloanarray) && $oldloan == 0 && $unsecuredloan == 0 && $foir->DateClosed == '') {
                                $maxSanctioned[] = $foir->ApprovedAmount - $foir->Balance;
                            }
                        }

                        $this->setFOIRAttributes($foir);
                    }

                    if($application->merchant->grade->accountType == 1){
                        if (!empty($this->AccountType)) {
                            return $this;
                        }
                    }else{
                        $this->AccountType = '';
                    }

                    if($application->merchant->grade->amount_paid_cr && $application->loan_amount && $creditCardLimit){
                        $crLimitShould = $application->loan_amount * $application->merchant->grade->amount_paid_cr / 100;
                        if(max($creditCardLimit) < $crLimitShould){
                            $this->amount_paid_cr = $crLimitShould;
                            return $this;
                        }
                    }
                    $flag = 0;
                    if($application->merchant->grade->guarantor == 1){
                        if (isset($ownership_types) && count($ownership_types) != 0 ) {
                            foreach($ownership_types as $ownership_type) {
                                if ($ownership_type != 'Guarantor') {
                                    $flag = 1;
                                }
                            }
                            if($flag == 0){
                                $this->guarantor = 1;
                                return $this;
                            }
                        }
                    }
                    $this->getFOIRCalculation($application);
                    //$this->getFOIRCalculation($application, 1);


                    //(new Slack(new Request(['title' => 'Auto Decision: FOIR Alert', 'fields' => ['id' => $application->id, 'total_existing_emi' => $this->total_existing_emi, 'this->credit_limit' => $this->credit_limit, 'Score' => $this->score, 'CF Foir' => $this->cfFoir, 'CF Foir grade' => $_cf_foir, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'foirIncludingCFEMI Grade' => $_foir], 'group' => Slack::$STAGE_TESTING])))->send();
                    if ($this->cfFoir > $_cf_foir) {
                        $this->cf_foir = $this->cfFoir;
                        return $this;
                    }
                    if ($this->foirIncludingCFEMI > $_foir) {
                        $this->foir = $this->foirIncludingCFEMI;
                        return $this;
                    }
                    $dpdRange = 0;
                    $dpdRangeAbove = 0;
                    $dpdSumAllTradeline = 0;
                    $dpdSumAllTradelineAbove = 0;
                    foreach ($application->foir as $foir) {

                        $foirData = json_decode($foir->dpd, 1);

                        if($application->merchant->grade->dpdCountRejection == 1){
                            $yearsLimit = isset($application->merchant->grade->dpdCountRejection_years) ? $application->merchant->grade->dpdCountRejection_years : 2;
                            $countLimit =  isset($application->merchant->grade->dpdCountRejection_dpds) ? $application->merchant->grade->dpdCountRejection_dpds : 6;
                            $noDPDDateRange = Carbon::now()->subYear($yearsLimit)->startOfDay()->toDateTimeString(); //no of dpd’s greater than 6 which is more the 1-15 days in last 2 year)
                            if (strtotime($foir->DateOpened) <= strtotime($noDPDDateRange)) {
                                $dpdCount = 0;
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $dpdCount += $item;
                                        if ($dpdCount > $countLimit) {
                                            $this->dpdCountRejection = 1;
                                        }
                                    }
                                }
                            }
                        }
                        if($application->merchant->grade->caseType == 1){
                            $keywords = [];
                            $casetypeValues = isset($application->merchant->grade->case_type_value) ? $application->merchant->grade->case_type_value : null;
                            if ($casetypeValues != ''){
                                $array = explode(",", $casetypeValues);
                                foreach($array as $item){
                                    array_push($keywords, $item);
                                }
                                    if ($foirData) {
                                        $caseType = array_keys($foirData);
                                        if ($caseType) {
                                            foreach ($caseType as $type) {
                                                if (in_array($type, $keywords)) {
                                                    $this->caseType = $type;
                                                    return $this;
                                                }
                                            }
                                        }
                                    }
                            }
                        }
                        if($application->merchant->grade->last_payment_date_number && !$foir->DateClosed && $foir->LastPaymentDate && $foir->Balance > 0 && $foir->LastPaymentDate) {
                            $days = Carbon::parse($foir->LastPaymentDate)->diffInDays(date('Y-m-d'));

                            if($days > $application->merchant->grade->last_payment_date_number){
                                $this->last_payment_date = 1;
                                return $this;
                            }
                        }

                        if($application->merchant->grade->threeYear == 1){
                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                            $dpdRange = $application->merchant->grade->threeYear_dpds ?? 0;
                            $dateRange = $application->merchant->grade->threeYear_years ?? 3;
                            $foirDateRange = Carbon::now()->subYear($dateRange)->startOfDay()->toDateTimeString();
                            $created_at = Carbon::parse($foir->created_at);
                            $diff_days = $foir->DateOpened ? $created_at->diffInDays($foir->DateOpened) : 0;
                            $dpdkeywords = isset($application->merchant->grade->dpd_keywords) ? $application->merchant->grade->dpd_keywords : null;
                            $all_keywords = [];
                            $years = ($diff_days)/365 ;
                            if(isset($dpdkeywords) && $dpdkeywords != ''){
                                $keywords = explode(",",$dpdkeywords);
                                foreach($keywords as $key){
                                    $keyword = trim($key);
                                    $keyword = trim($keyword,'"');
                                    array_push($all_keywords, $keyword);
                                }
                            }
                            if ($foirClean) {
                                if ($years <= $dateRange) {
                                    foreach ($foirData as $key => $item) {
                                        if (!in_array($key, $all_keywords)) {
                                            $dpdSumAllTradeline += $item;
                                        }
                                    }
                                }
                            }
                        }
                        if($application->merchant->grade->aboveThreeYear == 1){
                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                            $dpdRangeAbove = $application->merchant->grade->aboveThreeYear_dpds ?? 15;
                            $dateRange = $application->merchant->grade->aboveThreeYear_years ?? 3;
                            $foirDateRange = Carbon::now()->subYear($dateRange)->startOfDay()->toDateTimeString();
                            $created_at = Carbon::parse($foir->created_at);
                            $diff_days = $foir->DateOpened ? $created_at->diffInDays($foir->DateOpened) : 0;
                            $aboveDpdKeywords = isset($application->merchant->grade->above_dpd_keywords) ? $application->merchant->grade->above_dpd_keywords : null;
                            $all_keywords_above = [];
                            $years = ($diff_days)/365 ;
                            if(isset($aboveDpdKeywords) && $aboveDpdKeywords != ''){
                                $keywords = explode(",",$aboveDpdKeywords);
                                foreach($keywords as $key){
                                    $keyword = trim($key);
                                    $keyword = trim($keyword,'"');
                                    array_push($all_keywords_above, $keyword);
                                }
                            }
                            if ($foirClean) {
                                if ($years >= $dateRange) {
                                    foreach ($foirData as $key => $item) {
                                        if (!in_array($key, $all_keywords_above)) {
                                            $dpdSumAllTradelineAbove += $item;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if($application->merchant->grade->threeYear == 1){
                        if ($dpdSumAllTradeline > $dpdRange) {
                            $this->threeYear = $dpdSumAllTradeline;
                            return $this;
                        }
                    }
                    if($application->merchant->grade->aboveThreeYear == 1){
                        if ($dpdSumAllTradelineAbove > $dpdRangeAbove) {
                            $this->aboveThreeYear = $dpdSumAllTradelineAbove;
                            return $this;
                        }
                    }

                    // if ($threeYear || $aboveThreeYear) {
                    //     if($application->merchant->grade->threeYear == 1){
                    //         if ($threeYear && max($threeYear) > $dpdRange) {
                    //             $this->threeYear = max($threeYear);
                    //             return $this;
                    //         }
                    //     }
                    //     if($application->merchant->grade->aboveThreeYear == 1){
                    //         if ($aboveThreeYear && max($aboveThreeYear) > $dpdRangeAbove) {
                    //             $this->aboveThreeYear = max($aboveThreeYear);
                    //             return $this;
                    //         }
                    //     }
                    // }

                }

                if ($oldloan == 0 && $unsecuredloan == 0) {
                    $this->termLoan = 0;
                } else {
                    $this->termLoan = 1;
                }


                if(!$this->termLoan){
                    if($application->merchant->grade->amount_paid && $application->loan_amount && $maxSanctioned){
                        $crLimitShould = $application->loan_amount * $application->merchant->grade->amount_paid / 100;
                        if(max($maxSanctioned) < $crLimitShould){
                            $this->amount_paid = $crLimitShould;
                            return $this;
                        }
                    }
                }
            }
        }

        $rbiBlack = (new ConsumerApplicationController())->getBlacklistData($application);
        if ($rbiBlack['status']) {
            $this->black_list = 1;
            return $this;
        }

        $track_record = 1;
        if($application->merchant->grade->track_record == 1){

            $minAmount = min([$application->approved_amount * 50 / 100 , 50000]);

            foreach ($application->foir as $foir) {
                if ($foir->OwnershipType == 'Individual' && ($foir->DateClosed == '' || (strtotime($foir->DateClosed) >= strtotime($foirDateRange))) && strtotime($foir->DateOpened) <= strtotime($vintage6Month) && ($foir->AccountType == 'Credit Card' || !in_array($foir->AccountType, ['Gold Loan', 'Loan against Shares/Securities']))) {
                    /*if (($application->approved_amount * 50 / 100 <= $foir->ApprovedAmount) || $application->approved_amount * 50 / 100 <= 50000) {
                        $track_record = 0;
                        break;
                    }*/

                    if($minAmount <= $foir->ApprovedAmount){
                        $track_record = 0;
                        break;
                    }
                }
            }
        }else{
            $track_record=0;
        }

        if($track_record){
            $this->track_record = $track_record;
            return $this;
        }

        if($application->merchant->grade->is_pincode_approved == 1){
            $is_installation_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->application_element->installation_address_pincode)->first();
            $is_current_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->current_address_pincode)->first();
            if((!isset($is_installation_address_pin_approved)) && (empty($is_installation_address_pin_approved)) || ((!isset($is_permanent_address_pin_approved)) && empty($is_permanent_address_pin_approved))){
                $this->approved_pin = 1;
                return $this;
            }
        }

        return $this;

    }

    public function CallEPFKarza($application_id){
        try{

            $failureExists = EpfFailureLog::where('application_id', $application_id)
                ->where('status_code', '!=', 418)
                ->exists();
            if ($failureExists) {
                return; 
            }

            $status_logs = StatusLogs::where(
                'application_id', $application_id)->where(function($query) {
                $query->where(function($q) {
                        $q->whereIn('status', ['approved', 'cf approved', 'rejected', 'pre approved'])
                        ->where('user_id', '107');
                    })
                    ->orWhere('status', 'waiting for decision');
            })->get(['status', 'user_id']);;
            if($status_logs->isEmpty()){
                $employment_status = ConsumerApplication::whereNull('is_deleted')->where('id', $application_id)->first()->employee_status;
                if(isset($employment_status)){
                    if(strtolower($employment_status) == 'salaried'){
                    $controller = new ConsumerApplicationController();

                    $application_data = ConsumerApplication::with('application_element', 'company')->whereNull('is_deleted')->where('id', $application_id)->first();
                    $employer_name= $application_data->company->company;
                    $employee_name= $application_data->name;
                    $emp_mobile = $application_data->mobile_number;
                    $emp_email = $application_data->application_element->work_email;
                    // $epf = EPFUANLookup::where('application_id', $application_id)->first();
                    $emp_entity_id = null;
                    $uan_no = null;
                    if(isset($epf['data'])){
                        $emp_entity_id = $epf->entity_id;
                        $uan_no = $epf->uan_no;
                    }

                    $request = new Request();
                    $request->merge(['application_id'=>$application_id,'employerName'=>$employer_name,'employeeName'=>$employee_name, 'emp_mobile'=>$emp_mobile,'emp_email'=>$emp_email,'emp_entity_id'=>$emp_entity_id, 'uan_no'=>$uan_no, 'id'=>$application_id, 'type'=>'1']);
                    $controller->employmentVerificationAdvanced($request);
                    }
                }
            }
        }catch (\Exception $e){
            // (new Slack(new Request(['title'=>'Error auto fetching EPF data','fields'=>['ID'=>$application_id,'error'=>$e->getMessage(),'line'=>$e->getLine(),'trace'=>$e->getTraceAsString()], 'group' => Slack::$STAGE_TESTING])))->send();
            (new CloudWatchLoggerFactory())->logger(json_encode(['title' => 'Error auto fetching EPF data', 'application_id' => $application_id, 'error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
        }
    }

    public function ApprovalCheckV2($application_id)
    {
        $cwFactory = new CloudWatchLoggerFactory();
        $cwFactory->logger(json_encode(['title' => 'Auto Decision: ApprovalCheckV2', 'application_id' => $application_id]));

        $epf = EPFUANLookup::where('application_id', $application_id)->first();
        if (!isset($epf)){
            $this->CallEPFKarza($application_id);
        }
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.offer')->where('id', $application_id)->first();
        $this->CalculateFOIRbeforeAutoDecision($application_id, $application);

        return $this->MultiApprovalCheck($application_id, '', true);

        $status = true;
        $threeYear = [];
        $accounts = [];
        $aboveThreeYear = [];
        ConsumerApplication::$isCFFoirNotInclude = true;
        $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();
        $vintage6Month = Carbon::now()->subMonth(6)->startOfDay()->toDateTimeString();
        $noDPDDateRange = Carbon::now()->subYear(2)->startOfDay()->toDateTimeString(); //no of dpd’s greater than 6 which is more the 1-15 days in last 2 year)

        $this->appId = $application_id;
        $creReport = CreditReport::where('application_id', $application_id)->first(['id']);
        if(isset($creReport->id)) {
            //(new Slack(new Request(['title' => 'Auto Decision: refreshScoreCardData', 'fields' => ['id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
            (new ConsumerApplicationController())->refreshScoreCardData($application_id);
        }

        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.custom_grade', 'merchant.offer', 'products', 'bank_details')->where('id', $application_id)->first();


        if (!$application->merchant || (isset($application->merchant) && !$application->merchant->grade)) {
            $this->error = 1;
            if (isset($application->merchant) && $application->merchant->custom_grade_id && $application->merchant->custom_grade) {
                return $this->ApprovalCheckCustomV1($application_id);
            }
            return $this;
        }

        if (!$application->merchant->is_auto_approve) {
            $this->error = 1;
            return $this;
        }

        $total = DB::table('consumer_application')->select(DB::raw('count(*) as app_count'), DB::raw('SUM(approved_amount) as total_approved_amount'))->where('merchant_id', $application->merchant_id)->whereIn('state', ['approved', 'disbursement checklist done','ready for disbursement','disbursed','nach registered','closed'])->first();
        $total_remaining_amount = $application->merchant->max_approval_value - $total->total_approved_amount;
        if ($application->merchant->status == 'active' && $application->merchant->pre_status == 1 && ($application->loan_amount > $total_remaining_amount || $total->total_approved_amount > $application->merchant->max_approval_value || $total->app_count >= $application->merchant->max_no_cases)) {
            $this->error = 1;
            return $this;
        }


        if($application && $application->application_element && !empty($application->application_element->product_name) &&
            $application->products && count($application->products) > 0){
            $appl_prod = explode(',', $application->application_element->product_name);
            $products = Products::whereIn('id', $appl_prod)->get();
            $amount = 0;
            foreach($products as $product){
                $amount += $product->amount;
            }
            if($amount != 0 && $amount < $application['loan_amount']){
                $this->product_loan_amount = $application['loan_amount'] - $amount;
                return $this;
            }
        }

        if ($this->request->has('custom_grade_id')) {
            $f = Grades::find($this->request->get('custom_grade_id'));
            $t = new \stdClass();
            $t->grade = $f;
            $application['merchant'] = $t;
        }

        $status_array = ['aborted', 'rejected'];
        $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->get();
        if (isset($status_log[0])) {
            $this->rejected = true;
            return $this;
        }

        if ($checkDuplicates = $this->checkDuplicates($application)) {
            if($checkDuplicates == false){
                $this->checkDuplicates = 1;
                return $this;
            }
        }

        if (isset($application->creditReport[0]) && isset($application->creditReport[0]->Score)) {
            if ($application->creditReport[0]->Score < $application->merchant->grade->score && $application->creditReport[0]->Score > 10) {
                $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
                return $this;
            } elseif ($application->creditReport[0]->Score < 10) {

                if ((isset($application->merchant->grade->thin_file_loan_amount) && empty($application->merchant->grade->thin_file_loan_amount)) || (!isset($application->merchant->grade->thin_file_loan_amount))) {
                    $this->error = 1;
                    return $this;
                }

                $min_loan_amount = ((isset($application->merchant->grade->thin_file_min_loan_amount) && !empty($application->merchant->grade->thin_file_min_loan_amount))) ? $application->merchant->grade->thin_file_min_loan_amount : 0;
                $loan_amount = ((isset($application->merchant->grade->thin_file_loan_amount) && !empty($application->merchant->grade->thin_file_loan_amount))) ? $application->merchant->grade->thin_file_loan_amount : 0;
                $tenure = ((isset($application->merchant->grade->thin_file_tenure) && !empty($application->merchant->grade->thin_file_tenure))) ? $application->merchant->grade->thin_file_tenure : 0;
                $monthly_income = ((isset($application->merchant->grade->thin_file_monthly_income) && !empty($application->merchant->grade->thin_file_monthly_income))) ? $application->merchant->grade->thin_file_monthly_income : 0;
                $grade_age = ((isset($application->merchant->grade->thin_file_age) && !empty($application->merchant->grade->thin_file_age))) ? $application->merchant->grade->thin_file_age : 0;
                $_foir = ((isset($application->merchant->grade->thin_file_foir) && !empty($application->merchant->grade->thin_file_foir))) ? $application->merchant->grade->thin_file_foir : 0;
                $_cf_foir = ((isset($application->merchant->grade->thin_file_cf_foir) && !empty($application->merchant->grade->thin_file_cf_foir))) ? $application->merchant->grade->thin_file_cf_foir : 0;
                $threeYearDPD = 0;
                $aboveThreeYearDPD = 0;

                if ((!isset($application->current_address_status)) || empty($application->current_address_status) || (isset($application->current_address_status) && !in_array($application->current_address_status, array('OWNED', 'PARENTS HOUSE', 'Self Owned', 'Parent Owned')))) {
                    $this->address_status = "No Owned House";
                    return $this;
                }
                if (!$application->emi || (isset($application->emi) && $application->emi->upfront_from_customer <= 0)) {
                    if(!in_array($application->merchant_id, [5983, 5984, 5980, 5803])) {
                        $this->downpayment = isset($application->emi->upfront_from_customer) ? "Zero Downpayment" : 'emi_not_generated';
                        return $this;
                    }
                }

                if (((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) || ((isset($application->application_element->installation_address_pincode)) && !empty($application->application_element->installation_address_pincode))) {
                    $data['current_pincode'] = isset($application->current_address_pincode) && !empty($application->current_address_pincode) ? $application->current_address_pincode : "";
                    $data['installation_pincode'] = isset($application->application_element->installation_address_pincode) && !empty($application->application_element->installation_address_pincode) ? $application->application_element->installation_address_pincode : "";
                    $consumerApplicationConreoller = new ConsumerApplicationController();
                    $NegativeArearesponse = $consumerApplicationConreoller->getNegativeAreaList($data);
                    if ($NegativeArearesponse && isset($NegativeArearesponse->level) && $NegativeArearesponse->level == 1) {
                        $this->negative_area = "Negative Area";
                        return $this;
                    }
                }

                if(isset($application->employee_status)){
                    if($application->merchant->grade->thin_file_employee_status) {
                        $employee_status_array = explode(',',$application->merchant->grade->thin_file_employee_status);
                        if(!in_array($application->employee_status, $employee_status_array)) {
                            $this->employee_status = true;
                            return $this;
                        }
                    }
                }
                if(isset($application->merchant->grade->thin_file_bank_validation)){
                    if($application->merchant->grade->thin_file_bank_validation > 0){
                        $item = isset($application->bank_details) && isset($application->bank_details->karza_response) ? json_decode($application->bank_details->karza_response) : [];
                        if(isset($item->result)){
                            $item = $item->result;
                            $percentage = 0; $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
                            if(round($percentage,0) < $application->merchant->grade->thin_file_bank_validation){
                                $this->bank_validation = round($percentage,0);
                                return $this;
                            }
                        }
                    }
                }

                /* Required EPF Employment Verification for Thin File */
                if($application->merchant->grade->thin_file_epf_verification) {
                    if(strtolower($application->employee_status) == 'salaried'){
                        $epf = EPFUANLookup::where('application_id', $application->id)->first();
                        if(isset($epf) && !empty($epf)) {
                            $epf_data = json_decode($epf->data, 1);
                            $isEmployed = $uanNameMatch = false;
                            if ($epf_data['result']['uan'] && is_array($epf_data['result']['uan'])) {
                                foreach ($epf_data['result']['uan'] as $uanData) {
                                    foreach ($uanData['employer'] as $uanDataEmployer) {
                                        if (strtolower($uanDataEmployer['name']) == strtolower($epf->employerName)) {
                                            $isEmployed = $uanDataEmployer['isEmployed'] ?? false;
                                            $uanNameMatch = $uanDataEmployer['uanNameMatch'] ?? false;
                                        }
                                    }
                                }
                            }
                            if (!$isEmployed || $isEmployed == false || !$uanNameMatch || $uanNameMatch == false || (strtolower($application->company->company) != strtolower($epf->employerName))) {
                                $this->epf_verification = 1;
                                return $this;
                            }
                        }
                    }
                }
                /* Fetch GST Number using PAN for Thin File */
                if($application->merchant->grade->thin_file_fetch_gst) {
                    $emp_status = ['business', 'self employed - business', 'self employed - professional'];
                    if(in_array(strtolower($application->employee_status), $emp_status)) {
                        $gst_pan_data = GSTPANData::where('application_id', $application->id)->orderBy('created_at', 'desc')->first();
                        $gst_data = json_decode($gst_pan_data['data']);
                        if(!isset($gst_data->result[0]->authStatus) || (isset($gst_data->result[0]->authStatus) && $gst_data->result[0]->authStatus == 'Inactive')){
                            $this->fetch_gst = 1;
                            return $this;
                        }
                    }
                }

                $oldloan = 0;
                $unsecuredloan = 0;

            } else {
                $min_loan_amount = (isset($application->merchant->grade->min_loan_amount) && !empty($application->merchant->grade->min_loan_amount)) ? $application->merchant->grade->min_loan_amount : 0;
                $loan_amount = (isset($application->merchant->grade->loan_amount) && !empty($application->merchant->grade->loan_amount)) ? $application->merchant->grade->loan_amount : 0;
                $tenure = (isset($application->merchant->grade->tenure) && !empty($application->merchant->grade->tenure)) ? $application->merchant->grade->tenure : 0;
                $monthly_income = (isset($application->merchant->grade->monthly_income) && !empty($application->merchant->grade->monthly_income)) ? $application->merchant->grade->monthly_income : 0;
                $grade_age = (isset($application->merchant->grade->age) && !empty($application->merchant->grade->age)) ? $application->merchant->grade->age : 0;
                $_foir = (isset($application->merchant->grade->foir) && !empty($application->merchant->grade->foir)) ? $application->merchant->grade->foir : 0;
                $_cf_foir = (isset($application->merchant->grade->cf_foir) && !empty($application->merchant->grade->cf_foir)) ? $application->merchant->grade->cf_foir : 0;
                $threeYearDPD = 10;
                $aboveThreeYearDPD = 15;
                $oldloan = 1;
                $unsecuredloan = 1;

                if(isset($application->employee_status)){
                    if($application->merchant->grade->employee_status) {
                        $employee_status_array = explode(',',$application->merchant->grade->employee_status);
                        if(!in_array($application->employee_status, $employee_status_array)) {
                            $this->employee_status = true;
                            return $this;
                        }
                    }
                }
                if(isset($application->merchant->grade->bank_validation)){
                    if($application->merchant->grade->bank_validation > 0){

                        $item = isset($application->bank_details) && isset($application->bank_details->karza_response) ? json_decode($application->bank_details->karza_response) : [];
                        if(isset($item->result)){
                            $item = $item->result;
                            $percentage = 0; $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
                            if(round($percentage,0) < $application->merchant->grade->bank_validation){
                                $this->bank_validation = round($percentage,0);
                                return $this;
                            }
                        }
                    }
                }

                /* Required EPF Employment Verification */
                if($application->merchant->grade->epf_verification) {
                    if(strtolower($application->employee_status) == 'salaried'){
                        $epf = EPFUANLookup::where('application_id', $application->id)->first();
                        $epf_data = json_decode($epf['data'], 1);
                        $isEmployed = $uanNameMatch = false;
                        if($epf_data['result']['uan'] && is_array($epf_data['result']['uan'])) {
                            foreach ($epf_data['result']['uan'] as $uanData) {
                                foreach ($uanData['employer'] as $uanDataEmployer) {
                                    if(strtolower($uanDataEmployer['name']) == strtolower($epf->employerName)){
                                        $isEmployed = $uanDataEmployer['isEmployed'] ?? false;
                                        $uanNameMatch = $uanDataEmployer['uanNameMatch'] ?? false;
                                    }
                                }
                            }
                        }
                        if(!$isEmployed || $isEmployed == false || !$uanNameMatch || $uanNameMatch == false || (strtolower($application->company->company) != strtolower($epf->employerName))){
                            $this->epf_verification = 1;
                            return $this;
                        }

                    }
                }
                /* Fetch GST Number using PAN */
                if($application->merchant->grade->fetch_gst) {
                    $emp_status = ['business', 'self employed - business', 'self employed - professional'];
                    if(in_array(strtolower($application->employee_status), $emp_status)) {
                        $gst_pan_data = GSTPANData::where('application_id', $application->id)->orderBy('created_at', 'desc')->first();
                        $gst_data = json_decode($gst_pan_data['data']);
                        if(!isset($gst_data->result[0]->authStatus) || (isset($gst_data->result[0]->authStatus) && $gst_data->result[0]->authStatus == 'Inactive')){
                            $this->fetch_gst = 1;
                            return $this;
                        }
                    }
                }

            }
        } else {
            $this->score = 'no_equifax';
            return $this;
        }

        if ($application->loan_amount == 0 || $application->loan_amount > $loan_amount || $application->loan_amount < $min_loan_amount || $loan_amount == 0 || empty($loan_amount)) {
            $this->loan_amount = $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount;
            return $this;
        }

        //Run net tenure condition on multiple offers
        $product = $application->application_element->product_name;
        $productOffers = ProductOffers::where('product_id', $product)->whereNull('deleted_at')->pluck('offer_id');
        if (!$productOffers->isEmpty()) {
            $offers = MerchantOffers::whereIn('id', $productOffers)->where('status',1)->whereNull('deleted_at')->get();
        }
        else {
            $offers = MerchantOffers::where('merchant_id', $application->merchant_id)->where('status',1)->get();
        }
        if($offers) {
            foreach ($offers as $offer) {

                $_tenure = $offer->tenure;
                if ($offer->advance_type == 'emi') {
                    $_tenure = $offer->tenure - $offer->advance_emi;
                }

                // if (!$application->emi || $tenure == 0 || empty($tenure) || (isset($application->emi) && $_tenure > $tenure))
                if ($tenure == 0 || empty($tenure) || (isset($application->emi) && $_tenure > $tenure)){
                    $this->tenure = !$_tenure ? 'no offer found' : $_tenure;
                    $this->Atenure[] = ['tenure' => !$_tenure ? 'no offer found' : $_tenure, 'offer_id' => $offer->id, 'status' => 1];
                    //return $this;
                }else{
                    $this->Atenure[] = ['tenure' => !$_tenure ? 'no offer found' : $_tenure, 'offer_id' => $offer->id, 'status' => 0];
                }
            }
        }else{
            // if (!$application->emi || $tenure == 0 || empty($tenure) || (isset($application->emi) && $application->emi->remaining_emi > $tenure))
            if ($tenure == 0 || empty($tenure) || (isset($application->emi) && $application->emi->remaining_emi > $tenure)){
                $this->tenure = !isset($application->emi->remaining_emi) ? 'emi not generated' : $application->emi->remaining_emi;
                return $this;
            }
        }

        if (!$application->monthly_income || $monthly_income == 0 || empty($monthly_income) || ($application->monthly_income < $monthly_income)) {
            $this->monthly_income = $application->monthly_income;
            return $this;
        }



//        if(!isset($application->creditReport[0]) || isset($application->creditReport[0]) && isset($application->creditReport[0]->Score) && $application->creditReport[0]->Score < $application->merchant->grade->score){
//            $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
//            return $this;
//        }
        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
        if (isset($application->emi)) {
            $last_emi_date = Carbon::now()->addMonths($application->emi->remaining_emi)->toDateString();
            $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
        }
        if ($grade_age == 0 || empty($grade_age) || $age < $grade_age) {
            $this->age = $age;
            return $this;
        }
        if($application->merchant->grade->ageAtLastEMI == 1){
            $ageLimit = isset($application->merchant->grade->ageAtLastEMI_age) ? $application->merchant->grade->ageAtLastEMI_age : 60;
            if (isset($ageAtLastEMI)) {
                if ($ageAtLastEMI > $ageLimit) {
                    $this->ageAtLastEMI = $ageAtLastEMI;
                    return $this;
                }
            }
        }

        $creditCardAmount = 0;
        $creditCardLimit = [];
        $maxSanctioned = [];
        if (isset($application->creditReport[0])) {
            $creditReport = $application->creditReport[0];
            if($application->merchant->grade->pastDues == 1){
                $pastDueLimit = isset($application->merchant->grade->pastDues_value) ? (int)$application->merchant->grade->pastDues_value : 500;
                if ($creditReport->TotalPastDue > $pastDueLimit) {
                    $this->pastDues = $creditReport->TotalPastDue;
                    return $this;
                }
            }
            if ($status) {
                $termloanarray = ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan',
                    'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility',
                    'Business Non-Funded Credit Facility - Priority', 'Staff Loan'];
                if ($application->foir) {
                    $gold_loan = 0;
                    //(new Slack(new Request(['title' => 'Auto Decision: foir', 'fields' => ['id' => $application_id,'state' => json_encode($application->foir)], 'group' => Slack::$STAGE_TESTING])))->send();
                    foreach ($application->foir as $foir) {

                        $accounts[] = $foir->AccountType;

                        if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                            $gold_loan++;
                            if ($gold_loan >= 3) {
                                $this->AccountType = $foir->AccountType;
                                break;
                            }
                        }

                        if ($foir->AccountType == 'Credit Card' && $foir->DateClosed == '') {
                            $creditCardAmount += $foir->InstallmentAmount;
                            $creditCardLimit[] = $foir->ApprovedAmount - $foir->Balance;
                        }

                        if ($foir->DateOpened) {
                            if (!$foir->DateClosed) {
                                $foir->DateClosed = "";
                            }
                            if ($foir->DateClosed) {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened, $foir->DateClosed);
                            } else {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened);
                            }
//                            if ($foir->DateClosed) {
//                                $date = date('Y', strtotime($foir->DateClosed));
//                            } else {
//                                $date = date('Y', time());
//                            }
//
//                            $termLoan = (date('Y', strtotime($foir->DateOpened)) - $date);
                            if ($termLoan > 0 && $oldloan != 0) {
                                $oldloan = 0;
                            }

                            if ((in_array($foir->AccountType, $termloanarray)) && $unsecuredloan != 0) {
                                $unsecuredloan = 0;
                            }

                            if (in_array($foir->AccountType, $termloanarray) && $oldloan == 0 && $unsecuredloan == 0 && $foir->DateClosed == '') {
                                $maxSanctioned[] = $foir->ApprovedAmount - $foir->Balance;
                            }
                        }

                        $this->setFOIRAttributes($foir);
                    }

                    if (!empty($this->AccountType)) {
                        return $this;
                    }

                    if($application->merchant->grade->amount_paid_cr && $application->loan_amount && $creditCardLimit){
                        $crLimitShould = $application->loan_amount * $application->merchant->grade->amount_paid_cr / 100;
                        if(max($creditCardLimit) < $crLimitShould){
                            $this->amount_paid_cr = $crLimitShould;
                            return $this;
                        }
                    }

                    if (count($accounts) == 1) {
                        if (in_array('Guarantor', $accounts)) {
                            $this->guarantor = 1;
                            return $this;
                        }
                    }


                    if($offers) {

                        foreach ($offers as $offer) {

                            $this->request->merge(['merchant_id' => $application->merchant_id, 'loan_amount' => $application->loan_amount, 'merchant_offer_id' => $offer->id, 'category_id' => $application->purpose, 'interest_type_id' => $offer->interest_type_id, 'application_id' => $application->id]);

                            $emi = new EMICalculation($this->request);
                            $res = $emi->prepareCalculation();

                            $res = $res->getData();

                            $this->cfFoir = 0;
                            $this->foirIncludingCFEMI = 0;
                            $this->getFOIRCalculation($application, $res->emi);
                            $this->emiData[$offer->id] = ['emi' => $res->emi, 'payable' => $res->payable, 'interest_rate' => $res->flat_annual_interest, 'processing_fee' => $res->processing_fee, 'upfront_from_customer' => $res->up_front_from_customer];
                            //$this->getFOIRCalculation($application, 1);


                            //(new Slack(new Request(['title' => 'Auto Decision: FOIR Alert', 'fields' => ['id' => $application->id, 'total_existing_emi' => $this->total_existing_emi, 'this->credit_limit' => $this->credit_limit, 'Score' => $this->score, 'CF Foir' => $this->cfFoir, 'CF Foir grade' => $_cf_foir, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'foirIncludingCFEMI Grade' => $_foir], 'group' => Slack::$STAGE_TESTING])))->send();
                            if ($this->cfFoir > $_cf_foir) {
                                $this->cf_foir = $this->cfFoir;
                                $this->Acf_foir[] = ['offer_id' =>  $offer->id, 'cfFoir' => $this->cfFoir, 'status' => 1];
                                //return $this;
                            }else{
                                $this->Acf_foir[] = ['offer_id' =>  $offer->id, 'cfFoir' => $this->cfFoir, 'status' => 0];
                            }
                            if ($this->foirIncludingCFEMI > $_foir) {
                                $this->foir = $this->foirIncludingCFEMI;
                                $this->Afoir[] = ['offer_id' => $offer->id, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'status' => 1];
                                //return $this;
                            }else{
                                $this->Afoir[] = ['offer_id' => $offer->id, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'status' => 0];
                            }
                        }
                    }else{
                        $this->getFOIRCalculation($application);
                        //$this->getFOIRCalculation($application, 1);


                        //(new Slack(new Request(['title' => 'Auto Decision: FOIR Alert', 'fields' => ['id' => $application->id, 'total_existing_emi' => $this->total_existing_emi, 'this->credit_limit' => $this->credit_limit, 'Score' => $this->score, 'CF Foir' => $this->cfFoir, 'CF Foir grade' => $_cf_foir, 'foirIncludingCFEMI' => $this->foirIncludingCFEMI, 'foirIncludingCFEMI Grade' => $_foir], 'group' => Slack::$STAGE_TESTING])))->send();
                        if ($this->cfFoir > $_cf_foir) {
                            $this->cf_foir = $this->cfFoir;
                            return $this;
                        }
                        if ($this->foirIncludingCFEMI > $_foir) {
                            $this->foir = $this->foirIncludingCFEMI;
                            return $this;
                        }
                    }

                    foreach ($application->foir as $foir) {

                        $foirData = json_decode($foir->dpd, 1);


                        if (strtotime($foir->DateOpened) <= strtotime($noDPDDateRange)) {
                            $dpdCount = 0;
                            foreach ($foirData as $key => $item) {
                                if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                    $dpdCount += $item;
                                    if ($dpdCount > 6) {
                                        $this->dpdCountRejection = $dpdCount;
                                    }
                                }
                            }
                        }

                        if ($foirData) {
                            $caseType = array_keys($foirData);
                            if ($caseType) {
                                foreach ($caseType as $type) {
                                    if (in_array($type, ['PWOS', 'SET'])) {
                                        $this->caseType = $type;
                                        return $this;
                                    }
                                }
                            }
                        }

                        if($application->merchant->grade->last_payment_date_number && !$foir->DateClosed && $foir->LastPaymentDate && $foir->Balance > 0 && $foir->LastPaymentDate) {
                            $days = Carbon::parse($foir->LastPaymentDate)->diffInDays(date('Y-m-d'));

                            if($days > $application->merchant->grade->last_payment_date_number){
                                $this->last_payment_date = 1;
                                return $this;
                            }
                        }

                        $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                        if ($foirClean) {
                            if (strtotime($foir->DateOpened) <= strtotime($foirDateRange)) {
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $threeYear[] = $item;
                                    }
                                }
                            }
                            if (strtotime($foir->DateOpened) >= strtotime($foirDateRange)) {
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $aboveThreeYear[] = $item;
                                    }
                                }
                            }
                        }
                    }

                    if ($threeYear || $aboveThreeYear) {
                        if ($threeYear && max($threeYear) > $threeYearDPD) {
                            $this->threeYear = max($threeYear);
                            return $this;
                        }
                        if ($aboveThreeYear && max($aboveThreeYear) > $aboveThreeYearDPD) {
                            $this->aboveThreeYear = max($aboveThreeYear);
                            return $this;
                        }
                    }

                }

                if ($oldloan == 0 && $unsecuredloan == 0) {
                    $this->termLoan = 0;
                } else {
                    $this->termLoan = 1;
                }


                if(!$this->termLoan){
                    if($application->merchant->grade->amount_paid && $application->loan_amount && $maxSanctioned){
                        $crLimitShould = $application->loan_amount * $application->merchant->grade->amount_paid / 100;
                        if(max($maxSanctioned) < $crLimitShould){
                            $this->amount_paid = $crLimitShould;
                            return $this;
                        }
                    }
                }
            }
        }

        $rbiBlack = (new ConsumerApplicationController())->getBlacklistData($application);
        if ($rbiBlack['status']) {
            $this->black_list = 1;
            return $this;
        }

        $track_record = 1;
        if($application->merchant->grade->track_record == 1){

            $minAmount = min([$application->approved_amount * 50 / 100 , 50000]);

            foreach ($application->foir as $foir) {
                if ($foir->OwnershipType == 'Individual' && ($foir->DateClosed == '' || (strtotime($foir->DateClosed) >= strtotime($foirDateRange))) && strtotime($foir->DateOpened) <= strtotime($vintage6Month) && ($foir->AccountType == 'Credit Card' || !in_array($foir->AccountType, ['Gold Loan', 'Loan against Shares/Securities']))) {
                    /*if (($application->approved_amount * 50 / 100 <= $foir->ApprovedAmount) || $application->approved_amount * 50 / 100 <= 50000) {
                        $track_record = 0;
                        break;
                    }*/

                if($minAmount <= $foir->ApprovedAmount){
                    $track_record = 0;
                    break;
                }
               }
            }
        }else{
            $track_record=0;
        }

        if($track_record){
            $this->track_record = $track_record;
            return $this;
        }

        if($application->merchant->grade->is_pincode_approved == 1){
            $is_installation_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->application_element->installation_address_pincode)->first();
            $is_current_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->current_address_pincode)->first();
            if((!isset($is_current_address_pin_approved)) && (empty($is_current_address_pin_approved)) || ((!isset($is_installation_address_pin_approved)) && empty($is_installation_address_pin_approved))){
                $this->approved_pin = 1;
                return $this;
            }
        }

        return $this;

    }

    public function testingApprovalCheck($application_id)
    {
        $status = true;
        $threeYear = [];
        $accounts = [];
        $aboveThreeYear = [];
        ConsumerApplication::$isCFFoirNotInclude = true;
        $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();
        $noDPDDateRange = Carbon::now()->subYear(2)->startOfDay()->toDateTimeString(); //no of dpd’s greater than 6 which is more the 1-15 days in last 2 year)
        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.grade', 'merchant.offer')->where('id', $application_id)->first();
        /*if(!$application->merchant->grade){
            $this->error = 1;
            return $this;
        }*/

        if ($this->request->has('custom_grade_id')) { //$this->request->has('custom_grade_id')
            $f = Grades::find($this->request->get('custom_grade_id'));//$this->request->get('custom_grade_id')
            $t = new \stdClass();
            $t->grade = $f;
            $application['merchant'] = $t;
        }

        $status_array = ['aborted', 'rejected'];
        $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->get();
        if (isset($status_log[0])) {
            //$this->rejected = true;
            //return $this;
        }
        /*if(isset($application->application_element->negative_profile) && $application->application_element->negative_profile > 0){
            $this->negativeProfile = true;
            return $this;
        }
        if($checkDuplicates = $this->checkDuplicates($application)){
            $this->checkDuplicates = $checkDuplicates;
            return $this;
        }*/
        if ($application->loan_amount == 0 || $application->loan_amount > $application->merchant->grade->loan_amount) {
            $this->loan_amount = $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount;
            //return $this;
        }
        if (!$application->emi || isset($application->emi) && isset($application->merchant->grade->tenure) && $application->emi->remaining_emi > $application->merchant->grade->tenure) {
            $this->tenure[] = !isset($application->emi->remaining_emi) ? 'emi not generated' : $application->emi->remaining_emi;
            //return $this;
        }
        if (!$application->monthly_income || ($application->monthly_income < $application->merchant->grade->monthly_income)) {
            $this->monthly_income = $application->monthly_income;
            //return $this;
        }
        if (!isset($application->creditReport[0]) || isset($application->creditReport[0]) && isset($application->creditReport[0]->Score) && $application->creditReport[0]->Score < $application->merchant->grade->score) {
            $this->score = isset($application->creditReport[0]) ? $application->creditReport[0]->Score : 'no_equifax';
            //return $this;
        }
        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
        if (isset($application->emi)) {
            $last_emi_date = Carbon::now()->addMonths($application->emi->remaining_emi)->toDateString();
            $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
        }
        if ($age < $application->merchant->grade->age) {
            $this->age = $age;
            //return $this;
        }
        if (isset($ageAtLastEMI)) {
            if ($ageAtLastEMI > 60) {
                $this->ageAtLastEMI = $ageAtLastEMI;
                //return $this;
            }
        }

        $creditCardAmount = 0;
        if (isset($application->creditReport[0])) {
            $creditReport = $application->creditReport[0];
            $pastDueLimit = isset($application->merchant->grade->pastDues_value) ? (int)$application->merchant->grade->pastDues_value : 500;
            if ($creditReport->TotalPastDue > $pastDueLimit) {
                $this->pastDues = $creditReport->TotalPastDue;
                //return $this;
            }
            if ($status) {
                $oldloan = 1;
                $unsecuredloan = 1;
                $termloanarray = ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan',
                    'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility',
                    'Business Non-Funded Credit Facility - Priority', 'Staff Loan'];
                if ($application->foir) {
                    $gold_loan = 0;
                    foreach ($application->foir as $foir) {

                        $accounts[] = $foir->AccountType;

                        if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                            $gold_loan++;
                            if ($gold_loan >= 3) {
                                $this->AccountType = $foir->AccountType;
                                break;
                            }
                        }

                        if ($foir->AccountType == 'Credit Card' && $foir->DateClosed == '') {
                            $creditCardAmount += $foir->InstallmentAmount;
                        }

                        if ($foir->DateOpened) {
                            if (!$foir->DateClosed) {
                                $foir->DateClosed = "";
                            }
                            if ($foir->DateClosed) {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened, $foir->DateClosed);
                            } else {
                                $termLoan = self::calculatedifferenceindate($foir->DateOpened);
                            }
                            if ($termLoan > 0 && $oldloan != 0) {
                                $oldloan = 0;
                            }

                            if ((in_array($foir->AccountType, $termloanarray)) && $unsecuredloan != 0) {
                                $unsecuredloan = 0;
                            }
                        }

                        $this->setFOIRAttributes($foir);
                    }

                    if (!empty($this->AccountType)) {
                        //return $this;
                    }

                    if (count($accounts) == 1) {
                        if (in_array('Guarantor', $accounts)) {
                            $this->guarantor = 1;
                            //return $this;
                        }
                    }

                    $this->getFOIRCalculation($application);
                    //$this->getFOIRCalculation($application, 1);


                    if ($this->cfFoir > $application->merchant->grade->cf_foir) {
                        $this->cf_foir = $this->cfFoir;
                        //return $this;
                    }
                    if ($this->foirIncludingCFEMI > $application->merchant->grade->foir) {
                        $this->foir = $this->foirIncludingCFEMI;
                        //return $this;
                    }

                    foreach ($application->foir as $foir) {

                        $foirData = json_decode($foir->dpd, 1);


                        if (strtotime($foir->DateOpened) <= strtotime($noDPDDateRange)) {
                            $dpdCount = 0;
                            foreach ($foirData as $key => $item) {
                                if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                    $dpdCount += $item;
                                    if ($dpdCount > 6) {
                                        $this->dpdCountRejection = $dpdCount;
                                    }
                                }
                            }
                        }

                        if ($foirData) {
                            $caseType = array_keys($foirData);
                            if ($caseType) {
                                foreach ($caseType as $type) {
                                    if (in_array($type, ['PWOS', 'SET'])) {
                                        $this->caseType = $type;
                                        //return $this;
                                    }
                                }
                            }
                        }


                        $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                        if ($foirClean) {
                            if (strtotime($foir->DateOpened) <= strtotime($foirDateRange)) {
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $threeYear[] = $item;
                                    }
                                }
                            }
                            if (strtotime($foir->DateOpened) >= strtotime($foirDateRange)) {
                                foreach ($foirData as $key => $item) {
                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                        $aboveThreeYear[] = $item;
                                    }
                                }
                            }
                        }
                    }

                    if ($threeYear || $aboveThreeYear) {
                        if ($threeYear && max($threeYear) > 15) {
                            $this->threeYear = max($threeYear);
                            //return $this;
                        }
                        if ($aboveThreeYear && max($aboveThreeYear) > 60) {
                            $this->aboveThreeYear = max($aboveThreeYear);
                            //return $this;
                        }
                    }
                }

                if ($oldloan == 0 && $unsecuredloan == 0) {
                    $this->termLoan = 0;
                } else {
                    $this->termLoan = 1;
                }
            }
        }

        return $this;

    }

    public function generateEMIForDecision($consumerApplicationController, $application, $request, $id){
        $offer = MerchantOffers::with('disbursementOffersData')->where('id', $application->offer_id)->first(['subvention_type_id', 'interest_type_id']);

        $isAvanse = $request->has('avanse');
        $available_date = $consumerApplicationController->calculateFirstEMIDate($application, $isAvanse, $offer);
        $emi_date = date('d/m/Y', strtotime($available_date));
        $consumerApplicationController->updateProforma($id);
        $request->request->add(
            [
                'first_emi_date' => $emi_date,
                'loan_amount' => $application->approved_amount > 0 ? $application->approved_amount : $application->loan_amount,
                'merchant_id' => $application->merchant_id,
                'category_id' => $application->category->id,
                'interest_type_id' => $offer->interest_type_id,
                'merchant_offer_id' => $application->offer_id
            ]
        );

        $consumerApplicationController->generateEMI($request, $application, $id);
    }

    public function autoApproveInit($id, $isLog = true)
    {

        try {
            $is_bureau_generated = DB::connection('mysql_primary')->selectOne("SELECT id FROM credit_report WHERE application_id = $id AND applicant_type = 1");
            if (isset($is_bureau_generated->id)) {

                $response = [];

                $request = new Request();
                $application = ConsumerApplication::with('category', 'merchant', 'emi', 'creditReport', 'approval','application_element', 'activeOffer')->where('id', $id)->first();
                $consumerApplicationController = new ConsumerApplicationController();

                if (!$application->approved_amount && $application->loan_amount){
                    ConsumerApplication::where('id', $id)->update(['approved_amount' => $application->loan_amount]);
                }

                if (!$application->emi) {
                    $this->generateEMIForDecision($consumerApplicationController, $application, $request, $id);
                }

                if (!$application->creditReport) {
                    $consumerApplicationController->isRoot = false;
                    // $equifax = $consumerApplicationController->generateEqifaxReport($id);
                    $equifax = $consumerApplicationController->generateSoftBureauReport($id);

                    if (isset($equifax['status']) && $equifax['status'] == 'FAIL') {
                        $response[$equifax['message']] = false;

                        return response()->json($response, 200);
                    }
                }

                $shouldSkipReject = $this->request->attributes->get('skip_auto_reject') ?? false;
                if ($application->creditReport) {
                    $req_id = $this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : '';
                    if (!$shouldSkipReject) {
                        $autoRejectResult = (new AutoRejection($this->request))->autoReject(false, $id);
                        $cwFactory = new CloudWatchLoggerFactory();
                        $cwFactory->logger(json_encode(['title' => 'Auto Reject', 'application_id' => $id, 'auto_reject' => $autoRejectResult]));
                        if ($autoRejectResult) {
                            $consumer_application = ConsumerApplication::find($id);
                            $consumer_application->state = "rejected";
                            $consumer_application->save();
                            $status = 'rejected';
                            StatusLogs::insert([
                                'application_id' => $id,
                                'user_id' => 107,
                                'status' => $status,
                                'created_at' => Carbon::now()->toDateTimeString()
                            ]);
                            return response(['rejected_case' => true], 200);
                        }
                    }

                    (new Slack(new Request(['title' => 'Auto Decision V1 - Started', 'fields' => ['id' => $id, 'time' => Carbon::now()->toDateTimeString()], 'group' => Slack::$STAGE_TESTING])))->send();
                    $grade = $this->ApprovalCheckV1($id, $req_id);
                    (new Slack(new Request(['title' => 'Auto Decision V1 - Ended', 'fields' => ['id' => $id, 'time' => Carbon::now()->toDateTimeString()], 'group' => Slack::$STAGE_TESTING])))->send();
                    if ($grade) {
                        // CO-APPLICANT AUTO REJECT CHECK to block auto approval if co-applicant is rejected
                        $is_co_app_bureau_generated = DB::connection('mysql_primary')->selectOne("SELECT id FROM credit_report WHERE application_id = ? AND applicant_type = 2", [$id]);
                        if (isset($is_co_app_bureau_generated->id)) {
                            $isCoAppRejected = AutoRejectLogs::where('application_id', $id)->where('applicant_type', 2)->exists();
                            if ($isCoAppRejected) {
                                $grade = false;
                                $cwFactoryLogger = new CloudWatchLoggerFactory();
                                $cwFactoryLogger->logger(json_encode(['title' => 'Auto Decision', 'application_id' => $id, 'message' => 'Co-applicant BRE rejected, blocking auto approval.']));
                                $this->addComment($id, 107, 'Co-applicant BRE rejected, hence auto approval blocked.');
                            }
                        }
                    }
                    if($grade){
                        return response(['auto_approved' => false], 200);
                    } else if (!$this->request->has('communication') || $this->request->get('communication') == true) {
                        $this->initAutoDocumentation($grade, $application->id);
                    }
                }
            }
            (new Slack(new Request(['title' => 'Auto Approve Init', 'fields' => ['id' => $id, 'message' => 'Credit Report not found' ], 'group' => Slack::$STAGE_TESTING])))->send();
            return false;

        } catch (\Exception $e) {
            (new Slack(new Request(['title' => 'Auto Approve Init Error', 'fields' => ['id' => $id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString() ], 'group' => Slack::$STAGE_TESTING])))->send();
            return false;
        }
    }

    public function autoApproveInitCoapplicant($id)
    {
        try {
            $is_bureau_generated = DB::connection('mysql_primary')->selectOne("SELECT id FROM credit_report WHERE application_id = ? AND applicant_type = 2", [$id]);
            if (isset($is_bureau_generated->id)) {
                $isRejected = (new AutoRejection(new Request()))->autoRejectCoApplicantJSONBRE(false, $id, $tracking_id='');
            }
        } catch (\Exception $e) {
            (new Slack(new Request(['title' => 'Auto Approve Init Coapplicant Error', 'fields' => ['id' => $id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString() ], 'group' => Slack::$STAGE_TESTING])))->send();
        }
    }

    public function initAutoDocumentation($_grade, $id, $send_email = true)
    {
        if((new AvanseProcesses(new Request(['id' => $id])))->checkEligibility()){
            return false;
        }

        if((new Services())->checkEligibility($id)){
            return false;
        }

        $application = ConsumerApplication::with('merchant.document_rule', 'application_element', 'emi', 'creditReport','documents', 'application_element','activeOffer')->where('id', $id)->first();

        if(!$application->emi){
            $consumerApplicationController = new ConsumerApplicationController();
            $request = new Request();
            $this->generateEMIForDecision($consumerApplicationController, $application, $request, $id);
        }

        $status = false;
        $auto_document_rule_id = [];

        if ($application->merchant && (!$application->merchant->is_auto_approve || !$this->cfFoir)) {
            $this->getFOIRByID($application->id);
        }

        if ($application->merchant && $application->merchant->is_auto_doc && $application->merchant->document_rule) {
            foreach ($application->merchant->document_rule as $document_rule) {
                $auto_document_rule_id[] = $document_rule->id;
                if (isset($application->creditReport) && isset($application->creditReport[0]) && $application->creditReport[0]->Score >= $document_rule->score_from && $application->creditReport[0]->Score <= $document_rule->score_to) {
                    if ($application->loan_amount >= $document_rule->loan_amount_from && $application->loan_amount <= $document_rule->loan_amount_to) {
                        if (strpos(strtolower($application->employee_status), strtolower($document_rule->employment_type)) !== false) {
                            if ($application->monthly_income >= $document_rule->income_from && $application->monthly_income <= $document_rule->income_to) {
                                if (round($this->cfFoir) >= $document_rule->foir_from && round($this->cfFoir) <= $document_rule->foir_to) {
                                    $ap_amount = $application->approved_amount ? $application->approved_amount : $application->loan_amount;
                                    if($application->emi->upfront_from_customer) {

                                        $downPayment = 0;
                                        if($application->merchant->charge_subvention_remaining_amount){
                                            $downPayment = $application->emi->upfront_from_customer;
                                        }

                                        $disbursementAmount = ($ap_amount - ($application->emi->upfront_from_customer + (($ap_amount - $downPayment) * $application->emi->subvention / 100)));
                                    }else{
                                        $disbursementAmount = 0;
                                    }
                                    if ($disbursementAmount >= $document_rule->disbursement_from && $disbursementAmount <= $document_rule->disbursement_to) {
                                        if ($document_rule->negative_area == 1) {
                                            $negative_area = new ConsumerApplicationController();
                                            $isNegativeArea = $negative_area->getNegativeAreaList([
                                                'installation_pincode' => $application->application_element->installation_address_pincode, 'current_pincode' => $application->current_address_pincode]);
                                            if ($isNegativeArea) {
                                                if ($document_rule->negative_profile == 1) {
                                                    if ($application->application_element->negative_profile > 0) {
                                                        if ($document_rule->collateral_loan == 1 && $this->isCollateralLoan($id)) {
                                                            $status = $document_rule->id;
                                                            break;
                                                        } else if ($document_rule->collateral_loan == 0) {
                                                            $status = $document_rule->id;
                                                            break;
                                                        } else {
                                                            $this->autoDocumentation[] = ['collateral_loan' => 1, 'auto_document_rule_id' => $document_rule->id];
                                                        }
                                                    } else {
                                                        $this->autoDocumentation[] = ['negative_profile' => 1, 'auto_document_rule_id' => $document_rule->id];
                                                    }
                                                } elseif ($document_rule->collateral_loan == 1 && $this->isCollateralLoan($id)) {
                                                    $status = $document_rule->id;
                                                    break;
                                                } else if ($document_rule->collateral_loan == 0) {
                                                    $status = $document_rule->id;
                                                    break;
                                                } else {
                                                    $this->autoDocumentation[] = ['collateral_loan' => 1, 'auto_document_rule_id' => $document_rule->id];
                                                }
                                            } else {
                                                $this->autoDocumentation[] = ['negative_area' => 1, 'auto_document_rule_id' => $document_rule->id];
                                            }
                                        } else {
                                            if ($document_rule->negative_profile == 1) {
                                                if ($application->application_element->negative_profile > 0) {
                                                    if ($document_rule->collateral_loan == 1 && $this->isCollateralLoan($id)) {
                                                        $status = $document_rule->id;
                                                        break;
                                                    } else if ($document_rule->collateral_loan == 0) {
                                                        $status = $document_rule->id;
                                                        break;
                                                    } else {
                                                        $this->autoDocumentation[] = ['collateral_loan' => 1, 'auto_document_rule_id' => $document_rule->id];
                                                    }
                                                } else {
                                                    $this->autoDocumentation[] = ['negative_profile' => 1, 'auto_document_rule_id' => $document_rule->id];
                                                }
                                            } elseif ($document_rule->collateral_loan == 1 && $this->isCollateralLoan($id)) {
                                                $status = $document_rule->id;
                                                break;
                                            } else if ($document_rule->collateral_loan == 0) {
                                                $status = $document_rule->id;
                                                break;
                                            } else {
                                                $this->autoDocumentation[] = ['collateral_loan' => 1, 'auto_document_rule_id' => $document_rule->id];
                                            }
                                        }
                                    } else {
                                        $this->autoDocumentation[] = ['net_disbursement' => $disbursementAmount, 'auto_document_rule_id' => $document_rule->id];
                                    }
                                } else {
                                    $this->autoDocumentation[] = ['foir' => $this->cfFoir, 'auto_document_rule_id' => $document_rule->id];
                                }
                            } else {
                                $this->autoDocumentation[] = ['monthly_income' => $application->monthly_income, 'auto_document_rule_id' => $document_rule->id];
                            }
                        } else {
                            $this->autoDocumentation[] = ['employee_status' => $application->employee_status, 'auto_document_rule_id' => $document_rule->id];
                        }
                    } else {
                        $this->autoDocumentation[] = ['loan_amount' => $application->loan_amount, 'auto_document_rule_id' => $document_rule->id];
                    }
                } else {
                    $this->autoDocumentation[] = ['score' => isset($application->creditReport[0]) ? ($application->creditReport ? $application->creditReport[0]->Score : $this->score) : 'no equifax', 'auto_document_rule_id' => $document_rule->id];
                }
            }
            if($status) {
                $rbiBlack = (new ConsumerApplicationController())->getBlacklistData($application);
                if ($rbiBlack['status']) {
                    $this->autoDocumentation[] = ['black_list' => 1, 'auto_document_rule_id' => 0];
                    $status = false;
                }
            }
        } else {
            $this->autoDocumentation[] = ['status' => 1];
        }

        if ($status && $send_email) {
            if($application->merchant_id != 6543) {
                $this->sendDocumentEmailToCustomer($application, $status);
            }
            ConsumerApplicationElement::where('application_id', $application->id)->update(['auto_document_rule_id' => $status]);
        } else if(!$status){
            $_index = 0;
            foreach ($this->autoDocumentation as $index=>$autoDocumentation) {
                $_autoDocumentation = $autoDocumentation;
                $_autoDocumentation = array_merge($_autoDocumentation, ['application_id' => $id]);
                $requestID = $this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : '';
                //$_autoDocumentation = array_merge($_autoDocumentation, ['auto_document_rule_id' => isset($auto_document_rule_id[$_index]) ? $auto_document_rule_id[$_index] : 0]);
                $_autoDocumentation = array_merge($_autoDocumentation, ['created_at' => Carbon::now()->toDateTimeString(), 'request_id' => $requestID]);
                DocumentRuleLog::insert($_autoDocumentation);
                $_index++;
            }
        }else{
            ConsumerApplicationElement::where('application_id', $application->id)->update(['auto_document_rule_id' => $status]);
        }

        return $status;
    }

    public function getPreDocumentsList($documentRuleID, $application, $files = array())
    {
        if (!$files) {
            if ($application->documents) {
                foreach ($application->documents as $document) {
                    $docKey = strtolower(str_replace(' ', '_', $document->file_type));
                    if ($docKey == 'salary_slip') {
                        $files[] = 'pay_slip';
                    }
                    $files[] = $docKey;
                }
            }
        }

        $document = DocumentSets::find(DocumentRule::find($documentRuleID)->document_set);

        $docLists = [];
        $documentList = json_decode($document->documents);
        foreach ($documentList as $index => $item) {
            $docLists[$item->group][$item->optional == 'true' ? 2 : 1][] = $item->id;
        }

        $lists = [];
        foreach ($docLists as $group => $_list) {
            foreach ($_list as $bool => $list) {
                if ($group && $bool == 2) {
                    array_push($lists, implode(' or ', $list));
                } else {
                    $lists = array_merge($lists, $list);
                }
            }
        }

        //return $_docLists;
        $receivedDocument = $this->isDocumentReceived($lists, $files);

        $completeList = $receivedDocument['completeList'];
        $listsData = $receivedDocument['listsData'];
        $lists = $receivedDocument['lists'];

        $_docLists = [];
        $lists = array_values($lists);
        if (!$this->request->has('isNumberedList')) {
            foreach ($lists as $indexItem => $list) {
                $_docLists[] = ($indexItem + 1) . ') ' . $list;
            }
        }else{
            $_docLists = $lists;
        }

        return ['_docLists' => $_docLists, 'lists' => $listsData, 'completeList' => $completeList, 'received_files' => $files];
    }

    public function isDocumentReceived($lists, $files){
        $listsData = [];
        $completeList = [];
        foreach ($lists as $index => $item) {
            $isReceived = false;

            $item = str_replace('_',' ',$item);

            if (strpos($item, ' or ') !== false){
                foreach (explode(' or ', $item) as $indexNext=>$itemValue){
                    if (!$indexNext) {
                        $item = $itemValue;
                    }
                    $docItem = trim(str_replace(' ', '_', strtolower($itemValue)));
                    $completeList[] = trim(ucwords($itemValue));
                    if ($files && $this->strposaDocs($docItem, $files)) {
                        $isReceived = true;
                        break;
                    }
                }
            }

            $docItem = trim(str_replace(' ', '_', strtolower($item)));
            if ($files && $this->strposaDocs($docItem, $files)) {
                $isReceived = true;
            }
            if (!$isReceived) {
                $listsData[trim(ucwords($item))] = trim(str_replace(' ', '_', strtolower($item)));
            }else{
                unset($lists[$index]);
            }
            $completeList[] = trim(ucwords($item));
        }
        return ['completeList' => $completeList, 'listsData' => $listsData, 'lists' => $lists];
    }

    function strposaDocs($haystack, $needles=array()) {

        $status = false;
        if ($needles) {
            $needles = array_filter($needles);
            $needles = array_unique($needles);


            if ($haystack == 'co-applicant_pan_card'){
                if (($key = array_search('pan_card', $needles)) !== false) {
                    unset($needles[$key]);
                }
            }else if ($haystack == 'co-applicant_bank_statement'){
                if (($key = array_search('bank_statement', $needles)) !== false) {
                    unset($needles[$key]);
                }
            }else if ($haystack == 'co-applicant_aadhar_card'){
                if (($key = array_search('aadhar_card', $needles)) !== false) {
                    unset($needles[$key]);
                }
            }

            foreach ($needles as $needle) {
                similar_text($needle, $haystack, $percentage);
                if (strpos($haystack, $needle) !== false || $percentage > 95) {
                    $status = true;
                    break;
                }
            }
        }

        return $status;
    }

    public function sendDocumentEmailToCustomer($application, $documentRuleID)
    {

        $_docLists = $this->getPreDocumentsList($documentRuleID, $application);
        $_docLists = $_docLists['_docLists'];

        if ($_docLists) {


            if(true){

                $listString = '';
                $_listString = '';
                if ($_docLists) {
                    $listString = '<ul style="list-style: none;">';
                    foreach ($_docLists as $index => $list) {
                        $listString .= '<li>' . $list . '</li>';
                        $_listString .= ($index + 1) . ')' . $list . "<br/>";
                    }
                    if(isset($index)) {
                        $listString .= '<li>' . ($index + 1) . ') <a href="https://creditfair.in/netbanking/authentication/' . $application->id . '">Authenticate With NetBanking</a></li><li style="font-size: 10px;">(We don’t get access to your login password / Your data is secured by bank grade security)</li>';
                    }
                    $listString .= '</ul>';
                }

                (new ConsumerApplicationController())->sendPreApprovalCommunicationV1($application, $listString, 'Document’s required for loan process', new Request(['email_to_merchant' => true]));
            }else{
                $body = 'Dear ' . $application->name . ',<br/>

We have received your application for loan via ' . $application->merchant->merchant_name . ' To process your loan, we would want the following documents.
<br/><br/>List of documents:<br/> ' . implode('<br/>', $_docLists) . '
<br/><br/>Kindly provide these document’s within 2 day’s or else your loan will be cancelled';

                if ($application->email) {
                    \Mail::send('emails.reminders.basic_reminder',
                        ['body' => $body]
                        , function ($message) use ($application) {
                            $message->to($application->email)->subject('Document’s required for loan process');
                            $em = explode(',', $application->merchant->email);
                            array_push($em, 'centralops@creditfair.in');
                            $message->cc($em);
                        });
                }
            }

            if ($application->mobile_number) {

                $sms = 'Dear ' . $application->name . ',

We have received your application for loan from ' . $application->merchant->merchant_name . ' kindly submit these document’s to complete the loan process.
List of documents:
' . implode('<br/>', $_docLists) . '<br/>In case you face any issues, please call us on +91-99672 35047.<br/>Best Regards,<br/>Team Credit Fair';
                send_sms($application->mobile_number, ['message' => $sms, 'id' => $application->id, 'id_type' => 'application_id']);
            }
        }
    }

    public function isCollateralLoan($id)
    {
        $foir = FOIR::where('application_id', $id)->get();
        $status = true;
        if ($foir) {
            foreach ($foir as $item) {
                if (!in_array($item->AccountType, ['Credit Fair EMI', 'Gold Loan', 'Overdraft', 'Loan Against Bank Deposits', 'Loan against Shares/Securities'])) {
                    $status = false;
                    break;
                }
            }
        }

        return $status;
    }

    public function storeDocuments(Request $request)
    {
        try {
            $status = 'success';
            $message = 'Document rule saved successfully';
            $data = $request->all();
            unset($data['_token']);
            $rule = new DocumentRule();
            $rule->fill($data);
            $rule->created_at = Carbon::now()->toDateTimeString();
            $rule->collateral_loan = $request->has('collateral_loan') && $request->get('collateral_loan') ? 1 : 0;
            $rule->negative_area = $request->has('negative_area') && $request->get('negative_area') ? 1 : 0;
            $rule->negative_profile = $request->has('negative_profile') && $request->get('negative_profile') ? 1 : 0;
            $rule->status = 1;
            $rule->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }
        Session::flash($status, $message);
        return redirect()->back();
    }

    public function updateDocuments($id)
    {
        $data['document_set'] = DocumentSets::where('id', $id)->first();
        return view('admin.documentation.document_edit', $data);
    }

    public function addDocumentsUpdate($id, Request $request)
    {
        try {
            $status = 'success';
            $message = 'Document rule updated successfully';
            $data = $request->all();
            unset($data['_token']);
            $rule = DocumentRule::find($id);
            $documentrulelock = new DocumentRuleLock();
            $documentrulelock->fill($rule->toArray());
            $documentrulelock->created_at = Carbon::now()->toDateTimeString();
            $documentrulelock->update_by = Auth::user()->id;
            $documentrulelock->save();
            $rule->fill($data);
            $rule->created_at = Carbon::now()->toDateTimeString();
            $rule->collateral_loan = $request->has('collateral_loan') && $request->get('collateral_loan') ? 1 : 0;
            $rule->negative_area = $request->has('negative_area') && $request->get('negative_area') ? 1 : 0;
            $rule->negative_profile = $request->has('negative_profile') && $request->get('negative_profile') ? 1 : 0;
            $rule->status = 1;
            $rule->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }

        Session::flash($status, $message);
        return redirect()->back();
    }

    public function addDocuments()
    {
        $documents = DocumentSets::all();
        return view('admin.documentation.document_edit', ['documentations' => $documents]);
    }

    public function saveDocumentLists(Request $request)
    {

        $data = [];
        foreach ($request->get('documents') as $item) {
            if ($item[1]['optional'] == 'true' || $item[2]['mandatory'] == 'true') {
                $data[] = array(
                    'id' => $item[0]['id'],
                    'optional' => $item[1]['optional'],
                    'mandatory' => $item[2]['mandatory'],
                    'group' => $item[3]['group'] == "" ? 0 : $item[3]['group'],
                );
            }
        }

        $request->merge(['document_list' => json_encode($data)]);

        if (DocumentSets::saveDocument($request)) {
            Session::flash('success', 'Document list saved successfully');
            return response()->json(['status' => 'OK']);
        }
        Session::flash('error', 'Something went wrong, Duplicate Set Name');
        return response()->json(['status' => 'FAIL', 'message' => 'Duplicate Set Name']);
    }

    public function pre_approvalCheck($grade, $id)
    {
        if (!_env('PRE_APPROVAL'))
            return false;
//        $check_approval = $grade->getOutput();
        $credit = CreditReport::where('application_id', $id)->first(['Score', 'TotalPastDue']);
        $application = ConsumerApplication::with('merchant.preApproval', 'activeOffer', 'foir')->where('id', $id)->first();

        if (!$application->merchant || !$application->merchant->pre_approval || !$application->merchant->preApproval)
            return false;

        $current_address_status = ((isset($application->current_address_status) && !empty($application->current_address_status))) ? $application->current_address_status : 0;

        $this->getFOIRByID($application->id);

        $foirDateRange = Carbon::now()->subYear(3)->startOfDay()->toDateTimeString();

        $Score = -2;
        $TotalPastDue = 0;
        if (isset($credit->Score)) {
            $Score = $credit->Score;
            $TotalPastDue = $credit->TotalPastDue;
//        } else if (isset($check_approval['score'])) {
//            $Score = $check_approval['score'];
//            $TotalPastDue = $check_approval['pastDues'];
        }

        if(!isset($credit->Score)){
            $Score = -2;
        }

        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
        $age = $age ? $age : $this->age;

        $last_emi_date = Carbon::now()->addMonths($application->tenure)->toDateString();
        $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));

        $preApprovalID = 0;
        if ($application->merchant->preApproval) {
            foreach ($application->merchant->preApproval as $preApproval) {
                if (in_array(strtolower($application->employee_status), explode(',',strtolower($preApproval->employment_type)))) {
                    if ($TotalPastDue <= $preApproval->past_dues) {
                        if ($this->foirIncludingCFEMI <= $preApproval->foir) {
                            if ($this->cfFoir <= $preApproval->cf_foir) {
                                if (($Score <= 6) && $Score >= $preApproval->score) {

                                    $caseType = '';
                                    $isDPD = [];
                                    $_goldLoan = '';
                                    foreach ($application->foir as $foir) {
                                        $foirData = json_decode($foir->dpd, 1);

                                        if ($foirData) {
                                            $_caseType = array_keys($foirData);
                                            if ($_caseType) {
                                                foreach ($_caseType as $type) {
                                                    if (in_array($type, ['PWOS', 'SET'])) {
                                                        $caseType = $type;
                                                    }
                                                }
                                            }
                                        }

                                        if ($foirData) {
                                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                                            if ($foirClean) {
                                                foreach ($foirData as $key => $item) {
                                                    if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                                        $isDPD[] = $item;
                                                    }
                                                }
                                            }
                                        }

                                        if ($foir->AccountType == 'Gold Loan' && ($foir->DateClosed == '' || $foir->DateClosed == null)) {
                                            $_goldLoan = true;
                                            break;
                                        }
                                    }

                                    if ($_goldLoan) {
                                        $this->autoPreApprovalLog[] = ['account_type' => $foir->AccountType, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }

                                    if ($isDPD) {
                                        $this->autoPreApprovalLog[] = ['dpd' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }

                                    if ($caseType) {
                                        $this->autoPreApprovalLog[] = ['case_type' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }

                                    if ($application->loan_amount <= $preApproval->loan_amount && $application->loan_amount >= $preApproval->min_loan_amount) {
                                        if (($application->activeOffer->advnce_emi != 'emi' ? $application->activeOffer->tenure : ($application->activeOffer->tenure - $application->activeOffer->advance_emi)) <= $preApproval->net_tenure) {
                                            if (in_array(strtolower($current_address_status), explode(',',strtolower($preApproval->residence_status)))) {
                                                if ($application->monthly_income >= $preApproval->monthly_income) {
                                                    if ($age > $preApproval->min_age) {
                                                        if ($ageAtLastEMI < $preApproval->max_age) {
                                                            $preApprovalID = $preApproval->id;
                                                        } else {
                                                            $this->autoPreApprovalLog[] = ['age_at_last_emi' => $ageAtLastEMI, 'pre_approval_id' => $preApproval->id];
                                                        }
                                                    } else {
                                                        $this->autoPreApprovalLog[] = ['age' => $age, 'pre_approval_id' => $preApproval->id];
                                                    }
                                                } else if ($application->monthly_income >= $preApproval->monthly_income) {
                                                    if ($age > $preApproval->min_age) {
                                                        if ($ageAtLastEMI < $preApproval->max_age) {
                                                            $preApprovalID = $preApproval->id;
                                                        } else {
                                                            $this->autoPreApprovalLog[] = ['age_at_last_emi' => $ageAtLastEMI, 'pre_approval_id' => $preApproval->id];
                                                        }
                                                    } else {
                                                        $this->autoPreApprovalLog[] = ['age' => $age, 'pre_approval_id' => $preApproval->id];
                                                    }
                                                } else {
                                                    $this->autoPreApprovalLog[] = ['monthly_income' => $application->monthly_income, 'pre_approval_id' => $preApproval->id];
                                                }
                                            } else {
                                                $this->autoPreApprovalLog[] = ['residence_status' => $current_address_status, 'pre_approval_id' => $preApproval->id];
                                            }
                                        } else {
                                            $this->autoPreApprovalLog[] = ['tenure' => $application->tenure, 'pre_approval_id' => $preApproval->id];
                                        }
                                    } else {
                                        $this->autoPreApprovalLog[] = ['loan_amount' => $application->loan_amount, 'pre_approval_id' => $preApproval->id];
                                    }
                                } else if (($Score > 6) && $Score >= $preApproval->score) {

                                    $termLoan = 0;
                                    $caseType = '';
                                    $threeYear = [];
                                    $aboveThreeYear = [];
                                    foreach ($application->foir as $foir) {
                                        $foirData = json_decode($foir->dpd, 1);
                                        if (!in_array($foir->AccountType, ['Gold Loan', 'Overdraft']) && strtotime($foir->DateOpened) >= Carbon::now()->subYear(3)->timestamp && $termLoan == 0) {
                                            if ($foir->DateClosed) {
                                                $termLoan = self::calculatedifferenceindate($foir->DateOpened, $foir->DateClosed);
                                            } else {
                                                $termLoan = self::calculatedifferenceindate($foir->DateOpened);
                                            }
                                        }

                                        if ($foirData) {
                                            $_caseType = array_keys($foirData);
                                            if ($_caseType) {
                                                foreach ($_caseType as $type) {
                                                    if (in_array($type, ['PWOS', 'SET'])) {
                                                        $caseType = $type;
                                                    }
                                                }
                                            }
                                        }


                                        if ($foirData) {
                                            $foirClean = array_diff(array_keys($foirData), ['000', 'NEW', 'CLSD']);
                                            if ($foirClean) {
                                                if (($foir->DateClosed && strtotime($foir->DateClosed) >= strtotime($foirDateRange)) || ($foir->DateClosed == '' && $foir->DateClosed == null)) {
                                                    foreach ($foirData as $key => $item) {
                                                        if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                                            $threeYear[] = $item;
                                                        }
                                                    }
                                                }
                                                if (($foir->DateClosed != '' || $foir->DateClosed != null)) {
                                                    foreach ($foirData as $key => $item) {
                                                        if (!in_array($key, ['NEW', '*', '000', 'CLSD'])) {
                                                            $aboveThreeYear[] = $item;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    if ($threeYear || $aboveThreeYear) {
                                        if ($threeYear && max($threeYear) > 15) {
                                            $this->threeYear = max($threeYear);
                                            //return $this;
                                        }
                                        if ($aboveThreeYear && max($aboveThreeYear) > 60) {
                                            $this->aboveThreeYear = max($aboveThreeYear);
                                            //return $this;
                                        }
                                    }


                                    if ($termLoan == 0) {
                                        $this->autoPreApprovalLog[] = ['term_loan' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }
                                    if ($caseType) {
                                        $this->autoPreApprovalLog[] = ['case_type' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }
                                    if ($this->threeYear) {
                                        $this->autoPreApprovalLog[] = ['three_year' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }
                                    if ($this->aboveThreeYear) {
                                        $this->autoPreApprovalLog[] = ['above_three' => 1, 'pre_approval_id' => $preApproval->id];
                                        break;
                                    }


                                    if ($termLoan) {
                                        if ($application->loan_amount <= $preApproval->loan_amount && $application->loan_amount >= $preApproval->min_loan_amount) {
                                            if (($application->activeOffer->advnce_emi != 'emi' ? $application->activeOffer->tenure : ($application->activeOffer->tenure - $application->activeOffer->advance_emi)) <= $preApproval->net_tenure) {
                                                $gold_loan = 0;
                                                foreach ($application->foir as $foir) {
                                                    if ($foir->AccountType == 'Gold Loan' && $foir->DateClosed == '') {
                                                        $gold_loan++;
                                                        if ($gold_loan >= 3) {
                                                            break;
                                                        }
                                                    }
                                                }

                                                if ($gold_loan < 3) {
                                                    if ($application->monthly_income >= $preApproval->monthly_income) {
                                                        if (in_array(strtolower($current_address_status), explode(',',strtolower($preApproval->residence_status)))) {
                                                            if ($age > $preApproval->min_age) {
                                                                if ($ageAtLastEMI < $preApproval->max_age) {
                                                                    $preApprovalID = $preApproval->id;
                                                                } else {
                                                                    $this->autoPreApprovalLog[] = ['age_at_last_emi' => $ageAtLastEMI, 'pre_approval_id' => $preApproval->id];
                                                                }
                                                            } else {
                                                                $this->autoPreApprovalLog[] = ['age' => $age, 'pre_approval_id' => $preApproval->id];
                                                            }
                                                        } else {
                                                            $this->autoPreApprovalLog[] = ['residence_status' => $current_address_status, 'pre_approval_id' => $preApproval->id];
                                                        }
                                                    } else {
                                                        $this->autoPreApprovalLog[] = ['monthly_income' => $application->monthly_income, 'pre_approval_id' => $preApproval->id];
                                                    }
                                                } else {
                                                    $this->autoPreApprovalLog[] = ['gold' => $gold_loan, 'pre_approval_id' => $preApproval->id];
                                                }
                                            } else {
                                                $this->autoPreApprovalLog[] = ['tenure' => $application->tenure, 'pre_approval_id' => $preApproval->id];
                                            }
                                        } else {
                                            $this->autoPreApprovalLog[] = ['loan_amount' => $application->loan_amount, 'pre_approval_id' => $preApproval->id];
                                        }
                                    } else {
                                        $this->autoPreApprovalLog[] = ['term_loan' => $termLoan, 'pre_approval_id' => $preApproval->id];
                                    }
                                } else {
                                    $this->autoPreApprovalLog[] = ['score' => $Score, 'pre_approval_id' => $preApproval->id];
                                }
                            } else {
                                $this->autoPreApprovalLog[] = ['cf_foir' => $this->cfFoir, 'pre_approval_id' => $preApproval->id];
                            }
                        } else {
                            $this->autoPreApprovalLog[] = ['foir' => $this->foirIncludingCFEMI, 'pre_approval_id' => $preApproval->id];
                        }
                    } else {
                        $this->autoPreApprovalLog[] = ['past_dues' => $TotalPastDue, 'pre_approval_id' => $preApproval->id];
                    }
                } else {
                    $this->autoPreApprovalLog[] = ['employee_status' => $application->employee_status, 'pre_approval_id' => $preApproval->id];
                }

                if ($preApprovalID)
                    break;
            }
            if($preApprovalID) {
                $this->black_list = 0;
                $rbiBlack = (new ConsumerApplicationController())->getBlacklistData($application);
                if ($rbiBlack['status']) {
                    $this->autoPreApprovalLog[] = ['black_list' => 1, 'pre_approval_id' => 0];
                    $preApprovalID = 0;
                }
            }
        }

        if ($this->autoPreApprovalLog && !$preApprovalID) {
            foreach ($this->autoPreApprovalLog as $autoPreApprovalLog){
                $requestID = $this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : '';
                PreApprovalLog::insert(array_merge($autoPreApprovalLog, ['grade_id' => $application->merchant->grade_id, 'application_id' => $id, 'created_at' => Carbon::now()->toDateTimeString(), 'request_id' => $requestID]));
            }
        }

        if ($preApprovalID) {
            ConsumerApplicationElement::where('application_id', $id)->update(['pre_approval_id' => $preApprovalID]);
        }
        return $preApprovalID;
    }

    public function storePreApproval(Request $request)
    {

        $status = 'success';
        $message = 'Pre-Approval rule saved!';

        try {
            $data = $request->all();
            $preApproval = new PreApproval();
            unset($data['_token']);
            $preApproval->fill($data);
            $preApproval->residence_status = implode(',',$this->request->get('residence_status'));
            $preApproval->employment_type = implode(',',$this->request->get('employment_type'));
            $preApproval->thin_file = $request->has('thin_file') && $request->get('thin_file') == 'on' ? 1 : 0;
            $preApproval->status = 1;
            $preApproval->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }

        Session::flash($status, $message);
        return redirect()->back();
    }

    public function addPreApprovalUpdate($id, Request $request)
    {
        $status = 'success';
        $message = 'Pre-Approval rule updated!';

        try {
            $data = $request->all();
            $preApproval = PreApproval::find($id);
            $preApprovalLock = new PreApprovalLock();
            $preApprovalLock->fill($preApproval->toArray());
            $preApprovalLock->created_at = Carbon::now()->toDateTimeString();
            $preApprovalLock->status = 1;
            $preApprovalLock->update_by = Auth::user()->id;
            $preApprovalLock->save();
            unset($data['_token']);
            $preApproval->fill($data);
            $preApproval->residence_status = implode(',',$this->request->get('residence_status'));
            $preApproval->employment_type = implode(',',$this->request->get('employment_type'));
            $preApproval->thin_file = $request->has('thin_file') && $request->get('thin_file') == 'on' ? 1 : 0;
            $preApproval->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }

        Session::flash($status, $message);
        return redirect()->back();
    }

    public function updateAutoReject($id, Request $request){
        $status = 'success';
        $message = 'Auto Reject rule updated!';

        try {
            $data = $request->all();
            $preApproval = AutoReject::find($id);
            $autorejectLock = new AutoRejectLock();
            $autorejectLock->fill($preApproval->toArray());
            $autorejectLock->created_at = Carbon::now()->toDateTimeString();
            $autorejectLock->update_by = Auth::user()->id;
            $autorejectLock->save();
            unset($data['_token']);
            $preApproval->fill($data);
            $preApproval->negative_area = $request->has('negative_area') && $request->get('negative_area') == 'on' ? 1 : 0;
            $preApproval->approved_pincode = $request->has('approved_pincode') && $request->get('approved_pincode') == 'on' ? 1 : 0;
            $preApproval->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }

        Session::flash($status, $message);
        return redirect()->back();
    }

    public function updateAutoReject_v1($id, Request $request) {
        $cwFactory = new CloudWatchLoggerFactory();
        $status = 'success';
        $message = 'Auto Reject rule updated!';
        try {
            // If form_data is sent as a single JSON payload, decode it back into the expected array structure
            if ($request->has('form_data')) {
                $formFields = json_decode(html_entity_decode($request->input('form_data')), true);
                $parsed = $this->expandFormFieldsToArray($formFields);
                $allData = array_merge($request->only(['_token', 'grade_id', 'for_consumer']), $parsed);
            } else {
                $allData = $request->all();
            }
            $applicantTypes = [
                1 => 'applicant',
                2 => ['co_applicant_for_income', 'co_applicant_for_signing']
            ];

            foreach ($applicantTypes as $type => $inputKeys) {
                $output = [];
                
                if (is_array($inputKeys)) {
                    // Combine multiple tabs into one JSON for co-applicants
                    foreach ($inputKeys as $key) {
                        if (isset($allData[$key])) {
                            $output[$key] = $this->buildAutoRejectJson($allData[$key]);
                        }
                    }
                } else {
                    // Single tab for applicant
                    if (isset($allData[$inputKeys])) {
                        $output = $this->buildAutoRejectJson($allData[$inputKeys]);
                    }
                }

                if (empty($output)) {
                    continue;
                }
                $autoReject = new AutoRejectRule();
                $autoReject->modifications = json_encode($output);
                $autoReject->grade_id = $allData['grade_id'];
                $autoReject->status = 1;
                $autoReject->applicant_type = $type;
                $autoReject->updated_by = Auth::user()->id;
                $autoReject->created_at = Carbon::now()->toDateTimeString();
                $autoReject->save();
            }
        } catch (\Exception $e) {
            $cwFactory->logger(json_encode(['message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }
        Session::flash($status, $message);
        if ($request->ajax()) {
            return response()->json(['status' => $status, 'message' => $message]);
        }
        return redirect()->back();
    }

    /**
     * Expand a flat list of {name, value} pairs (with PHP-style bracket names like
     * "applicant[dpd_rules][0][operator]") into a nested array. Unlike parse_str(),
     * this is not constrained by the max_input_vars ini setting.
     */
    private function expandFormFieldsToArray($formFields) {
        $result = [];
        if (!is_array($formFields)) {
            return $result;
        }
        foreach ($formFields as $field) {
            if (!isset($field['name'])) {
                continue;
            }
            $name = $field['name'];
            $value = isset($field['value']) ? $field['value'] : '';
            $keys = [];
            if (preg_match('/^([^\[]+)((?:\[[^\]]*\])*)$/', $name, $m)) {
                $keys[] = $m[1];
                if (!empty($m[2]) && preg_match_all('/\[([^\]]*)\]/', $m[2], $bm)) {
                    foreach ($bm[1] as $bracketKey) {
                        $keys[] = $bracketKey;
                    }
                }
            } else {
                $keys[] = $name;
            }
            $cursor = &$result;
            $lastIdx = count($keys) - 1;
            foreach ($keys as $i => $k) {
                if ($i === $lastIdx) {
                    if ($k === '') {
                        $cursor[] = $value;
                    } else {
                        $cursor[$k] = $value;
                    }
                } else {
                    if ($k === '') {
                        $cursor[] = [];
                        end($cursor);
                        $cursor = &$cursor[key($cursor)];
                    } else {
                        if (!isset($cursor[$k]) || !is_array($cursor[$k])) {
                            $cursor[$k] = [];
                        }
                        $cursor = &$cursor[$k];
                    }
                }
            }
            unset($cursor);
        }
        return $result;
    }

    private function buildAutoRejectJson($data) {
        $ruleCategories = [
            'dpd',
            'keyword',
            'principal_written_off',
            'account_status',
            'past_dues',
            'nach_bounce'
        ];
        $output = ['new_rejection_rules' => []];
        foreach ($ruleCategories as $categoryPrefix) {
            $ownershipKey = $categoryPrefix . '_ownership';
            $rulesKey = $categoryPrefix . '_rules';

            $ownershipData = isset($data[$ownershipKey]) ? $data[$ownershipKey] : [];
            $inputRules = isset($data[$rulesKey]) ? $data[$rulesKey] : [];

            $processedRules = [];
            if (is_array($inputRules)) {
                foreach ($inputRules as $rule) {
                    $processedRule = [];
                    if (is_array($rule)) {
                        foreach ($rule as $key => $value) {
                            $newKey = $key;
                            $newValue = str_replace('amp;', '', $value);

                            if ($key === 'values') {
                                $newKey = 'value';
                            }

                            if ($key === 'operator') {
                                $newValue = html_entity_decode($value);
                            }

                            $processedRule[$newKey] = $newValue;
                        }
                    }
                    if (!empty($processedRule)) {
                        $processedRules[] = $processedRule;
                    }
                }
            }
            $categoryObject = [
                'ownership' => $ownershipData,
                'rules' => $processedRules
            ];
            $currentPrefix = $categoryPrefix;
            if ($categoryPrefix == 'principal_written_off') {
                $currentPrefix = 'PRINCIPAL_WRITTEN_OFF_AMOUNT';
            } else if ($categoryPrefix == 'past_dues') {
                $currentPrefix = 'TOTAL_PAST_DUES';
            }
            $output['new_rejection_rules'][strtoupper($currentPrefix)] = [$categoryObject];
        }
        $output['new_rejection_rules']['MAX_AGE'] = isset($data['ec_max_age']) ? $data['ec_max_age'] : null;
        $output['new_rejection_rules']['MIN_AGE'] = isset($data['ec_min_age']) ? $data['ec_min_age'] : null;
        $output['new_rejection_rules']['MONTHLY_INCOME'] = isset($data['ec_monthly_income']) ? $data['ec_monthly_income'] : null;
        $output['new_rejection_rules']['MIN_SCORE'] = isset($data['ec_min_score']) ? $data['ec_min_score'] : null;
        $output['new_rejection_rules']['MAX_SCORE'] = isset($data['ec_max_score']) ? $data['ec_max_score'] : null;
        $output['new_rejection_rules']['APPROVED_PINCODE'] = isset($data['ec_approved_pincode']) && $data['ec_approved_pincode'] == 1 ? true : false;
        $output['new_rejection_rules']['NEGATIVE_AREA'] = isset($data['ec_negative_area']) && $data['ec_negative_area'] == 1 ? true : false;
        
        return $output;
    }

    public function addAutoReject(Request $request){
        $status = 'success';
        $message = 'Auto Reject rule saved!';

        try {
            // If form_data is sent as a single JSON payload, decode it back
            if ($request->has('form_data')) {
                $formFields = json_decode(html_entity_decode($request->input('form_data')), true);
                $parsed = $this->expandFormFieldsToArray($formFields);
                $data = array_merge($request->only(['_token', 'grade_id', 'for_consumer']), $parsed);
            } else {
                $data = $request->all();
            }
            $autoReject = new AutoReject();
            unset($data['_token']);
            $autoReject->fill($data);
            $autoReject->negative_area = $request->has('negative_area') && $request->get('negative_area') == 'on' ? 1 : 0;
            $autoReject->approved_pincode = $request->has('approved_pincode') && $request->get('approved_pincode') == 'on' ? 1 : 0;
            $autoReject->save();
        } catch (\Exception $e) {
            $status = 'error';
            $message = 'Something went wrong, please try again later';
        }

        Session::flash($status, $message);
        if ($request->ajax()) {
            return response()->json(['status' => $status, 'message' => $message]);
        }
        return redirect()->back();
    }

    public function ApprovalCheckCustomV1($application_id){

        $application = ConsumerApplication::with('emi', 'application_element', 'creditReport', 'foir', 'merchant', 'merchant.custom_grade', 'merchant.offer')->where('id', $application_id)->first();
        if (!$application->merchant || (isset($application->merchant) && !$application->merchant->custom_grade)) {
            $this->error = 1;
            return $this;
        }

        if (!$application->merchant->is_auto_approve) {
            $this->error = 1;
            return $this;
        }

        $total = DB::table('consumer_application')->select(DB::raw('count(*) as app_count'), DB::raw('SUM(approved_amount) as total_approved_amount'))->where('merchant_id', $application->merchant_id)->where('state', 'approved')->first();
        $total_remaining_amount = $application->merchant->max_approval_value - $total->total_approved_amount;
        if ($application->merchant->status == 'active' && $application->merchant->pre_status == 1 && ($application->loan_amount > $total_remaining_amount || $total->total_approved_amount > $application->merchant->max_approval_value || $total->app_count >= $application->merchant->max_no_cases)) {
            $this->error = 1;
            return $this;
        }

        $status_array = ['aborted', 'rejected'];
        $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->get();
        if (isset($status_log[0])) {
            $this->rejected = true;
            return $this;
        }

        $this->isLatestRule = true;
        if($application->merchant->custom_grade && $application->merchant->custom_grade && $application->merchant->custom_grade->grade){
            foreach ($application->merchant->custom_grade->grade as $grade){
                $item = explode('.',$grade->condition);
                $table = $item[0];
                $column = $item[1];
                $data = DB::table($table)->where($column, $grade->operator, $grade->value)->orderBy('created_at','desc')->first([$column]);
                if(!$data){
                    $this->approvalLogs[$grade->condition] = $data;
                    break;
                }
            }
        }
        return $this;
    }

    public function calculateLTV($application, $offer){
        $loan_amount = isset($application->loan_amount) ? (float)$application->loan_amount : 0;
        $inverter_gross_project_amount = isset($application->application_element->inverter_gross_project_amount) ? (float)$application->application_element->inverter_gross_project_amount : 0;
        
        $autoBRE = new \App\Http\Controllers\Admin\autoBRE();
        $net_loan_amount = $autoBRE->calculateNetLoanAmount($loan_amount, $offer);

        $ltv_gross_project_amount = 0;
        if ($inverter_gross_project_amount > 0) {
            $ltv_gross_project_amount = round(($loan_amount / $inverter_gross_project_amount) * 100);
        }

        $ltv_net_loan_amount = 0;
        if ($loan_amount > 0) {
            $ltv_net_loan_amount = round(($net_loan_amount / $loan_amount) * 100);
        }

        return [
            'ltv_gross_project_amount' => $ltv_gross_project_amount,
            'ltv_net_loan_amount' => $ltv_net_loan_amount,
            'loan_amount' => $loan_amount,
            'inverter_gross_project_amount' => $inverter_gross_project_amount,
            'net_loan_amount' => round($net_loan_amount,2)
        ];
    }
}
