<?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;


class GradeController extends Controller
{
    public $applicant_type = null;
    private $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 $eligibleTenureOffer = null;
    public $eligibleTenure = 0;
    public $emiData = [];
    private $cf_foir = 0;
    private $lastResponse;
    private $Acf_foir = [];
    private $foir = 0;
    private $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 function __construct(Request $request)
    {

        $this->request = $request;
    }

    public function index()
    {
        return $this->index_v1();
        $grades = Grades::paginate(10);
        return view('admin.grade.index', ['grades' => $grades]);
    }
    /* Index page that populates data from the new Grade table */
    public function index_v1()
    {
        $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){
                $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}}';
        $rejectionJson = AutoRejectRule::where(['grade_id' => $id, 'status' => 1])->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}}';
        return view('admin.grade.edit_v1', ['grade' => $grade, 'rejection_json' => isset($rejectionJson->modifications) ? $rejectionJson->modifications : $defaultJson]);
    }
    /* 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_loan_amount':
                return ['type' => 'text', 'key' => 'min_loan_amount', 'label' => 'Min Loan Amount', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s loan amount >= Min loan amount, then the rule has passed, else fail'];
            case 'max_loan_amount':
                return ['type' => 'text', 'key' => 'max_loan_amount', 'label' => 'Max Loan Amount', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s loan amount <= Max 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 'tenure':
                return ['type' => 'text', 'key' => 'tenure', 'label' => 'Net Tenure', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If the application’s net tenure <= net tenure field, 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 '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 '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':
                return ['type' => 'checkbox', 'key' => 'is_pincode_approved', 'label' => 'Pincode Approval', '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 pincode list. 2] If permanent address pincode is past of the approved 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 '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' => 'number', 'key' => 'bureau_surrogate', 'label' => 'Surrogate', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => ''];
//            case 'case_type_value':
//               return ['case_type_value' => [['type' => 'text', 'key' => 'case_type_value', 'label' => 'Case Type Fields', 'value' => $val ?? '', 'placeholder' => '']];
            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 '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 'past_dues':
                return ['type' => 'number', 'key' => 'past_dues', 'label' => 'Past Dues', 'value' => $val ?? '', 'placeholder' => '',
                    'title' => 'If total past due amount >= input, then fail else pass. If the field is blank, then the rule is to be skipped'];
            case 'track_record':
                return ['type' => 'checkbox', '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' => ''];
            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_loan_amount' => ['type' => 'text', 'key' => 'min_loan_amount', 'label' => 'Min Loan Amount', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s loan amount >= Min loan amount, then the rule has passed, else fail'],
            'max_loan_amount' => ['type' => 'text', 'key' => 'max_loan_amount', 'label' => 'Max 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'],
            'tenure' => ['type' => 'text', 'key' => 'tenure', 'label' => 'Net Tenure', 'value' => '', 'placeholder' => '',
                'title' => 'If the application’s net tenure <= net tenure field, 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'],
            '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'],
            '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' => ['type' => 'checkbox', 'key' => 'is_pincode_approved', 'label' => 'Pincode Approval', '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 pincode list. 2] If permanent address pincode is past of the approved 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' => 'number', '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'],
            'past_dues' => ['type' => 'number', 'key' => 'past_dues', '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'],
            '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' => 'checkbox', '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' => ''],
           ];
        return $list;
    }

    public function add()
    {
        return $this->add_v1();
        if ($this->request->has('grade') && $this->request->has('clone')) {
            $grade = Grades::find($this->request->get('grade'));
            return view('admin.grade.edit', ['grade' => $grade]);
        }
        return view('admin.grade.edit');
    }
    /* Create or Clone a Grade in the new format */
    public function add_v1()
    {
        if ($this->request->has('grade') && $this->request->has('clone')) {
            return $this->edit_v1($this->request->get('grade'));
//            $grade = GradesV1::find($this->request->get('grade'));
//            return view('admin.grade.edit_v1', ['grade' => $grade]);
        }
        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]);
                }
            }

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

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

            $_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', $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) {
                    ApprovalRule::where('grade_id', $grade_id)->where('rule_name', $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', $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')) {
                $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 createBrePayload($application_id) {
        // currently hardcoded for june kyc grade
        // $_grade = ApprovalRule::where('id', '63')->where('status', 1)->first(['rules']);
        // $_grade = ApprovalRule::where('id', '2')->where('status', 1)->first(['rules']);
        // $rule = json_decode($_grade->rules, 1);
        // $test = array( 'identifier' => $application_id, 'max_loan_amount' => $rule['max_loan_amount']);
        // $request_data =  array( 'identifier' => $application_id, 'max_loan_amount' => (int)$rule['max_loan_amount'], 'min_loan_amount' => (int)$rule['min_loan_amount'], 'employee_status' => $rule['employee_status'], 'past_due_amount' => (int)$rule['past_dues'], 'bureau_created_at' => null, 'credit_card_percentage' =>(float)"5", 'age' => (int)$rule['age'], 'ageAtLastEMI' => (int)$rule['ageAtLastEMI'], 'monthly_income' => (int)$rule['monthly_income'], 'credit_score' => (int)$rule['score'], 'net_tenure' => (int)$rule['tenure'], 'cfFoir' => (int)$rule['cf_foir'], 'foir' => (int)$rule['foir'], 'case_type' => $rule['caseType'], 'dpd_years_above_0' => (int)$rule['dpd_years_above_zero'], 'dpd_count_above_0' => (int)$rule['dpd_count_above_zero'], 'pre_dpd_years' => (int)$rule['pre_dpd_years'], 'pre_dpd_count' => (int)$rule['pre_dpd_count'], 'pre_dpd_keywords' => $rule['pre_dpd_keywords'], 'post_dpd_years' => (int)$rule['post_dpd_year'], 'post_dpd_count' => (int)$rule['post_dpd_count'], 'post_dpd_keywords' => $rule['post_dpd_keywords']);
        $payload = array(
            'identifier' => $application_id,
            'grade' => array(
                'rules' => null
                )
            );
        return $payload;
    }

    public function get_exhaustive_criteria_json($file_path, $application_id){
        $cwFactory = new CloudWatchLoggerFactory();
        try {
            $s3 = Storage::disk('s3');
            $cwFactory->logger(json_encode(['title' => 'readFile checking', 'file_path' => $file_path, 'application_id'=>$application_id]));
//            (new Slack(new Request(['title' => 'readFile checking', 'fields' => ['file_path' => $file_path], 'group' => Slack::$STAGE_TESTING])))->send();
            if ($s3->exists($file_path)) {
                $cwFactory->logger(json_encode(['title' => 'exhaustive_json file readFile exists', 'file_path' => $file_path, 'application_id'=>$application_id]));
//                (new Slack(new Request(['title' => 'equifax readFile exists', 'fields' => ['exists' => 1,'file_path' => $file_path], 'group' => Slack::$STAGE_TESTING])))->send();
                return $s3->get($file_path);
            }
            return false;
        } catch (\Exception $e) {
            $cwFactory->logger(json_encode(['title' => 'exhaustive_json file readFile does not exists', 'file_path' => $file_path, 'error' =>$e, 'application_id'=>$application_id]));
            //@todo: report if file do not exist on S3
            return false;
        }

    }

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

        $rule_list = [];
        $request_data = [];

        foreach ($rule_details as $key => $value) {
            try{
                if (!in_array($exhaustive_criteria_json[$key], $rule_list)) {
                    $rule_list[] = $exhaustive_criteria_json[$key];  // Add the value to the rule list
                    if ($exhaustive_criteria_json[$key]){
                        $fallback_rule = $exhaustive_criteria_json[$key]['fallback'] ?? null;
                        if (is_array($fallback_rule) && isset($fallback_rule['rule'])){
                            $rule_list[] = $exhaustive_criteria_json[$fallback_rule['rule']];
                        }
                    }
                }
            }
            catch (\Exception $e) {
                $this->bre_rules_ignored[] = ['rule' => $key];
                (new Slack(new Request(['title' => 'Skipped a rule', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), 'application_id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();

            }
        }
        return $rule_list;
    }

    public function runAutoDecisionBRE($payload) {
        $curl = curl_init();
            curl_setopt_array($curl, array(
                CURLOPT_URL => _env('BRE_API_UAT_URL'),
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 120,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => "GET",
                CURLOPT_POSTFIELDS => json_encode($payload),
                CURLOPT_HTTPHEADER => array(
                    "Content-Type: application/json",
                    // "X-Client-Id: "._env('EXPERIAN_SOFT_PULL_ID'),
                    // "X-Client-Secret: "._env('EXPERIAN_SOFT_PULL_SECRET'),
                ),
            ));
            $res = curl_exec($curl);
            $data = json_decode($res, 1);
            $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            $err = curl_error($curl);
            curl_close($curl);
            // $cwFactory = new CloudWatchLoggerFactory();
            // $cwFactory->logger(json_encode(json_encode(['bre_response' => json_encode($res), 'http_code' => $httpcode])));
            return response()->json(['req' => $payload, 'res'=> $res, 'code' => $httpcode], 200);


    }

    public function store_jsonbre_response($response, $req_id){
        $data = $response->getData();
        $decoded_response = isset($data->res) ? json_decode($data->res) : "";
        $bre_api_payload = isset($data->req) ? $data->req : "";
        $log = new BreLog();
        $log->application_id = $bre_api_payload->identifier;
        $log->request = json_encode($data->req);
        $log->response = json_encode($decoded_response);
        $log->rule_ignored = json_encode($this->bre_rules_ignored);
        $log->created_at = Carbon::now()->toDateTimeString();
        $log->request_batch_id = $req_id;
        $log->save();
        if (!empty($decoded_response)) {
            // Loop through the associative array
            foreach ($decoded_response as $key => $value) {
                // Store the key as a variable
                if ($key === 'status') {
                    continue; // This skips the rest of the loop for this iteration
                }
                $logv2 = new JsonBreApprovalStatusLog();
                $logv2->rule_id = (int)substr($key, 7);
                $logv2->application_id = $bre_api_payload->identifier;
                $logv2->failed_condition = isset($value->failed_condition) ? json_encode($value->failed_condition->key) : "";
                $logv2->reason = isset($value->failed_condition->reason)? json_encode($value->failed_condition->reason) : "";
                $logv2->request_batch_id = $req_id;
                $logv2->status=(int)$value->policy_status;
                $logv2->created_at = Carbon::now()->toDateTimeString();
                $logv2->save();

            }
        }
        else{
            $logv2 = new JsonBreApprovalStatusLog();
            $logv2->rule_id = 0;
            $logv2->application_id = $bre_api_payload->identifier;
            $logv2->failed_condition = '';
            $logv2->reason = 'Unhandled Scenario';
            $logv2->request_batch_id = $req_id;
            $logv2->status=0;
            $logv2->created_at = Carbon::now()->toDateTimeString();
            $logv2->save();
        }
    }

    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;
    }

    /* New Multi Approval Logic */
    public function MultiApprovalCheck($application_id, $req_id='', $tableOfOffers = false)
    {
        $cwFactory = new CloudWatchLoggerFactory();
        $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->id)->where('status', 1)->get();

        //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 = $this->createBrePayload($application_id);
                try{
                    $file_path = _env('JSON_BRE_EXHAUSTIVE_JSON');
                    $exhaustive_criteria_json = $this->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_due_amount' => 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
                                                    , 'credit_score' => isset($rule['score']) ? (int)($rule['score']) : null
                                                    , 'net_tenure' => isset($rule['tenure']) ? (int)($rule['tenure']) : null
                                                    , 'cfFoir' => isset($rule['cf_foir']) ? (int)($rule['cf_foir']) : null
                                                    , 'foir' => isset($rule['foir']) ? (int)($rule['foir']) : null
                                                    , 'case_type' => 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
                                                    , 'inverter_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_check' => 0
                                                    , 'bank_validation' => isset($rule['bank_validation']) ? (int)($rule['bank_validation']) : null);

                    // (new Slack(new Request(['title' => 'BRE_API payload addition attempted', 'fields' => ['application_id' => $application_id, 'rule'=>$grade_rule->id], 'group' => Slack::$STAGE_TESTING])))->send();
                    $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;
                    }
                }
                try{
                    $response = $this->runAutoDecisionBRE($bre_api_payload);
                    if($this->request->has('json_bre_for_log')){
                        return $response;
                    }
                    $this->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]));
                    // (new Slack(new Request(['title' => 'Payload', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), 'application_id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
                }
            }
            catch(\Exception $e) {
                $cwFactory->logger(json_encode(['title' => 'Create BRE Payload failed', 'application_id' => $application_id, 'error'=>$e]));
                // (new Slack(new Request(['title' => 'Payload', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), 'application_id' => $application_id], 'group' => Slack::$STAGE_TESTING])))->send();
            }
        }
        //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($status, true, $is_power_saving_grade, $req_id);
            $cwFactory->logger(json_encode(['title' => 'Auto Decision: Power Saving Rule done', 'application_id' => $application_id, 'decisionTableResult' => $decisionTableResult]));
            return $decisionTableResult;
        }

        return !$allFailed;
    }

        // runAutoDecisionBRE($application, $grade_rules);

        /*foreach($grade_rules as $grade_rule) {
            $rule_details = json_decode($grade_rule->rules);

            // $rule_details = json_decode($grade_rule->rules);
            $response = '';
            $this->Atenure = [];
            $this->Afoir = [];
            $this->Acf_foir = [];
            $status = 'success';
            foreach ($rule_details as $key=>$value) {

               $response = $this->ruleBasedCheck($application, $application_id, $key, $value, $rule_details, $tableOfOffers);

               if($response['failed_condition'] != '' && $response['reason'] != ''){
                   $status = 'failed';
                   break;
               }
            }

            $this->saveApprovalStatus($grade_rule, $application_id, $req_id, $status, $response);

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

//        // Check if the application was aborted or rejected in the past
//        if($application->merchant->grade->rejected == 1){
//            $status_array = ['aborted', 'rejected'];
//            $status_log = StatusLogs::where('application_id', $application_id)->whereIn('status', $status_array)->first(['id']);
//            if (isset($status_log->id)) {
//                $this->failed_condition = json_encode(['rejected' => true]);
//                $this->reason = "Application was aborted or rejected in the past";
//                return $this;
//            }
//        }
//
//        // Check if the applicant has a negative profile
//        /*if(isset($application->application_element->negative_profile) && $application->application_element->negative_profile > 0){
//            $this->failed_condition = json_encode(['negativeProfile' => true]);
//            $this->reason = "Applicant has a negative profile";
//            return $this;
//        }*/
//
//        // De-dupe Check
//        if($application->merchant->grade->checkDuplicates == 1){
//            $checkDuplicates = $this->checkDuplicates($application);
//            if($checkDuplicates == false){
//                $this->failed_condition = json_encode(['checkDuplicates' => true]);
//                $this->reason = "Repeat applicant";
//                return $this;
//            }
//        }
//
//        // Check if the applicant's score meets the grade criteria
//        if ($application->creditReport[0]->Score < $application->merchant->grade->score && $application->creditReport[0]->Score > 10) {
//            $this->failed_condition = json_encode(['score' => $application->creditReport[0]->Score]);
//            $this->reason = "Applicant score didn't match the grade criteria";
//            return $this;
//        }
//        //TODO: Cross verify the logic
//        elseif ($application->creditReport[0]->Score < 10) {
//            $oldloan = 0;
//            $unsecuredloan = 0;
//        }
//        else {
//            $oldloan = 1;
//            $unsecuredloan = 1;
//        }
//        //TODO: End of todo
//
//        $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;
//        $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
//        $last_emi_date = Carbon::now()->addMonths($application->emi->remaining_emi)->toDateString();
//        $ageAtLastEMI = (date('Y', strtotime($last_emi_date)) - date('Y', strtotime($application->dob)));
//        $status = true;
//        $track_record = 0;
//        $vintage6Month = Carbon::now()->subMonth(6)->startOfDay()->toDateTimeString();
//
//        // Check if the requested loan amount meets the expected criteria
//        if ($application->loan_amount == 0 || $application->loan_amount > $loan_amount || $application->loan_amount < $min_loan_amount || $loan_amount == 0 || empty($loan_amount)) {
//            $this->failed_condition = json_encode(['loan_amount' => $application->loan_amount == 0 ? 'loan_amount_missing' : $application->loan_amount]);
//            $this->reason = "Requested loan amount does not match the grade criteria";
//            return $this;
//        }
//
//        // Check if the requested tenure meets the expected criteria
//        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;
//            $this->failed_condition = json_encode(['tenure' => !isset($application->emi->remaining_emi) ? 'emi not generated' : $application->emi->remaining_emi]);
//            $this->reason = "Requested tenure does not match the grade criteria";
//            return $this;
//        }
//
//        // Check if the monthly income meets the expected criteria
//        if (!$application->monthly_income || $monthly_income == 0 || empty($monthly_income) || ($application->monthly_income < $monthly_income)) {
//            $this->monthly_income = $application->monthly_income;
//            $this->failed_condition = json_encode(['monthly_income' => $application->monthly_income]);
//            $this->reason = "Applicants monthly income does not match the grade criteria";
//            return $this;
//        }
//
//        // Check if the employee status meets the grade criteria
//        if(isset($application->employee_status) && $application->merchant->grade->employee_status){
//            $employee_status_array = explode(',',$application->merchant->grade->employee_status);
//            if(!in_array($application->employee_status, $employee_status_array)) {
//                $this->failed_condition = json_encode(['employee_status' => true]);
//                $this->reason = "Employee's current status does not match the grade criteria";
//                return $this;
//            }
//        }
//
//        // Check the bank account details of the applicant after validation is done
//        if(isset($application->merchant->grade->bank_validation) && $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 returns the num of similar chars and $percentage returns the % value of the compared strings below
//                $compare = isset($item->accountName) ? similar_text(strtolower($application->name),strtolower($item->accountName),$percentage) : 0;
//                if(round($percentage,0) < $application->merchant->grade->bank_validation){
//                    $this->failed_condition = json_encode(['bank_validation' => round($percentage,0)]);
//                    $this->reason = "Bank account name validation % does not match the grade criteria";
//                    return $this;
//                }
//            }
//        }
//
//        // Verify EPF details of salaried applicants
//        if($application->merchant->grade->epf_verification && 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->failed_condition = json_encode(['epf_verification' => true]);
//                    return $this;
//                }
//            }
//        }
//
//        // Verify GST details of self-employed applicants
//        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->failed_condition = json_encode(['fetch_gst' => true]);
//                    $this->reason = "GST verification failed";
//                    return $this;
//                }
//            }
//        }
//
//        // Check the age of the applicant at the time of application
//        if ($grade_age == 0 || empty($grade_age) || $age < $grade_age) {
//            $this->failed_condition = json_encode(['age' => $age]);
//            $this->reason = "Applicant age does not not match the grade criteria";
//            return $this;
//        }
//
//        // Check the age of the applicant at the end of his tenure
//        if($application->merchant->grade->ageAtLastEMI == 1){
//            $ageLimit = $application->merchant->grade->ageAtLastEMI_age ?? 60;
//            if (isset($ageAtLastEMI)) {
//                if ($ageAtLastEMI > $ageLimit) {
//                    $this->failed_condition = json_encode(['ageAtLastEMI' => $ageAtLastEMI]);
//                    $this->reason = "Applicant's age at the end of tenure does not not match the grade criteria";
//                    return $this;
//                }
//            }
//        }
//
//        //TODO: Past due logic
//        $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;
//                        }
//                    }
//                }
//            }
//        }
//        //TODO: End of past due logic
//
//
//
//        // Check if the applicant's track record matches the grade criteria
//        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;
//                    }
//                }
//            }
//
//            $this->failed_condition = json_encode(['track_record' => $track_record]);
//            $this->reason = "Applicant's track record does not match the grade criteria";
//            return $this;
//        }
//
//        // Check if the applicant's address pincode is approved and matches the grade criteria
//        if($application->merchant->grade->is_pincode_approved == 1){
//            $is_current_address_pin_approved = ApprovedPincodeLists::where('pin_codes', $application->permanent_address_pincode)->first();
//            $is_permanent_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_permanent_address_pin_approved)) && empty($is_permanent_address_pin_approved))){
//                $this->failed_condition = json_encode(['approved_pin' => true]);
//                $this->reason = "Applicant's address pincode is not approved";
//                return $this;
//            }
//        }
//
//        // Check if the applicant owns a house to meet the grade criteria
//        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->failed_condition = json_encode(['address_status' => "No Owned House"]);
//                $this->reason = "No house is owned to match the grade criteria";
//                return $this;
//            }
//        }
//
//        // Check if the down payments details are present to meet the grade criteria
//        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->failed_condition = json_encode(['downpayment' => isset($application->emi->upfront_from_customer) ? "Zero Downpayment" : 'emi_not_generated']);
//                    $this->reason = "No down-payment amount present to match the grade criteria";
//                    return $this;
//                }
//            }
//        }
//
//        // Check if the applicant lives in negative location
//        if($application->merchant->grade->negative_area == 1){
//            if (((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) || ((isset($application->permanent_address_pincode)) && !empty($application->permanent_address_pincode)) || ((isset($application->co_applicant_address_pincode)) && !empty($application->co_applicant_address_pincode))) {
//                $data['current_pincode'] = ((isset($application->current_address_pincode)) && !empty($application->current_address_pincode)) ? $application->current_address_pincode : "";
//                $data['permanent_pincode'] = ((isset($application->permanent_address_pincode)) && !empty($application->permanent_address_pincode)) ? $application->permanent_address_pincode : "";
//                $data['co_applicant_pincode'] = ((isset($application->co_applicant_address_pincode)) && !empty($application->co_applicant_address_pincode)) ? $application->co_applicant_address_pincode : "";
//                $consumerApplicationConreoller = new ConsumerApplicationController();
//                $NegativeArearesponse = $consumerApplicationConreoller->getNegativeAreaList($data);
//                if ($NegativeArearesponse && isset($NegativeArearesponse->level) && $NegativeArearesponse->level == 1) {
//                    $this->failed_condition = json_encode(['negative_area' => "Negative Area"]);
//                    $this->reason = "Applicant's address is considered in negative area";
//                    return $this;
//                }
//            }
//        }
    //     return false;
    // }
    /* 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";
            }
            //TODO: Custom Grade condition
//            if (isset($application->merchant) && $application->merchant->custom_grade_id && $application->merchant->custom_grade) {
//                return $this->ApprovalCheckCustomV1($application_id);
//            }
        }

        // 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':
                // 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]));
        $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 autoReject($grade, $id, $source = 'bot')
    {
        try {
            $cwFactory = new CloudWatchLoggerFactory();
            $this->rejectRules = [];
            $failLogs = [];
            $check_approval = [];
            $credit = CreditReport::where('application_id', $id)->first(['Score', 'TotalPastDue']);
            $application = ConsumerApplication::find($id);

            $statusLogs = StatusLogs::where('application_id',$id)->where('status', 'rejected')->where('user_id', 107)->first(['id']);
            $cwFactory->logger(json_encode(['title' => 'Status Log Check', 'application_id' => $id, 'statusLogs' => isset($statusLogs->id) ? 'true' : 'false']));
            if (isset($statusLogs->id)){
                return false;
            }

            if((new ConsumerApplicationController())->isExistingCustomer($id)) {
                $cwFactory->logger(json_encode(['title' => 'Existing Customer failed', 'application_id' => $id]));
                return false;
            }

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

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

            $age = (date('Y', strtotime($application->created_at)) - date('Y', strtotime($application->dob)));
            $age = $age ? $age : $this->age;
            $application = ConsumerApplication::with(['merchant', 'merchant.autoRejectConsumer', 'merchant.autoReject', 'merchant.autoRejectRule', 'application_element' => function ($query) {
                $query->select('application_id', 'installation_address_pincode');
            }, 'foir'])
                ->where('id', $id)
                ->first(['id', 'name', 'email', 'mobile_number', 'lender_id', 'loan_amount', 'merchant_id', 'monthly_income', 'current_address_pincode', 'permanent_address_pincode', 'co_applicant_address_pincode']);
            $autoReject = true;

            $noDPDDateRange = Carbon::now()->subYear(2)->startOfDay()->toDateTimeString();



            $dpdCountRejection = $this->dpdCountRejection;
            if(!$this->dpdCountRejection && count($application->foir)){
                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) {
                                    $dpdCountRejection = $dpdCount;
                                }
                            }
                        }
                    }
                }
            }

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

            if ((!isset($credit->Score) || !$application->monthly_income || !$age) && $source != 'consumer') {
                $cwFactory->logger(json_encode(['title' => 'Basic Check', 'application_id' => $id]));
                return false;
            }


            if($application->merchant && !$application->merchant->grade_v1){
                if (($Score > 10 && $Score < 580 && (($TotalPastDue > 5000) || $dpdCountRejection)) || ($age > 65)) {
                    $applicationController = new ConsumerApplicationController();
                    $applicationController->applicationRejectMail($application, $autoReject);
                    $applicationController->sendMessageToMerchant('rejected', $application->id);


                    if($Score > 10 && $Score < 580) {
                        $this->rejectRules[] = 'score';
                    }if($TotalPastDue > 5000){
                        $this->rejectRules[] = 'past dues';
                    }if($dpdCountRejection){
                        $this->rejectRules[] = 'dpd';
                    }if($age > 65){
                        $this->rejectRules[] = 'age';
                    }

                    $this->autoRejectLog($id);

                    return true;
                }
            }


            $dataLists = (new ConsumerApplicationController())->getUnapprovedPincodes($id);
            $pincode_approval = false;
            if ($dataLists['unapproved_pin_codes'] && (!isset($dataLists['approver_data_exist']->id))) {
                $pincode_approval = true;
            }

            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) {
                    $check_approval['negative_area'] = true;
                }
            }


            if($source == 'consumer'){

                try {

                    $autoRejectRule = $application->merchant && $application->merchant->autoRejectConsumer ? $application->merchant->autoRejectConsumer : '';

                    if (!$autoRejectRule->negative_area) {
                        $check_approval['negative_area'] = false;
                    }

                    if(isset($autoRejectRule->id)) {

                        $foirData = FOIR::where('application_id', $id)->whereNotIn('AccountType', ['Gold Loan', 'Overdraft', 'Loan against Shares/Securities'])->first(['id']);

                        if (!$autoRejectRule->approved_pincode) {
                            $pincode_approval = false;
                        }

                        if ((($Score >= $autoRejectRule->min_score && $Score <= $autoRejectRule->max_score) || $TotalPastDue >= $autoRejectRule->past_dues) || ($dpdCountRejection >= $autoRejectRule->max_dpd) || $age >= $autoRejectRule->age || $application->monthly_income <= $autoRejectRule->monthly_income ||
                            (!isset($foirData->id) && $Score != -2) || ($this->cfFoir >= $autoRejectRule->foir) || $check_approval['negative_area'] || $pincode_approval) {
                            $this->sendAutoRejectCommunication($application, $autoReject);



                            if($Score >= $autoRejectRule->min_score && $Score <= $autoRejectRule->max_score) {
                                $this->rejectRules[] = 'score';
                            }if($TotalPastDue >= $autoRejectRule->past_dues){
                                $this->rejectRules[] = 'past dues';
                            }if($dpdCountRejection >= $autoRejectRule->max_dpd){
                                $this->rejectRules[] = 'dpd';
                            }if($age >= $autoRejectRule->age){
                                $this->rejectRules[] = 'age';
                            }if($application->monthly_income <= $autoRejectRule->monthly_income){
                                $this->rejectRules[] = 'income';
                            }if((!isset($foirData->id) && $Score != -2)){
                                $this->rejectRules[] = 'score';
                            }if($this->cfFoir >= $autoRejectRule->foir){
                                $this->rejectRules[] = 'foir';
                            }if($check_approval['negative_area']){
                                $this->rejectRules[] = 'negative area';
                            }if($pincode_approval){
                                $this->rejectRules[] = 'pincode approval';
                            }


                            $this->autoRejectLog($id);

                            return true;
                        }
                    }
                }catch (\Exception $e){

                }
                return false;
            }

            $autoRejectRule = $application->merchant && $application->merchant->autoRejectRule ? $application->merchant->autoRejectRule : '';

            $cwFactory->logger(json_encode(['title' => 'Reject Rule Check', 'application_id' => $id, 'autoRejectRule' => isset($autoRejectRule) ? 'true' : 'false']));
            if($autoRejectRule && isset($autoRejectRule)){
                try{
                    $hashids = new Hashids('Creditfair by CS', 20);
                    $hashed_application_id = $hashids->encode($application->id);
                    $url = 'http://127.0.0.1:5050/api/run-auto-reject/'.$hashed_application_id;
                    // $token = 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTc0NTgzNzU2OCwiZXhwIjoxNzQ4MzQzMDQyfQ.WUcDLs-Gw5hNb9p4mdqZVJaLxV9A3W7srwvKRJLmLypp2wQF1x1B-vN6LrSB-HPRfN2Y93g1lUgRpAlapyHBYQ';
                    
                    $jwt = new JWTAccess();
                    $request = new Request();
                    $request->merge(['application_id'=> $hashed_application_id]);
                    $token = $jwt->encodeJWTDecisionEngine($request, _env("JWT_KEY_512"));

                    if ($source != 'banking') {
                        $ch = curl_init();
                        curl_setopt($ch, CURLOPT_URL, $url);
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                        curl_setopt($ch, CURLOPT_HTTPHEADER, [
                            "Authorization: Bearer $token"
                        ]);

                        $response = curl_exec($ch);
                        // $response = '{"status":"success","auto_reject_status":false,"rejection_logs":[{"MAX_AGE":{"result":true}},{"MIN_AGE":{"result":true}},{"NACH_BOUNCE":{"result":true}},{"NEGATIVE_AREA":{"result":true}},{"ACCOUNT_STATUS":{"result":true}},{"MONTHLY_INCOME":{"result":true}},{"TOTAL_PAST_DUES":{"result":true}},{"APPROVED_PINCODE":{"result":true}},{"PRINCIPAL_WRITTEN_OFF_AMOUNT":{"result":true}},{"DPD_KEYWORD":{"result":false,"details":[{"rule":{"value":"30","operator":">=","tradelines":"1","name":"dpd","months":6},"records":["XXXXXXXXXX3336 - {\"Year\": \"2025\", \"Month\": \"03\", \"Days_Past_Due\": \"33\", \"Asset_Classification\": \"?\"}"]},{"rule":{"value":"60","operator":">=","tradelines":"1","name":"dpd","months":12},"records":["XXXXXXXXXX3336 - {\"Year\": \"2025\", \"Month\": \"04\", \"Days_Past_Due\": \"62\", \"Asset_Classification\": \"?\"}"]},{"rule":{"value":"M","operator":">=","tradelines":"1","name":"keyword","months":24},"records":["XXXXXXXXXX3336 - {\"Year\": \"2024\", \"Month\": \"10\", \"Days_Past_Due\": null, \"Asset_Classification\": \"M\"}","XXXXXXXXXX9594 - {\"Year\": \"2025\", \"Month\": \"04\", \"Days_Past_Due\": null, \"Asset_Classification\": \"M\"}","XXXXXXXXXX9180 - {\"Year\": \"2025\", \"Month\": \"03\", \"Days_Past_Due\": null, \"Asset_Classification\": \"M\"}"]}]}},{"MIN_MAX_SCORE":{"result":true}}]}';
                        $rejectionData = json_decode($response, 1);
                        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                        $err = curl_error($ch);
                        curl_close($ch);

                        $cwFactory->logger(json_encode(['err' => $err, 'httpcode' => $httpcode,'token' => $token, 'url' => $url, 'key' => _env("JWT_KEY_512"), 'response' => $response, 'application_id' => $id, 'title'=> 'Auto-reject-API']));
                        if (isset($rejectionData['status']) && $rejectionData['status'] == 'success' && isset($rejectionData['auto_reject_status']) && !$rejectionData['auto_reject_status']) {
                            $rejectionLogs = $rejectionData['rejection_logs'];
                            foreach($rejectionLogs as $index => $arrayData){
                                foreach ($arrayData as $key => $result) {
                                    if (isset($result['result']) && $result['result'] == false) {
                                        $this->rejectRules[] = $key;
                                        if ($key == 'DPD_KEYWORD'){
                                            if (isset($result['details'])) {
                                                foreach($result['details'] as $item) {
                                                    $ruleName = strtoupper($item['rule']['name']);
                                                    if (!isset(($failLogs[$ruleName]))) {
                                                        $failLogs[$ruleName]['rules'] = [];
                                                    }
                                                    $failLogs[$ruleName]['rules'][] = $item['rule'];
                                                    $failLogs[$ruleName]['records'][] = $item['records'];
                                                }
                                            }
                                        } else {
                                            $failLogs[$key] = ['rules' => isset($result['details']) ? (array_column($result['details'], 'rule') != null ? array_column($result['details'], 'rule') : $result['details']['rule']) : null];
                                        }
                                    }
                                }
                            }
                        }
                    }
                    # Check if bank analysis exists
                    $fileType = DB::select("select file_type from consumer_application_files where consumer_application_id = ".$id." and file_type = 'pirimid_analysis_excel'");
                    if (isset($fileType[0]) && $fileType[0]->file_type == 'pirimid_analysis_excel') {
                        $bankLogs = $this->runBankRejection($hashed_application_id, $token);
                        $failLogs = array_merge($failLogs, $bankLogs);
                    }
                    if ($this->rejectRules != []) {
                        $this->sendAutoRejectCommunication($application, $autoReject);
                        $this->autoRejectLog($id, json_encode($failLogs));
                        return true;
                    }
                } catch (\Exception $e){
                    $cwFactory->logger(json_encode(['application_id' => $id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
                }
            }
            return false;
        } catch (\Exception $e) {
            $cwFactory->logger(json_encode(['application_id' => $id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            return false;
        }
    }

    public function autoRejectLog($id, $logs=null){
        if($this->rejectRules) {
            $requestID = $this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : '';
            AutoRejectLogs::insert([
                'application_id' => $id,
                'reason' => implode(', ', $this->rejectRules),
                'created_at' => Carbon::now()->toDateTimeString(),
                'request_id' => $requestID,
                'failure_details' => $logs
            ]);

            $application = ConsumerApplication::where('id', $id)->first(['merchant_id']);
            if(isset($application->merchant_id) && $application->merchant_id > 0) {
                $status = 'rejected';
                $applicationController = new ConsumerApplicationController();
                $applicationController->webhook($id, ['merchant_id' => $application->merchant_id, 'type' => 'Application-Webhook', 'status' => $status, 'data' => $applicationController->getMConnectPayload($id, $status)]);
            }
        }
    }

    public function sendAutoRejectCommunication($application, $autoReject){
        $applicationController = new ConsumerApplicationController();
        $applicationController->applicationRejectMail($application, $autoReject);
        $applicationController->sendMessageToMerchant('rejected', $application->id);
    }

    public function runBankRejection($hashed_application_id, $token) {
        $url = "http://127.0.0.1:5050/api/run-auto-reject-bank/".$hashed_application_id;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Authorization: Bearer $token"
        ]);
        // $bankResponse = '{"status":"success","auto_reject_bank_status":false,"rejection_logs":{"NACH_BOUNCE":{"result":false,"details":{"rule":[{"rule":{"value":"1","months":"12","operator":">"},"bank_transactions":[{"month":"2024-09-01T00:00:00","totalEmiBounceTxn":1,"totalEmiBounceAmt":1000},{"month":"2025-02-01T00:00:00","totalEmiBounceTxn":1,"totalEmiBounceAmt":2000}]}]}}}}';
        $bankResponse = curl_exec($ch);
        $bankData = json_decode($bankResponse, 1);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $err = curl_error($ch);
        curl_close($ch);
        if (isset($bankData['status']) && $bankData['status'] == 'success' && isset($bankData['auto_reject_bank_status']) && !$bankData['auto_reject_bank_status']) {
            $bankRejectionLogs = $bankData['rejection_logs'];
            foreach($bankRejectionLogs as $bankKey => $value) {
                if (isset($value['result']) && $value['result'] == false) {
                    $this->rejectRules[] = $bankKey;
                    $logs[$bankKey]['rules'] = array_column($value['details'], 'rule');
                }
            }
        }
        return isset($logs) ? $logs : [];
    }

    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($type) {
        if($InstallmentAmount == 0) {
            $creditFairEMI = FOIR::where('application_id', $application->id)->where('AccountType', 'Credit Fair EMI')->where('InstallmentAmount', '>', 0)->first(['InstallmentAmount']);
        }
        //}
        //if($application->monthly_income > 0) {
        $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;
        }

        //(new Slack(new Request(['title' => 'Auto Decision: getFOIRCalculation', 'fields' => ['id' => $application->id,'monthly_income' => $monthly_income, 'total_existing_emi' => $this->total_existing_emi, 'credit_limit' => $this->credit_limit,  'total_credit_card_limit_five' => $total_credit_card_limit_five, 'total_monthly_payment' => $total_monthly_payment], 'group' => Slack::$STAGE_TESTING])))->send();
        //if($type){
        $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;
        }
        //}else {
        //  $this->foirNAIncludingCFEMI = ($total_monthly_payment / $application->monthly_income) * 100;
        //}
        //}

        $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();
        $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']);
        }
        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']);
            }
        }
        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']);
            }
        }

        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 saveDecisionInTable_old($approved, $isAdminCall = false, $is_power_saving_grade = false, $req_id='')
    // {
    //     $approvalStatus = false;

    //     if (!$approved && !$isAdminCall) {
    //         return $approved;
    //     }

    //     try {
    //         DecisionTable::where('application_id', $this->appId)->delete();

    //         $table = [];

    //         foreach ($this->Acf_foir as $cfF) {
    //             $table[$cfF['offer_id']][] = ['type' => 'cf_foir', 'value' => $cfF['cfFoir'], 'status' => $cfF['status']];
    //         }

    //         foreach ($this->Afoir as $cfF) {
    //             $table[$cfF['offer_id']][] = ['type' => 'foir', 'value' => $cfF['foirIncludingCFEMI'], 'status' => $cfF['status']];
    //         }

    //         foreach ($this->Atenure as $cfT) {
    //             $table[$cfT['offer_id']][] = ['type' => 'tenure', 'value' => $cfT['tenure'], 'status' => $cfT['status']];
    //         }


    //         $offers = [];
    //         $date = Carbon::now()->toDateTimeString();

    //         foreach ($table as $offerId => $items) {
    //             $cf_foir = 0;
    //             $foir = 0;
    //             $tenure = 0;
    //             $status = 0;
    //             $reason = '';
    //             foreach ($items as $item) {
    //                 if ($item['type'] == 'cf_foir') {
    //                     $cf_foir = $item['value'];
    //                 }
    //                 if ($item['type'] == 'foir') {
    //                     $foir = $item['value'];
    //                 }
    //                 if ($item['type'] == 'tenure') {
    //                     $tenure = $item['value'];
    //                 }

    //                 if (!$status) {
    //                     $status = $item['status'];
    //                 }

    //                 if ($item['status']) {
    //                     $reason .= $item['type'] . ',';
    //                 }

    //                 if (is_string($tenure) && $tenure == 'no offer found') {
    //                     $reason .= 'offer missing,';
    //                     $status = 1;
    //                 }
    //             }

    //             $reason = rtrim($reason, ',');
    //             if (!isset($this->emiData[$offerId])) {
    //                 $reason .= 'Emi data missing';
    //                 $status = 1;
    //             } else {
    //                 $offers[] = [
    //                     'application_id' => $this->appId,
    //                     'offer_id' => $offerId,
    //                     'cf_foir' => $cf_foir,
    //                     'foir' => $foir,
    //                     'tenure' => $tenure,
    //                     'status' => $status,
    //                     'payable' => $this->emiData[$offerId]['payable'],
    //                     'emi' => $this->emiData[$offerId]['emi'],
    //                     'interest_rate' => $this->emiData[$offerId]['interest_rate'],
    //                     'processing_fee' => $this->emiData[$offerId]['processing_fee'],
    //                     'up_front_from_customer' => $this->emiData[$offerId]['upfront_from_customer'],
    //                     'reason' => $reason,
    //                     'updated_at' => $date,
    //                     'created_at' => $date
    //                 ];
    //             }
    //             if (!$status && !$isAdminCall) {
    //                 $approvalStatus = true;
    //             }
    //         }

    //         if ($isAdminCall) {
    //             if($is_power_saving_grade){
    //                 $application = ConsumerApplication::with('merchant', 'application_element', 'emi', 'activeOffer')->where('id', $this->appId)->first();
    //                 $power_saving_value = isset($application->application_element->inverter_power_savings) ? (float)$application->application_element->inverter_power_savings : 0;

    //                 // Loop through $this->emiData and remove offers where EMI is greater than the power saving value
    //                 foreach ($this->emiData as $offerId => $emiDetails) {
    //                     if ($emiDetails['emi'] > $power_saving_value) {
    //                         unset($this->emiData[$offerId]);
    //                     }else {
    //                         foreach ($offers as $offer) {
    //                             if ($offer['offer_id'] == $offerId && $offer['status'] == 1) {
    //                                 unset($this->emiData[$offerId]);
    //                                 break; // exit inner loop early as we found the matching offer
    //                             }
    //                         }
    //                     }
    //                 }
    //                 if (empty($this->emiData)) {
    //                     DecisionTable::insert($offers);
    //                     return false;
    //                 }

    //                 $final_offer_id = 0;
    //                 if (!empty($offers)) {
    //                     // Traverse through emiData to find the closest offer if isAdminCall is true
    //                     $this->getClosestOffer($application);

    //                     if ($this->closestOffer !== null) {
    //                         // Check if the closest offer data is in $offers
    //                         $closestOfferData = collect($offers)->firstWhere('offer_id', $this->closestOffer);

    //                         if ($closestOfferData) {
    //                             $final_offer_id = $closestOfferData['offer_id'];
    //                         } else {
    //                             // Insert any other available offer
    //                             $final_offer_id = $offers[0]['offer_id'];
    //                         }
    //                     } else {
    //                         // Insert any other available offer if closest offer is not found
    //                         $final_offer_id = $offers[0]['offer_id'];
    //                     }

    //                     $previous_applied_offer = isset($application->offer_id) ? $application->offer_id : 0;
    //                     if($previous_applied_offer != $final_offer_id){
    //                         $approvalStatus = $this->regenerateEMIAfterDecision($application,$final_offer_id,$is_power_saving_grade,$req_id,$source = 'power_saving');
    //                     }
    //                     ConsumerApplicationElement::where('application_id', $application->id)->whereNull('previous_applied_offer')->update(['previous_applied_offer' => $previous_applied_offer]);

    //                     if ($application->emi) {
    //                         $application->emi->table_of_offers_logic = "power_saving";
    //                         $application->emi->save();
    //                     }
    //                     if($approved){
    //                         $approvalStatus = true;
    //                     }
    //                 } else {
    //                     $approvalStatus = false;
    //                 }
    //             }else{
    //                 $application = ConsumerApplication::with('merchant', 'application_element', 'emi', 'activeOffer')->where('id', $this->appId)->first();

    //                 foreach ($this->emiData as $offerId => $emiDetails) {
    //                     foreach ($offers as $offer) {
    //                         if ($offer['offer_id'] == $offerId && $offer['status'] == 1) {
    //                         // if ($offer['offer_id'] == $offerId){
    //                             unset($this->emiData[$offerId]);
    //                             break; // exit inner loop early as we found the matching offer
    //                         }
    //                     }
    //                 }
    //                 $final_offer_id = 0;

    //                 if (empty($this->emiData)) {
    //                     $approvalStatus = false;
    //                     $emiDetails = $this->getNextBasedAmountOffer($application->id, true);
    //                     if (empty($emiDetails)) {
    //                         DecisionTable::insert($offers);
    //                         return $approvalStatus;
    //                     }else{
    //                         // Step 1: Get offer_ids from $offers
    //                         $offerIds = array_column($offers, 'offer_id');

    //                         // Step 2: Filter $emiDetails to only those matching $offerIds
    //                         $filteredEmiDetails = array_filter($emiDetails, function ($emiDetail) use ($offerIds) {
    //                             return in_array($emiDetail->id, $offerIds);
    //                         });
    //                         foreach ($offers as $key => $offer) {
    //                             foreach ($filteredEmiDetails as $emiDetail) {
    //                                 if ($offer['offer_id'] == $emiDetail->id) {
    //                                     $offers[$key]['eligible_amount'] = $emiDetail->loan_amount;
    //                                     break;
    //                                 }
    //                             }
    //                         }
    //                         if ($application->emi) {
    //                             $application->emi->table_of_offers_logic = "residual_emi";
    //                             $application->emi->save();
    //                         }
    //                         $highestLoanOffer = collect($filteredEmiDetails)->sortByDesc('loan_amount')->first();
    //                         $offerId = $highestLoanOffer->id ?? null;
    //                         $final_offer_id = $offerId;

    //                         if ($highestLoanOffer && isset($highestLoanOffer->loan_amount)) {
    //                             $application->approved_amount = $highestLoanOffer->loan_amount;
    //                             $application->save();
    //                         }

    //                         $previous_applied_offer = isset($application->offer_id) ? $application->offer_id : 0;

    //                         if($final_offer_id != 0 && $previous_applied_offer != 0){
    //                             if($previous_applied_offer != $final_offer_id){
    //                                 $approvalStatus = $this->regenerateEMIAfterDecision($application,$final_offer_id,$is_power_saving_grade,$req_id,$source = 'minimum_tenure');
    //                             }
    //                             ConsumerApplicationElement::where('application_id', $application->id)->whereNull('previous_applied_offer')->update(['previous_applied_offer' => $previous_applied_offer]);


    //                             if($approved){
    //                                 $approvalStatus = true;
    //                             }
    //                         }

    //                         DecisionTable::insert($offers);
    //                         return $approvalStatus;
    //                     }
    //                 }

    //                 if (!empty($offers)) {
    //                     // Traverse through emiData to find the Maximum Tenure Offer offer if isAdminCall is true
    //                     $this->getEligibleTenureOffer($application);

    //                     if ($this->eligibleTenureOffer !== null) {

    //                         $eligibleOfferData = collect($offers)->firstWhere('offer_id', $this->eligibleTenureOffer);

    //                         if ($eligibleOfferData) {
    //                             $final_offer_id = $eligibleOfferData['offer_id'];
    //                         } else {
    //                             // Insert any other available offer
    //                             $final_offer_id = $offers[0]['offer_id'];
    //                         }
    //                     } else {
    //                         // Insert any other available offer if Maximum Tenure Offer offer is not found
    //                         $final_offer_id = $offers[0]['offer_id'];
    //                     }

    //                     $previous_applied_offer = isset($application->offer_id) ? $application->offer_id : 0;
    //                     if($previous_applied_offer != $final_offer_id){
    //                         $approvalStatus = $this->regenerateEMIAfterDecision($application,$final_offer_id,$is_power_saving_grade,$req_id, $source = 'residual_emi');
    //                     }
    //                     ConsumerApplicationElement::where('application_id', $application->id)->whereNull('previous_applied_offer')->update(['previous_applied_offer' => $previous_applied_offer]);

    //                     if ($application->emi) {
    //                         $application->emi->table_of_offers_logic = "minimum_tenure";
    //                         $application->emi->save();
    //                     }
    //                     if($approved){
    //                         $approvalStatus = true;
    //                     }
    //                 }  else {
    //                     $approvalStatus = false;
    //                 }
    //             }
    //         }
    //         if (!empty($offers)) {
    //             DecisionTable::insert($offers);
    //         }
    //         if(!$approvalStatus && !$isAdminCall) {
    //             $response['failed_condition'] = null;
    //             $response['reason'] = "Table of Offers failed";
    //             $this->saveApprovalStatus(0, $this->appId, null, 'failed', $response);
    //             return $approvalStatus;
    //         }
    //     } catch (\Exception $e) {
    //         $approvalStatus = false;
    //         (new \App\Slack(new Request(['title' => 'TOF Auto assign offer Error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
    //         return false;
    //     }
    //     return $approvalStatus;
    // }

    public function saveDecisionInTable($approved, $isAdminCall = false, $is_power_saving_grade = false, $req_id = '')
    {
        $approvalStatus = false;

        if (!$approved && !$isAdminCall) {
            return $approved;
        }

        try {
            DecisionTable::where('application_id', $this->appId)->delete();

            $table = $this->buildDecisionTable();
            // Pass $offers by reference to handleAdminCall so it can be modified (e.g., adding 'eligible_amount')
            $offers = $this->processOffers($table); 

            if ($isAdminCall) {
                $approvalStatus = $this->handleAdminCall($approved, $offers, $is_power_saving_grade, $req_id);
            } else {
                $approvalStatus = $this->checkApprovalStatus($offers);
                if (!empty($offers)) {
                    DecisionTable::insert($offers);
                }
                $this->handleRejection($approvalStatus, false);
            }
            
            return $approvalStatus;

        } catch (\Exception $e) {
            $this->handleException($e);
            return false;
        }
    }

    private function buildDecisionTable() 
    {
        $table = [];

        foreach ($this->Acf_foir as $cfF) {
            $table[$cfF['offer_id']][] = [
                'type' => 'cf_foir',
                'value' => $cfF['cfFoir'],
                'status' => $cfF['status']
            ];
        }

        foreach ($this->Afoir as $cfF) {
            $table[$cfF['offer_id']][] = [
                'type' => 'foir',
                'value' => $cfF['foirIncludingCFEMI'],
                'status' => $cfF['status']
            ];
        }

        foreach ($this->Atenure as $cfT) {
            $table[$cfT['offer_id']][] = [
                'type' => 'tenure',
                'value' => $cfT['tenure'],
                'status' => $cfT['status']
            ];
        }

        return $table;
    }

    private function processOffers(array $table) 
    {
        $offers = [];
        $date = Carbon::now()->toDateTimeString();

        foreach ($table as $offerId => $items) {
            $offerData = $this->processOfferItems($items);
            
            if (!isset($this->emiData[$offerId])) {
                $offerData['reason'] .= 'Emi data missing';
                $offerData['status'] = 1;
                continue;
            }

            $offers[] = $this->buildOfferRecord($offerId, $offerData, $date);
        }

        return $offers;
    }

    private function processOfferItems(array $items) 
    {
        $cf_foir = 0;
        $foir = 0;
        $tenure = 0;
        $status = 0;
        $reason = '';

        foreach ($items as $item) {
            switch ($item['type']) {
                case 'cf_foir':
                    $cf_foir = $item['value'];
                    break;
                case 'foir':
                    $foir = $item['value'];
                    break;
                case 'tenure':
                    $tenure = $item['value'];
                    break;
            }

            if (!$status) {
                $status = $item['status'];
            }

            if ($item['status']) {
                $reason .= $item['type'] . ',';
            }

            if (is_string($tenure) && $tenure == 'no offer found') {
                $reason .= 'offer missing,';
                $status = 1;
            }
        }

        return [
            'cf_foir' => $cf_foir,
            'foir' => $foir,
            'tenure' => $tenure,
            'status' => $status,
            'reason' => rtrim($reason, ',')
        ];
    }

    private function buildOfferRecord(string $offerId, array $offerData, string $date) 
    {
        return [
            'application_id' => $this->appId,
            'offer_id' => $offerId,
            'cf_foir' => $offerData['cf_foir'],
            'foir' => $offerData['foir'],
            'tenure' => $offerData['tenure'],
            'status' => $offerData['status'],
            'payable' => $this->emiData[$offerId]['payable'],
            'emi' => $this->emiData[$offerId]['emi'],
            'interest_rate' => $this->emiData[$offerId]['interest_rate'],
            'processing_fee' => $this->emiData[$offerId]['processing_fee'],
            'up_front_from_customer' => $this->emiData[$offerId]['upfront_from_customer'],
            'reason' => $offerData['reason'],
            'updated_at' => $date,
            'created_at' => $date
        ];
    }

    private function handleAdminCall($approved, array &$offers, $is_power_saving_grade, $req_id)
    {
        if ($is_power_saving_grade) {

            return $this->handlePowerSavingGrade($approved, $offers, $req_id);
        }
        
        return $this->handleRegularAdminCall($approved, $offers, $req_id);
    }

    private function handlePowerSavingGrade($approved, array $offers, $req_id)
    {
        $application = $this->getApplicationWithRelations();
        $power_saving_value = (float)($application->application_element->inverter_power_savings ?? 0);

        $this->filterEmiDataByPowerSaving($power_saving_value, $offers);

        if (empty($this->emiData)) {
            DecisionTable::insert($offers);
            return false;
        }

        $final_offer_id = $this->selectFinalOffer($application, $offers);
        $approvalStatus = $this->processOfferChange($application, $final_offer_id, true, $req_id, 'power_saving');

        $this->updateApplicationLogic($application, 'power_saving');
        if (!empty($offers)) {
            DecisionTable::insert($offers);
        }
        return $approved ? true : false;
    }

    private function handleRegularAdminCall($approved, array &$offers, $req_id)
    {
        $application = $this->getApplicationWithRelations();
        $this->removeRejectedOffers($offers);

        if (empty($this->emiData)) {
            return $this->handleEmptyEmiData($application, $offers, $approved, $req_id);
        }

        $final_offer_id = $this->selectEligibleTenureOffer($application, $offers);
        $approvalStatus = $this->processOfferChange($application, $final_offer_id, false, $req_id, 'minimum_tenure');

        $this->updateApplicationLogic($application, 'minimum_tenure');

        if (!empty($offers)) {
            DecisionTable::insert($offers);
        }

        return $approved ? true : false;
    }

    private function getApplicationWithRelations()
    {
        return ConsumerApplication::with('merchant', 'application_element', 'emi', 'activeOffer')
            ->where('id', $this->appId)
            ->first();
    }

    private function filterEmiDataByPowerSaving($power_saving_value, array $offers)
    {
        foreach ($this->emiData as $offerId => $emiDetails) {
            if ($emiDetails['emi'] > $power_saving_value) {
                unset($this->emiData[$offerId]);
                continue;
            }

            if ($this->isOfferRejected($offerId, $offers)) {
                unset($this->emiData[$offerId]);
            }
        }
    }

    private function removeRejectedOffers(array $offers)
    {
        foreach ($this->emiData as $offerId => $emiDetails) {
            if ($this->isOfferRejected($offerId, $offers)) {
                unset($this->emiData[$offerId]);
            }
        }
    }

    private function isOfferRejected($offerId, array $offers) 
    {
        foreach ($offers as $offer) {
            if ($offer['offer_id'] == $offerId && $offer['status'] == 1) {
                return true;
            }
        }
        return false;
    }

    private function selectFinalOffer($application, array $offers)
    {
        $this->getClosestOffer($application);

        if ($this->closestOffer !== null) {
            $closestOfferData = collect($offers)->firstWhere('offer_id', $this->closestOffer);
            return $closestOfferData ? $closestOfferData['offer_id'] : $offers[0]['offer_id'];
        }

        return $offers[0]['offer_id'];
    }

    private function selectEligibleTenureOffer($application, array $offers)
    {
        $this->getEligibleTenureOffer($application);

        if ($this->eligibleTenureOffer !== null) {
            $eligibleOfferData = collect($offers)->firstWhere('offer_id', $this->eligibleTenureOffer);
            return $eligibleOfferData ? $eligibleOfferData['offer_id'] : $offers[0]['offer_id'];
        }

        return $offers[0]['offer_id'];
    }

    private function processOfferChange($application, $final_offer_id, $is_power_saving_grade, $req_id, $source)
    {
        $previous_applied_offer = $application->offer_id ?? 0;

        if ($previous_applied_offer != $final_offer_id) {
            $approvalStatus = $this->regenerateEMIAfterDecision(
                $application,
                $final_offer_id,
                $is_power_saving_grade,
                $req_id,
                $source
            );
        } else {
            $approvalStatus = true;
        }

        ConsumerApplicationElement::where('application_id', $application->id)
            ->whereNull('previous_applied_offer')
            ->update(['previous_applied_offer' => $previous_applied_offer]);

        return $approvalStatus;
    }

    private function updateApplicationLogic($application, $logic)
    {
        if ($application->emi) {
            $application->emi->table_of_offers_logic = $logic;
            $application->emi->save();
        }
    }

    private function handleEmptyEmiData($application, array $offers, $approved, $req_id)
    {
        $emiDetails = $this->getNextBasedAmountOffer($application->id, true);

        if (empty($emiDetails)) {
            DecisionTable::insert($offers);
            return false;
        }

        $this->processResidualEmi($application, $offers, $emiDetails, $approved, $req_id);
        DecisionTable::insert($offers);

        return $approved;
    }

    private function processResidualEmi($application, array &$offers, $emiDetails, $approved, $req_id)
    {
        $offerIds = array_column($offers, 'offer_id');
        $filteredEmiDetails = array_filter($emiDetails, function ($emiDetail) use ($offerIds) {
            return in_array($emiDetail->id, $offerIds);
        });

        $this->updateOffersWithEligibleAmount($offers, $filteredEmiDetails);
        $this->updateApplicationLogic($application, 'residual_emi');

        $highestLoanOffer = collect($filteredEmiDetails)->sortByDesc('loan_amount')->first();
        $final_offer_id = $highestLoanOffer->id ?? null;

        if ($highestLoanOffer && isset($highestLoanOffer->loan_amount)) {
            $application->approved_amount = $highestLoanOffer->loan_amount;
            $application->save();
        }

        if ($final_offer_id != 0) {
            $this->processOfferChange($application, $final_offer_id, false, $req_id, 'residual_emi');
        }
    }

    private function updateOffersWithEligibleAmount(array &$offers, $filteredEmiDetails)
    {
        foreach ($offers as $key => $offer) {
            foreach ($filteredEmiDetails as $emiDetail) {
                if ($offer['offer_id'] == $emiDetail->id) {
                    $offers[$key]['eligible_amount'] = $emiDetail->loan_amount;
                    break;
                }
            }
        }
    }

    private function checkApprovalStatus(array $offers) 
    {
        foreach ($offers as $offer) {
            if (!$offer['status']) {
                return true;
            }
        }
        return false;
    }

    private function saveOffersToDatabase(array $offers)
    {
        if (!empty($offers)) {
            DecisionTable::insert($offers);
        }
    }

    private function handleRejection($approvalStatus, $isAdminCall)
    {
        if (!$approvalStatus && !$isAdminCall) {
            $response = [
                'failed_condition' => null,
                'reason' => "Table of Offers failed"
            ];
            $this->saveApprovalStatus(0, $this->appId, null, 'failed', $response);
        }
    }

    private function handleException(\Exception $e)
    {
        $slackData = [
            'title' => 'TOF Auto assign offer Error',
            'fields' => [
                'error' => $e->getMessage(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]
        ];

        (new \App\Slack(new Request($slackData)))->send();
    }

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

    public function generateApprovalLog($app_id,$reason,$req_id=''){
        ApprovalStatusLog::insert([
            'rule_id' => 0,
            'application_id' => $app_id,
            'failed_condition' => null,
            'reason' => $reason,
            'request_batch_id' => $req_id,
            'status' => 1,
            'created_at' => Carbon::now()->toDateTimeString(),
            'updated_at' => Carbon::now()->toDateTimeString(),
        ]);
    }

    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 getEligibleTenureOffer($application){
        $current_offer = $application->offer_id ?? 0;
        foreach ($this->emiData as $offerId => $emiDetails) {
            if($offerId == $current_offer){
                $this->eligibleTenureOffer = $offerId;
                $this->eligibleTenure = $emiDetails['tenure'];
                break;
            }
            if (isset($emiDetails['tenure']) && ($emiDetails['tenure'] < $this->eligibleTenure || $this->eligibleTenure == 0)) {
                $this->eligibleTenureOffer = $offerId;
                $this->eligibleTenure = $emiDetails['tenure'];
            }
        }
    }

    public function getNextBasedAmountOffer($application_id, $runAgain = false)
    {
        try {
            $scoreCard = new ScoreCard(new Request());
            $application = ConsumerApplication::with('emi')->find($application_id);

            if (!$application) {
                return [];
            }

            $residual_emi = 0;

            if ($runAgain) {
                $residual_emi = $scoreCard->getEligibleEmiByResidualFOIR($application_id);
            } else {
                $residual_emi = !empty($application->emi->residual_emi) && $application->emi->residual_emi > 0
                    ? $application->emi->residual_emi
                    : $scoreCard->getEligibleEmiByResidualFOIR($application_id);
            }

            // Save residual_emi if applicable
            if ($application->emi) {
                $application->emi->residual_emi = $residual_emi;
                $application->emi->save();
            }

            // Prepare EMI calculation request
            $request = new Request();
            $request->attributes->add([
                'merchant_id'    => $application->merchant_id,
                'category_id'    => $application->purpose,
                'emi_amount'     => $residual_emi,
                'application_id' => $application_id,
            ]);

            $calculation = new \App\Http\Controllers\Admin\EMICalculation($request);
            $emi         = $calculation->prepareCalculation();
            $emiDetails  = $emi->getData();

            return !empty($emiDetails) ? $emiDetails : [];

        } catch (\Exception $e) {
            (new \App\Slack(new Request([
                'title'  => 'TOF next based amount assign error',
                'fields' => [
                    'error' => $e->getMessage(),
                    'line'  => $e->getLine(),
                    'trace' => $e->getTraceAsString(),
                ],
            ])))->send();

            return [];
        }
    }

    public function regenerateEMIAfterDecision($application,$final_offer_id,$is_power_saving_grade = false,$req_id='',$source='minimum_tenure'){
        if($final_offer_id > 0) {
            $offer_details = MerchantOffers::with('disbursementOffersData')->where('id', $final_offer_id)->first();
        }

        $day = date('j'); // Gets the day of the month as a number (1-31)
        if(isset($offer_details->disbursementOffersData) && count($offer_details->disbursementOffersData) > 0){
            $startDate = strtotime(date('Y-m-d', strtotime('now + 15 days')));
            $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
        }else {
            if (((isset($offer_details) && $offer_details->subvention_type_id > 1) || $application->activeOffer->subvention_type_id > 1) && $day >= 1 && $day < 5) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 31 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 64 days')));
            } elseif ($application->activeOffer->subvention_type_id > 1 && $day == 5) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 22 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
            } elseif ($application->application_element->is_bnpl) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 60 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 90 days')));
            } else {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 15 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
            }
        }

        $i = 1;

        $arrayDate = ((isset($offer_details) && $offer_details->subvention_type_id > 1) || $application->activeOffer->subvention_type_id > 1) ? [5] : [5, 18];

        /*if ($application->lender_id == AvanseServices::$lender_id){
            $arrayDate = [7];
            if(Carbon::now()->day <= 20){
                $timestamp = new Carbon('first day of next month');
                $startDate = $timestamp->timestamp;
                $endDate = Carbon::parse(date('Y-m-d', $startDate))->addDays(45)->timestamp;
            }else{
                $timestamp = new Carbon('first day of next month');
                $startDate = $timestamp->addMonth(1)->timestamp;
                $endDate = Carbon::parse(date('Y-m-d', $startDate))->addDays(45)->timestamp;
            }
        }*/


        $available_dates = array();
        do {
            $newTime = strtotime('+' . $i++ . ' days', $startDate);
            if (in_array(date('d', $newTime), $arrayDate)) {
                array_push($available_dates, date('Y-m-d', $newTime));
            }
        } while ($newTime < $endDate);

        $emi_date = date('Y-m-d H:i:s', strtotime($available_dates[0]));

        $first_emi_date = $emi_date ?? $application->emi->emi_date;
        $loan_amount = $application->loan_amount ?? 0;
        $approved_amount = $application->approved_amount ?? 0;
        $category_id = $application->purpose ?? 0;
        $merchant_id = $application->merchant_id ?? 0;
        $previous_offer_id = $application->offer_id ?? 0;
        $previousOfferDetails = MerchantOffers::where('id', $previous_offer_id)->first();

        if (strlen($first_emi_date) > 0) {
            $converted_first_emi_date = Carbon::createFromFormat('Y-m-d H:i:s', $first_emi_date)->format('d/m/Y');
        }

        $approvalStatus = false;
        if ($final_offer_id > 0) {
            $request = new Request();
            $request->merge([
                'merchant_id' => $merchant_id,
                'loan_amount' => $approved_amount,
                'category_id' => $category_id,
                'merchant_offer_id' => $final_offer_id,
                'application_id' => $this->appId
            ]);

            $emiCalculation = new \App\Http\Controllers\Admin\EMICalculation($request);
            $new_emi_data = $emiCalculation->prepareCalculation($request, $this->appId);
            $decoded_new_emi_data = $new_emi_data->getData(true);

            // Calling RegenerateEMI function
            $requestData = new Request();
            $requestData->merge([
                "payable_by_customer" => $decoded_new_emi_data['payable'],
                "upfront_from_customer" => $decoded_new_emi_data['up_front_from_customer'],
                "tenure" => $decoded_new_emi_data['total_emi'],
                "remaining_emi" => $decoded_new_emi_data['emi_remaining'],
                "advance_emi" => $decoded_new_emi_data['advance_emi'],
                "interest_rate" => $decoded_new_emi_data['flat_annual_interest'],
                "subvention" => $decoded_new_emi_data['subvention'],
                "emi" => $decoded_new_emi_data['emi'],
                "upfront_from_credit_fair" => $decoded_new_emi_data['up_front_from_credit_fair'],
                "received_by_merchant" => $decoded_new_emi_data['total_amount_received_by_merchant'],
                "processing_fee" => $decoded_new_emi_data['processing_fee'],
                "subvention_cgst" => $decoded_new_emi_data['subvention_cgst'],
                "subvention_sgst" => $decoded_new_emi_data['subvention_sgst'],
                "subvention_igst" => $decoded_new_emi_data['subvention_igst'],
                "payment_frequency" => $decoded_new_emi_data['payment_frequency'],
                "disbursement_method" => $decoded_new_emi_data['disbursement_method'],
                "net_loan_amount" => $decoded_new_emi_data['net_loan_amount'],
                "first_emi_date" => $converted_first_emi_date,
                "offer_id" => $final_offer_id
            ]);

            $emiCalculation = new \App\Http\Controllers\Admin\EMICalculation($requestData);
            $emiCalculation->generateEMI($requestData, $this->appId);

            $username = isset(Auth::user()->name) ? Auth::user()->name : 'creditfair';
            if(in_array($application->state,['cf approved','approved'])){
                $comment = "Trigger Point - Edit FOIR page Submit button <br><br>
                Applied Amount - Rs. ".$loan_amount." Applied Tenure - ".$previousOfferDetails->slug.", ".$previousOfferDetails->interest_rate."% interest, ".$previousOfferDetails->advance_emi." Advance EMIs <br>
                Eligible Amount - Rs. ".$application->approved_amount." Eligible Tenure - ".$offer_details->slug.", ".$offer_details->interest_rate."% interest, ".$offer_details->advance_emi." Advance EMIs

                @".$username." Please reach out to the @credit team if any additional documents are required.";

            }else{
                $comment = "Applied Amount - Rs. ".$loan_amount." Applied Tenure - ".$previousOfferDetails->slug.", ".$previousOfferDetails->interest_rate."% interest, ".$previousOfferDetails->advance_emi." Advance EMIs <br>
                Eligible Amount - Rs. ".$application->approved_amount." Eligible Tenure - ".$offer_details->slug.", ".$offer_details->interest_rate."% interest, ".$offer_details->advance_emi." Advance EMIs

                Please find below the list of documents required to process your original loan request:
                <br/> 1. Last 6-months Bank statement of the applicant
                <br/> 2. Earning co-app details <br/>

                @".$username." Please reach out to the @credit team if any additional documents are required.";
            }

            $this->addComment($this->appId, Auth::user()->id ?? 107, $comment);

            if($source == 'power_saving'){
                $comment = "Plan changed as per the power savings";
            }elseif($source == 'residual_emi'){
                $comment = "Plan changed as per the next based amount TOF";
            }else{
                $comment = "Plan changed as per the minimum tenure TOF";
            }
            // $status = "cf approved";
            // $this->updateStatus($this->appId, $status);
            $this->generateApprovalLog($this->appId, $comment,$req_id);

            $approvalStatus = true;

        } else {
            $approvalStatus = false;
        }

        // Returning false because don't want to move the case to cf approved after regenereted emi case will move to waiting for decision
        return false;  // if returned true here the case will move to cf approved if false then waiting for decision
    }

    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{
            $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);
        /*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)

        $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')) { //$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)) {
            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 ($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 ($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']);

        $day = date('j'); // Gets the day of the month as a number (1-31)
        if(isset($offer->disbursementOffersData) && count($offer->disbursementOffersData) > 0){
            $startDate = strtotime(date('Y-m-d', strtotime('now + 15 days')));
            $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
            if ($application->application_element->is_bnpl) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 60 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 90 days')));
            }
        }else {
            if ($application->activeOffer->subvention_type_id > 1 && $day != 5) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 31 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 64 days')));
            } elseif ($application->activeOffer->subvention_type_id > 1 && $day == 5) {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 22 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
            } else {
                $startDate = strtotime(date('Y-m-d', strtotime('now + 15 days')));
                $endDate = strtotime(date('Y-m-d', strtotime('now + 45 days')));
                if ($application->application_element->is_bnpl) {
                    $startDate = strtotime(date('Y-m-d', strtotime('now + 60 days')));
                    $endDate = strtotime(date('Y-m-d', strtotime('now + 90 days')));
                }
            }
        }

        $i = 1;

        $arrayDate = $application->activeOffer->subvention_type_id > 1 ? [5] : [5, 18];

        if ($request->has('avanse')){
            $arrayDate = [7];
            if(Carbon::now()->day <= 20){
                $timestamp = new Carbon('first day of next month');
                $startDate = $timestamp->timestamp;
                $endDate = Carbon::parse(date('Y-m-d', $startDate))->addDays(45)->timestamp;
            }else{
                $timestamp = new Carbon('first day of next month');
                $startDate = $timestamp->addMonth(1)->timestamp;
                $endDate = Carbon::parse(date('Y-m-d', $startDate))->addDays(45)->timestamp;
            }
        }


        $available_dates = array();
        do {
            $newTime = strtotime('+' . $i++ . ' days', $startDate);
            if (in_array(date('d', $newTime), $arrayDate)) {
                array_push($available_dates, date('Y-m-d', $newTime));
            }
        } while ($newTime < $endDate);

        $emi_date = date('d/m/Y', strtotime($available_dates[0]));
        $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);
                    }
                }

                if ($application->creditReport) {
                    $req_id = $this->request->has('request_ap_id') ? $this->request->get('request_ap_id') : '';

                    $autoRejectResult = $this->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();
                    // $approvalStatus = $grade->getOutput();

                    // }
//                    if ($isLog) {
//                        PWAApplicationForm::approvalLog($approvalStatus, $id, $req_id);
//                    }
//                    if (empty(array_filter($approvalStatus))) {
                    if($grade){
                        return response(['auto_approved' => false], 200);
                    }

//                    if (empty(array_filter($approvalStatus))) {
                    if($grade){
                        //$consumerApplicationController->updateApplicationStatus($id, 'approved');  --- don't remove
                        $this->initAutoDocumentation($grade, $application->id);
                        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 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{
            $data = $request->all();
            $autoReject = new AutoRejectRule();
            $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;
                            }
                        }
                        // Add the processed rule only if it's not empty
                        if (!empty($processedRule)) {
                        $processedRules[] = $processedRule;
                        }
                    }
                }
                $categoryObject = [
                    'Ownership' => $ownershipData,
                    'rules' => $processedRules
                ];
                if ($categoryPrefix == 'principal_written_off') {
                    $categoryPrefix = 'PRINCIPAL_WRITTEN_OFF_AMOUNT';
                } else if ($categoryPrefix == 'past_dues') {
                    $categoryPrefix = 'TOTAL_PAST_DUES';
                }
                $output['new_rejection_rules'][strtoupper($categoryPrefix)] = [$categoryObject];
            }
            $output['new_rejection_rules']['MAX_AGE'] = $data['ec_max_age'];
            $output['new_rejection_rules']['MIN_AGE'] = $data['ec_min_age'];
            $output['new_rejection_rules']['MONTHLY_INCOME'] = $data['ec_monthly_income'];
            $output['new_rejection_rules']['MIN_SCORE'] = $data['ec_min_score'];
            $output['new_rejection_rules']['MAX_SCORE'] = $data['ec_max_score'];
            $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;
            $autoReject->modifications = json_encode($output);
            $autoReject->grade_id = $data['grade_id'];
            $autoReject->status = 1;
            $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);
        return redirect()->back();
    }

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

        try {
            $data = $request->all();
            $preApproval = new AutoReject();
            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 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;
    }
}
