<?php

namespace App\Http\Controllers\Admin;

use App\ABFLDocuments;
use App\ABFLDrawdownWrapper;
use App\ABFLKYC;
use App\ABFLSanctionWrapper;
use App\APIWrapper\Wrapper;
use App\ConsumerApplication;
use App\ConsumerApplicationFiles;
use App\Http\Controllers\Controller;
use App\JMDocuments;
use App\JMLoanBooking;
use App\JMMandate;
use App\JMOnboarding;
use App\JMRepayment;
use App\Method\ABFL\ABFLMethods;
use App\Method\JM\JMMethods;
use App\Method\JM\Payload\Payload;
use App\PaymentTransaction;
use Illuminate\Http\Request;
use App\ABFLBreDecision;
use App\StatusLogs;
use Illuminate\Support\Facades\Input;

class JMController extends Controller{

    private $request;

    public function __construct(Request $request){

        $this->request = $request;
    }

    public function checkWorthiness(){

        $wrapper = new Wrapper();
        $wrapperMethods = $wrapper->register(JMMethods::class);
        $request = new Request(['id' => $this->request->get('id')]);
        $wrapper->payload->addPayload($request);

        $JMBooking = JMLoanBooking::where('application_id', $this->request->get('id'))->first(['id', 'lead_id', 'status']);
        if (!isset($JMBooking->id)) {
            $wrapperRes = $wrapperMethods->createLoan($wrapper);
            /*if (!$wrapperRes->errorBag)
                return response()->json(['status' => 'OK', 'data' => ['Message' => 'Loan application sent to JM for decision']]);*/

            if($wrapperRes->errorBag)
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
        }

        if(!isset($JMBooking->lead_id)){
            $JMBooking = JMLoanBooking::where('application_id', $this->request->get('id'))->first(['id', 'lead_id', 'status']);
        }


        $request->merge(['jm_lead_id' => $JMBooking->lead_id]);
        $wrapper->payload->addPayload($request);
        $rejectionStatusList = ['Rejected','Rejected By Loan Officer'];
        if($JMBooking->status != 'Approved' && !in_array($JMBooking->status, $rejectionStatusList)){
            $wrapperRes = $wrapperMethods->getLoanStatus($wrapper);
            if ($wrapperRes->errorBag)
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
        }

        $rejectionStatus = 'Rejected By Loan Officer';
        if(in_array($JMBooking->status, $rejectionStatusList)){
            return response()->json(['status' => 'FAIL', 'data' => array_filter(['Message' => $JMBooking->status])]);
        }


        $JMOnboarding = JMOnboarding::where('application_id', $this->request->get('id'))->first(['id', 'status']);
        if (!isset($JMOnboarding->id) || $JMOnboarding->status != 'Approved') {
            $wrapperRes = $wrapperMethods->onboardingCompleted($wrapper);
            if (!$wrapperRes->errorBag) {
                $message = $wrapperRes->response->data->status ?? 'Loan application sent to JM for decision';
                return response()->json(['status' => in_array($message, [$rejectionStatus, 'Completely Submitted']) ? 'FAIL' : 'OK', 'data' => ['Message' => $message]]);
            }

            return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
        }



        $JMRepayment = JMRepayment::where('application_id', $this->request->get('id'))->first(['id']);
        $status = StatusLogs::where('application_id', $this->request->get('id'))->where('status', 'disbursement checklist done')->first(['id']);
        if(isset($status->id)){
            $wrapperRes = $wrapperMethods->updateLoan($wrapper);
            if ($wrapperRes->errorBag) {
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
            }

            if (!isset($JMRepayment->id)) {
                if($resRepayment = $this->updateRepayment($wrapperMethods, $wrapper, $request)) {
                    return $resRepayment;
                }
            }

            if($resUpload = $this->uploadMultipleDocuments($wrapperMethods, $wrapper, array(), $request)) {
                return $resUpload;
            }

            $jmMandate = JMMandate::where('application_id', $this->request->get('id'))->first(['id']);
            if(!isset($jmMandate->id)) {
                $application = ConsumerApplication::with('checkmandate')->where('id', $this->request->get('id'))->first(['id']);
                if(!isset($application->checkmandate->id)){
                    return response()->json(['status' => 'FAIL', 'data' => ['Message' => 'Mandate is not active or created']]);
                }
                $request->merge(['mandate_id' => $application->checkmandate->mandate_id]);
                $wrapperRes = $wrapperMethods->mandate($wrapper);
                if ($wrapperRes->errorBag) {
                    return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
                }else{
                    return response()->json(['status' => 'OK', 'message' => 'JM Mandate Called']);
                }
            }else{
                return response()->json(['status' => 'OK', 'message' => 'JM Mandate Called']);
            }
        }else{
            return response()->json(['status' => 'FAIL', 'data' => array_filter(['Error'=>'Running Api on Wrong stage or Waiting for Decision from JM'])]);
        }
    }

    private function updateRepayment($wrapperMethods, $wrapper, $request){
        $transactions = PaymentTransaction::where('application_id', $this->request->get('id'))->whereIn('payment_for', ['processing_fee', 'advance_amount'])->get(['id']);

        foreach($transactions as $transaction) {
            if (isset($transaction->id)) {
                $JMRepayment = JMRepayment::where('application_id', $this->request->get('id'))->where('payment_id', $transaction->id)->first(['id']);
                if (!isset($JMRepayment->id)) {
                    $request->merge(['payment_id' => $transaction->id, 'id' => $this->request->get('id')]);
                    $wrapper->payload->addPayload($request);
                    $wrapperRes = $wrapperMethods->repayment($wrapper);
                    if ($wrapperRes->errorBag) {
                        return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
                    }
                }
            }
        }
        return false;
    }

    private function uploadMultipleDocuments($wrapperMethods, $wrapper, $fileTypes, Request $request){
        if (empty($fileTypes)) {
            $fileTypes = (new Payload())->getFileType();
        }
        $files = ConsumerApplicationFiles::where('consumer_application_id', Input::get('id'))->whereIn('file_type', $this->getDocumentName($fileTypes))->orderBy('created_at', 'desc')->get(['id', 'file_type', 'file_path']);
        $lastDocsLists = [];
        foreach ($files as $file) {
            if (in_array($file->file_type, ['sanction_letter', 'loan_agreement_esign'])){
                $lastDocsLists[$file->file_type] = $file;
            }else {
                $this->sendDocumentToJM($request, $wrapper, $wrapperMethods, $file, $fileTypes);
            }
        }

        if (isset($lastDocsLists['sanction_letter'])) {
            $file = ConsumerApplicationFiles::where('consumer_application_id', Input::get('id'))->where('file_type', 'sanction_letter')->orderBy('created_at', 'desc')->first(['id', 'file_type', 'file_path']);
            $lastDocsLists[$file->file_type] = $file;
            $this->sendDocumentToJM($request, $wrapper, $wrapperMethods, $lastDocsLists['sanction_letter'], $fileTypes);
        }
        if (isset($lastDocsLists['loan_agreement_esign'])) {
            $file = ConsumerApplicationFiles::where('consumer_application_id', Input::get('id'))->where('file_type', 'loan_agreement_esign')->orderBy('created_at', 'desc')->first(['id', 'file_type', 'file_path']);
            $lastDocsLists[$file->file_type] = $file;
            $this->sendDocumentToJM($request, $wrapper, $wrapperMethods, $lastDocsLists['loan_agreement_esign'], $fileTypes);
        }

        return false;
    }

    private function getDocumentName($fileTypes, $get_key = false){
        $data = [];
        $search_key = false;
        foreach ($fileTypes as $key => $fileType){
            if (is_array($fileType)){
                foreach ($fileType as $item) {
                    if ($get_key == $item){
                        $search_key = $key;
                        break;
                    }
                    $data[] = $item;
                }
            }else{
                $data[] = $fileType;
                if ($get_key == $fileType){
                    $search_key = $key;
                    break;
                }
            }
        }

        return $search_key ? $search_key : $data;
    }

    public function sendDocumentToJM($request, $wrapper, $wrapperMethods, $file, $fileTypes){
        $documentsCount = JMDocuments::where('consumer_application_file_id', $file->id)->first(['id']);
        if (!isset($documentsCount->id)) {
            $filePath = storage_path($file->id . '_' . time()).'.'.$this->getFileExtension($file);
            $request->merge(['file_id' => $file->id, 'document_id' => $this->getDocumentName($fileTypes, $file->file_type), 'file_path' => $filePath]);
            $wrapper->payload->addPayload($request);
            $wrapperRes = $wrapperMethods->uploadDocument($wrapper);
            if (file_exists($filePath)) {
                unlink($filePath);
            }
            if ($wrapperRes->errorBag)
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
        }
    }

    private function getFileExtension($file){
        $getExtension = explode('.', $file->file_path);
        return $getExtension[count($getExtension) - 1] ?? 'pdf';
    }

    public function sanctionWrapper($wrapperMethods, $wrapper){

        $ABFLSanctionWrapper = ABFLSanctionWrapper::where('application_id', $this->request->get('id'))->first(['id']);

        if (!isset($ABFLSanctionWrapper->id)) {
            $wrapperRes = $wrapperMethods->createAccountv2($wrapper);
            if ($wrapperRes->errorBag) {
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
            }
        }

        $ABFLDrawdownWrapper = ABFLDrawdownWrapper::where('application_id', $this->request->get('id'))->first(['id']);
        if (!isset($ABFLDrawdownWrapper->id)) {
            $wrapperRes = $wrapperMethods->captureChargev2($wrapper);
            if ($wrapperRes->errorBag) {
                return response()->json(['status' => 'FAIL', 'data' => array_filter($wrapperRes->errorBag)]);
            }
        }

        $application = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->where('file_type', 'loan_agreement_esign')->first(['id']);

        if (!isset($application->id)){
            return response()->json(['status' => 'FAIL', 'data' => ['Message' => 'Loan agreement signing is pending']]);
        }

        $this->request->merge(['file_id' => $application->id, 'id' => $this->request->get('id')]);
        $uploadDocument =  $this->sendDocumentToABFL();
        $uploadDocumentArg = $uploadDocument->getData();

        if ($uploadDocumentArg->status == 'OK'){
            return response()->json(['status' => 'OK', 'data' => ['Message' => 'DrawDownWrapper triggered']]);
        }

        return $uploadDocument;
    }

    public function sendDocumentToABFL(){

        $wrapper = new Wrapper();
        $wrapperMethods = $wrapper->register(ABFLMethods::class);
        $wrapper->payload->addPayload($this->request);

        $wrapperRes = $wrapperMethods->uploadDocumentBase64($wrapper);
        if (!$wrapperRes->errorBag) {
            return response()->json(['status' => 'OK', 'message' => 'Upload Document triggered']);
        }
        return response()->json(['status' => 'FAIL', 'message' => $wrapperRes->errorBag['Error']]);
    }

    public function getDocumentMapping(){

        $mappedDocumentExists = [];

        if(!$this->request->has('file_type')) {
            $files = ConsumerApplicationFiles::where('consumer_application_id', $this->request->get('id'))->get(['id', 'file_type']);

            foreach ($files as $file) {
                $filesExistIds[$file->file_type][] = $file->id;
                $mappedDocumentExists[$file->file_type] = $file->file_type;
            }
        }else{
            $filesExistIds[$this->request->get('file_type')][] = $this->request->get('file_id');
            $mappedDocumentExists[$this->request->get('file_type')] = $this->request->get('file_id');
        }

        $mappedDocumentAvExists = [];

        if (isset($filesExistIds) && $filesExistIds) {
            foreach ($filesExistIds as $mainKey => $filesExistId) {
                $avansePushed = ABFLDocuments::where('application_id', $this->request->get('id'))->whereIn('consumer_application_file_id', $filesExistId)->first();
                if (isset($avansePushed->id)) {
                    $mappedDocumentAvExists[$mainKey] = $mainKey;
                }
            }
        }

        return [$mappedDocumentExists, $mappedDocumentAvExists];
    }
}
