<?php

namespace App;

use Carbon\Carbon;
use Hashids\Hashids;
use Illuminate\Http\Request;

class NotificationHub
{

    private $users = [];
    private $applicationIds = null;
    private $notifications = null;
    private $day;

    public function __construct(){
        $this->setUsers();
        $this->day = Carbon::now()->day;
    }

    public function setUsers(){
        $GCMRegistrations = GCMRegistraion::where('status', 'Active')->get();
        if($GCMRegistrations) {
            foreach ($GCMRegistrations as $registration) {
                if (!in_array($registration->user_id, $this->users)) {
                    $this->users[] = $registration->user_id;
                }
            }
        }
    }

    public function getUsers($applications){
        $applicationsData = ConsumerApplication::whereIn('id', $applications)->groupBy('user_id')->get(['user_id']);
        $users = [];
        if ($applicationsData) {
            foreach ($applicationsData as $application) {
                $users[] = $application->user_id;
            }
        }
        return $users;
    }

    //When customer has registered but not applied for loan. Send once every month (15th of every month). No end cycle for this notification. This notification will not be sent to repeat customers.
    public function notAppliedForLoan(){
        $applications = ConsumerApplication::whereIn('user_id', $this->users)->orderBy('created_at','desc')->get(['user_id','id']);
        if($applications) {
            $users = [];
            foreach ($applications as $application) {
                if (!in_array($application->user_id, $users)) {
                    $users[] = $application->user_id;
                    $this->applicationIds[] = $application->id;
                }
            }

            if ($users || $this->users) {
                $users = array_values(array_diff($this->users, $users));
                if ($users) {
                    $this->notifications[] = ['title' => 'Stress-free loans = stress-free life!', 'body' => 'Enjoy NO COST EMI facility with 500+ merchant partners for home renovation, education, medical treatments, and electric vehicles', 'users' => $users,
                        'details' => ['day' => 5, 'time' => 11, 'frequency' => 'monthly'], 'deeplink' => '/apply'];
                }
            }
        }
    }

    //When loan application started but not submitted. I.e. when it is in ‘incomplete form’ stage on admin panel. Every alternate day from the date of filling in the form this notification should be pushed. No end cycle.
    public function incompleteApplications(){

        if($this->applicationIds) {
            $applications = ConsumerApplication::whereIn('id', $this->applicationIds)->where('state', 'incomplete form')->get(['id', 'created_at']);
            if ($applications) {

                $applicationsIds = [];

                $day = Carbon::now()->day;

                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                }
                if ($applicationsIds) {
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {
                        $this->notifications[] = ['title' => 'Pending loan application', 'body' => 'Finish your application and get loan approved in a day', 'users' => $users,
                            'details' => ['day' => $day, 'time' => 11, 'frequency' => 'alternate_day'], 'deeplink' => '/apply/identity'];
                    }
                }
            }
        }
    }

    //When application is changed from ‘in process’ status to ‘approved’ on admin panel. Notification to go everyday till the application status is changed from “approved” to “disbursement checklist done”
    public function approvedApplications(){

        if ($this->applicationIds) {
            $applications = ConsumerApplication::with('application_element')->whereIn('id', $this->applicationIds)->where('state', 'approved')->get(['id', 'approved_amount', 'created_at', 'user_id']);

            if ($applications) {

                $applicationsIds = [];
                $applicationsUserWiseData = [];

                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                    $applicationsUserWiseData[$application->user_id] = $application;
                }
                if ($applicationsIds) {
                    $hashId = new Hashids('Creditfair by CS', 20);
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {

                        foreach ($users as $user) {

                            $esign = asset("esign/id/".$hashId->encode($applicationsUserWiseData[$user]->id));

                            $this->notifications[] = ['title' => 'Congratulations!', 'body' => 'Congratulations, your loan for Rs. ' . $applicationsUserWiseData[$user]->approved_amount . ' has been approved', 'users' => $user,
                                'details' => ['day' => 1, 'time' => 13, 'frequency' => 'daily'], 'deeplink' => '/esign', 'payload' => ['signing_link' => $esign, 'id' => $applicationsUserWiseData[$user]->id]];
                        }
                    }
                }
            }
        }
    }

    //5
    //Once every month on 5th. For new customer and for repeat customer (irrespective of the category of previous loan) after 3 months of closing application/rejected application/ aborted application. no end cycle.
    //20
    // Once every month on 20th. For new customer and for repeat customer (irrespective of the category of previous loan) after 3 months of closing application/rejected application/ aborted application. no end cycle.
    //25
    //Once every month on 25th. For new customer and for repeat customer (irrespective of the category of previous loan) after 3 months of closing application/rejected application/ aborted application. no end cycle.

    public function rejectedAbortedApplications(){

        if ($this->applicationIds) {
            $applications = ConsumerApplication::with('closed', 'rejected', 'aborted')->whereIn('id', $this->applicationIds)->whereIn('state', ['closed', 'aborted', 'rejected'])->get(['id', 'created_at', 'state', 'user_id']);

            if ($applications) {

                $applicationsIds = [];
                $applicationsData = [];
                $applicationsUserWiseData = [];

                foreach ($applications as $application) {
                    if ($application->closed) {
                        $date = $application->closed->created_at;
                    } else if ($application->rejected) {
                        $date = $application->rejected->created_at;
                    } else if ($application->aborted) {
                        $date = $application->aborted->created_at;
                    }
                    if (isset($date) && Carbon::parse($date)->addMonths(3)->timestamp < Carbon::now()->timestamp) {
                        $applicationsIds[] = $application->id;
                        $applicationsData[$application->id] = $application;
                        $applicationsUserWiseData[$application->user_id] = $application;
                    }
                }
                if ($applicationsIds) {
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {

                        $this->notifications[] = ['title' => [
                            5 => 'Go green with Credit Fair!',
                            20 => 'Upgrade your house with Credit Fair!',
                            25 => 'Study now, pay later'
                        ], 'body' => [
                            5 => 'Get EASY EMIs on purchase of Electric Vehicle.',
                            20 => 'Take a home renovation loan at NO COST EMI',
                            25 => 'Vishal pursued Data Science from Upgrad and got a salary hike. You can too'
                        ], 'users' => $users,
                            'details' => ['day' => [5, 20, 25], 'time' => 11, 'frequency' => 'monthly'], 'deeplink' => '/apply'];
                    }
                }
            }
        }
    }

    //1 notification to be sent 3 days before EMI due date. to be sent for applications that are in “disbursed” and “nach registered”.
    public function disbursedNachRegistered(){
        if ($this->applicationIds) {
            $emiPayments = EmiPayment::whereIn('application_id', $this->applicationIds)->where('emi_date', Carbon::now()->addDays(3)->toDateString())->get(['emi_date', 'application_id']);
            if ($emiPayments) {
                $applicationsIds = [];
                foreach ($emiPayments as $payment) {
                    if (!in_array($payment->application_id, $applicationsIds) && $payment->emi_date) {
                        $applicationsIds[] = $payment->application_id;
                    }
                }

                $applications = ConsumerApplication::whereIn('id', $applicationsIds)->whereIn('state', ['disbursed','nach registered'])->get(['id']);
                $applicationsIds = [];
                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                }

                $users = $this->getUsers($applicationsIds);

                if ($users) {
                    $this->notifications[] = ['title' => 'Your EMI due date is approaching', 'body' => 'Pay now to maintain healthy credit score. Ignore if already paid.', 'users' => $users,
                        'details' => ['day' => 1, 'time' => 11, 'frequency' => 'one_time'], 'deeplink' => '/payment'];
                }
            }
        }
    }

    //on the EMI due date morning before 10am. To be sent for applications that are in “disbursed” and “nach registered”.
    public function disbursedNachRegisteredOnEMI(){

        if ($this->applicationIds) {
            $emiPayments = EmiPayment::whereIn('application_id', $this->applicationIds)->where('emi_date', Carbon::now()->toDateString())->get(['emi_date', 'application_id']);
            if ($emiPayments) {
                $applicationsIds = [];
                foreach ($emiPayments as $payment) {
                    if (!in_array($payment->application_id, $applicationsIds) && $payment->emi_date) {
                        $applicationsIds[] = $payment->application_id;
                    }
                }

                $applications = ConsumerApplication::whereIn('id', $applicationsIds)->whereIn('state', ['disbursed','nach registered'])->get(['id']);
                $applicationsIds = [];
                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                }

                $users = $this->getUsers($applicationsIds);

                if ($users) {
                    $this->notifications[] = ['title' => 'Your EMI is due today', 'body' => 'Pay now to avoid late charges. Ignore if already paid.', 'users' => $users,
                        'details' => ['day' => 1, 'time' => 9, 'frequency' => 'one_time'], 'deeplink' => '/payment'];
                }
            }
        }
    }

    //everyday twice (morning and evening) till the payment is made. to be sent for applications that are in “disbursed” and “nach registered”.
    public function disbursedNachRegisteredMissed(){

        if ($this->applicationIds) {
            $emiPayments = EmiPayment::whereIn('application_id', $this->applicationIds)->where('emi_date', '<', Carbon::now()->toDateString())->whereIn('payment_status', ['pending','rejected'])->get(['emi_date', 'application_id']);
            if ($emiPayments) {
                $applicationsIds = [];
                foreach ($emiPayments as $payment) {
                    if (!in_array($payment->application_id, $applicationsIds) && $payment->emi_date) {
                        $applicationsIds[] = $payment->application_id;
                    }
                }

                $applications = ConsumerApplication::whereIn('id', $applicationsIds)->whereIn('state', ['disbursed','nach registered'])->get(['id']);
                $applicationsIds = [];
                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                }

                $users = $this->getUsers($applicationsIds);

                if ($users) {
                    $this->notifications[] = ['title' => 'You missed your EMI due date', 'body' => 'Pay now to avoid lowering of your credit score. Ignore if already paid.', 'users' => $users,
                        'details' => ['day' => 1, 'time' => [11, 18], 'frequency' => 'morning_evening'], 'deeplink' => '/payment'];
                }
            }
        }
    }

    //when application is changed to ‘waiting for documents’ in admin panel. notification to be sent once every day. To be sent till the status of application is changed from 'waiting for documents” to “waiting for decision”
    public function waitingForDocument(){

        if ($this->applicationIds) {
            $applications = ConsumerApplication::whereIn('id', $this->applicationIds)->where('state', 'waiting for documents')->get(['id', 'approved_amount', 'created_at']);

            if ($applications) {

                $applicationsIds = [];

                foreach ($applications as $application) {
                    $applicationsIds[] = $application->id;
                }
                if ($applicationsIds) {
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {
                        $this->notifications[] = ['title' => 'We are waiting for your documents!', 'body' => 'Submit pending documents and get a decision in 24 hours', 'users' => $users,
                            'details' => ['day' => 1, 'time' => 11, 'frequency' => 'daily'], 'deeplink' => '/pending-document'];
                    }
                }
            }
        }
    }

    //3 months after closing loan. Only applicable to repeat customer who have loans closed. Once every week. No end cycle.
    public function closedLoan(){

        if ($this->applicationIds) {
            $applications = ConsumerApplication::with('closed')->whereIn('id', $this->applicationIds)->whereIn('state', ['closed'])->orderBy('created_at','desc')->get(['id', 'created_at', 'state']);

            if ($applications) {

                $applicationsIds = [];

                foreach ($applications as $application) {
                    if ($application->closed && Carbon::parse($application->closed->created_at)->addMonths(3)->timestamp < Carbon::now()->timestamp) {
                        $applicationsIds[] = $application->id;
                    }
                }
                if ($applicationsIds) {
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {
                        $this->notifications[] = ['title' => 'You are eligible for loan', 'body' => 'Apply for easy EMI loan with Credit Fair and get approval in a day', 'users' => $users,
                            'details' => ['day' => 1, 'time' => 11, 'weekDay' => [1], 'frequency' => 'weekly'], 'deeplink' => '/apply'];
                    }
                }
            }
        }
    }

    //3 months after previous loan application was rejected/aborted. Once every week. no end cycle.
    public function rejectedAbortedAfterThreeMonth(){

        if ($this->applicationIds) {
            $applications = ConsumerApplication::with('aborted', 'rejected')->whereIn('id', $this->applicationIds)->whereIn('state', ['aborted', 'rejected'])->get(['id', 'created_at', 'state']);

            if ($applications) {

                $applicationsIds = [];

                foreach ($applications as $application) {

                    $date = '';

                    if ($application->rejected) {
                        $date = $application->rejected->created_at;
                    } else if ($application->aborted) {
                        $date = $application->aborted->created_at;
                    }

                    if ($date && Carbon::parse($date)->addMonths(3)->timestamp < Carbon::now()->timestamp) {
                        $applicationsIds[] = $application->id;
                    }
                }
                if ($applicationsIds) {
                    $users = $this->getUsers($applicationsIds);
                    if ($users) {
                        $this->notifications[] = ['title' => 'Still looking for a loan?', 'body' => 'Apply for easy EMI loan with Credit Fair and get approval in a day', 'users' => $users,
                            'details' => ['day' => 1, 'time' => 11, 'weekDay' => [1], 'frequency' => 'weekly'], 'deeplink' => '/apply'];
                    }
                }
            }
        }
    }

    public function loanEligibility(){
        if($this->users) {
            if ($this->users) {
                $this->notifications[] = ['title' => 'Check loan eligibility', 'body' => 'Thinking of applying for a loan. Check loan eligibility now.', 'users' => $this->users,
                    'details' => ['day' => 10, 'time' => 11, 'frequency' => 'monthly'], 'deeplink' => '/calculator'];
            }
        }
    }

    public function sendNotification(){
        if ($this->notifications) {
            foreach ($this->notifications as $notification) {
                switch ($notification['details']['frequency']) {
                    case 'monthly':
                        if (((is_array($notification['details']['day']) && in_array($this->day, $notification['details']['day'])) || (is_numeric($notification['details']['day']) && $notification['details']['day'] == $this->day)) && $notification['details']['time'] == Carbon::now()->hour) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                    case 'alternate_day':
                        if ($notification['details']['day'] % 2 == 0 && $notification['details']['time'] == Carbon::now()->hour) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                    case 'one_time':
                        if($notification['details']['time'] == Carbon::now()->hour) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                    case 'morning_evening':
                        if ((is_array($notification['details']['time']) && in_array(Carbon::now()->hour, $notification['details']['time'])) || (is_numeric($notification['details']['time']) && $notification['details']['time'] == Carbon::now()->hour)) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                    case 'daily':
                        if ((is_array($notification['details']['time']) && in_array(Carbon::now()->hour, $notification['details']['time'])) || (is_numeric($notification['details']['time']) && $notification['details']['time'] == Carbon::now()->hour)) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                    case 'weekly':
                        if (((is_array($notification['details']['weekDay']) && in_array(Carbon::now()->dayOfWeek, $notification['details']['weekDay'])) || (is_numeric($notification['details']['weekDay']) && $notification['details']['weekDay'] == Carbon::now()->dayOfWeek)) && $notification['details']['time'] == Carbon::now()->hour) {
                            $users = is_array($notification['users']) ? $notification['users'] : [$notification['users']];
                            $this->initiateService($users, $notification);
                        }
                        break;
                }
            }
        }
    }

    public function initiateService($users, $notification){
        foreach ($users as $user) {
            new FCMNotification(new Request([
                'type' => 'user',
                'id' => $user,
                'service_id' => $user,
                'notification_type' => 'application',
                'title' => is_array($notification['title']) ? $notification['title'][Carbon::now()->day] : $notification['title'],
                'body' => is_array($notification['body']) ? $notification['body'][Carbon::now()->day] : $notification['body'],
                'deeplink' => $notification['deeplink'],
                'fcm_payload' => isset($notification['payload']) ? $notification['payload'] : '',
                'auth_id' => 107
            ]));
        }
    }
}
