<?php
/**
 * Created by PhpStorm.
 * User: sunil
 * Date: 12/11/18
 * Time: 2:02 PM
 */

namespace App\Imports;

use App\BulkPayments;
use App\Console\Commands\TallyBridge;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\LoanManagement;
use App\Mandate;
use App\MandateLogs;
use App\PaymentTransaction;
use App\ProFormaInvoice;
use App\Settlement;
use App\Slack;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToCollection;

class PaymentFile
{
    private $request;

    private $reasons = [
        1 => 'Account Closed',
        2 => 'No Such Account',
        4 => 'Balance Insufficient',
        5 => 'Not Arranged For/Amount Exceeding Limit set by A/c Holder',
        6 => 'Payment Stopped by Drawer',
        7 => 'Payment Stopped Under Court Order/Account Under Litigation',
        11 => 'Invalid IFSC/MICR code',
        12 => 'Mismatch in mandate frequency',
        13 => 'Duplicate transaction - transaction already debited either under ACh or NACH debit(ECS)',
        14 => 'Mandate Expired',
        15 => 'Incorrect amount-Mismatch between mandate & transaction',
        16 => 'Customer Name Mismatch',
        17 => 'Returned as per customer request',
        51 => 'Miscellaneous - KYC Documents Pending',
        52 => 'Miscellaneous - Documents Pending for Account Holder Turning Major',
        53 => 'Account inoperative',
        54 => 'Dormant account',
        55 => 'Miscellaneous - A/c in Zero Balance/No Transactions have Happened, First Transaction in Cash or Self Cheque',
        56 => 'Small Account, first transaction to be from Base Branch',
        57 => 'Miscellaneous - Amount exceeds limit set on account by bank for debit per transaction',
        58 => 'Miscellaneous - Account reached maximum debit limit set on account by bank',
        59 => 'Miscellaneous - Network Failure (CBS)',
        60 => 'Account Holder Expired',
        61 => 'Mandate Cancelled',
        68 => 'Account Blocked / Frozen',
        69 => 'Customer Insolvent / Insane',
        70 => 'Customer to refer to the Branch',
        95 => 'INITIAL REJECT',
        98 => 'Pending' // manually added
    ];

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

    public function collection($data)
    {
        $consumerApplication = new ConsumerApplicationController();
        // TODO: Implement collection() method.
        //$data = $collection->toArray();
        $payment_date = Carbon::parse($this->request->get('emi_date'))->toDateString();
        $payment_reconciliation_date = Carbon::parse($this->request->get('payment_reconciliation_date'))->toDateString();
        $totalAmountReceived = 0;
        $tallyData = [];

        $payment_date_with_time = Carbon::parse($this->request->get('emi_date'))->startOfDay()->toDateTimeString();

        (new Slack(new Request(['title' => 'Bulk ID summary', 'fields' => ['data_count' => count($data), 'request' => json_encode($this->request->all())], 'group' => Slack::$STAGE_TESTING])))->send();


        if ($this->request->get('bank_name') == 1) {
            foreach ($data as $item) {

                try {
                    $PaymentEmi = new LoanManagement();
                    $execution_status = [];
                    $communicationData = [];
                    $bulk_payment_id = isset($item['bulk_payment_id']) ? $item['bulk_payment_id'] : 0;
                    $item = isset($item['item']) ? $item['item'] : $item;

                    $status = ($item[13] == 1) ? 'success' : (($item[13] == 3) ? 'pending' : (($item[14] == 95) ? 'initial_reject' : 'rejected'));
                    $application_id = $this->getApplicationID($item[22], $item[19]);
                    $execution_status['status'] = $status;
                    if (!empty($item[22]) && $this->isProcessed($item[10], $item[22], $payment_date_with_time, $status, $application_id)) {
                        if ($application_id > 0) {
                            $reason = $this->getReason($item[14]);
                            $paymentReconcileData = [
                                'mode' => 7,
                                'paid_by' => '',
                                'application_id' => $application_id,
                                'bank_id' => $this->request->get('bank_name'),
                                'umrn' => $item[22],
                                'collected_by' => 107,
                                'trasanction_id' => $item[19],
                                'wallet_name' => '',
                                'payment_date' => $payment_date,
                                'payment_reconciliation_date' => $payment_reconciliation_date,
                                'amount' => $item[10],
                                'status' => $status,
                                'reason' => $reason,
                                'trasanction_acknowledgement' => $this->request->get('file_path'),
                                'online_payment_id' => ''
                            ];
                            $communicationData = $PaymentEmi->paymentReconcile($paymentReconcileData);
                            $execution_status['reconciled'] = 1;
                            if ($status == 'success') {
                                $tallyData[] = $paymentReconcileData;
                                $totalAmountReceived += (int)$item[10];
                            }

                            $this->saveMandateLogs($item[8], [$item[10], $reason, $status]);

                        } else {
                            $this->mismatchedPayment($item, $payment_date, 0, $consumerApplication);
                            $execution_status['mismatch'] = 1;
                        }
                    } else {
                        $execution_status['already_processed'] = 1;
                    }

                    if ($bulk_payment_id) {
//                        BulkPayments::where('id', $bulk_payment_id)->update(['execution_status' => json_encode($execution_status), 'communication' => 0, 'communication_data' => json_encode($communicationData ?? [])]);
                        BulkPayments::where('id', $bulk_payment_id)->update(['execution_status' => json_encode($execution_status), 'communication' => 0, 'communication_data' => '[]']);
                    } else {
                        (new Slack(new Request(['title' => 'Bulk ID error', 'fields' => ['data' => json_encode($item)], 'group' => Slack::$STAGE_TESTING])))->send();
                    }
                }catch (\Exception $exception){
                    (new Slack(new Request(['title' => 'Payment upload error', 'fields' => ['e' => $exception->getMessage(),'l' => $exception->getLine(),'t' => $exception->getTraceAsString(),'item' => isset($item) ? $item : '', 'payment_date' => $payment_date, 'payment_reconciliation_date' => $payment_reconciliation_date], 'group' => 'payment_collection'])))->send();
                }
            }
        } else {
            foreach ($data as $item) {
                try {
                    $PaymentEmi = new LoanManagement();
                    $execution_status = [];
                    $communicationData = [];
                    $bulk_payment_id = isset($item['bulk_payment_id']) ? $item['bulk_payment_id'] : 0;
                    $item = isset($item['item']) ? $item['item'] : $item;

                    $status = ($item[12] == 'PAID') ? 'success' : (($item[12] == 'BANK EXTENSION') ? 'pending' : 'rejected');
                    $application_id = $this->getApplicationID($item[8]);
                    $execution_status['status'] = $status;
                    if (!empty($item[8]) && $this->isProcessed($item[6], $item[8], $payment_date_with_time, $status, $application_id)) {
                        if ($application_id > 0) {
                            $paymentReconcileData = [
                                'mode' => 7,
                                'paid_by' => '',
                                'application_id' => $application_id,
                                'bank_id' => $this->request->get('bank_name'),
                                'umrn' => $item[8],
                                'collected_by' => 107,
                                'trasanction_id' => '',
                                'wallet_name' => '',
                                'payment_date' => $payment_date,
                                'payment_reconciliation_date' => $payment_reconciliation_date,
                                'amount' => $item[6],
                                'status' => $status,
                                'reason' => $item[12],
                                'trasanction_acknowledgement' => $this->request->get('file_path'),
                                'online_payment_id' => ''
                            ];
                            $communicationData = $PaymentEmi->paymentReconcile($paymentReconcileData);
                            $execution_status['reconciled'] = 1;
                            if ($status == 'success') {
                                $tallyData[] = $paymentReconcileData;
                                $totalAmountReceived += (int)$item[6];
                            }

                        } else {
                            $this->mismatchedPayment($item, $payment_date, 1, $consumerApplication);
                            $execution_status['mismatch'] = 1;
                        }
                    } else {
                        $execution_status['already_processed'] = 1;
                    }

                    if ($bulk_payment_id) {
//                        BulkPayments::where('id', $bulk_payment_id)->update(['execution_status' => json_encode($execution_status), 'communication' => 0, 'communication_data' => json_encode($communicationData)]);
                        BulkPayments::where('id', $bulk_payment_id)->update(['execution_status' => json_encode($execution_status), 'communication' => 0, 'communication_data' => '[]']);
                    } else {
                        (new Slack(new Request(['title' => 'Bulk ID error', 'fields' => ['data' => json_encode($item)], 'group' => Slack::$STAGE_TESTING])))->send();
                    }
                }catch (\Exception $exception){
                    (new Slack(new Request(['title' => 'Payment upload error', 'fields' => ['e' => $exception->getMessage(),'l' => $exception->getLine(),'t' => $exception->getTraceAsString(),'item' => isset($item) ? $item : '', 'payment_date' => $payment_date, 'payment_reconciliation_date' => $payment_reconciliation_date], 'group' => 'payment_collection'])))->send();
                }
            }
        }

        if($totalAmountReceived && $tallyData){
            Settlement::import(['data' => $tallyData, 'settled_amount' => $totalAmountReceived, 'payment_date' => $payment_date, 'reconciliation_date' => $payment_reconciliation_date, 'type' => 'nach']);
        }


        /*try {


        }catch (\Exception $exception){
            (new Slack(new Request(['title' => 'Payment upload error', 'fields' => ['e' => $exception->getMessage(),'l' => $exception->getLine(),'t' => $exception->getTraceAsString(),'item' => isset($item) ? $item : '', 'payment_date' => $payment_date, 'payment_reconciliation_date' => $payment_reconciliation_date], 'group' => 'payment_collection'])))->send();
        }*/
    }

    public function mismatchedPayment($item, $payment_date, $type, ConsumerApplicationController $consumerApplication){
        //send mismatched payments to slack
        if($type == 0){
            $data = [
                'bank' => 'HDFC',
                'umrn' => $item[22],
                'payment_date' => $payment_date,
                'amount' => $item[10],
                'name' => $item[5],
                'status' => ($item[13] == 1) ? 'success' : 'rejected',
                'reason' => $this->getReason($item[14]),
            ];
        }else{
            $data = [
                'bank' => 'RBL',
                'umrn' => $item[8],
                'payment_date' => $payment_date,
                'amount' => $item[6],
                'name' => $item[5],
                'status' => ($item[12] == 'PAID') ? 'success' : 'rejected',
                'reason' => $item[12]
            ];
        }

        $consumerApplication->sendslackmessage(0,'mismatchedPayment',$data);
    }

    public function isProcessed($amount, $umrn, $payment_date, $status, $application_id){
        $payment = PaymentTransaction::where('application_id', $application_id)->where('payment_date',$payment_date)->where('umrn',$umrn)->whereNull('is_deleted_at')->first(['id','status']);
        return (isset($payment->id) && strtolower($payment->status) == strtolower($status)) ? false : true;
    }

    public function getReason($code){
        return isset($this->reasons[$code]) ? $this->reasons[$code] : '';
    }

    public function getApplicationID($umrn, $reference_id = null){
        if ($reference_id) {
            $ProFormaInvoice = ProFormaInvoice::where('loan_application_no', $reference_id)->get(['id', 'loan_application_no','application_id']);
        }
        if (isset($ProFormaInvoice) && $ProFormaInvoice && count($ProFormaInvoice) == 1){
            $mandate = Mandate::where('consumer_application_id', $ProFormaInvoice[0]->application_id)->where('umrn',$umrn)->first();
        }else{
            $mandate = Mandate::where('umrn',$umrn)->first();
        }

        return isset($mandate->consumer_application_id) ? $mandate->consumer_application_id : 0;
    }

    public function saveMandateLogs($umrn, $data){
        $previousMandateData = Mandate::where('umrn',$umrn)->first();
        if(isset($previousMandateData->id) && $previousMandateData->mandate_amount != $data[0]) {
            Mandate::where('umrn',$umrn)->update(['mandate_amount' => $data[0]]);
            (new MandateLogs())->lockPrevious($previousMandateData, $previousMandateData->id, new Request(['mandate_amount' => $data[0], 'reason' => $data[1], 'status' => $data[2]]));
        }
    }
}
