<?php

namespace App;

use App\Http\Controllers\Admin\AccountingController;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\Http\Controllers\Admin\RiskController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\LoanHypothecation\LoanHypothecation;
use App\Singularity\Singularity;
use MathPHP\Finance;

class EMICalculation
{
    private $loan_amount = 0;
    private $net_loan_amount = 0;

    private $annualized_irr = 0;

    private $tenure = 0;
    private $interest_rate = 0;
    private $emi = 0;
    private $advance_emi = 0;
    private $upFrontFromCustomer = 0;
    private $tenure_remaining = 0;
    private $upFrontFromCreditFair = 0;
    private $subvention = 0;
    private $totalAmountReceivedByMerchant = 0;
    private $emis = [];

    private $disbursement_offers_data = [];
    private $payable;
    private $interest_type = 0;
    private $processing_fee = 0;
    private $processing_fee_type;
    private $advance_type;
    private $processing_fee_collected = 0;
    private $slug;
    private $offer_id = 0;
    private $subvention_type = 0;
    private $subvention_cgst = 0;
    private $subvention_sgst = 0;
    private $subvention_igst = 0;
    private $application_id = 0;
    public $appId = 0;
    private $payment_frequency = 1;
    private $processing_fee_on_advance_amount = 0;
    private $frequency = 12;
    private $process_fee = 0;
    public $legal_charges = 0;
    /*Monthly (1)	12
    Bi-Monthly (2)	24
    Weekly (3)	52
    Daily (4)	365
    Quarterly (5)	4
    Half-Yearly (6)	2
    Annually (7)	1*/
    private $payment_frequency_offer = [1 => 12, 2 => 24, 3 => 52, 4 => 365, 5 => 4, 6 => 2, 7 => 1];
    private $disbursement_method = 1;
    private $riskBasedInterestRateFlag = false;
    private $risk_based_interest_rate_excluding_pf = false;
    private $gross_roi = 0;
    private $insurance_fee = 0;
    private $downPayment = 0;
    private $ChargeSubventionRemainingAmount = 0;
    private $add_insurance_in_loan_amount = false;

    public function init(){
        $this->frequency = $this->payment_frequency_offer[$this->payment_frequency];

        $this->tenure_remaining = ($this->advance_type == 'emi') ? $this->tenure - $this->advance_emi : $this->tenure;

        switch ($this->interest_type){
            case 4:
            case 3:
                $this->generalEmiCalculation();
                $this->getUpFrontFromCustomer();
                $this->updateLoanAmount();
                $this->upFrontFromCreditFair();
                $this->totalAmountReceivedByMerchant();
                break;
            default:
                $this->getUpFrontFromCustomer();
                $this->updateLoanAmount();
                $this->generalEmiCalculation();
                $this->upFrontFromCreditFair();
                $this->totalAmountReceivedByMerchant();
                break;
        }
    }

    public function calculateEMI(){
        $this->init();
        $this->updateProcessingFeeOnRemainingAmount();
        $this->isInsuranceFeeApplicable();
        $this->generateEMIs();
        $this->adjustLastEMI();
        $this->totalPayableByCustomer();
        $this->calculateGSTonSubvention($this->subvention, $this->loan_amount, $this->offer_id, true,$this->application_id);
        return [
            'id' => $this->offer_id,
            'total_emi' => $this->tenure,
            'payable_in_advanced' => $this->advance_emi,
            'emi_remaining' => $this->tenure_remaining,
            'flat_annual_interest' => $this->interest_rate,
            'subvention' => $this->subvention,
            'emi' => round($this->emi),
            'up_front_from_customer' => round($this->upFrontFromCustomer),
            'up_front_from_credit_fair' => round($this->upFrontFromCreditFair),
            'total_amount_received_by_merchant' => round($this->totalAmountReceivedByMerchant),
            'emis' => $this->emis,
            'payable' => $this->payable,
            'advance_emi' => $this->advance_emi,
            'processing_fee' => round($this->processing_fee),
            'processing_fee_type' => $this->processing_fee_type,
            'processing_fee_on_advance_amount' => $this->processing_fee_on_advance_amount,
            'advance_type' => $this->advance_type,
            'processing_fee_collected' => $this->processing_fee_collected,
            'legal_charges' => $this->legal_charges,
            'slug' => $this->slug,
            'subvention_type' => $this->subvention_type,
            'loan_amount' => round($this->loan_amount,0),
            'net_loan_amount' => round($this->net_loan_amount,0),
            'subvention_cgst' => round($this->subvention_cgst,0),
            'subvention_sgst' => round($this->subvention_sgst,0),
            'subvention_igst' => round($this->subvention_igst,0),
            'payment_frequency' => $this->payment_frequency,
            'disbursement_method' => $this->disbursement_method,
            'insurance_fee' => $this->insurance_fee,
            'charge_subvention_remaining_amount' => $this->ChargeSubventionRemainingAmount,
            'annualized_irr' => $this->annualized_irr,
            'disbursement_offers_data' => $this->disbursement_offers_data,
            'riskBasedInterestRateFlag' => $this->riskBasedInterestRateFlag,
            'risk_based_interest_rate_excluding_pf' => $this->risk_based_interest_rate_excluding_pf,
            'gross_roi' => $this->calculateGrossROI() //$this->gross_roi
        ];
    }

    public function isInsuranceFeeApplicable(){
        $proFormaInvoice = ProFormaInvoice::where('application_id',$this->application_id)->first();
        if((isset($proFormaInvoice->insurance_premium_applicable) && $proFormaInvoice->insurance_premium_applicable == 1)){
            if($proFormaInvoice->insurance_premium_by_merchant == 1) {
                $this->insurance_fee = $proFormaInvoice->insurance_premium_amount;
            }
            if($this->add_insurance_in_loan_amount){
                $this->insurance_fee = 0;
                return $proFormaInvoice->insurance_premium_amount ?? 0;
            }
        }
    }

    private function get_insurance_amount_if_applcable(){
        $proFormaInvoice = ProFormaInvoice::where('application_id',$this->appId)->first();
        if((isset($proFormaInvoice->insurance_premium_applicable) && $proFormaInvoice->insurance_premium_applicable == 1)){
            if($proFormaInvoice->insurance_premium_by_merchant == 2) {
                return $proFormaInvoice->insurance_premium_amount;
            }
        }

        return 0;
    }

    public function checkAgreementSigned($application_id) {
        $applicationDetails = DB::selectOne("SELECT id, state, lender_id from consumer_application where id = ?", [$application_id]);
        if (isset($applicationDetails) && $applicationDetails->lender_id == Singularity::$lender_id){
            $homevilleAgreement = DB::selectOne("SELECT application_id, case_id, doc_type from homeville_document_info where application_id = ? and created_at < '2025-12-06 00:00:00' and doc_type in ('signed_document', 'sign_request')", [$application_id]);
            if(!empty($homevilleAgreement)) {
                return true;
            }
        } else {
            $agreement = DB::selectOne("SELECT status, first_party_signing, applicant_signing, co_applicant_signing from loan_hypothecation_model where application_id = ? and created_at < '2025-12-06 00:00:00' and deleted_at is null", [$application_id]);
            if (!empty($agreement) && ($agreement->status == 'success' || ($agreement->applicant_signing || $agreement->co_applicant_signing || $agreement->first_party_signing))) {
                return true;
            }
        }
        return false;
    }

    public function calculateGSTonSubvention($subvention, $loan_amount, $offer_id, $type = false, $application_id = 0, $subvention_part_percentage = false){

        if($insurance_amount = $this->get_insurance_amount_if_applcable()){
            $loan_amount -= $insurance_amount;
        }

        $subvention_cgst = 0;
        $subvention_sgst = 0;
        $subvention_igst = 0;
        if($subvention > 0) {

            if(!$this->downPayment && !$subvention_part_percentage){
                //$merchant_details = MerchantOffers::with('merchant')->where('id', $offer_id)->select('charge_subvention_remaining_amount')->first();
                $merchant_details = MerchantOffers::with('merchant:is_gst,id,state,charge_subvention_remaining_amount')->where('id', $offer_id)->select('id', 'merchant_id')->first();
                if (isset($merchant_details->merchant) && $merchant_details->merchant->charge_subvention_remaining_amount){
                    $applicationEMICalculation = ApplicationEMICalculation::where('application_id',$application_id)->first(['subvention', 'upfront_from_customer']);
                    if(isset($applicationEMICalculation->subvention)) {
                        $this->downPayment = $applicationEMICalculation->upfront_from_customer;
                    }
                }
            }

            $subvention_amount =  ($subvention_part_percentage) ? $subvention : (($loan_amount - $this->downPayment)*$subvention)/100;
            if($subvention_amount > 0) {
                if(!isset($merchant_details)) {
                    $merchant_details = MerchantOffers::with('merchant:is_gst,id,state')->where('id', $offer_id)->select('id', 'merchant_id')->first();
                }
                if ($merchant_details) {
                    if (isset($merchant_details->merchant->is_gst) && $merchant_details->merchant->is_gst == 1 && isset($merchant_details->merchant->state) && !empty($merchant_details->merchant->state)) {
                            if($application_id == 0){
                                $state = $merchant_details->merchant->state;
                            }else{
                                $user = ConsumerApplication::with('merchant','application_element.merchant_center')->where('id',$application_id)->first();
                                if(isset($user->application_element->merchant_center->gst_number) && !empty($user->application_element->merchant_center->gst_number) && !empty($user->application_element->merchant_center->state)){
                                    $state = $user->application_element->merchant_center->state;
                                }else{
                                    $state = $user->merchant->state;

                                }
                            }
                            $gstDetails = (new ConsumerDocument(new Request()))->getGSTDetails(
                                [
                                    'amount' => $subvention_amount,
                                    'state' => $state
                                ],0
                            );
                            if($gstDetails){
                                foreach ($gstDetails as $gst){
                                    if(isset($gst['taxes']) && $gst['taxes'] == "CGST"){
                                        if($type) {
                                            $this->subvention_cgst = $gst['gst_amount'];
                                        }else{
                                            $subvention_cgst = $gst['gst_amount'];
                                        }
                                    }elseif (isset($gst['taxes']) && $gst['taxes'] == "SGST"){
                                        if($type) {
                                            $this->subvention_sgst = $gst['gst_amount'];
                                        }else{
                                            $subvention_sgst = $gst['gst_amount'];
                                        }
                                    }else{
                                        if($type) {
                                            $this->subvention_igst = $gst['gst_amount'];
                                        }else{
                                            $subvention_igst = $gst['gst_amount'];
                                        }
                                    }
                                }
                            }
                    }
                }
            }
        }

        return ['subvention_cgst' => $subvention_cgst, 'subvention_sgst' => $subvention_sgst, 'subvention_igst' => $subvention_igst];
    }

    public function totalPayableByCustomer(){
        switch ($this->interest_type){
            case 1:
                $this->payable = ($this->interest_rate) ? round($this->upFrontFromCustomer + ($this->emi * $this->tenure_remaining) + $this->processing_fee + $this->insurance_fee) : round($this->upFrontFromCustomer + ($this->emi * $this->tenure_remaining) + $this->processing_fee + $this->insurance_fee);
                break;
            case 2:
                $this->payable = round($this->upFrontFromCustomer + ($this->emi * $this->tenure_remaining) + $this->processing_fee + $this->insurance_fee);
                break;
            case 3:
                $this->payable = ($this->interest_rate) ? round($this->upFrontFromCustomer + ($this->emi * $this->tenure_remaining) + $this->processing_fee + $this->insurance_fee) : round( array_sum($this->emis) + $this->upFrontFromCustomer + $this->processing_fee + $this->insurance_fee);
                break;
            case 4:
                $this->payable = round(($this->emi * $this->tenure) + $this->processing_fee + $this->insurance_fee);
                break;
        }

        $this->payable += $this->legal_charges;
    }

    public function generateEMIs(){
        for($i = 1; $i <=$this->tenure_remaining; $i++){
            $this->emis[] = round($this->emi);
        }
    }


    public function tableView(){
        return
            '<table border="1"><tr><th>Total EMI</th><th>Payable In Advance</th><th>EMI Remaining</th><th>Flat Annual Interest</th><th>Subvention</th><th>EMI</th><th>UP Front From Customer</th><th>UP Front From Credit Fair</th><th>Total Amount Received By Merchant</th></tr>'.
            '<tr><td>'.$this->tenure.'</td>'.
            '<td>'.$this->advance_emi.'</td>'.
            '<td>'.$this->tenure_remaining.'</td>'.
            '<td>'.$this->interest_rate.'</td>'.
            '<td>'.$this->subvention.'</td>'.
            '<td>'.$this->emi.'</td>'.
            '<td>'.$this->upFrontFromCustomer.'</td>'.
            '<td>'.$this->upFrontFromCreditFair.'</td>'.
            '<td>'.$this->totalAmountReceivedByMerchant.'</td></tr></table>';
    }

    /*public function getUpFrontFromCustomer(){

        switch ($this->interest_type){
            case 1:
                $this->upFrontFromCustomer = $this->getBasedOnAdvanceType();
                break;
            case 2:
                $this->upFrontFromCustomer = $this->getBasedOnAdvanceType();
                break;
            case 3:
                $this->upFrontFromCustomer = $this->getBasedOnAdvanceType();
                break;
        }
    }*/

    public function getUpFrontFromCustomer(){
        if($this->loan_amount > 0 && $this->loan_amount != "") {
            switch ($this->advance_type) {
                case 'emi':
                    $this->upFrontFromCustomer = ($this->interest_type == 3 && $this->interest_rate) ? round($this->emi * $this->advance_emi, 2) : (($this->interest_type == 4 && $this->interest_rate) ? $this->emi * $this->advance_emi : round($this->loan_amount / $this->tenure * $this->advance_emi));
                    break;
                case 'fixed_amount':
                    $this->upFrontFromCustomer = $this->advance_emi;
                    break;
                case 'percentage':
                    $this->upFrontFromCustomer = ($this->advance_emi / 100) * $this->loan_amount;
                    break;
            }
        }else if($this->net_loan_amount > 0 && $this->net_loan_amount != "") {
            $adv_calculations = $this->upFrontFromCustomer =
                (($this->interest_type == 3) && $this->interest_rate) ?
                    round(((($this->net_loan_amount * $this->tenure) / ($this->tenure - $this->advance_emi)) * (1 + ($this->interest_rate * $this->tenure / 12))) * $this->advance_emi / $this->tenure) :
                    (($this->interest_type == 4 && $this->interest_rate) ?
                        round(((($this->net_loan_amount * $this->tenure) / ($this->tenure - $this->advance_emi)) * (1 + $this->interest_rate)) * $this->advance_emi / $this->tenure) :
                        ($this->advance_emi / 100) * ($this->net_loan_amount * 100) / (100 - $this->advance_emi));//round(($this->net_loan_amount * $this->advance_emi) / ($this->tenure - $this->advance_emi)));

            switch ($this->advance_type) {
                case 'percentage':
                case 'emi':
                    $this->upFrontFromCustomer = $adv_calculations;
                    break;
                case 'fixed_amount':
                    $this->upFrontFromCustomer = $this->advance_emi;
                    break;
            }
        }else{
            switch ($this->advance_type) {
                case 'emi':
                    $this->upFrontFromCustomer = $this->advance_emi * $this->emi;
                    break;
                case 'fixed_amount':
                    $this->upFrontFromCustomer = $this->advance_emi;
                    break;
                case 'percentage':
                        $this->generalEmiCalculation();
                    break;
            }
        }

        if($this->ChargeSubventionRemainingAmount){
            $this->downPayment = $this->upFrontFromCustomer;
        }
    }

    public function upFrontFromCreditFair(){

        $loan_amount = $this->loan_amount;

        $loan_amount -= $this->removeInsuranceFromLoanAmount();

        switch ($this->interest_type){
            case 1:
                //$advance = $this->upFrontFromCreditFairBasedOnAdvanceType();
                $subvention = ((($loan_amount - $this->downPayment)*$this->subvention)/100);
                $this->upFrontFromCreditFair = ($this->interest_rate) ?  $loan_amount - $this->upFrontFromCustomer - $subvention : $this->getupFrontFromCreditFair();
                break;
            case 2:
                $this->upFrontFromCreditFair = $loan_amount - $this->upFrontFromCustomer - ($this->subvention * ($loan_amount - $this->downPayment))/100;
                break;
            case 3:
                $this->upFrontFromCreditFair = ($this->interest_rate) ? $loan_amount - $this->upFrontFromCustomer - (($loan_amount - $this->downPayment) * $this->subvention)/100 : ($loan_amount*($this->tenure_remaining/$this->tenure) - (($loan_amount - $this->downPayment)*$this->subvention)/100);
                break;
            case 4:
                $this->upFrontFromCreditFair = $loan_amount - $this->upFrontFromCustomer - ((($loan_amount - $this->downPayment) * $this->subvention)/100);
                break;
        }
    }

    public function upFrontFromCreditFairBasedOnAdvanceType(){
        $amount = 0;
        switch ($this->advance_type){
            case 'emi':
                $amount = ($this->interest_type == 1) ? $this->loan_amount* ($this->tenure_remaining/$this->tenure) : $this->loan_amount * ($this->tenure_remaining/$this->tenure) - (($this->loan_amount - $this->downPayment) * $this->subvention)/100;
                break;
            case 'fixed_amount':
                $amount = $this->advance_emi;
                break;
            case 'percentage':
                $amount = ($this->advance_emi / 100) * $this->loan_amount;
                break;
        }

        return $amount;
    }

    public function getupFrontFromCreditFair(){
        $getupFrontFromCreditFair = ($this->loan_amount*($this->tenure_remaining/$this->tenure) - (($this->loan_amount - $this->downPayment)*$this->subvention)/100);;
        if ($this->advance_type == 'percentage'){
            if ($this->upFrontFromCustomer && $getupFrontFromCreditFair){
                return $getupFrontFromCreditFair - $this->upFrontFromCustomer;
            }
        }
        return $getupFrontFromCreditFair;
    }

    public function totalAmountReceivedByMerchant(){
        $this->totalAmountReceivedByMerchant = $this->upFrontFromCustomer + $this->upFrontFromCreditFair;
    }

    public function getEMI(){
        return $this->totalAmountReceivedByMerchant;
    }

    public function netLoanCalculation($return=false){
        switch ($this->advance_type) {
            case 'emi':
                if ($this->loan_amount > 0 && $this->loan_amount != "") {
                    $this->net_loan_amount = ($this->loan_amount * ($this->tenure - $this->advance_emi))/$this->tenure;
                }else{
                    $this->loan_amount = ($this->net_loan_amount * $this->tenure)/($this->tenure - $this->advance_emi);
                }
                break;
            case 'fixed_amount':
                if ($this->loan_amount > 0 && $this->loan_amount != "") {
                    $this->net_loan_amount = $this->loan_amount - $this->advance_emi;
                }else {
                    $this->loan_amount = $this->net_loan_amount + $this->advance_emi;
                }
                break;
            case 'percentage':
                if ($this->loan_amount > 0 && $this->loan_amount != "") {
                    $this->net_loan_amount = ($this->loan_amount * (100 - $this->advance_emi)) / 100;
                }else {
                    $this->loan_amount = ($this->net_loan_amount * 100) / (100 - $this->advance_emi);
                }
                break;
        }
        if ($return) {
            return $this->net_loan_amount;
        }
    }

    public function loanCalculation(){
        switch ($this->interest_type) {
            case 1:
                $this->emi = ($this->interest_rate) ? (($this->loan_amount - $this->upFrontFromCustomer) + (($this->loan_amount - $this->upFrontFromCustomer) * $this->interest_rate * ($this->tenure_remaining / $this->frequency) / 100)) / $this->tenure_remaining : $this->calculatePMT();
                break;
            case 2:
                $this->emi = $this->calculatePMT();
                break;
            case 3:
                $this->emi = ($this->interest_rate) ? $this->loan_amount * (1 + ($this->interest_rate * ($this->tenure / $this->frequency) / 100)) / $this->tenure : ($this->loan_amount / $this->tenure);//($this->loan_amount - $this->upFrontFromCustomer)/($this->tenure_remaining ? $this->tenure_remaining : 1);
                break;
            case 4:
                $this->emi = ($this->interest_rate) ? $this->loan_amount * (1 + $this->interest_rate / 100) / $this->tenure : $this->emiAmount();
                break;
        }
    }

    public function generalEmiCalculation(){
     //if(($this->emi == 0 || $this->emi == null) && ($this->loan_amount == 0 || $this->loan_amount ==null)){
         if ($this->loan_amount > 0 && $this->loan_amount != "") {
             $this->loanCalculation();
             $this->netLoanCalculation();
         } else if ($this->net_loan_amount > 0 && $this->net_loan_amount != "") {
             $this->netLoanCalculation();
             $this->loanCalculation();
         } else {
             switch ($this->interest_type) {
                 case 1:
                     $present_value = (($this->interest_rate) ? $this->emi * $this->tenure_remaining / (1 + ($this->interest_rate * ($this->tenure_remaining / $this->frequency) / 100)) : ($this->emi * $this->tenure_remaining));
                     $this->loan_amount = $present_value + $this->getUpFrontFromCustomerForLoanAmount($present_value);
                     break;
                 case 2:
                     $present_value = $this->calculatePV();
                     $this->loan_amount = $present_value + $this->getUpFrontFromCustomerForLoanAmount($present_value);
                     break;
                 case 3:
                     $this->loan_amount = ($this->interest_rate) ? $this->emi * $this->tenure / (1 + ($this->interest_rate * ($this->tenure / $this->frequency) / 100)) : ($this->emi * $this->tenure);//($this->loan_amount - $this->upFrontFromCustomer)/($this->tenure_remaining ? $this->tenure_remaining : 1);
                     break;
                 case 4:
                     $this->loan_amount = ($this->interest_rate) ? $this->emi * $this->tenure / (1 + $this->interest_rate / 100) : ($this->emi * $this->tenure);//($this->loan_amount - $this->upFrontFromCustomer)/($this->tenure_remaining ? $this->tenure_remaining : 1);
                     break;
             }
             $this->netLoanCalculation();
         }
     //}
    }

    public function emiAmount(){
        if ($this->advance_type == 'percentage'){
            $this->getUpFrontFromCustomer();
            if (isset($this->emi) && $this->emi){
                return $this->emi;
            }
        }
        return ($this->loan_amount - $this->upFrontFromCustomer)/($this->tenure ? $this->tenure : 1);
        //$emi = ($this->loan_amount / $this->tenure);//($this->loan_amount - $this->upFrontFromCustomer)/($this->tenure_remaining ? $this->tenure_remaining : 1);
    }

    public function getUpFrontFromCustomerForLoanAmount($pv){
        if($this->upFrontFromCustomer > 0){
            return $this->upFrontFromCustomer;
        }else{
            if($this->advance_type == "percentage") {
                $this->upFrontFromCustomer = ((($pv * (1 / ((100 - $this->advance_emi) / 100)))) * ($this->advance_emi / 100));
                return $this->upFrontFromCustomer;
            }
        }
    }

    public function calculatePMT(){
        $type = $future = 0;

        $rate = $this->interest_rate / ($this->frequency * 100);
        $tenure_remaining = $this->tenure_remaining;
        $pv   = $this->loan_amount - $this->upFrontFromCustomer;

        if ($rate > 0) {
            return -(-$future - $pv * pow(1 + $rate, $tenure_remaining)) / (1 + $rate * $type) / ((pow(1 + $rate, $tenure_remaining) - 1) / $rate);
        } else {
            return -(-$pv - $future) / $tenure_remaining;
        }
    }

    public function calculatePV(){
        $rate = $this->interest_rate / ($this->frequency * 100);
        $tenure_remaining = $this->tenure_remaining;
        $pmt   = $this->emi;

        if($rate > 0){
            return ($pmt*((1-pow((1+$rate),-$tenure_remaining))/$rate));
        }else{
            return ($pmt * $tenure_remaining);
        }
    }

    public function setLoanAmount($amount){
        $this->loan_amount = $amount;
        return $this;
    }

    public function setAnnualizedIrr($irr){
        $this->annualized_irr = $irr;
        return $this;
    }

    public function setDisbursementOffersData($tranchData){
        $this->disbursement_offers_data = $tranchData;
        return $this;
    }

    public function setNetLoanAmount($amount){
        $this->net_loan_amount = $amount;
        return $this;
    }

    public function setTenure($tenure){
        $this->tenure = $tenure;
        return $this;
    }

    public function setSlug($slug){
        $this->slug = $slug;
        return $this;
    }

    public function setOfferID($id){
        $this->offer_id = $id;
        return $this;
    }

    public function setAdvanceEMI($advance_emi){
        $this->advance_emi = $advance_emi;
        return $this;
    }

    public function setInterestRate($interest_rate){
        $this->interest_rate = $interest_rate;
        return $this;
    }

    public function setSubvention($subvention){
        $this->subvention = $subvention;
        return $this;
    }

    public function setChargeSubventionRemainingAmount($charge_subvention_remaining_amount){
        $this->ChargeSubventionRemainingAmount = $charge_subvention_remaining_amount;
        return $this;
    }

    public function setSubventionType($subvention_type){
        $this->subvention_type = $subvention_type;
        return $this;
    }

    public function setEmi($requested_emi_amount){
        $this->emi = $requested_emi_amount;
        return $this;
    }

    public function setProcessingFee($fee, $base=false){
        switch ($this->processing_fee_type){
            case 'fixed_amount':
                $this->processing_fee = $fee;
                break;
            case 'percentage':
                $amount = 0;
                if ($this->add_insurance_in_loan_amount && $this->checkAgreementSigned($this->appId)){
                    $amount += $this->get_insurance_amount_if_applcable(); // not added in updateProcessingFeeOnRemainingAmount since the loan_amount is updated with insurance amount
                }
                $this->processing_fee = round(($fee / 100) * ($this->loan_amount + $amount));
                break;
        }

        if ($base) {
            return $this->processing_fee;
        }

        if($this->processing_fee >= 0) {
            $riskController = new RiskController(new Request());
            $this->processing_fee = $riskController->getProcessingFee($this->appId, $this->processing_fee);
            $rbpAmount = $riskController->getRiskBasedPFCalculation($this->appId, $this->processing_fee);
            $this->processing_fee += $rbpAmount;
        }

        return $this;
    }

    public function setLegalCharges($fee){
        $this->legal_charges = $fee;
        return $this;
    }

    public function updateProcessingFeeOnRemainingAmount(){
        if($this->processing_fee_on_advance_amount == 1 && $this->processing_fee_type == 'percentage'){
            $riskController = new RiskController(new Request());
            $insurance_fee = $this->isInsuranceFeeApplicable();
            if ($this->checkAgreementSigned($this->appId)) {
                $insurance_fee = 0;
            }
            $this->processing_fee = round(($this->process_fee / 100) * ($this->loan_amount - $insurance_fee - $this->upFrontFromCustomer));
            $pf_surcharge_amount = $riskController->getProcessingFeesForNetLoanAmount($this->appId, $this->processing_fee);
            $this->processing_fee += $pf_surcharge_amount;
            $rbpAmount = $riskController->getRiskBasedPFCalculation($this->appId, $this->processing_fee);
            $this->processing_fee += $rbpAmount;
        }
    }

    public function setAdvanceType($advance_type){
        $this->advance_type = $advance_type;
        return $this;
    }

    public function setPaymentFrequency($payment_frequency){
        $this->payment_frequency = $payment_frequency;
        return $this;
    }

    public function setDisbursementMethod($disbursement_method){
        $this->disbursement_method = $disbursement_method;
        return $this;
    }

    public function setRiskBasedInterestRate($riskBasedInterestRateFlag){
        $this->riskBasedInterestRateFlag = $riskBasedInterestRateFlag;
        return $this;
    }

    public function setRiskBasedInterestRateExcludingPF($risk_based_interest_rate_excluding_pf){
        $this->risk_based_interest_rate_excluding_pf = $risk_based_interest_rate_excluding_pf;
        return $this;
    }

    public function setGrossROI($gross_roi){
        $this->gross_roi = $gross_roi;
        return $this;
    }

    private function calculateGrossROI(){

        if ($this->riskBasedInterestRateFlag) {
            $emi_irr_array = array();

            $loanamount = \App\Http\Controllers\Admin\EMICalculation::getLoanAmountWithInsuranceAmount($this->application_id) - $this->upFrontFromCustomer;

            $application = ConsumerApplication::where('id', $this->application_id)->first(['approved_amount', 'loan_amount']);
            $subvention_amount = ($this->subvention > 0) ? ((((isset($application->approved_amount) && $application->approved_amount != 0) ? $application->approved_amount : $application->loan_amount) * ($this->subvention)) / 100) : 0;
            $amount_disbursed = $loanamount - $subvention_amount;

            if (!$this->risk_based_interest_rate_excluding_pf) {
                $amount_disbursed -= $this->processing_fee / 1.18;
            }

            array_push($emi_irr_array, -($amount_disbursed));

            foreach ($this->emis as $emi) {
                array_push($emi_irr_array, $emi);
            }

            $response['irr_rate'] = (Finance::irr($emi_irr_array)) * 100;
            return round($response['irr_rate'] * 12, 2);
        }

        return 0;
    }

    public function setProcessingFeesOnAdvanceAmount($processing_fee_on_advance_amount,$processing_fee_value){
        $this->process_fee = $processing_fee_value;
        $this->processing_fee_on_advance_amount = $processing_fee_on_advance_amount;
        return $this;
    }

    public function setProcessingFeeCollected($processing_fee_collected){
        $this->processing_fee_collected = $processing_fee_collected;
        return $this;
    }

    public function setProcessingFeeType($processing_fee_type){
        $this->processing_fee_type = $processing_fee_type;
        return $this;
    }

    public function setInterestType($interest_type){
        $this->interest_type = $interest_type;
        return $this;
    }

    public function setApplicationId($application_id){
        $this->application_id = $application_id;
        return $this;
    }

    public function setAddInsuranceInLoanAmount($bool){
        $this->add_insurance_in_loan_amount = $bool;
        return $this;
    }

    /* In case insurance amount added in loan amount*/
    public function updateLoanAmount(){
        if ($this->add_insurance_in_loan_amount) {
            $insurance_fee = 0;
            if (!$this->insurance_fee) {
                $insurance_fee = $this->isInsuranceFeeApplicable();
            }
            $this->loan_amount = $this->loan_amount + $insurance_fee;
        }
    }

    public function removeInsuranceFromLoanAmount(){
        if ($this->add_insurance_in_loan_amount) {
            $insurance_fee = 0;
            if (!$this->insurance_fee) {
                $insurance_fee = $this->isInsuranceFeeApplicable();
            }
            return $insurance_fee ?? $this->insurance_fee;
        }
    }


    public function adjustLastEMI(){
        $this->totalPayableByCustomer();
        $payable = $this->payable - ($this->processing_fee + $this->insurance_fee + $this->legal_charges);
        if(($this->upFrontFromCustomer + array_sum($this->emis)) != ($this->interest_rate) ? $payable : $this->loan_amount){
            $adjustableAmount = (($this->interest_rate) ? $payable : $this->loan_amount) - round($this->upFrontFromCustomer + array_sum($this->emis));
            $this->emis[count($this->emis) - 1] = round($this->emis[count($this->emis) - 1] + $adjustableAmount);
        }
    }
}
