<?php
/**
 * Created by PhpStorm.
 * User: sunil
 * Date: 16/11/18
 * Time: 11:56 AM
 */

namespace App\Http\Controllers\Couriers;


use App\ConsumerApplication;
use App\Couriers;
use App\Exports\Exporter;
use App\Exports\ExporterMultipleSheet;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\Http\Controllers\Controller;
use App\Mandate;
use App\Merchant;
use App\StatusLogs;
use App\User;
use Carbon\Carbon;
use function GuzzleHttp\Psr7\str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;

class CouriersController extends Controller
{
    private $request;
    public $isNachStatus = false;
    public $isActionDateFilter = false;
    private $isSendMail = false;
    private $queueable = true;
    private $sendApplications = [];

    public function __construct(Request $request){

        $this->request = $request;
    }


    public function getCouriers(){
        $from_date = ($this->request->has('from_date') && !empty($this->request->get('from_date'))) ? Carbon::createFromFormat('Y-m-d',$this->request->get('from_date'))->startOfDay()->toDateTimeString() : Carbon::now()->startOfDay()->toDateTimeString();
        $to_date = ($this->request->has('to_date') && !empty($this->request->get('to_date'))) ? Carbon::createFromFormat('Y-m-d',$this->request->get('to_date'))->endOfDay()->toDateTimeString() : Carbon::now()->endOfDay()->toDateTimeString();
        $data['from_date'] = date('Y-m-d',strtotime($from_date));
        $data['to_date'] = date('Y-m-d',strtotime($to_date));
        $couriers = Couriers::with('sender','recipient')->where('created_at','>=',$from_date)
            ->where('created_at','<=',$to_date)
            ->get();
        $data['couriers'] = $couriers;
        return view('admin.courier.index', $data);
    }

    public function addCouriers(){
        $data['receipts'] = User::where('user_type','>=',5)->get();
        return view('admin.courier.edit', $data);
    }

    public function getLists(){
        $id = $this->request->get('id');
        $name = $this->request->get('name');
        $ul_id = $this->request->get('ul_id');
        $options = '<ul>';
        if($id == 2) {
            $data = ConsumerApplication::whereNull('is_deleted')->where('name','LIKE','%'.$name.'%')->orderBy('created_at','desc')->get();
            foreach ($data as $item){
                $options .= '<li data-id="'.$ul_id.'" class="select_company_list" value="'.$item->id.'">'.$item->name. '('.$item->email.')'.'</li>';
            }
            $options .= '</ul>';
        }elseif($id == 3) {
            $data = User::where('name','LIKE','%'.$name.'%')->where('user_type','>=',5)->orderBy('created_at','desc')->get();
            foreach ($data as $item){
                $options .= '<li data-id="'.$ul_id.'" class="select_company_list" value="'.$item->id.'">'.$item->name. '('.$item->email.')'.'</li>';
            }
            $options .= '</ul>';
        }else{
            $data = Merchant::where('merchant_name','LIKE','%'.$name.'%')->get();
            foreach ($data as $item){
                $options .= '<li data-id="'.$ul_id.'" class="select_company_list" value="'.$item->id.'">'.$item->merchant_name.'</li>';
            }
            $options .= '</ul>';
        }

        return response()->json(['options'=>$options],200);
    }

    public function acceptCourier($id){
        $data['receipts'] = User::where('user_type','>=',5)->get();
        $data['courier'] = Couriers::find($id);
        return view('admin.courier.edit', $data);
    }

    public function saveCouriers(){


        $courier = [
            'courier_company' => $this->request->get('courier_company'),
            'tracking_id' => $this->request->get('tracking_id'),
            'website' => $this->request->get('website'),
            'recipient_id' => $this->request->get('recipient_id'),
            'couriered_at' => $this->request->get('couriered_at'),
            'documents' => $this->request->has('couriers') && $this->request->get('couriers') ? $this->request->get('couriers') : [],
            'user_id' => Auth::user()->id,
            'created_at' => Carbon::now()->toDateTimeString(),
        ];

        if($this->request->has('_get_request')){
            try {
                $courier['recipient_name'] = User::find($courier['recipient_id'])->name;
                $courier['sender_name'] = Auth::user()->name;
                return response()->json($courier, 200);
            }catch (\Exception $e){
                return response()->json(['status'=>'FAIL'], 200);
            }
        }

        $id = Couriers::insertGetId($courier);


        if($this->request->hasFile('receipt_ack')){
            $receipt_ack = $this->request->file('receipt_ack');
            $s3 = Storage::disk('s3');
            $file_path = '/couriers/'.$id;
            $s3->put($file_path, $receipt_ack);
            $files = $s3->listContents($file_path);
            $courier = Couriers::find($id);
            $courier->receipt_ack = $files[0]['path'];
            $courier->save();
        }

        \Session::flash('success', 'Courier created successfully');
        return redirect()->back();
    }

    public function receivedCourier($id){
        $documents =  $this->request->get('document_id');
        $received_quantity = $this->request->get('received_quantity');
        $is_received = $this->request->get('is_received');
        $data = [];
        foreach ($documents as $key=>$document_id){
            $data[$document_id] = array(
                'document_id' => $document_id,
                'is_received' => (isset($is_received[$document_id]) && $is_received[$document_id][0] && $is_received[$document_id][0] == 'on') ? 1 :0,
                'document_count' => (isset($received_quantity[$document_id]) && isset($received_quantity[$document_id][0])) ? $received_quantity[$document_id][0] : 0
            );
        }

        if($data){
            $courier = Couriers::find($id);
            $courier->received_by = Auth::user()->id;
            $courier->received_document = ($data) ? json_encode($data) : [];
            $courier->save();
        }

        \Session::flash('success', 'Courier received successfully');
        return redirect()->to('/admin/couriers');
    }

    public function getCourier($id, $type, $couriers = array()){
        $couriersData = [];
        $response = [];

        if ($this->isActionDateFilter){
            $couriers = Couriers::where('created_at','>=',$this->request->get('from_date'))->where('created_at','<=',$this->request->get('to_date'))->get();
        }

        $couriers = ($couriers) ? $couriers : Couriers::get();
        foreach($couriers as $courier){
            $documents = json_decode($courier->documents);
            if($documents){
                $couriersData = [];
                $listDocument = [];
                foreach ($documents as $document){
                    if($document->document_for == $type && $document->document_for_id == $id){
                        if($this->isNachStatus && $document->document == 'nach'){
                            return ['courier_sent'=>$courier->id, 'courier_received'=>$courier->received_by, 'created_at'=>$courier->created_at];
                        }
                        $listDocument[] = $document;
                        $couriersData = $courier;
                    }
                }
                if($listDocument){
                    $courier->documents = json_encode($listDocument);
                }
            }
            if($couriersData) {
                $response[] = $couriersData;
            }
        }
        return $response;
    }

    public function getYesterdaysDisbursements(){
        $applications = ConsumerApplication::whereHas('logs', function($query){
                $query->where('status','disbursed');
        })->whereIn('state',['disbursed','nach register'])->whereNull('is_deleted')->groupBy('id')->get(['id']);

        $data = [];
        if($applications) {
            foreach ($applications as $application) {

                $mandate = Mandate::where('consumer_application_id',$application->id)->first();
                if(isset($mandate->id)) {
                    if(empty($mandate->umrn)) {
                        $data[] = $application->id;
                    }
                }else{
                    $data[] = $application->id;
                }
            }
        }

        $logs = StatusLogs::whereIn('application_id',$data)->where('status','disbursed')->get();
        $now = Carbon::now();
        $data = [];
        foreach ($logs as $log){
            $date = Carbon::parse($log->created_at);
            if($date->diffInDays($now) >= 3){
                $data[] = $log->application_id;
            }
        }
        return array_unique($data);
    }

    public function NACHStatus($application_id, $type = false){
        $nachStatus = '';
        $this->isNachStatus = true;
        $this->isSendMail = $type;


        $couriers = [];
        if($type) {
            $applications = $this->getYesterdaysDisbursements();
            if ($applications) {
                $couriers = Couriers::get();
            }
        } else {
            $applications[] = $application_id;
        }


        foreach ($applications as $application){
            $courierStatus = $this->getCourier($application, 2, $couriers);
            $nachType = $this->checkNachInitiated($application, $courierStatus, true);
            if($nachType != false){
                $nachStatus = $nachType;
            }elseif(isset($courierStatus['courier_received']) && $courierStatus['courier_received']){
                $nachStatus = 'Couriered Received';
            }elseif(isset($courierStatus['courier_sent']) && $courierStatus['courier_sent']){
                $this->courierNotReceived($courierStatus, $application);
                $nachStatus = 'Couriered';
            }elseif(!isset($courierStatus['courier_sent'])){
                $this->courierNotSent($application);
                $nachStatus = 'Courier Not Sent';
            }
        }

        return ($type) ? $this->sendNachReminder() : $nachStatus;
    }

    public function sendNachReminder(){
        $file = time().'_'.Carbon::now()->toDateTimeString().'_Nach_Status.xlsx';
        $this->getAttachment($file);

        Mail::send('emails.reminders.nach_reminder',
            ['applications'=>$this->sendApplications]
            , function ($message) use ($file) {
                $message->to('collections@creditfair.in')->subject('Nach Status Reminder');
                $message->cc(['mithila@kmglobal.in', 'snehagangawane@creditfair.in']);
//                $message->cc(['mithila@kmglobal.in','mehul@creditfair.in','payments@creditfair.in', 'snehagangawane@creditfair.in']);
                $message->attachData(file_get_contents(storage_path().'/app/'.$file), 'Nach Status Reminder '.Carbon::now()->toDateTimeString().'.xlsx');
            });

        if(file_exists(storage_path().'/app/'.$file)){
            unlink(storage_path().'/app/'.$file);
        }
        return $this->queueable;
    }

    public function getAttachment($file){
        $request = new Request([
            'sheet' => ['Nach Status','Nach Submitted','Courier Status'],
            'data'  => $this->getApplicationsArraySheets()
        ]);
        Excel::store(new ExporterMultipleSheet($request), $file);
    }

    public function getApplicationsArraySheets(){
        $data = $this->getApplicationsArray();

        $CourierResponse = [];
        $NachResponse = [];
        $NachSubmittedResponse = [];
        foreach ($data as $index=>$item){
            if (isset($item['nach_status']) && in_array($item['nach_status'], ['Courier Not Sent', 'Couriered Received', 'Couriered'])){
                $CourierResponse[] = $item;
            }else if (isset($item['nach_status']) && in_array($item['nach_status'], ['Nach is Submitted'])){
                $NachSubmittedResponse[] = $item;
            }else if (isset($item['nach_status'])){
                $NachResponse[] = $item;
            }

            if ($index == 0){
                //for headers
                $CourierResponse[] = $item;
                $NachResponse[] = $item;
            }
        }

        return [$NachResponse, $NachSubmittedResponse, $CourierResponse];
    }

    public function getApplicationsArray(){
        $consumerDocument = new ConsumerDocument(new Request());
        foreach ($this->sendApplications as $merchant_name=>$applicationData){
            foreach ($applicationData as $applicationItem) {
                $application = $applicationItem['applications'];

                $disbursed_date = $consumerDocument->getDisbursedDate($application->id);

                $days_of_pendency = '';

                if ($disbursed_date) {
                    $date = Carbon::parse($disbursed_date);
                    $days_of_pendency = $date->diffInDays(Carbon::now());
                }

                $data[] = [
                    'name' => $application->name,
                    'approved_amount' => $application->approved_amount,
                    'tenure' => $application->tenure,
                    'phone' => $application->mobile_number,
                    'email' => $application->email,
                    'merchant_name' => $merchant_name,
                    'advisor' => ($application->advisor) ? $application->advisor->name : '',
                    'center' => isset($application->application_element->merchant_center->name) ? $application->application_element->merchant_center->name : '',
                    'nach_status' => $applicationItem['type'],
                    'disbursed_date' => $disbursed_date,
                    'emi_date' => ($application->emi) ? $application->emi->emi_date : '',
                    'bank' => ($application->bank_details) ? $application->bank_details->bank_name : '',
                    'lender' => ($application->lender) ? $application->lender->name : '',
                    'days_of_pendency' => $days_of_pendency
                ];
            }
        }

        usort($data, function($a, $b) {
            return new \DateTime($a['disbursed_date']) <=> new \DateTime($b['disbursed_date']);
        });

        $response[] = ['Name','Approved Amount','Tenure','Phone','Email','Merchant Name','Advisor','Center Name','Nach Status','Disbursed Date','EMI Date','Bank Name','Lender Name', 'Days of Pendency'];
        $response = array_merge($response, $data);
        return $response;
    }

    public function checkNachInitiated($application_id, $isNachReceived, $type = false){
        $mandateCheck = Mandate::where('consumer_application_id',$application_id)->get(['id','status','umrn']);

        if($mandateCheck) {
            $mandatesStatus = [];
            foreach ($mandateCheck as $item) {
                $mandatesStatus[] = $item->status;
            }
            if($mandatesStatus){
                if(in_array('active', $mandatesStatus)){
                    return 'active';
                }else if(in_array('submitted', $mandatesStatus)){
                    $this->sendReminderEmail('submitted', $application_id);
                    return 'submitted';
                }else if(in_array('pending', $mandatesStatus)){
                    return 'pending';
                }else if(in_array('rejected', $mandatesStatus)){
                    $this->sendReminderEmail('rejected', $application_id);
                    return 'rejected';
                }else if(in_array('COMPLETED', $mandatesStatus)){
                    return 'Completed';
                }else if(in_array('REJECTED', $mandatesStatus)){
                    $this->sendReminderEmail('rejected', $application_id);
                    return 'rejected';
                }else if(in_array('PENDING', $mandatesStatus)){
                    return 'pending';
                }
            }
        }
        if(isset($isNachReceived['created_at'])){
            $date = Carbon::parse($isNachReceived['created_at']);
            $now = Carbon::now();
            if($date->diffInDays($now) > 3){
                $this->sendReminderEmail('nachInitiated', $application_id);
            }
        }

        return false;
    }

    public function courierNotReceived($isNachReceived, $application_id){
        if(isset($isNachReceived[3])){
            $date = Carbon::parse($isNachReceived[3]);
            $now = Carbon::now();
            if($date->diffInDays($now) > 6){
                $this->sendReminderEmail('courierNotReceived', $application_id);
            }
        }
    }

    public function courierNotSent($application_id){
        $statusLogs = StatusLogs::where('application_id',$application_id)->where('status','disbursed')->first(['created_at','id']);
        if(isset($statusLogs->id)){
            $date = Carbon::parse($statusLogs->created_at);
            $now = Carbon::now();
            if($date->diffInDays($now) >= 3){
                $this->sendReminderEmail('courierNotSent', $application_id);
            }
        }
    }

    public function sendReminderEmail($type, $application_id){
        if($this->isSendMail) {
            $subject = '';
            switch ($type) {
                case 'nachInitiated':
                    $subject = 'Nach is not initiated';
                    break;
                case 'courierNotReceived':
                    $subject = 'Courier Not Received';
                    break;
                case 'courierNotSent':
                    $subject = 'Courier Not Sent';
                    break;
                case 'rejected':
                    $subject = 'Nach is Rejected';
                    break;
                case 'submitted':
                    $subject = 'Nach is Submitted';
                    break;
            }

            if ($subject) {
                $application = ConsumerApplication::with('merchant','advisor','application_element.merchant_center','emi','bank_details','lender')->where('id',$application_id)->first();
                if(isset($application->merchant->merchant_name) && $application->merchant->merchant_name) {
                    $this->sendApplications[$application->merchant->merchant_name][] = ['applications' => $application, 'type' => $subject];
                }
                //$this->sendMail($subject, $application);
            }
        }
    }

    public function sendMail($subject, $application){
        Mail::send('emails.reminders.nach_reminder',
            ['application'=>$application,'nach_status'=>$subject]
            , function ($message) use ($subject) {
                $message->to(_env('NOTIFY_EMAIL', ''))->subject($subject);
            });
    }
}
