<?php

namespace App\Http\Controllers;

use Hashids\Hashids;
use App\CommunicationMapping;
use App\CommunicationService;
use App\Merchant;
use App\Shortio;
use Carbon\Carbon;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\Templates;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Http\Request;
use App\BNPL;
use App\ConsentLog;
use App\ConsumerApplicationFiles;
use App\Logging\CloudWatchLoggerFactory;
use App\Http\Controllers\Admin\autoBRE;
use App\MerchantOffers;
use App\Helpers\DatapointHelper;
use Illuminate\Support\Facades\Storage;
use App\JobProvider;
use App\QueueLog;
use App\Events\V1\EventAutoDecision;

class ConsentController extends Controller
{

    public function showConsentPage($hashed_id, $applicant_type = 1)
    {
        $hashids = new Hashids('Creditfair by CS', 20);
        $decoded = $hashids->decode($hashed_id);

        if (empty($decoded)) {
            abort(404, 'Invalid link');
        }

        $id = $decoded[0];

        if ($applicant_type == 2) {
            $application = DB::connection('mysql_primary')
                ->table('consumer_application')
                ->where('id', $id)
                ->first(['id', 'co_applicant_name as name', 'merchant_id']);
        } else {
            $application = DB::connection('mysql_primary')
                ->table('consumer_application')
                ->where('id', $id)
                ->first(['id', 'name', 'merchant_id']);
        }

        if (!$application) {
            abort(404, 'Application not found');
        }
        $doc_name = $applicant_type == 1 ? 'consent_logs' : 'co_app_consent_logs';
        $merchant = DB::table('merchant')->where('id', $application->merchant_id)->first(['merchant_name']);
        $consumerApplicationElement = ConsumerApplicationElement::where('application_id', $id)
            ->first(['is_consent', 'is_co_app_consent']);
        $consumerApplicationFiles = ConsumerApplicationFiles::where('consumer_application_id', $id)
            ->where('applicant_type', $applicant_type)
            ->where('file_type', $doc_name)
            ->whereNull('deleted_at')
            ->first(['id']);

        $alreadyLogged = $applicant_type == 1 ? $consumerApplicationElement->is_consent : $consumerApplicationElement->is_co_app_consent;
        if ($consumerApplicationElement && $consumerApplicationFiles && $consumerApplicationFiles->id && $alreadyLogged) {
            $message = 'We have already logged your Consent';
            $title = 'Thank You!';
            return view('front.message-redirect', ['message' => $message, 'title' => $title]);
        }

        return view('front.consent_page', [
            'name' => $application->name,
            'merchant_name' => $merchant->merchant_name ?? '',
            'application_id' => $hashed_id,
            'applicant_type' => $applicant_type,
        ]);
    }

    public function sendConsentMessage($id, $applicant_type = 1)
    {
        $hashids = new Hashids('Creditfair by CS', 20);
        
        if ($applicant_type == 2) {
            $application = DB::connection('mysql_primary')
                ->table('consumer_application')
                ->where('id', $id)
                ->first(['id', 'co_applicant_name as name', 'co_applicant_email as email', 'co_applicant_mobile_number as mobile_number', 'merchant_id']);
        } else {
            $application = DB::connection('mysql_primary')
                ->table('consumer_application')
                ->where('id', $id)
                ->first(['id', 'name', 'email', 'mobile_number', 'merchant_id']);
        }

        $mobile_number = isset($application->mobile_number) ? wall_decrypt($application->mobile_number) : null;
        $mobile_hash = $mobile_number ? hexdec(substr(md5($mobile_number), 0, 7)) : null;
        
        if ($mobile_hash !== null) {
            $hashed_id = $hashids->encode($id, $mobile_hash);
        } else {
            $hashed_id = $hashids->encode($id);
        }
        
        $consent_path = $hashed_id;
        
        if ($applicant_type == 2) {
            $consent_path .= "/2";
        }

        if ($application->merchant_id && !BNPL::is($application->merchant_id)) {
            $email = isset($application->email) ? wall_decrypt($application->email) : null;
            $merchant = Merchant::where('id', $application->merchant_id)->first(['merchant_name']);
            $consent_key = array_search('Consent', CommunicationService::$com_category);
            $email_comm = CommunicationMapping::whereRaw('FIND_IN_SET('.$consent_key.',type_ids)')
                ->where('communication_id', 1)
                ->where('merchant_id', $application->merchant_id)
                ->count();
            $communication = CommunicationMapping::where('merchant_id', $application->merchant_id)->count();

            if (isset($email) && ($email_comm == 1 || $communication == 0)) {
                $body = '
                    <div style="font-size:13px;font-family:verdana,arial;line-height:1.5">
                        Dear ' . $application->name . ',
                            By clicking "I Accept", I hereby declare all information provided by me is correct and hereby consent to Blacksoil Capital Private Limited and its <a href="' . asset('affiliate-partners') . '">affiliate lending partners</a> to receive my bureau details and other financial /KYC details for financing purpose for purchase made with ' . $merchant->merchant_name . '
                        <div>Annual household Income > 3L</div>
                        <table style="width:100%">
                            <tbody>
                                <tr>
                                    <td align="center" style="padding:30px 30px 30px 30px">
                                        <table cellpadding="0" cellspacing="0" border="0">
                                            <tbody>
                                                <tr>
                                                    <td align="center" style="border-radius:3px;background-color:#0055cc;padding:11px 26px">
                                                        <a href="' . route('consent.page', ['hashed_id' => $hashed_id, 'applicant_type' => $applicant_type]) . '" style="color:white;text-decoration:none;text-transform:uppercase;font-size:16px" target="_blank">
                                                        I Agree</a>
                                                    </td>
                                                </tr>
                                            </tbody>
                                        </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>';

                if ($application->merchant_id != _env("Finsall_id")) {
                    Mail::send('emails.reminders.basic_reminder',
                        ['body' => $body],
                        function ($message) use ($email) {
                            $message->to([$email])->subject('IMPORTANT: Consent required');
                        });
                }
            }

            $link = Shortio::getUrl(asset("consent-page/" . $consent_path));
            $merchant_name = $merchant->merchant_name;
            $affiliateLink = "https://lnk.creditfair.in/5jES";
            $sms_body = "By clicking on link ".$link." I hereby declare all data provided by me is correct and hereby consent to K.M.Global Credit Pvt Ltd. and its affiliate lending partners ".$affiliateLink." to receive my bureau and other financial /KYC details for financing purpose for purchase made with ".$merchant_name.". Regards, Team Credit fair (KM Global)";
            $args = [$link, $merchant_name];
            $entity = ['templateid' => '1307173331891592692', 'entityid' => Templates::$entityid];
            
            send_sms($mobile_number, [
                'message' => $sms_body,
                'id' => $application->id,
                'id_type' => 'application_id',
                'templateDetails' => $entity,
                'args' => $args
            ]);

            $WA_comm = CommunicationMapping::whereRaw('FIND_IN_SET("'.$consent_key.'",type_ids)')
                ->where('communication_id', 3)
                ->where('merchant_id', $application->merchant_id)
                ->count();

            if ($mobile_number && ($WA_comm == 1 || $communication == 0)) {
                sendWhatsAppMessage($mobile_number, [
                    'id' => $id,
                    'templateId' => Templates::$consent_bureau_pull_v1,
                    'args' => [$merchant->merchant_name, $consent_path],
                    'templateType' => 'buttonTemplate'
                ]);
            }
        }
    }

    public function saveConsent($application_id, $applicant_type = 1, $status, $request) {
        $hashids = new Hashids('Creditfair by CS', 20);
        $hashed_id = $hashids->decode($application_id);
        $message = 'Please try after sometime';
        $title = 'Sorry!';

        if (isset($hashed_id[0])) {
            $application_id_decoded = $hashed_id[0];
            $link_mobile_hash = isset($hashed_id[1]) ? $hashed_id[1] : null;
            $fileName = 'consent_logs';
            $coFileName = 'co_app_consent_logs';

            if ($status === 'deny') {
                $fileName = 'deny_consent_logs';
                $coFileName = 'deny_co_app_consent_logs';
            }

            $field_map = [
                1 => ['consent_flag' => 'is_consent', 'mobile_field' => 'mobile_number', 'name_field' => 'name', 's3_folder' => $fileName],
                2 => ['consent_flag' => 'is_co_app_consent', 'mobile_field' => 'co_applicant_mobile_number', 'name_field' => 'co_applicant_name', 's3_folder' => $coFileName]
            ];

            $config = $field_map[$applicant_type];

            $consumerApplicationElement = ConsumerApplicationElement::where('application_id', $application_id_decoded)
                ->first([$config['consent_flag'], 'type_of_customer', 'solar_power_type']);

            if (isset($consumerApplicationElement->{$config['consent_flag']}) && (!$consumerApplicationElement->{$config['consent_flag']})) {
                try {
                    $application = ConsumerApplication::with('proFormaInvoice')
                        ->where('id', $application_id_decoded)
                        ->first(['id', 'name', 'co_applicant_name', 'mobile_number', 'co_applicant_mobile_number', 'lender_id', 'state', 'updated_by', 'loan_amount', 'offer_id', 'merchant_id']);

                    if ($application) {
                        $current_mobile_encrypted = $application->{$config['mobile_field']};
                        $current_mobile = isset($current_mobile_encrypted) ? wall_decrypt($current_mobile_encrypted) : null;
                        
                        if ($link_mobile_hash !== null && $current_mobile) {
                            $current_mobile_hash = hexdec(substr(md5($current_mobile), 0, 7));
                            if ($current_mobile_hash !== $link_mobile_hash) {
                                $message = 'This consent link has expired as your mobile number has changed. A new link has been sent to your updated number.';
                                $title = 'Link Expired';
                                return view('front.message-redirect', ['message' => $message, 'title' => $title]);
                            }
                        }

                        $mobile = '';
                        $ip = '';
                        $ip = (new ApiController())->get_client_ip();
                        $mobile = $application->{$config['mobile_field']};

                        $req_lat = $request->input('latitude');
                        $req_lng = $request->input('longitude');

                        if ((empty($req_lat) || empty($req_lng)) && $application->updated_by != 'WHATSAPP AGENT') {
                            $message = 'Location access is required to provide consent.';
                            $title = 'Location Required';
                            return view('front.message-redirect', ['message' => $message, 'title' => $title]);
                        }

                        $message = 'We have logged your Denial of Consent';
                        $title = 'Thank You!';
                        
                        if ($status != 'deny') {
                            $message = 'We have logged your Consent';
                            ConsumerApplicationElement::where('application_id', $application->id)->update([$config['consent_flag'] => 1]);                            
                            self::removeConsentFromMandatoryList($application->id, $config['s3_folder']);
                        }
                        $consentLog = new ConsentLog();
                        $consentLog->application_id = $application->id;
                        $consentLog->ips = $ip;
                        $consentLog->latitude = $req_lat;
                        $consentLog->longitude = $req_lng;
                        $consentLog->status = $status == 'agree' ? '1' : '0';
                        $consentLog->created_at = date('Y-m-d H:i:s');
                        $consentLog->updated_at = date('Y-m-d H:i:s');
                        $consentLog->type = 'Bureau & KYC';
                        $consentLog->applicant_type = $applicant_type;
                        $consentLog->source = 'admin';
                        $consentLog->save();
                    }
                } catch (\Exception $e) {
                    $cwFactory = new CloudWatchLoggerFactory();
                    $cwFactory->logger(json_encode([
                        'application_id' => $application_id,
                        'message' => $e->getMessage(),
                        'line' => $e->getLine(),
                        'trace' => $e->getTraceAsString()
                    ]));
                }
            } else {
                $message = 'We have already logged your Consent';
                $title = 'Thank You!';
            }
            $payload = [
                'payload' => json_encode(['application_id' => $application_id_decoded, 'source' => 'admin', 'applicant_type' => $applicant_type, 'status' => $status]),
                'from' => 'mconnectConsent',
                'application_id' => $application_id_decoded,
                'available_at' => Carbon::now()->toDateTimeString(),
                'created_at' => Carbon::now()->toDateTimeString(),
                'is_available' => 0
            ];
            JobProvider::insert($payload);
        }

        return view('front.message-redirect', ['message' => $message, 'title' => $title]);
    }

    public function addConsentDocument($application_id, $applicant_type = 1, $status, $request) {
        $cwFactory = new CloudWatchLoggerFactory();
        $hashids = new Hashids('Creditfair by CS', 20);
        $hashed_id = $hashids->decode($application_id);
        $message = 'Success';

        if (!isset($hashed_id[0])) {
            return response()->json(['status' => 'ERROR', 'message' => 'Invalid application id'], 400);
        }
        $application_id_decoded = $hashed_id[0];
        $link_mobile_hash = isset($hashed_id[1]) ? $hashed_id[1] : null;
        $fileName = 'consent_logs';
        $coFileName = 'co_app_consent_logs';

        if ($status === 'deny') {
            $fileName = 'deny_consent_logs';
            $coFileName = 'deny_co_app_consent_logs';
        }

        $field_map = [
            1 => ['consent_flag' => 'is_consent', 'mobile_field' => 'mobile_number', 'name_field' => 'name', 's3_folder' => $fileName],
            2 => ['consent_flag' => 'is_co_app_consent', 'mobile_field' => 'co_applicant_mobile_number', 'name_field' => 'co_applicant_name', 's3_folder' => $coFileName]
        ];

        $config = $field_map[$applicant_type];

        $consumerApplicationElement = ConsumerApplicationElement::where('application_id', $application_id_decoded)
            ->first([$config['consent_flag'], 'type_of_customer', 'solar_power_type']);

        try {
            $application = ConsumerApplication::with('proFormaInvoice', 'merchant')->where('id', $application_id_decoded)->first(['id', 'name', 'co_applicant_name', 'mobile_number', 'co_applicant_mobile_number', 'lender_id', 'state', 'updated_by', 'loan_amount', 'offer_id', 'merchant_id']);
            if ($application) {
                $mobile = '';
                $ip = '';
                $ip = (new ApiController())->get_client_ip();
                $mobile = $application->{$config['mobile_field']};
                $consentLog = ConsentLog::where('application_id', $application_id_decoded)->where('applicant_type', $applicant_type)->first(['latitude', 'longitude']);

                if ($consentLog) {
                    $req_lat = $consentLog->latitude;
                    $req_lng = $consentLog->longitude;
                }

                if ((!isset($req_lat) || !isset($req_lng)) && !in_array($application->updated_by, ['WHATSAPP AGENT', 'WhatsApp'])) {
                    $cwFactory->logger(json_encode(['application_id' => $application_id_decoded,'message' => 'Location access is required to provide consent.']));
                    return response()->json(['status' => 'ERROR', 'message' => $message], 400);
                }

                $data = [
                    'loan_application_no' => $application->proFormaInvoice && isset($application->proFormaInvoice->loan_application_no)
                        ? ucwords($application->proFormaInvoice->loan_application_no) : '',
                    'name' => $application->{$config['name_field']},
                    'mobile' => $mobile,
                    'consent_timestamp' => Carbon::now()->toDateTimeString(),
                    'lender_id' => $application->lender_id
                ];

                if ($ip) $data['ip'] = $ip;
                $data['latitude'] = $req_lat;
                $data['longitude'] = $req_lng;
                $data['status'] = $status;
                
                $view = view('admin.consumer-application.consent_logs_document', ['data' => $data]);

                $pdf = App::make('snappy.pdf.wrapper');
                $request = new Request(['type_of_applicant' => $applicant_type]);
                (new ConsumerDocument($request))->uploadToS3($config['s3_folder'], $application_id_decoded, $pdf->loadHTML($view)->output());
                
                DatapointHelper::refresh($application_id_decoded); // Redis force refresh

                if ($status != 'deny') {
                    if ($applicant_type == 1 || $applicant_type == 2) {
                        $autoBRE = new autoBRE();
                        $merchantOffer = MerchantOffers::where('id', $application->offer_id)->first(['tenure', 'advance_type', 'advance_emi']);
                        $application_status = $application->state;
                        
                        $cwFactory = new CloudWatchLoggerFactory();
                        $cwFactory->logger(json_encode([
                            'application_id' => $application->id, 
                            'net_loan_amount' => $autoBRE->calculateNetLoanAmount($application->loan_amount, $merchantOffer), 
                            'type_of_customer' => $consumerApplicationElement->type_of_customer, 
                            'solar_power_type' => $consumerApplicationElement->solar_power_type
                        ]));

                        if (in_array($application_status, ['in-process', 'incomplete form', 'form completed', 'waiting for documents']) 
                            && in_array($application->updated_by, ['admin', 'MERCHANT API', 'consumer_app', 'merchant admin panel', 'WhatsApp'])
                            && $autoBRE->calculateNetLoanAmount($application->loan_amount, $merchantOffer) <= 500000 && !$application->breMerchant&& $application->merchant->category_id == _env('SOLAR_CATEGORY_ID')) {

                            $merchant = DB::select('select m.id, m.is_auto_approve, m.is_auto_doc, m.pre_approval, m.grade_id from consumer_application c inner join merchant m on c.merchant_id = m.id where c.id = '.$application->id);
                            if (isset($merchant[0]->id) && ($merchant[0]->is_auto_approve || $merchant[0]->is_auto_doc || $merchant[0]->pre_approval) && $merchant[0]->grade_id) {
                                
                                $triggerAutoDecision = true;
                                if ($application_status == 'waiting for documents') {
                                    $required_docs_record = ConsumerApplicationElement::where('application_id', $application->id)->first(['mandatory_document_list']);
                                    if ($required_docs_record && !empty($required_docs_record->mandatory_document_list)) {
                                        $req_docs = explode(',', $required_docs_record->mandatory_document_list);
                                        $other_docs = array_diff($req_docs, ['consent_logs', 'co_app_consent_logs']);
                                        if (count($other_docs) > 0) {
                                            $triggerAutoDecision = false;
                                        }
                                    }
                                }

                                if ($triggerAutoDecision) {
                                    if (!DatapointHelper::isRedisFlow()) {
                                        $jobId = QueueLog::where('application_id', $application->id)->where('cmd', 'command:AutoDecision')
                                                ->where('input', 'like', '%"applicant_type":'.(int) $applicant_type.'%')->value('job_id');
                                        if (is_null($jobId)) {
                                            event(new EventAutoDecision(['id' => $application->id, 'applicant_type' => (int) $applicant_type]));
                                        }
                                    } else {
                                        // This is the ONLY dispatch trigger for the co-applicant
                                        // rejection tier. The observers deliberately dispatch for
                                        // the applicant only, because a co-applicant bureau pull
                                        // needs co-applicant consent and this is the point at
                                        // which that consent exists. The applicant type is passed
                                        // explicitly so consenting as one never dispatches for
                                        // the other.
                                        $dispatched = DatapointHelper::dispatchIfReady($application->id, (int) $applicant_type);
                                        $cwFactory->logger(json_encode([
                                            'title' => 'ConsentDatapointDispatch',
                                            'application_id' => $application->id,
                                            'applicant_type' => (int) $applicant_type,
                                            'dispatched' => $dispatched,
                                            // Both tiers: $dispatched can be true for the rejection
                                            // tier while approval is still waiting on data points.
                                            // Keyed by applicant type; key 2 appears only when the
                                            // application has a co-applicant.
                                            'pending' => DatapointHelper::pendingByApplicant($application->id),
                                        ]));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (\Exception $e) {
            $cwFactory = new CloudWatchLoggerFactory();
            $cwFactory->logger(json_encode([
                'application_id' => $application_id,
                'message' => $e->getMessage(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]));
        }

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

    public function preEligibilityConsentDocument($application_id){
        try {
            $preEligibility = DB::table('pre_eligibility_applications')
                ->where('id', $application_id)
                ->first(['id', 'customer_name', 'mobile_number']);

            if (!$preEligibility) {
                return;
            }

            $data = [
                'loan_application_no' => $preEligibility->id,
                'name'                => $preEligibility->customer_name,
                'mobile'              => $preEligibility->mobile_number,
                'consent_timestamp'   => Carbon::now()->toDateTimeString(),
                'status'              => 'agree',
                'lender_id'           => 2
            ];

            $view = view('admin.consumer-application.consent_logs_document', ['data' => $data]);
            $pdf  = app('snappy.pdf.wrapper');

            $file_path = '/pre_eligibility/' . $application_id . '/consent_logs_' . rand(1, 99) . '.pdf';
            Storage::disk('s3')->put($file_path, $pdf->loadHTML($view)->output());
        } catch (\Exception $e) {
            (new CloudWatchLoggerFactory())->logger(json_encode([
                'title'          => 'consentDocument Failed',
                'pre_eligibility_application_id' => $application_id,
                'message'        => $e->getMessage(),
                'line'           => $e->getLine(),
                'file'           => $e->getFile(),
            ]));
        }
    }


    public function submitConsent(Request $request){
        $status = $request->input('consent_status');
        $application_id = $request->input('application_id');
        $applicant_type = $request->input('applicant_type');
        $request->merge(['em' => true]);

        return $this->saveConsent($application_id, $applicant_type, $status, $request);
    }
    public static function removeConsentFromMandatoryList($application_id, $file_type) {
        if (!in_array($file_type, ['consent_logs', 'co_app_consent_logs'])) {
            return;
        }

        $element = ConsumerApplicationElement::where('application_id', $application_id)->first();
        if ($element && !empty($element->mandatory_document_list)) {
            $mandatoryDocs = explode(',', $element->mandatory_document_list);
            if (($key = array_search($file_type, $mandatoryDocs)) !== false) {
                unset($mandatoryDocs[$key]);
                $element->mandatory_document_list = empty($mandatoryDocs) ? null : implode(',', $mandatoryDocs);
                $element->save();
            }
        }
    }
}
