<?php

namespace App\Tally;

use App\ConsumerApplication;
use App\Http\Controllers\Admin\AccountingController;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\LiabilityLog;
use App\PaymentTransaction;
use App\Slack;
use App\StatusLogs;
use App\TallyJobsListener;
use Illuminate\Http\Request;

class Tally{

    private $request;
    private $connector;
    private $response;

    public function __construct(Request $request, TallyConnector $connector){
        $this->request = $request;
        $this->connector = $connector->connect();
        if (!$this->connector){
            throw new \Exception('tally not responding');
        }
    }

    public function createMasters($id){
        TallyListener::$creditorAndDebtors = array();
        $consumerApplication = null;
        $consumerApplication = ConsumerApplication::with('merchant','emi','proFormaInvoice','application_element.disbursedFromBank', 'offer')->where('id',$id)->first();

        if($consumerApplication->permanent_address_line_1) {
            $address = $consumerApplication->permanent_address_line_1 . ' ' . $consumerApplication->permanent_address_state . ' ' . $consumerApplication->permanent_address_city . ' ' . $consumerApplication->permanent_address_landmark . ', ' . $consumerApplication->permanent_address_pincode;
        }else{
            $address = $consumerApplication->current_address_line_1 . ' ' . $consumerApplication->current_address_state . ' ' . $consumerApplication->current_address_city . ' ' . $consumerApplication->current_address_landmark . ', ' . $consumerApplication->current_address_pincode;
        }
        $this->createLedger([
            'id' => $consumerApplication->merchant->id,
            'name' => str_replace('&','',$this->simplyMerchantName($consumerApplication->merchant->merchant_name)),
            'address' => str_replace('&','',$consumerApplication->merchant->address),
            'pincode' => $consumerApplication->merchant->pincode,
            'email' => $consumerApplication->merchant->email,
            'mobile_number' => $consumerApplication->merchant->contact_number,
            'state' => $consumerApplication->merchant->state
        ], 'CR');

        $this->createLedger([
            'id' => $consumerApplication->id,
            'name' => str_replace('&','',$consumerApplication->name),
            'address' => str_replace('&','',$address),
            'pincode' => $consumerApplication->pincode,
            'email' => $consumerApplication->email,
            'mobile_number' => $consumerApplication->mobile_number,
            'state' => ($consumerApplication->permanent_address_state) ? str_replace('&','',$consumerApplication->permanent_address_state) : str_replace('&','',($consumerApplication->current_address_state ? $consumerApplication->current_address_state : ''))
        ], 'DR');


        $this->addEntryInMaster($consumerApplication);

        return $this->response;
    }

    public function addEntryInMaster($consumerApplication){

        TallyListener::$creditorAndDebtors = array();

        $disbursed_date = static::getDisbursedDate($consumerApplication->id);

        $upfront_from_credit_fair = $consumerApplication->emi->upfront_from_credit_fair;

        $processing_fee = $consumerApplication->emi->processing_fee;

        $legal_charges = $consumerApplication->emi->legal_charges;

//        $subvention = ($consumerApplication->approved_amount * $consumerApplication->emi->subvention) / 100;
        $subv = (new ConsumerApplicationController())->getSubventionDetails($consumerApplication, true, true);
        $subvention = $subv['Net'];

        $processing_fee_by_merchant = $consumerApplication->proFormaInvoice->processing_fee_by_merchant;
        if($processing_fee_by_merchant == 1){
            $upfront_from_credit_fair = $upfront_from_credit_fair - $processing_fee;
        }

        if($legal_charges){
            $upfront_from_credit_fair = $upfront_from_credit_fair - $legal_charges;
        }

        $ledgerNameMerchant = $this->simplyMerchantName($consumerApplication->merchant->merchant_name).'-'.$consumerApplication->merchant->id;
        $ledgerNameCustomer = $consumerApplication->name.'-'.$consumerApplication->id;
        $amountCustomer = ($upfront_from_credit_fair + $subvention);
        if ($processing_fee_by_merchant == 1){
            $amountCustomer += $processing_fee;
        }

        if($legal_charges){
            $amountCustomer += $legal_charges;
        }

        if ($subvention > 0) {
            if($consumerApplication->merchant->is_gst) {
                $subvention_gst = $this->getSubventionGSTDetails($consumerApplication, $subvention);

                $sub_gst_amount = 0;
                foreach ($subvention_gst as $gst) {
                    if($gst['gst_amount']) {
                        $sub_gst_amount += round($gst['gst_amount']);
                    }
                }

                foreach ($subvention_gst as $gst) {
                    if($gst['gst_amount']) {
                        TallyListener::setCreditors($gst['taxes'] . ' ON SUBVENTION', round($gst['gst_amount']));
                    }
                }

                $upfront_from_credit_fair -= round($sub_gst_amount);
                TallyListener::setCreditors('Subvention (Advance)', round($subvention));
            }else{
                TallyListener::setCreditors('INTEREST RECEIVED IN ADVANCE', round($subvention));
            }
        }

        /* Deducting the Hold Amount in present from the Net Disbursal amount */
        /*$withheld_percent = LiabilityLog::where('application_id', $consumerApplication->id)->orderBy('created_at', 'desc')->first(['liability_percent']);
        $hold_amount = 0;
        if(isset($withheld_percent->liability_percent) && $withheld_percent->liability_percent){
            $hold_amount = $upfront_from_credit_fair * $withheld_percent->liability_percent/100;
            $upfront_from_credit_fair = round($upfront_from_credit_fair - $hold_amount);
        }*/

        TallyListener::setCreditors($ledgerNameMerchant, round($upfront_from_credit_fair));
        TallyListener::setCreditors('Legal Document Charges', round($legal_charges));

        TallyListener::setDebtors($ledgerNameCustomer, round($amountCustomer));

        if ($processing_fee) {
            if ($processing_fee_by_merchant == 1) {
                $processing_fee_gst = $this->getGSTDetails($processing_fee, $consumerApplication);

                $gst_amount = 0;
                foreach ($processing_fee_gst as $gst) {
                    $gst_amount += round($gst['gst_amount']);
                }

                TallyListener::setCreditors('Processing Fee', round($processing_fee - $gst_amount));
                foreach ($processing_fee_gst as $gst) {
                    TallyListener::setCreditors($gst['taxes'], round($gst['gst_amount']));
                }
                $payment = TallyListener::$creditorAndDebtors;
            } else {
                $payment = TallyListener::$creditorAndDebtors;
                // Processing Fee collected by customer
                $this->createProcessingFeeEntry($processing_fee, $consumerApplication);
            }
        }else{
            $payment = TallyListener::$creditorAndDebtors;
        }

        $narration = 'Amount paid to the ' . $this->simplyMerchantName($consumerApplication->merchant->merchant_name) . ' ' .
            $consumerApplication->merchant->id . '- Customer Name - ' . $consumerApplication->name . ' ' . $consumerApplication->id;

//        if($hold_amount > 0){
//            $narration .= ' - Hold Amount - ' . $hold_amount;
//        }

        $voucher = (object)[
            'id' => $consumerApplication->id,
            'ledger_id' => $consumerApplication->id,
            'name' => $consumerApplication->name,
            'narration' => $narration,
            'date' => date('Ymd',strtotime($disbursed_date)),
            'lender_id' => $consumerApplication->lender_id
        ];

        (new Slack(new Request(['title' => 'Tally Details-JV', 'fields' => ['voucher' => json_encode($voucher)]])))->send();

        $tally = new TallyListener(new Request([
            'voucher' => $voucher,
            'payments' => $payment
        ]));

        $this->response = $tally->createJournalVoucher();

        /* Deducting the Hold Amount from the Net Disbursal amount only in the Payment entry*/
        $withheld_percent = LiabilityLog::where('application_id', $consumerApplication->id)->orderBy('created_at', 'desc')->first(['liability_percent']);
        $hold_amount = 0;
        // Liability amount logic changed as per 6088 ticket
        if(isset($withheld_percent->liability_percent) && $withheld_percent->liability_percent){
            $hold_amount = ($consumerApplication->approved_amount - $consumerApplication->emi->upfront_from_customer) * $withheld_percent->liability_percent/100;
            $upfront_from_credit_fair = round($upfront_from_credit_fair - $hold_amount, 2);
        }

        $this->createDisbursedBankEntry($upfront_from_credit_fair, $consumerApplication, $ledgerNameMerchant, $disbursed_date, $hold_amount);
    }

    public function getSubventionGSTDetails($application, $subvention){
        $subventionGST = (new \App\EMICalculation())->calculateGSTonSubvention($subvention, $application->approved_amount, $application->emi->offer_id, false, $application->id, true);

        return [
            ['taxes' => 'CGST', 'gst_amount' => $subventionGST['subvention_cgst']],
            ['taxes' => 'SGST', 'gst_amount' => $subventionGST['subvention_sgst']],
            ['taxes' => 'IGST', 'gst_amount' => $subventionGST['subvention_igst']]
        ];
    }

    public function createProcessingFeeEntry($processing_fee, $consumerApplication){
        TallyListener::$creditorAndDebtors = array();
        $processing_fee_gst = $this->getGSTDetails($processing_fee, $consumerApplication);

        $gst_amount = 0;
        foreach ($processing_fee_gst as $gst) {
            $gst_amount += round($gst['gst_amount']);
        }

        if ($processing_fee > 0) {
            $disbursed_date = static::getDisbursedDate($consumerApplication->id);
            if($consumerApplication->lender && $consumerApplication->lender->bank_details){
                TallyListener::setDebtors($consumerApplication->name.'-'.$consumerApplication->id, round($processing_fee), [
                    'summary' => [(object)[
                        'INSTRUMENTDATE' => date('Ymd',strtotime($disbursed_date)),
                        'TRANSACTIONTYPE' => $this->getTransactionType('Online Tranfer'),
                        'BANKNAME' => $consumerApplication->lender->bank_details->bank_name,
                        'INSTRUMENTNUMBER' => time(),
                        'PAYMENTMODE' => 'Transacted',
                        'id' => rand(pow(10, 3-1), pow(10, 3)-1),
                        'amount' => round($processing_fee - $gst_amount)
                    ]
                    ]]);
            }

            TallyListener::setCreditors('Processing Fee', round($processing_fee - $gst_amount));
        }

        foreach ($processing_fee_gst as $gst) {
            TallyListener::setCreditors($gst['taxes'], round($gst['gst_amount']));
        }

        if(!isset($disbursed_date)) {
            $disbursed_date = static::getDisbursedDate($consumerApplication->id);
        }

        $voucher = (object)[
            'id' => $consumerApplication->id,
            'ledger_id' => $consumerApplication->id,
            'name' => $consumerApplication->name,
            'narration' => $consumerApplication->name.' '.$consumerApplication->id,
            'date' => date('Ymd',strtotime($disbursed_date))
        ];

        $tally = new TallyListener(new Request([
            'voucher' => $voucher,
            'processing_fee' => TallyListener::$creditorAndDebtors
        ]));

        $this->response = $tally->createJournalVoucher();
    }

    public function createDisbursedBankEntry($amountCustomer, $consumerApplication, $ledgerNameMerchant, $disbursed_date, $hold_amount = 0){
        TallyListener::$creditorAndDebtors = array();
        if ($amountCustomer > 0) {
            if($consumerApplication->lender && $consumerApplication->lender->bank_details){
                TallyListener::setDebtors($consumerApplication->application_element && $consumerApplication->application_element->disbursedFromBank ? $consumerApplication->application_element->disbursedFromBank->bank_name : $consumerApplication->lender->bank_details->bank_name, round($amountCustomer), [
                    'summary' => [(object)[
                        'INSTRUMENTDATE' => date('Ymd',strtotime($disbursed_date)),
                        'TRANSACTIONTYPE' => $this->getTransactionType('Online Tranfer'),
                        'BANKNAME' => $consumerApplication->application_element && $consumerApplication->application_element->disbursedFromBank ? $consumerApplication->application_element->disbursedFromBank->bank_name : $consumerApplication->lender->bank_details->bank_name,
                        'INSTRUMENTNUMBER' => time(),
                        'PAYMENTMODE' => 'Transacted',
                        'id' => rand(pow(10, 3-1), pow(10, 3)-1),
                        'amount' => round($amountCustomer)
                    ]
                    ]]);
            }

            TallyListener::setCreditors($ledgerNameMerchant, round($amountCustomer));

            $narration = 'Amount paid to the ' . $this->simplyMerchantName($consumerApplication->merchant->merchant_name) . ' ' .
                $consumerApplication->merchant->id . '- Customer Name - ' . $consumerApplication->name . ' ' . $consumerApplication->id;

            if($hold_amount > 0){
                $narration .= ' - Hold Amount - ' . $hold_amount;
            }

            $voucher = (object)[
                'id' => $consumerApplication->id /*$consumerApplication->merchant->id*/,
                'ledger_id' => $consumerApplication->merchant->id,
                'name' => $this->simplyMerchantName($consumerApplication->merchant->merchant_name),
                'narration' => $narration,
                'date' => date('Ymd',strtotime($disbursed_date))
            ];

            (new Slack(new Request(['title' => 'Tally Details-Payment', 'fields' => ['voucher' => json_encode($voucher), 'hold_amount' => $hold_amount]])))->send();

            $tally = new TallyListener(new Request([
                'voucher' => $voucher,
                'bank' => TallyListener::$creditorAndDebtors
            ]));

            $this->response = $tally->createPaymentEntry();
        }
    }

    public function createEMIBankEntry($amountCustomer, $consumerApplication, $customerLedger){
        TallyListener::$creditorAndDebtors = array();
        if ($amountCustomer > 0) {
            $disbursed_date = static::getDisbursedDate($consumerApplication->id);
            if($consumerApplication->lender && $consumerApplication->lender->bank_details){
                TallyListener::setDebtors($consumerApplication->lender->bank_details->bank_name, round($amountCustomer), [
                    'summary' => [(object)[
                        'INSTRUMENTDATE' => date('Ymd',strtotime($disbursed_date)),
                        'TRANSACTIONTYPE' => $this->getTransactionType('Online Tranfer'),
                        'BANKNAME' => $consumerApplication->lender->bank_details->bank_name,
                        'INSTRUMENTNUMBER' => time(),
                        'PAYMENTMODE' => 'Transacted',
                        'id' => rand(pow(10, 3-1), pow(10, 3)-1),
                        'amount' => round($amountCustomer)
                    ]
                    ]]);
            }

            TallyListener::setCreditors($customerLedger, round($amountCustomer));

            $voucher = (object)[
                'id' => $consumerApplication->id,
                'ledger_id' => $consumerApplication->id,
                'name' => $consumerApplication->name,
                'narration' => $consumerApplication->name.' '.$consumerApplication->id,
                'date' => date('Ymd',strtotime($consumerApplication->created_at))
            ];

            $tally = new TallyListener(new Request([
                'voucher' => $voucher,
                'bank' => TallyListener::$creditorAndDebtors
            ]));

            $this->response = $tally->createPaymentEntry();
            return $this->response;
        }
    }

    public function createLedger($ledgerData, $sundry){
        $ledger = (object)[
            'id' => $ledgerData['id'],
            'name' => $ledgerData['name'],
            'address' => $ledgerData['address'],
            'pincode' => $ledgerData['pincode'],
            'email' => $ledgerData['email'],
            'state' => $ledgerData['state'],
            'mobile_number' => $ledgerData['mobile_number'],
        ];


        $tally = new TallyListener(new Request([
            'ledger' => $ledger,
            'sundry' => $sundry
        ]));

        $this->response = $tally->createLedger();
    }

    public function getGSTDetails($amount, $consumerApplication, $type = 1){
        return (new ConsumerDocument(new Request()))->getGSTDetails(
            [
                'amount' => $amount,
                'state' => (isset($consumerApplication->permanent_address_state) && !empty($consumerApplication->permanent_address_state)) ? $consumerApplication->permanent_address_state : (isset($consumerApplication->current_address_state) && !empty($consumerApplication->current_address_state) ? $consumerApplication->current_address_state : '')
            ], $type
        );
    }


    public function createEMIEntryV1($paymentsReceived, $application_id, $emiPaymentIDs){
        //return $this->createIncomeLedger($paymentsReceived, $application_id, $emiPaymentIDs);
        TallyListener::$creditorAndDebtors = array();

        $consumerApplication = ConsumerApplication::with('merchant','emi','lender.bank_details')->where('id',$application_id)->first();

        $bounce_charges = 0;
        $delay_penalty = 0;
        $bounce_gst = 0;
        $penal_gst = 0;
        $gstAttributes = ['IGST'=>0,'CGST'=>0,'SGST'=>0];
        $accounting = new AccountingController();
        $viewLoanSchedule = $accounting->viewloanschedule($application_id, 1);
        $schedules = $viewLoanSchedule['schedule'];
        $interestAmount = 0;
        $subventionAmount = 0;
        $emiTransaction = [];
        $totalAmount = 0;

        $customerLedger = $consumerApplication->name.'-'.$consumerApplication->id;

        foreach ($paymentsReceived as $emi_date=>$item) {

            if (isset($item['bounce_charges']) && $item['bounce_charges'] > 0){
                $bounce_charges += round($item['bounce_charges']);
                $bounce_charge_gst =  $this->getGSTDetails($item['bounce_charges'], $consumerApplication);
                if ($bounce_charge_gst){
                    foreach ($bounce_charge_gst as $gst) {
                        $bounce_gst += round($gst['gst_amount']);
                        $gstAttributes[$gst['taxes']] += round($gst['gst_amount']);
                    }
                }
            }
            if (isset($item['penal_interest']) && $item['penal_interest'] > 0){
                $delay_penalty += round($item['penal_interest']);
                $delay_penalty_gst =  $this->getGSTDetails($item['penal_interest'], $consumerApplication);
                if ($delay_penalty_gst){
                    foreach ($delay_penalty_gst as $gst) {
                        $penal_gst += round($gst['gst_amount']);
                        $gstAttributes[$gst['taxes']] += round($gst['gst_amount']);
                    }
                }
            }

            if (isset($item['emi_amount'])) {
                foreach ($schedules as $schedule) {
                    if ($schedule['emi_date'] == $emi_date) {
                        $interest = 0;
                        $subvention = 0;
                        $amountReceived = $item['emi_amount'];
                        if (isset($schedule['transaction']) && $schedule['transaction']) {
                            $interest = $this->getInterest($amountReceived, $schedule);
                            $subvention = $this->getSubvention($amountReceived, $schedule);
                            $emiTransaction = isset($schedule['transaction']) && isset($schedule['transaction'][0]) ? $schedule['transaction'][0] : '';
                        }
                        $interestAmount += $interest;
                        $subventionAmount += $subvention;
                        break;
                    }
                }
            }

            $totalAmount += (isset($item['emi_amount']) ? $item['emi_amount'] : 0 );
        }

        $totalAmount += $bounce_charges + $delay_penalty;

        if ($interestAmount > 0) {
            TallyListener::setCreditors('Interest (Received)', round($interestAmount));
        }

        foreach ($gstAttributes as $tax_type => $amount) {
            if ($amount) {
                TallyListener::setCreditors($tax_type, round($amount));
            }
        }

        if (($bounce_charges - $bounce_gst) > 0 ) {
            TallyListener::setCreditors('Bank Charges', round(($bounce_charges - $bounce_gst)));
        }
        if (($delay_penalty - $penal_gst) > 0) {
            TallyListener::setCreditors('Interest (Late Payment)', round(($delay_penalty - $penal_gst)));
        }

        if (($interestAmount + $bounce_charges + $delay_penalty) > 0){
            TallyListener::setDebtors($customerLedger, (round($interestAmount) + $bounce_charges + $delay_penalty));
        }


        $payments = TallyListener::$creditorAndDebtors;
        TallyListener::$creditorAndDebtors = array();


        /*if ($totalAmount > 0 && $emiTransaction) {
            if($consumerApplication->lender && $consumerApplication->lender->bank_details){
                TallyListener::setDebtors($consumerApplication->lender->bank_details->bank_name, round($totalAmount), [
                    'summary' => [(object)[
                        'INSTRUMENTDATE' => date('Ymd',strtotime($emiTransaction->payment_reconciliation_date ? $emiTransaction->payment_reconciliation_date : $emiTransaction->payment_date)),
                        'TRANSACTIONTYPE' => $this->getTransactionType($emiTransaction->mode),
                        'BANKNAME' => $consumerApplication->lender->bank_details->bank_name,
                        'INSTRUMENTNUMBER' => $emiTransaction->trasanction_id,
                        'PAYMENTMODE' => 'Transacted',
                        'id' => rand(pow(10, 3-1), pow(10, 3)-1),
                        'amount' => round($totalAmount)
                    ]
                    ]]);
            }

            TallyListener::setCreditors($consumerApplication->name.'-'.$consumerApplication->id, round($totalAmount));
        }*/

        $bank = TallyListener::$creditorAndDebtors;
        TallyListener::$creditorAndDebtors = array();


        if ($subventionAmount > 0) {
            TallyListener::setDebtors('Subvention (Advance)', round($subventionAmount));
            TallyListener::setCreditors('Subvention (Income)', round($subventionAmount));
        }

        $voucher = (object)[
            'id' => $consumerApplication->id.'-'.$emiPaymentIDs,
            'ledger_id' => $consumerApplication->id,
            'name' => $consumerApplication->name,
            'narration' => $consumerApplication->name.' '.$consumerApplication->id,
            'date' => date('Ymd',strtotime($emiTransaction->payment_reconciliation_date ? $emiTransaction->payment_reconciliation_date : $emiTransaction->payment_date)),
            'lender_id' => $consumerApplication->lender_id
          ];

        $tally = $this->getTallyListener($voucher, $payments, $bank, TallyListener::$creditorAndDebtors);

        if ($this->request->has('is_auto') && $this->request->get('is_auto'))
            return $tally;

        return $tally->createJournalVoucher();

        //return $this->createEMIBankEntry($totalAmount, $consumerApplication, $customerLedger);
    }

    public function getTallyListener($voucher, $payments, $bank, $creditorAndDebtors){
        $tally = new TallyListener(new Request([
            'voucher' => json_decode(json_encode($voucher)),
            'payments' => ($payments) ? json_decode(json_encode(array_reverse($payments))) : [],
            'bank' => ($bank) ? json_decode(json_encode($bank)) : [],
            'subvention' => json_decode(json_encode($creditorAndDebtors))
        ]));

        return $tally;
    }

    public function createEMIEntry($payment){
        $accounting = new AccountingController();
        $viewLoanSchedule = $accounting->viewloanschedule($payment->application_id, 1);
        $consumerApplication = ConsumerApplication::with('merchant','emi','lender.bank_details')->where('id',$payment->application_id)->first();

        $schedule = $viewLoanSchedule['schedule'];
        $emiTransaction = [];
        $totalAmount = 0;
        $emi_amount = 0;
        foreach ($schedule as $item){

                foreach ($item['transaction'] as $transaction){
                    $emi_amount += $transaction->amount;

                    if ($item['payment'] == $transaction->amount){
                        $emiTransaction = $transaction;
                    }
                }

                if ($item['interest'] > 0){
                    TallyListener::setCreditors('Interest (Received)', round($item['interest'],2));
                    $totalAmount += round($item['interest'], 2);
                }
                if ($item['bounce_charges'] > 0){
                    $totalAmount += round($item['bounce_charges'],2);
                    $bounce_charge_gst =  $this->getGSTDetails($item['bounce_charges'], $consumerApplication);
                    $bounce_charge_gst_amount = 0;
                    if ($bounce_charge_gst){
                        foreach ($bounce_charge_gst as $gst) {
                            TallyListener::setCreditors($gst['taxes'], $gst['gst_amount']);
                            $bounce_charge_gst_amount += $gst['gst_amount'];
                        }
                    }

                    TallyListener::setCreditors('Bank Charges', round(($item['bounce_charges'] - $bounce_charge_gst_amount),2));
                }
                if ($item['delay_penalty'] > 0){
                    $totalAmount += round($item['delay_penalty'],2);
                    $delay_penalty_gst =  $this->getGSTDetails($item['delay_penalty'], $consumerApplication);
                    $delay_penalty_gst_amount = 0;
                    if ($delay_penalty_gst){
                        foreach ($delay_penalty_gst as $gst) {
                            TallyListener::setCreditors($gst['taxes'], $gst['gst_amount']);
                            $delay_penalty_gst_amount += $gst['gst_amount'];
                        }
                    }

                    TallyListener::setCreditors('Interest (Late Payment)', round(($item['delay_penalty'] - $delay_penalty_gst_amount),2));
                }
        }

        if ($totalAmount > 0){
            TallyListener::setDebtors($consumerApplication->name.'-'.$consumerApplication->id, $totalAmount);
        }


        $payments = TallyListener::$creditorAndDebtors;
        TallyListener::$creditorAndDebtors = array();


        if ($emi_amount > 0 && $emiTransaction) {
            if($consumerApplication->lender && $consumerApplication->lender->bank_details){
                TallyListener::setDebtors($consumerApplication->lender->bank_details->bank_name, $emi_amount, [
                    'summary' => [(object)[
                        'INSTRUMENTDATE' => date('Ymd',strtotime($emiTransaction->payment_date)),
                        'TRANSACTIONTYPE' => $this->getTransactionType($emiTransaction->mode),
                        'BANKNAME' => 'Yes Bank',
                        'INSTRUMENTNUMBER' => $emiTransaction->trasanction_id,
                        'PAYMENTMODE' => 'Transacted',
                        'id' => rand(pow(10, 3-1), pow(10, 3)-1),
                        'amount' => $emi_amount
                    ]
                ]]);
            }

            TallyListener::setCreditors($consumerApplication->name.'-'.$consumerApplication->id, $emi_amount);
        }

        $voucher = (object)[
            'id' => $consumerApplication->id,
            'name' => $consumerApplication->name,
            'narration' => $consumerApplication->name.' '.$consumerApplication->id
        ];

        $tally = new TallyListener(new Request([
            'voucher' => $voucher,
            'payments' => array_reverse($payments),
            'bank' => TallyListener::$creditorAndDebtors
        ]));

        $tally->createJournalVoucher();
    }

    public function getSubvention($amountReceived, $schedule){
        if ($amountReceived < $schedule['amount']) {
            $subvention = ($amountReceived / $schedule['amount']) * $schedule['subvention'];
        } else if ($amountReceived > $schedule['amount']) {
            $remaining = ($amountReceived - $schedule['amount']);
            $subvention = ($remaining / $schedule['amount']) * $schedule['subvention'];
            $subvention += $schedule['subvention'];
        } else {
            $subvention = $schedule['subvention'];
        }

        return $subvention;
    }

    public function getInterest($amountReceived, $schedule){
        if ($amountReceived < $schedule['amount']) {
            $interest = ($amountReceived / $schedule['amount']) * $schedule['interest'];
        } else if ($amountReceived > $schedule['amount']) {
            $remaining = ($amountReceived - $schedule['amount']);
            $interest = ($remaining / $schedule['amount']) * $schedule['interest'];
            $interest += $schedule['interest'];
        } else {
            $interest = $schedule['interest'];
        }

        return $interest;
    }

    public function getTransactionType($type){

        switch ($type){
            case 'CASH DEP':
                return 'Cash';
                break;
            case 'Cheque/DD':
                return 'Cash';
                break;
            case 'NACH-HDFC':
            case 'NACH-LOTUS':
            case 'NACH-RBL':
            return 'ECS';
                break;
            case 'Online Tranfer':
            case 'Razorpay':
            case 'UPI':
            return 'Inter Bank Transfer';
                break;
            default:
                return 'Inter Bank Transfer';
                break;
        }
    }

    public static function getDisbursedDate($id){
        $status = StatusLogs::where('application_id',$id)
            ->where('status','disbursed')
            ->orderBy('id','desc')->first(['created_at']);

        return isset($status->created_at) ? $status->created_at : '';
    }


    public function createIncomeLedger($paymentsReceived, $application_id, $emiPaymentIDs){

        TallyListener::$creditorAndDebtors = array();

        $consumerApplication = ConsumerApplication::with('merchant','emi','lender.bank_details')->where('id',$application_id)->first();

        if(!isset(TallyJobsListener::$schedule[$application_id])) {
            $accounting = new AccountingController();
            $viewLoanSchedule = $accounting->viewloanschedule($application_id, 1);
            TallyJobsListener::$schedule[$application_id] = $viewLoanSchedule;
        }else{
            $viewLoanSchedule = TallyJobsListener::$schedule[$application_id];
        }
        $schedules = $viewLoanSchedule['schedule'];
        $interestAmount = 0;
        $subventionAmount = 0;
        $emiTransaction = [];

        $customerLedger = $consumerApplication->name.'-'.$consumerApplication->id;

        foreach ($paymentsReceived as $emi_date=>$item) {

            if (isset($item['emi_amount'])) {
                foreach ($schedules as $schedule) {
                    if ($schedule['emi_date'] == $emi_date) {
                        $interest = 0;
                        $subvention = 0;
                        $amountReceived = $item['emi_amount'];
                        if (isset($schedule['transaction']) && $schedule['transaction']) {
                            $interest = $this->getInterest($amountReceived, $schedule);
                            $subvention = $this->getSubvention($amountReceived, $schedule);
                            $emiTransaction = isset($schedule['transaction']) && isset($schedule['transaction'][0]) ? $schedule['transaction'][0] : '';
                        }
                        $interestAmount += $interest;
                        $subventionAmount += $subvention;
                        break;
                    }
                }
            }
        }

        if ($interestAmount > 0) {
            TallyListener::setCreditors('Interest (Received)', round($interestAmount));
            TallyListener::setDebtors($customerLedger, (round($interestAmount)));
        }

        $interestLedger = TallyListener::$creditorAndDebtors;

        if ($subventionAmount > 0) {
            TallyListener::setDebtors('Subvention (Advance)', round($subventionAmount));
            TallyListener::setCreditors('Subvention (Income)', round($subventionAmount));
        }

        $subventionLedger = TallyListener::$creditorAndDebtors;

        $voucher = (object)[
            'id' => $consumerApplication->id.'-'.$emiPaymentIDs,
            'ledger_id' => $consumerApplication->id,
            'name' => $consumerApplication->name,
            'narration' => $consumerApplication->name.' '.$consumerApplication->id,
            'date' => date('Ymd',strtotime($emi_date)), //$emiTransaction->payment_reconciliation_date
            'lender_id' => $consumerApplication->lender_id
        ];

        $tally = new TallyListener(new Request([
            'voucher' => json_decode(json_encode($voucher)),
            'payments' =>json_decode(json_encode($interestLedger)),
            'subvention' => json_decode(json_encode($subventionLedger))
        ]));

        return $tally->createJournalVoucher();

        //return $this->createEMIBankEntry($totalAmount, $consumerApplication, $customerLedger);
    }

    private function simplyMerchantName($name){
        return preg_replace("/\s*\(.*?\)/", "", $name);
    }
}
