<?php

namespace App;

use App\Avanse\Services\AvanseServices;
use App\Console\Commands\AdvanceReminders;
use App\Console\Commands\BasicReminders;
use App\Console\Commands\TallyBridge;
use App\Console\Commands\TallySettlement;
use App\Events\V1\EventAvansePaymentProcess;
use App\Http\Controllers\Admin\CoLendingController;
use App\Http\Controllers\Admin\CollectionController;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\Http\Controllers\Admin\EMICalculation;
use App\Http\Controllers\Admin\AccountingController;
use App\Http\Controllers\Admin\CampaignController;
use App\Http\Controllers\Admin\FLDGController;
use App\Http\Controllers\Admin\DaSystemDataController;
use App\Http\Controllers\Admin\HypothecationController;
use App\Http\Controllers\Admin\LenderController;
use App\Http\Controllers\Admin\MerchantController;
use App\Http\Controllers\NachController;
use App\Http\Controllers\TestingController;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use App\Events\V1\EventSendDbBackupEmail;

class CampaignsJobProvider extends Model
{

    protected $table = 'campaigns_jobs';

    protected $fillable = ['payload','application_id','from','available_at', 'applicant_type'];
    private $event;

    public function application(){
        return $this->hasOne('App\ConsumerApplication','id','application_id');
    }

    public function start($event)
    {
        $this->event = $event;
        if (isset($this->event->job_id) && $this->event->job_id > 0) {
            $jobs = CampaignsJobProvider::where('id', $this->event->job_id)->get();
        } else if (isset($this->event->id) && $this->event->id > 0) {
            $jobs = CampaignsJobProvider::where('id', $this->event->id)->get();
        } else {
            $jobs = CampaignsJobProvider::where('is_available', 0)->where('available_at', '<=', Carbon::now()->toDateTimeString());
            if (isset($this->event->from)) {
                $jobs = $jobs->where('from', $this->event->from);
            }
            $jobs = $jobs->get();
        }

        $isPayment = false;
        $disableIds = [];
        foreach ($jobs as $job) {
            if($job->from == 'payment_file_nach_process') {
                if(count($jobs) == 1){
                    $isPayment = true;
                    $disableIds[] = $job->id;
                }
            }else{
                $disableIds[] = $job->id;
            }
        }

        CampaignsJobProvider::whereIn('id', $disableIds)->update(['is_available' => 1]);

        if ($jobs->count()) {
            foreach ($jobs as $job) {
                switch ($job->from) {
                    case 'campaign_service':
                        $payload = json_decode($job->payload);
                        return (new CampaignController(new Request()))->startCampaignService($payload);
                        break;
                    case 'export_payment_file':
                        $payload = json_decode($job->payload);
                        return (new EMICalculation(new Request((array) $payload)))->showEMIS();
                        break;
                    case 'export_document_zip':
                        return (new TestingController())->documentGeneration();
                        break;
                    case 'export_bureau_document_zip':
                        return (new TestingController())->bureauDocumentGeneration();
                        break;
                    case 'accrued_revenue':
//                        $this->event->comment($job->from);
                        $payload = json_decode($job->payload);
                        (new AccountingController())->getAccruedProfitOnEmail(new Request((array) $payload));
                        break;
                    case 'payment_file_manual':
                        $payload = json_decode($job->payload);
                        return (new AccountingController())->startManualPaymentFileProcess(new Request((array) $payload));
                        break;
                    case 'payment_file_nach':
                        $payload = json_decode($job->payload);
                        return (new AccountingController())->startPaymentFileProcess(new Request((array) $payload));
                        break;
                    case 'hypothecation_data_upload':
                        $payload = json_decode($job->payload);
                        return (new HypothecationController())->startFileProcess(new Request((array) $payload));
                        break;
                    case 'da_system_data_upload':
                        $payload = json_decode($job->payload);
                        return (new DaSystemDataController())->startFileProcess(new Request((array) $payload));
                        break;
                    case 'da_system_payment_upload':
                        $payload = json_decode($job->payload);
                        return (new DaSystemDataController())->startDAPaymentFileProcess(new Request((array) $payload));
                        break;
                    case 'da_system_rps_upload':
                        $payload = json_decode($job->payload);
                        return (new DaSystemDataController())->startDARPSFileProcess(new Request((array) $payload));
                        break;
                    case 'co_lending_system_rps_upload':
                        $payload = json_decode($job->payload);
                        return (new CoLendingController())->startCoLendingRPSFileProcess(new Request((array) $payload));
                        break;
                    case 'co_lending_system_payment_upload':
                        $payload = json_decode($job->payload);
                        return (new CoLendingController())->startCoLendingPaymentFileProcess(new Request((array) $payload));
                        break;
                    case 'sageMakerDataSets':
                        $payload = json_decode($job->payload);
                        return (new TestingController())->sageMakerDataSets(new Request((array) $payload), $this->event);
                        break;
                    case 'rabbitMqQueue':
                        Artisan::call('command:RQConsumerListener', ['q_name' => 'q_job', 'q_tag' => 'q_job', 'q_bind' => 1, 'exchange' => 'job_exch', 'route_key' => 'exch_rout_key_job']);
                        Artisan::call('command:RQConsumerListener', ['q_name' => 'q_sms', 'q_tag' => 'q_sms', 'q_bind' => 1, 'exchange' => 'sms_exch', 'route_key' => 'exch_rout_key_cmd']);
                        break;
                    case 'savePrincipalOutstanding':
                        $payload = json_decode($job->payload);
                        return (new BasicReminders())->savePrincipalOutstanding($this->event, $payload->date);
                        break;
                    case 'uploadMerchantLogoOnS3':
                        return (new TestingController())->uploadMerchantLogoOnS3();
                        break;
                    case 'tally_settlement_run':
                        $payload = json_decode($job->payload);
                        Artisan::call('tally:settlement', ['--settlement_id' => $payload->settlement_id]);
                        break;
                    case 'tally_settlement_lotuspay':
                        $payload = json_decode($job->payload);
                        $data = ['settlement_date' => $payload->settlement_date, 'lender_id' => $payload->lender_id];
                        (new TallyBridge())->importLotusPaySettlement($data);
                        break;
                    case 'dailyExcelMailToOPs':
                        $caObj = new ConsumerApplicationController();
                        $caObj->dailyCronJobForExcelMail();
                        //return event(new EventSendDbBackupEmail('excelMailToOPs'));
                        break;
                    case 'creditLineTestingV1':
                        return (new TestingController())->creditLineTestingV1();
                        break;
                    case 'lotuspay_webhook_job':
                        $payload = json_decode($job->payload);
                        if (!isset($payload->responsedata->id)){
                            $data['responsedata'] = $payload->responsedata;
                            $data['job'] = 1;
                        }else{
                            $data = (array)$payload->request;
                        }
                        return (new NachController())->getWebhookNotification($payload->lender_id, new Request($data));
                        break;
                    case 'merchantRelationshipAnalytics':
                        return (new MerchantController())->merchantRelationshipAnalytics($this->event);
                        break;
                    case 'SanctionLetterAuto':
                        return (new TestingController())->generateCustomerDocuments('SanctionLetter');
                        break;
                    case 'WelcomeLetterAuto':
                        return (new TestingController())->generateCustomerDocuments('WelcomeLetter');
                        break;
                    case 'updateLastReportedDate':
                        return (new TestingController())->updateLastReportedDate();
                        break;
                    case 'getDPDReport':
                        $payload = json_decode($job->payload);
                        return (new AccountingController())->getDPDReport(new Request((array) $payload));
                        break;
                    case 'getDPDReportV1':
                        $payload = json_decode($job->payload);
                        return (new AccountingController())->getDPDReportV1(new Request((array) $payload));
                        break;
                    case 'reUploadInvoice':
                        return (new TestingController())->reUploadInvoice();
                        break;
                    case 'run_onfido':
                        $payload = json_decode($job->payload);
                        return (new OnfidoIntegration())->runOnfido($payload->id,$job->applicant_type);
                        break;
                    case 'export_emis':
                        $payload = json_decode($job->payload);
                        return (new EMICalculation(new Request((array) $payload)))->showEMIS();
                        break;
                    case 'export_overdue_emis':
                        $payload = json_decode($job->payload);
                        return (new EMICalculation(new Request((array) $payload)))->showEMIS();
                        break;
                    case 'getImranPaymentData':
                        return (new TestingController())->getImranPaymentData();
                        break;
                    case 'dailyPtpInfo':
                        $payload = json_decode($job->payload);
                        return (new CollectionController(new Request((array) $payload)))->dailyPtpInfo();
                        break;
                    case 'advanceReminder':
                        return (new AdvanceReminders())->handle(json_decode($job->payload));
                        break;
                    case 'getAdityaData':
                        return (new TestingController())->getAdityaData();
                        break;
                    case 'getPrincipalsOutstanding':
                        return (new TestingController())->getPrincipalsOutstanding();
                        break;
                    case 'creditReportEntries':
                        return (new TestingController())->creditReportEntries();
                        break;
                    case 'getPrincipalsOutstandingAditya':
                        $payload = json_decode($job->payload);
                        return (new TestingController())->getPrincipalsOutstandingAditya($payload->type);
                        break;
                    case 'getPrincipalsOutstandingAdityaV1':
                        return (new TestingController())->getPrincipalsOutstandingAdityaV1();
                        break;
                    case 'getPrincipalsOutstandingAdityaV2':
                        $payload = json_decode($job->payload);
                        return (new TestingController())->getPrincipalsOutstandingAdityaV2($payload->date);
                        break;
                    case 'DpdLogs':
                        $accounting = new AccountingController();
                        $accounting->dpd_report_cron();
                        break;
                    case 'delinquencyReport':
                        $accounting = new TestingController();
                        $accounting->delinquencyReport();
                        break;
                    case 'kmg_p2p_repayments_update':
                        $payload = json_decode($job->payload);
                        $accounting = new LenderController(new Request((array) $payload));
                        $accounting->pushRepaymentsToLender();
                        break;
                    case 'getPrincipalsOutstandingAdityaNCD':
                        $payload = json_decode($job->payload);
                        return (new TestingController())->getPrincipalsOutstandingAdityaNCD($payload);
                        break;
                    case 'paymentMISReport':
                        $payload = json_decode($job->payload);
                        return (new CollectionController(new Request((array) $payload)))->sendMISReport();
                        break;
                    case 'salesMISReport':
                        $payload = json_decode($job->payload);
                        return (new ConsumerApplicationController())->salesMisReport(new Request((array) $payload));
                        break;
                    case 'generateEMIPPendingCase':
                        $payload = json_decode($job->payload);
                        return (new CollectionController(new Request((array) $payload)))->generateEMIPPendingCase();
                        break;
                    case 'generateAuditReport':
                        return (new TestingController())->getSantoshji();
                        break;
                    case 'getDisbursementData':
                        return (new TestingController())->disbursementDataReport();
                        break;
                    case 'overDuePaymentReminder':
                        $payload = json_decode($job->payload);
                        (new Slack(new Request(['title' => 'Over Due Reminder Summary - started', 'fields' => ['Name' => 'overDuePaymentReminder'], 'group' => Slack::$STAGE_TESTING])))->send();
                        //$dayOfWeek = date('l',Carbon::now()->timestamp);
                        $all_due_cases = 0;
                        //if($dayOfWeek == 'Monday'){
                        $all_due_cases = 1;
                        //}
                        $start_time = time();

                        $loan_management = new LoanManagement();
                        $response = $loan_management->overDueReminder(explode(',', $payload->id), 1, 1, 0, $all_due_cases, $this->event);

                        if ($loan_management->smsCount || $loan_management->emailCount) {
                            (new Slack(new Request(['title' => 'Over Due Reminder Summary', 'fields' => ['Total Email Sent' => $loan_management->emailCount, 'Total SMS Sent' => $loan_management->smsCount], 'group' => 'payment_collection'])))->send();
                        }else{
                            (new Slack(new Request(['title' => 'Over Due Reminder Summary', 'fields' => ['Total Email Sent' => 0], 'group' => 'payment_collection'])))->send();
                        }
                        (new Services())->log('Over Due Reminder', ['status' => true, 'service_count' => ((isset($response['service_count']))? (isset($response['service_count'])) : 0), 'start_time' => $start_time]);
                        break;
                    case 'getAccruedRevenue':
                        return (new TestingController())->accruedRevenueSinceInception(['lender_id' => 2]);
                        break;
                    case 'generatePOSReport':
                        try{
                            return (new TestingController())->getPrincipalsOutstandingforCases();
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'POS report Error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'manual_payment_avanse':
                        $payload = json_decode($job->payload, 1);
                        $payload['id'] = $job->application_id;
                        return (new AvanseServices(new Request((array) $payload)))->manualPayment();
                        break;
                    case 'payment_file_nach_process':
                        if($isPayment) {
                            $payload = json_decode($job->payload);
                            $request = new Request((array)$payload);
                            $accountingController = new AccountingController();
                            $accountingController->startPaymentFileProcessing($request);
                            $hasMorePayment = BulkPayments::where('is_available', 0)->where('created_at', '>=', Carbon::now()->subDays(5)->toDateTimeString())->get(['id']);
                            if(count($hasMorePayment)){
                                CampaignsJobProvider::where('id', $job->id)->update(['is_available' => 0,'available_at' => Carbon::now()->addMinute(1)->toDateTimeString()]);
                            }else{
                                (new Slack(new Request(['title' => 'Payment file processed successfully', 'fields' => ['Payment Date' => $request->get('emi_date'),'Payment Reconciliation Date' => $request->get('payment_reconciliation_date'), 'Bank Name' => ($request->get('bank_name') == 1 ? 'HDFC' : ($request->has('transaction_type') ? 'LotusPay' : 'RBL'))], 'group' => 'payment_collection'])))->send();
                                $accountingController->createCommunicationJob($request, $job->id);
                                event(new EventAvansePaymentProcess(['id' => $job->id, 'date' => $job->created_at]));
                            }
                        }
                        break;
                    case 'payment_file_communication_process':
                        $payload = json_decode($job->payload);
                        $request = new Request((array)$payload);
                        $accountingController = new AccountingController();
                        $accountingController->startPaymentCommunication();
                        $hasMorePayment = BulkPayments::where('communication', 0)->where('created_at', '>=', Carbon::now()->subDays(5)->toDateTimeString())->whereNotNull('communication_data')->get(['id']);
                        if(count($hasMorePayment)){
                            CampaignsJobProvider::where('id', $job->id)->update(['is_available' => 0,'available_at' => Carbon::now()->toDateTimeString()]);
                        }else{
                            (new Slack(new Request(['title' => 'Payment communication sent successfully', 'fields' => ['Payment Date' => $request->get('emi_date'),'Payment Reconciliation Date' => $request->get('payment_reconciliation_date'), 'Bank Name' => ($request->get('bank_name') == 1 ? 'HDFC' : ($request->has('transaction_type') ? 'LotusPay' : 'RBL'))], 'group' => Slack::$STAGE_TESTING])))->send();
                        }
                        break;
                    case 'export_subvention_invoice':
                        try{
                            $payload = json_decode($job->payload);
                            return (new AccountingController())->exportSubventionInvoice(new Request((array) $payload));
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Monthly Invoice Creation Error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'exportAccountingReport':
                        try{
                            $payload = json_decode($job->payload);
                            return (new AccountingController())->exportAccountingReport(new Request((array) $payload));
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Accounting Report error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'credit_report_file':
                        try{
                            return (new TestingController())->uploadCreditReportFileToS3();
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'File uploading failed', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'OLDBureauDataSave':
                        return (new TestingController())->OLDBureauDataSave();
                        break;
                    case 'bureau_report_file':
                        try{
                            return (new TestingController())->getBureauJsonForABFL();
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Bureau Report not found', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'calculate_liability_hold':
                        try{
//                            return (new FLDGController(new Request()))->fetchLiabilityHoldCases();
                            $next_date = Carbon::tomorrow()->endOfDay()->subHour()->toDateTimeString();
                            (new FLDGController(new Request()))->fetchLiabilityHoldCases();
                            return CampaignsJobProvider::where('id', $job->id)->update(['is_available' => 0,'available_at' => $next_date]);
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Calculate liability hold error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'getAgencyReport':
                        try{
                            $payload = json_decode($job->payload);
                            return (new TestingController())->getAgencyReport(new Request((array) $payload));
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Agency Report error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'getSubventionInterestReport':
                        try{
                            $payload = json_decode($job->payload, 1);
                            return (new AccountingController())->getSubventionInterest($payload, true);
                        }catch (\Exception $e){
                            (new \App\Slack(new Request(['title' => 'Subvention Interest Report error', 'fields' => ['error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]])))->send();
                        }
                        break;
                    case 'downloadMISReport':
                        $payload = json_decode($job->payload);
                        return (new MerchantController())->downloadMISReport(new Request((array) $payload));
                    case 'generateFinbitAnalysisReport':
                        $payload = json_decode($job->payload);
                        (new FinBit(new Request((array) $payload)))->generateFinbitAnalysisReport();
                        break;
                    case 'newRPSScript':
                        (new TestingController())->newRPSScript();
                        break;
                    case 'runAllocationScriptBPI':
                        (new TestingController())->runAllocationScriptBPI();
                        break;
                }
            }
        }
    }
}
