<?php
/**
 * Created by PhpStorm.
 * User: sunil
 * Date: 10/15/18
 * Time: 2:33 PM
 */

namespace App;


use App\Http\Controllers\Grade\GradeController;
use Carbon\Carbon;
use Illuminate\Http\Request;

class ScoreCard
{

    private $request;
    private $score = 0;
    private $maxFOIR = 75/100;
    private $enquiryIn12Month = 0;
    private $enquiryIn24Month = 0;
    private $enquiryTotal = 0;
    private $loan_amount = 0;
    private $tenure = 0;
    private $interest_rate = 0;
    private $profession = '';

    private $loan_account = [
        'Tractor Loan' => ['rate' => 18, 'tenure' => 36],
        'Commercial Vehicle Loan' => ['rate' => 15, 'tenure' => 60],
        'Loan Against Bank Deposits' => ['rate' => 2, 'tenure' => 1200],
        'Loan Against Shares / Securities' => ['rate' => 2, 'tenure' => 12],
        'Education' => ['rate' => 15, 'tenure' => 60],
        'Business Loan - Priority Sector- Agriculture' => ['rate' => 6, 'tenure' => 1200],
        'Business Loan - Priority Sector- Others' => ['rate' => 15, 'tenure' => 24],
        'Business Loan Against Bank Deposits' => ['rate' => 2, 'tenure' => 1200],
        'Business Loan - Priority Sector- Small Business' => ['rate' => 2, 'tenure' => 12],
        'Business Non-funded Credit Facility' => ['rate' => 6, 'tenure' => 1200],
        'Used Car Loan' => ['rate' => 15, 'tenure' => 36],
        'Housing Loan' => ['rate' => 9, 'tenure' => 180],
        'Property Loan' => ['rate' => 12, 'tenure' => 120],
        'Auto Loan' => ['rate' =>10, 'tenure' => 60],
        'Personal Loan' => ['rate' => 15, 'tenure' => 36],
        'Consumer Loan' => ['rate' => 15, 'tenure' => 9],
        'Gold Loan' => ['rate' => 12, 'tenure' => 1200],
        'Microfinance Business Loan' => ['rate' => 18, 'tenure' => 36],
        'Microfinance Housing Loan' => ['rate' => 12, 'tenure' => 120],
        'Microfinance Others' => ['rate' => 18, 'tenure' => 36],
        'Loan To Professional' => ['rate' => 18, 'tenure' => 36],
        'Construction Equipment Loan' => ['rate' => 15, 'tenure' => 60],
        'Mudra Loans - Shishu / Kishor / Tarun' => ['rate' => 12, 'tenure' => 36],
        'Pradhan Mantri Awas Yojana - Credit Link Subsidy Scheme May Clss' => ['rate' => 9, 'tenure' => 180],
        'Prime Minister Jaan Dhan Yojana - Overdraft' => ['rate' => 12, 'tenure' => 1200],
        'Overdraft' => ['rate' => 12, 'tenure' => 1200],
    ];

    //private $loan_account = array("Housing Loan"=>array("rate"=>9,"tenure"=>180),"Property Loan"=>array("rate"=>10,"tenure"=>120),"Auto Loan"=>array("rate"=>10,"tenure"=>60),"Personal Loan"=>array("rate"=>13,"tenure"=>36),"Consumer Loan"=>array("rate"=>11,"tenure"=>9),"Gold Loan"=>array("rate"=>15,"tenure"=>12));
    private $professionCreditFair = ['UNEMPLOYED'=>'UNEMPLOYED','SALARIED'=>'Salaried','BUSINESS'=>'Self Employed','Self Employed - Professional' => 'Self Employed - Professional', 'Self Employed - Business' => 'Self Employed - Business'];
    public static $professionTypeCreditFair = [['valueS' => 'Private Limited','ValueT' => 6],['valueS' => 'Sole proprietorship','ValueT' => 0], ['valueS' => 'Unregistered Partnership','ValueT' => 2], ['valueS' => 'Registered Partnership','ValueT' => 4],['valueS' => 'HUF/ AOP','ValueT' => 0], ['valueS' => 'Unlisted Public Limited','ValueT' => 8], ['valueS' => 'Listed Public Limited','ValueT' => 10]];
    public static $industryCreditFair = ['Services', 'Manufacturing', 'Trading'];
    private $companyCategoryCreditFair = ['CAT A' => 8, 'CAT B' => 6, 'CAT C' => 4, 'CAT D' => 2, 'Super CAT A' => 10, 'NA' => 2];
    private $profession_type = '';
    private $industry = '';
    private $company_category = '';
    private $company_name = '';
    private $total_loan_count = 0;
    private $zero_balance = 0;
    private $overDueAmountApplicant = 0;
    private $overDueAmountCoApplicant = 0;
    private $bureauInput = [];
    private $bureauInputCoApplicant = [];
    private $application = [];
    private $total_existing_emi;
    private $credit_limit;
    private $applicant_type;
    private $foirRatio = 0;
    private $ResidualFOIR;
    private $maxEligible;
    private $scoreCard;
    private $scoreBand = ['< 625' => 2.5, '625,674' => 5, '675,719' => 7.5, '720,780' => 10, '> 780' => 12.5];
    private $enquiryBand = ['< 6' => 'A','6,11'=>'B','12,17'=>'C','> 18' => 'D'];
    private $unSecuredTradeLinesLoans = ['Others', 'Commercial Loan', 'Business Loan', 'Credit Card', 'Personal Loan'];
    private $liveTermLoansNotIn = ['Credit Card'];
    private $dpdChart = ['000'=>0, '01+'=>15,'30+'=>45,'60+'=>75,'90+'=>105,'120+'=>150,'180+'=>270,'360+'=>450,'540+'=>610,'720+'=>720,'STD'=>0,'SPM'=>60,'SUB'=>180,'DBT'=>720];
    private $unSecuredTradeLinesLoansCount;
    private $unSecuredTradeLines;
    private $liveTermLoans;
    private $liveTermLoansNotInCount;
    private $recencyOfTrades;
    private $maxDays = 366;
    private $maxScore = 100;
    private $unSecuredTradeLinesBefore;
    private $liveTermLoansBefore;
    private $credit_hungriness;
    private $rtr_quality;
    private $average_dpd;
    private $max_dpd;
    private $constituion;
    private $applicant_age;
    private $income_bracket;
    private $monthlyIncome;
    private $foir_bracket;
    private $finalScore = 0;
    private $finalCategory;
    private $structuredScoreCard;
    private $oldFinalScore;
    private $withoutCFEMI = 0;


    public function __construct(Request $request){
        $this->request = $request;
    }

    public function setApplication($application){
        $this->application = $application;
    }

    public function getScore(){
        $this->initFOIR();
        $this->initCreditReport();
        $this->getScoreCard();
        $this->structuredScoreCard();

        return $this->structuredScoreCard;
    }

    public function structuredScoreCard(){
        $this->structuredScoreCard = [
            'bureauInputCoApplicant' => $this->bureauInputCoApplicant,
            'bureauInput' => $this->bureauInput,
            'scoreCard' => $this->scoreCard,
            'totalLoanCount' => $this->total_loan_count,
            'zeroBalance' => $this->zero_balance,
            'overDueAmount' => $this->overDueAmountApplicant,
            'score' => $this->score,
            'enquiryPast12' => $this->enquiryIn12Month,
            'loan_amount' => $this->loan_amount,
            'interest_rate' => $this->interest_rate,
            'tenure' => $this->tenure,
            'profession' => $this->profession,
            'profession_type' => $this->profession_type,
            'industry' => $this->industry,
            'company_category' => $this->company_category,
            'company_name' => $this->company_name,
            'monthly_income' => $this->monthlyIncome,
            'foir' => $this->foirRatio,
            'ResidualFOIR' => $this->ResidualFOIR,
            'max_eligible' => $this->maxEligible,
            'max_emi_serviced' => $this->max_emi_serviced,
            'current_emi_sum' => $this->current_emi_sum,
            'application' => $this->application,
            'finalScore' => $this->finalScore,
            'finalCategory' => $this->finalCategory,
            'maxScore' => $this->maxScore
        ];
    }

    public function initFOIR(){
        $jointLoans = [];
        foreach ($this->application->foir as $item){
            $acName = ucwords(strtolower($item->AccountType));
            if($item->applicant_type == 1 && $item->OwnershipType != 'Guarantor'){
                $jointLoans[$acName][] = $item->OwnershipType;
                $this->overDueAmountApplicant += $this->getBureauInputs($item);
            }
            if($item->applicant_type == 2){
                $inc_foir = 1;
                if($item->applicant_type == 2 && $item->OwnershipType == 'Joint Account' && isset($jointLoans[$acName]) && in_array($item->OwnershipType, $jointLoans[$acName])){
                    $inc_foir = 0;
                }
                if($inc_foir) {
                    $this->overDueAmountCoApplicant += $this->getBureauInputs($item);
                }else{
                    $this->getBureauInputs($item);
                }
            }
        }
        return $this;
    }

    public function executePerformanceMatrix($installmentAmountOLD, $item){
        //$installmentAmountNEW = $this->getEmiTenure($item->AccountType, $item->ApprovedAmount, $item->Balance, $item->DateOpened, $item->LastPaymentDate, true);
        $accountName = ucwords(strtolower($item->AccountType));
        if(isset($this->loan_account[$accountName])){
            $rate = ($this->loan_account[$accountName]['rate'])/1200;
            $tenure_remaining = $this->loan_account[$accountName]['tenure'];
        }else{
            $rate = 12/1200;
            $tenure_remaining = 24;
        }

        $installmentAmountNEW = $this->calculatePMT($rate, $tenure_remaining, $item->ApprovedAmount);

        if($installmentAmountNEW){
            if($installmentAmountOLD > $installmentAmountNEW * 1.5 || $installmentAmountOLD < $installmentAmountNEW * 0.5){
                return ['emi' => $installmentAmountNEW, 'new' => true];
            }
        }
        return ['emi' => $installmentAmountOLD, 'new' => false, 'new_emi' => $installmentAmountNEW];
    }

    public function getRecencyOfTradesInDays($date){
        $date = Carbon::parse($date);
        return $date->diffInDays(Carbon::now());
    }

    public function calculateEMISave($item){
        $accName = ucwords(strtolower($item->AccountType));
        $installmentAmount = $this->getEmiTenure($accName, $item->ApprovedAmount, $item->Balance, $item->DateOpened, $item->LastPaymentDate);
        $installmentAmount = $this->executePerformanceMatrix($installmentAmount, $item);
        $_installmentAmountNew = isset($installmentAmount['new_emi']) ? $installmentAmount['new_emi'] : 0;
        $installmentAmount = !empty($installmentAmount['emi']) ? $installmentAmount['emi'] : 0;
        $installmentAmountNew = !empty($installmentAmount['new']) ? $installmentAmount['new'] : 0;
        $item->InstallmentAmount = $installmentAmount;
        $item->save();

        return ['installmentAmountNew' => $installmentAmountNew, '_installmentAmountNew' => $_installmentAmountNew];
    }

    public function getBureauInputs($item){
        $installmentAmount = $item->InstallmentAmountOLD ? $item->InstallmentAmountOLD : $item->InstallmentAmount;
        $installmentAmountPROld = $item->InstallmentAmountOLD ? $item->InstallmentAmountOLD : $item->InstallmentAmount;
        $item->InstallmentAmountOLD = $installmentAmount;
        $installmentAmountNew = 0;
        $acctName = ucwords(strtolower($item->AccountType));

        if($installmentAmount && isset($this->loan_account[$acctName]) && isset($this->loan_account[$acctName]['calcOnSanction']) && $this->loan_account[$acctName]['calcOnSanction']) {

            $installmentAmount = ($item->ApprovedAmount * $this->loan_account[$acctName]['calcOnSanction']) / 100;

            if (($installmentAmountPROld < ($item->ApprovedAmount * 5) / 100) || ($installmentAmountPROld > ($item->ApprovedAmount * 10) / 100)) {
                $bEMI = $item->InstallmentAmount;
                $item->InstallmentAmount = $installmentAmount;
                $item->save();
                $installmentAmountNew = $installmentAmount;
                $installmentAmount = $bEMI;
            }else{
                $installmentAmountNew = $installmentAmount;
                $installmentAmount = $item->InstallmentAmount;
            }
        }else if ($item->InstallmentAmount == 0) {
            $calculateEMISave = $this->calculateEMISave($item);
            $installmentAmountNew = $calculateEMISave['installmentAmountNew'];
            $_installmentAmountNew = $calculateEMISave['_installmentAmountNew'];
        }else{
            $installmentAmount = $this->executePerformanceMatrix($installmentAmount, $item);
            $_installmentAmountNew = isset($installmentAmount['new_emi']) ? $installmentAmount['new_emi'] : 0;
            $installmentAmount = $installmentAmount['emi'];
        }


        $item->InstallmentAmountNEW = $installmentAmountNew ? $installmentAmount : (isset($_installmentAmountNew) ? $_installmentAmountNew : 0);
        $item->save();

        $DPDs = $this->getDPDs($item->dpd);

        $inputs = [
            'date_opened' => $item->DateOpened,
            'date_closed' => $item->DateClosed,
            'type_of_loan' => $acctName,
            'owner_ship' => $item->OwnershipType,
            'loan_sanctioned' => $item->ApprovedAmount,
            'loan_outstanding' => $item->Balance,
            'over_due_amount' => ($item->PastDueAmount > 0) ? $item->PastDueAmount : 0,
            'schedule_emi' => $installmentAmount,
            'schedule_emi_new' => $installmentAmountNew ? $installmentAmountNew : (isset($_installmentAmountNew) ? $_installmentAmountNew : 0),
            'cc_loan' => $item->cc_loan,
            'last_emi_amount_paid' => ($item->LastPayment) ? $item->LastPayment : $installmentAmount,
            'max_dpd' => $DPDs['maxDPD'],
            'average_dpd' => $DPDs['averageDPD'],
            'highlight' => $DPDs['highlight'],
            'last_payment_date' => $item->LastPaymentDate,
            'reported_date' => $item->ReportedDate,
            'is_close_date_updated' => $item->is_close_date_updated
        ];

        if($item->applicant_type == 2){
            $this->bureauInputCoApplicant[] = $inputs;
            return $item->PastDueAmount;
        }else{
            $this->bureauInput[] = $inputs;
        }

        if($DPDs['maxDPD'] > 30) {
            $this->max_dpd += 1;
        }
        if($DPDs['averageDPD'] > 12){
            $this->average_dpd += 1;
        }

        $this->recencyOfTrades[] = empty($item->DateOpened) ? '' : $this->getRecencyOfTradesInDays($item->DateOpened);

        if(in_array($acctName,$this->unSecuredTradeLinesLoans)){
            $this->unSecuredTradeLinesLoansCount += 1;
        }

        if($item->Balance > 0) {
            if (!in_array($acctName, $this->liveTermLoansNotIn)) {
                $this->liveTermLoansNotInCount += 1;
            }
        }

        if($item->isOpened == 1) {
            if ($item->cc_loan === 0) {
                $this->credit_limit += $item->Balance;
            } else if($item->Balance > 0 || $item->created_by > 0){
                $this->total_existing_emi += $item->InstallmentAmount;
            }
        }
        return $item->PastDueAmount;
    }

    public function setFOIRCalculation(){
        $monthlyIncome = $this->application->monthly_income;
        if($this->applicant_type == 2){
            $monthlyIncome = $this->application->co_applicant_monthly_income + $this->application->monthly_income;
        }

        if($powerSavingIncome = (new GradeController($this->request))->getPowerSavingIncome($this->application->id)){
            $monthlyIncome += $powerSavingIncome;
        }

        $this->monthlyIncome = $monthlyIncome;
        $this->foirRatio = $this->getFOIRCalculation($monthlyIncome);
        $this->ResidualFOIR = $this->maxFOIR - $this->foirRatio;
        $this->maxEligible = round($monthlyIncome * $this->ResidualFOIR * $this->tenure);
        $this->max_emi_serviced = $this->application->creditReport[0]->max_emi_serviced ?? $this->application->creditReport[0]->max_emi_serviced ?? 0;
        $this->current_emi_sum = $this->application->creditReport[0]->current_emi_sum ?? $this->application->creditReport[0]->current_emi_sum ?? 0;
        $this->foirRatio = round($this->foirRatio * 100);
        $this->ResidualFOIR = round($this->ResidualFOIR * 100);
    }

    public function getEligibleEmiByResidualFOIR($application_id = 0){
        $application = ConsumerApplication::with('creditReport', 'foir', 'merchant.offer', 'application_element', 'emi')->where('id', $application_id)->first();
        $this->setApplication($application);
        $monthlyIncome = $this->application->monthly_income;
        if($this->applicant_type == 2){
            if(isset($application->co_applicant_monthly_income) && !empty($application->co_applicant_monthly_income)){
                $monthlyIncome = $this->application->co_applicant_monthly_income + $this->application->monthly_income;
            }
        }

        if($powerSavingIncome = (new GradeController($this->request))->getPowerSavingIncome($this->application->id)){
            $monthlyIncome += $powerSavingIncome;
        }

        $this->monthlyIncome = $monthlyIncome;
        $this->initFOIR();
        $this->withoutCFEMI = 1;
        $this->foirRatio = $this->getFOIRCalculation($monthlyIncome);
        $this->ResidualFOIR = $this->maxFOIR - $this->foirRatio;
        $eligibleEmiAmount = $this->monthlyIncome * $this->ResidualFOIR;
        return $eligibleEmiAmount;
    }

    public function getAverageDPDs($foir, $type = 1){
        $DPDsArray = [];
        foreach ($foir as $item) {
            if ($item->applicant_type == $type && $item->DateClosed == '') {
                $t = $item->dpd;
                $DPDs = json_decode($t,true);
                if($DPDs) {
                    foreach ($DPDs as $key => $element) {
                        if (isset($this->dpdChart[$key]) && $key != '000') {
                            $DPDsArray[$key][] = $element;
                        }
                    }
                }
            }
        }

        return $DPDsArray;
    }

    public function getFOIRCalculation($income){
        $creditFairEMI = FOIR::where('application_id',$this->application->id)->where('AccountType', 'Credit Fair EMI')->where('InstallmentAmount','>',0)->first(['InstallmentAmount']);
        if($income > 0) {
            $total_credit_card_limit_five = ($this->credit_limit * 5) / 100;
            $total_monthly_payment = $this->total_existing_emi + $total_credit_card_limit_five;
            $foirIncludingCFEMI = $foirNAIncludingCFEMI = ($total_monthly_payment / $income) * 100;
            if(isset($creditFairEMI->InstallmentAmount)){
                $total_monthly_payment += $creditFairEMI->InstallmentAmount;
                $foirIncludingCFEMI = ($total_monthly_payment / $income) * 100;
            }


            CreditReport::where('application_id', $this->application->id)->where('applicant_type', 1)->update(['foirIncludingCFEMI' => $foirIncludingCFEMI, 'foirNAIncludingCFEMI' => $foirNAIncludingCFEMI]);
            if($this->withoutCFEMI == 1){
                return $foirNAIncludingCFEMI / 100;
            }
            return $total_monthly_payment / $income;
        }
        return 0;
    }


    public function initCreditReport(){
        foreach ($this->application->creditReport as $creditReport) {
            $company = Company::where('id',$this->application->company_name)->first(['category','company']);
            if($creditReport->applicant_type == 1) {
                $this->score = $creditReport->Score;
                $this->enquiryIn12Month = $creditReport->Past12Months;
                $this->enquiryIn24Month = $creditReport->Past24Months;
                $this->enquiryTotal = $creditReport->TotalEnquiry;
                $this->loan_amount = $this->application->loan_amount;
                $this->tenure = $this->application->tenure;
                $this->interest_rate = $this->getInterestRate();
                $this->profession = isset($this->professionCreditFair[$this->application->employee_status]) ? $this->professionCreditFair[$this->application->employee_status] : '';
                $this->company_name = isset($company->company) ? $company->company : '';
                $this->total_loan_count = count($this->application->foir);
                $this->zero_balance = $creditReport->zeroBalanceAccount;
                $this->company_category = isset($company->category) ? $company->category : '';
                $this->industry = isset($this->application->application_element->industry) ? static::$industryCreditFair[$this->application->application_element->industry]: '';
                $this->profession_type = isset($this->application->application_element->profession_type) ? static::$professionTypeCreditFair[$this->application->application_element->profession_type]['valueS'] : '';
                $this->oldFinalScore = $creditReport->finalCategory;
            }
        }
    }

    public function getInterestRate(){

        if(isset($this->application->emi->interest_rate)){
            return $this->application->emi->interest_rate;
        }

        foreach($this->application->merchant->offer as $offer){
            if($offer->tenure == $this->application->tenure){
                return $offer->interest_rate;
            }
        }
        return 0;
    }

    public function getDPDs($dpd){
        $DPDs = json_decode($dpd);
        $DPDsArray = [];
        $highlight = false;
        foreach ($DPDs as $key=>$item){
            if(isset($this->dpdChart[$key])) {
                $DPDsArray[] = $this->dpdChart[$key] * $item;
            }

            if (in_array($key, ['DBT','FPD','WDF','PWOS','WOF', 'LOSS','SPM','SFR','SF','WDF','SFWD','WOF','SFWO','WDWO','SWDW','SET'])){
                $highlight = true;
            }
        }
        $DPDs = array_values((array)$DPDs);

        return [
            'maxDPD' => ($DPDsArray) ? max($DPDsArray) : '',
            'averageDPD' => (count($DPDs) > 0) ? array_sum($DPDsArray)/count($DPDs): '',
            'highlight' => $highlight
        ];
    }

    private function isLoanClosed($foir){
        if($foir->Balance <= 0 || ($foir->ApprovedAmount > 0 && $foir->Balance / $foir->ApprovedAmount * 100 <= 5)){
            return 1;
        }
        return 0;
    }

    public function updateLoanStatus($id){
        $foirData = FOIR::where('application_id', $id)->get();
        foreach ($foirData as $item) {
            if (strlen($item->DateClosed) == 0 && $item->Balance > 0 && $this->isLoanClosed($item)) {
                FOIR::where('id', $item->id)->update(['Balance' => 0]);
            }
            if(strlen($item->DateClosed) > 0 && $item->Balance > 0 && $item->is_close_date_updated == 0){
                $update = [];
                if($this->isLoanClosed($item)) {
                    $update['Balance'] = 0;
                }else{
                    $update['DateClosed'] = null;
                    $update['is_close_date_updated'] = 1;
                    $update['isOpened'] = 1;
                }
                FOIR::where('id', $item->id)->update($update);

            }
        }
    }

    public function getEmiTenure($loanType,$loan_amount,$outstanding_amount,$creation_date,$last_payment_date, $isCheck = false){
        if($outstanding_amount == 0){
            return 0;
        }
        if($last_payment_date == null || $last_payment_date == ""){
            $last_payment_date = date('Y-m-d');
        }
        if(isset($this->loan_account[$loanType]) && $this->loan_account[$loanType]['rate']){
            $rate = ($this->loan_account[$loanType]['rate'])/1200;
            $tenure_remaining = $this->loan_account[$loanType]['tenure'];
        }else{
            $rate = 12/1200;
            $tenure_remaining = 24;
        }
        $pv = $loan_amount;
        $creation_date = new \DateTime($creation_date);
        $last_payment_date = new \DateTime($last_payment_date);
        $interval = $last_payment_date->diff($creation_date);
        $emiPaid = $interval->format('%m') + ($interval->format('%y')*12) + 1;
        $bal_max = $outstanding_amount + ($outstanding_amount * (0.5 / 100));
        $bal_min = $outstanding_amount - ($outstanding_amount * (0.5 / 100));
        $emi_array = array();
        $data = [];
        for($q=$tenure_remaining; $q>0;$q=$q-0.01) {
            $q = round($q,2);
            $emi = $this->calculatePMT($rate, $q, $pv);
            $balance_amount = $pv;
            for($i=1;$i<=$q;$i++){
                $interest = round($balance_amount * $rate);
                $principle = $emi - $interest;
                $balance_amount = round($balance_amount - $principle);
                if($i == $emiPaid){

                    if($isCheck){
                        return $emi;
                    }

                    if($balance_amount == $outstanding_amount){
                        $final_emi = $this->calculatePMT($rate, ceil($q), $pv);
                        return $final_emi;
                    }else{
                        array_push($emi_array,$balance_amount);
                        $data[$balance_amount] =  $q;
                        break;
                    }
                }
            }
        }
        if(count($emi_array) > 0) {
            sort($emi_array);
            $nearest_match = $this->getNearest($emi_array, $outstanding_amount);
            $finalTenure = ceil($data[$nearest_match]);
            $final_emi = $this->calculatePMT($rate, $finalTenure, $pv);
        }else{
            $final_emi = $finalTenure = 0;
        }
        return $final_emi;
    }

    function getNearest($arr,$var){
        usort($arr, function($a,$b) use ($var){
            return  abs($a - $var) - abs($b - $var);
        });
        return array_shift($arr);
    }

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

    public function getAge(){
        return (date('Y') - date('Y',strtotime($this->application->dob)));
    }

    public function beforeScoreInit(){
        $this->applicant_age = $this->getAge();
        if($this->total_loan_count == 0){
            $this->unSecuredTradeLinesBefore = 0;
            $this->liveTermLoansBefore = 0;
        }else{
            $this->unSecuredTradeLinesBefore = $this->unSecuredTradeLinesLoansCount/$this->total_loan_count;
            $this->liveTermLoansBefore = $this->liveTermLoansNotInCount/$this->total_loan_count;
        }
        $this->unSecuredTradeLines = round($this->unSecuredTradeLinesBefore * 100);
        $this->liveTermLoans = round($this->liveTermLoansBefore * 100);

        if($this->recencyOfTrades == null){
            $this->recencyOfTrades = array();
        }
        else {
            $this->recencyOfTrades = array_filter($this->recencyOfTrades);
            $this->recencyOfTrades = array_filter($this->recencyOfTrades, function ($n) {
                return $n < $this->maxDays;
            });
        }
        if($this->total_loan_count == 0){
            $this->recencyOfTrades = 0;
        }else{
            $this->recencyOfTrades = round(count($this->recencyOfTrades) / $this->total_loan_count * 100,2);
        }
        $this->credit_hungriness = $this->getBandValue($this->enquiryBand,$this->enquiryIn12Month);
        $this->rtr_quality = $this->getRTRQuality();
        $this->constituion = (strtolower($this->profession) == strtolower($this->professionCreditFair["SALARIED"])) ? $this->company_category.'-'.$this->company_name : $this->profession_type.'-'.$this->company_name;
        $this->income_bracket = $this->getIncomeRage();
        $this->foir_bracket = $this->getFIRBracket();


    }

    public function getFIRBracket(){
        if($this->foirRatio < 20){
            return '<20%';
        }else if($this->foirRatio >= 20 && $this->foirRatio < 30){
            return '20-30%';
        }else if($this->foirRatio >= 30 && $this->foirRatio < 40){
            return '30-40%';
        }else if($this->foirRatio >= 40 && $this->foirRatio < 50){
            return '40-50%';
        }else if($this->foirRatio >= 50 && $this->foirRatio < 60){
            return '50-60%';
        }else if($this->foirRatio >= 60 && $this->foirRatio < 70){
            return '60-70%';
        }else if($this->foirRatio >= 70){
            return '70%+';
        }
    }

    public function getIncomeRage(){
        return ($this->monthlyIncome >= 15000 && $this->monthlyIncome < 25000) ? '15K-25K' : (($this->monthlyIncome >= 25000 && $this->monthlyIncome < 40000) ? '25K-40K' : (($this->monthlyIncome >= 40000 && $this->monthlyIncome < 75000) ? '40K-75K' : (($this->monthlyIncome >= 75000 && $this->monthlyIncome < 150000) ? '75K-150K' : (($this->monthlyIncome >= 150000) ? '150K+' : 0))));
    }

    public function getRTRQuality(){
        if($this->total_loan_count == 0){
            $RTROne = 0;
            $RTRTwo = 0;
        }else{
            $RTROne = round($this->max_dpd / $this->total_loan_count * 100);
            $RTRTwo = round($this->average_dpd / $this->total_loan_count * 100);
        }

        if($RTROne == 0 && $RTRTwo == 0){
            return "ETR";
        }elseif($RTROne == 0.1 && $RTRTwo == 0.1){
            return "GTR";
        }elseif($RTROne == 0.25 && $RTRTwo == 0.25){
            return "ATR";
        }else{
            return "PTR";
        }
    }

    public function getScoreCard(){
        $this->setFOIRCalculation();
        $this->beforeScoreInit();

        $this->scoreCard = [
            ['Parameter'=>'Score Band', 'value' => $this->score, 'score' => $this->getScoreBand('score_band'), 'max_score' => 12.5],
            ['Parameter'=>'Unsecured Trade Lines', 'value' => $this->unSecuredTradeLines, 'score' => $this->getScoreBand('unsecured_trade_lines'), 'max_score' => 7.5],
            ['Parameter'=>'Live Term Loans', 'value' => $this->liveTermLoans, 'score' => $this->getScoreBand('live_term_loans'), 'max_score' => 6.25],
            ['Parameter'=>'Recency of Trades', 'value' => $this->recencyOfTrades, 'score' => $this->getScoreBand('recency_of_trades'), 'max_score' => 5],
            ['Parameter'=>'Credit Hungriness', 'value' => $this->credit_hungriness, 'score' => $this->getScoreBand('credit_hungriness'), 'max_score' => 5],
            ['Parameter'=>'RTR Quality', 'value' => $this->rtr_quality, 'score' => $this->getScoreBand('rtr_quality'), 'max_score' => 13.75],
            ['Parameter'=>'Constituion', 'value' => $this->constituion, 'score' => $this->getScoreBand('constituion'), 'max_score' => 10],
            ['Parameter'=>'Applicant Age', 'value' => $this->applicant_age, 'score' => $this->getScoreBand('applicant_age'), 'max_score' => 10],
            ['Parameter'=>'Income Bracket', 'value' => $this->income_bracket, 'score' => $this->getScoreBand('income_bracket'), 'max_score' => 15],
            ['Parameter'=>'Foir', 'value' => $this->foir_bracket, 'score' => $this->getScoreBand('foir'), 'max_score' => 15],
        ];

        $this->finalScore = round($this->finalScore);
        $this->finalCategory = $this->getFinalCategory();
        $this->updateApplicantScore();
    }

    public function updateApplicantScore(){
        if($this->oldFinalScore != $this->finalCategory) {
            CreditReport::where('application_id', $this->application->id)
                ->update(['finalCategory' => $this->finalCategory]);
        }
    }

    public function getFinalCategory(){
        if($this->finalScore < 42){
            return 'R';
        }else if($this->finalScore >= 42 && $this->finalScore < 52){
            return 'C';
        }else if($this->finalScore >= 52 && $this->finalScore < 72){
            return 'B';
        }else if($this->finalScore >= 72 && $this->finalScore < 90){
            return 'A';
        }else if($this->finalScore >= 90){
            return 'AAA';
        }else{
            return '';
        }
    }

    public function getScoreBand($band){
        $band_value = 0;
        switch ($band){
            case 'score_band':
                $band_value = $this->getBandValue($this->scoreBand,$this->score);
                break;
            case 'unsecured_trade_lines':
                if($this->unSecuredTradeLinesBefore < 0.2){
                    $band_value = 4.5;
                }else if($this->unSecuredTradeLinesBefore < 0.4){
                    $band_value = 7.5;
                }else if($this->unSecuredTradeLinesBefore < 0.6){
                    $band_value = 3.0;
                }else if($this->unSecuredTradeLinesBefore < 0.8){
                    $band_value = 1.5;
                }else {
                    $band_value = 0;
                }
                break;
            case 'live_term_loans':
                if($this->liveTermLoansBefore < 0.2){
                    $band_value = 5;
                }else if($this->liveTermLoansBefore < 0.4){
                    $band_value = 6.25;
                }else if($this->liveTermLoansBefore < 0.6){
                    $band_value = 3.75;
                }else if($this->liveTermLoansBefore < 0.8){
                    $band_value = 2.5;
                }else {
                    $band_value = 1.25;
                }
                break;
            case 'recency_of_trades':
                if($this->recencyOfTrades < 25){
                    $band_value = 2;
                }else if($this->recencyOfTrades < 50){
                    $band_value = 5;
                }else if($this->recencyOfTrades < 75){
                    $band_value = 3;
                }else {
                    $band_value = 1;
                }
                break;
            case 'credit_hungriness':
                if($this->credit_hungriness =="A"){
                    $band_value = 5;
                }elseif($this->credit_hungriness =="B"){
                    $band_value = 3;
                }elseif($this->credit_hungriness =="C"){
                    $band_value = 2;
                }else{
                    $band_value = 1;
                }
                break;
            case 'rtr_quality':
                if($this->rtr_quality =="ETR"){
                    $band_value = 13.75;
                }elseif($this->rtr_quality =="GTR"){
                    $band_value = 6.875;
                }elseif($this->rtr_quality =="ATR"){
                    $band_value = 4.125;
                }else{
                    $band_value = 0;
                }
                break;
            case 'constituion':
                if(strtolower($this->profession) == strtolower($this->professionCreditFair["SALARIED"])){
                    $band_value = isset($this->companyCategoryCreditFair[$this->company_category]) ? $this->companyCategoryCreditFair[$this->company_category] : 0;
                }else{
                    $band_value = isset(static::$professionTypeCreditFair[$this->application->application_element->profession_type]['valueT']) ? static::$professionTypeCreditFair[$this->application->application_element->profession_type]['valueT'] : 0;
                }
                break;
            case 'applicant_age':
                $band_value = ($this->applicant_age < 25) ? 2 :(($this->applicant_age >= 25 && $this->applicant_age < 40) ? 8 : (($this->applicant_age >= 40 && $this->applicant_age < 50) ? 10 : (($this->applicant_age >= 50 && $this->applicant_age < 60) ? 6 : (($this->applicant_age >= 60) ? 4 : 0))));
                break;
            case 'income_bracket':
                if($this->income_bracket == '15K-25K'){
                    $band_value = 3;
                }else if($this->income_bracket == '25K-40K'){
                    $band_value = 6;
                }else if($this->income_bracket == '40K-75K'){
                    $band_value = 9;
                }else if($this->income_bracket == '75K-150K'){
                    $band_value = 12;
                }else if($this->income_bracket == '150K+'){
                    $band_value = 15;
                }
                break;
            case 'foir':
                if($this->foir_bracket == '<20%'){
                    $band_value = 15;
                }else if($this->foir_bracket == '20-30%'){
                    $band_value = 12;
                }else if($this->foir_bracket == '30-40%'){
                    $band_value = 9;
                }else if($this->foir_bracket == '40-50%'){
                    $band_value = 6;
                }else if($this->foir_bracket == '50-60%'){
                    $band_value = 3;
                }else if($this->foir_bracket == '60-70%'){
                    $band_value = 1.5;
                }else if($this->foir_bracket == '70%+'){
                    $band_value = 0;
                }
                break;
            default:
                $band_value = 0;
                break;
        }

        $this->finalScore += $band_value;
        return $band_value;
    }

    public function getBandValue($scoreBand, $score){
        foreach ($scoreBand as $key=>$band){
            $con = explode(',',$key);
            $t = (int)trim(str_replace('>','',$key));
            $v = (int)trim(str_replace('<','',$key));
            if ((strpos($key,'<') !== false) && $score < $v) {
                return $band;
            }else if ((strpos($key,'>') !== false) && $score >= $t) {
                return $band;
            }else if ( isset($con[0]) && isset($con[1]) && in_array($score, range($con[0],$con[1])) ) {
                return $band;
            }
        }
        return $scoreBand['< 625'];
    }
}
