<?php
/**
 * Created by PhpStorm.
 * User: mindu
 * Date: 17/8/18
 * Time: 11:05 AM
 */
namespace App\Http\Controllers\Service;

use App\Comments;
use App\ConsumerApplicationElement;
use App\ConsumerApplicationFiles;
use App\Http\Controllers\Admin\ConsumerApplicationController;
use App\Http\Controllers\Admin\DisbursementController;
use App\Http\Controllers\Admin\EMICalculation;
use App\ConsumerApplication;
use App\Http\Controllers\ApiController;
use App\Http\Controllers\Controller;
use App\Http\Controllers\FrontController;
use App\JMService\JMServices;
use App\JWTAccess;
use App\KMGP2P;
use App\Merchant;
use App\MerchantOffers;
use App\ProFormaInvoice;
use App\PWAApplicationForm;
use App\Slack;
use App\CreditReport;
use App\SMSLogs;
use App\StatusLogs;
use App\User;
use App\Utkarsh\Utkarsh;
use App\Vivriti;
use Carbon\Carbon;
use Hashids\Hashids;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Grade\GradeController;
use App\Http\Controllers\Admin\ConsumerDocument;
use App\Events\V1\EventAutoDecision;
use Illuminate\Support\Facades\App;
use App\Logging\CloudWatchLoggerFactory;
use App\Http\Controllers\TestingController;
use App\DigitalSignDetails;
use App\JobProvider;
use Illuminate\Support\Facades\Storage;

class ServiceController extends Controller
{

    /**
     * @var Request
     */
    private $request;
    private $groups = null;

        /**
     * @var array
     */
    private $parsedData = [];
    /**
     * @var false
     */
    private $user;

    public $consumerApplicationSchemaRules = [
        // Integers & Foreign Keys
        'user_id'                      => ['nullable', 'integer'],
        'merchant_id'                  => ['nullable', 'integer'],
        'merchant_location_id'         => ['nullable', 'integer'],
        'tenure'                       => ['nullable', 'integer'],
        'lender_id'                    => ['nullable', 'integer'], // tinyint
        'approved_amount'              => ['numeric'], // NO nullable, defaults to 0
        'monthly_income'               => ['nullable', 'integer'],
        'experience'                   => ['nullable', 'integer'],
        'completed_stage'              => ['nullable', 'integer'],
        'co_applicant_monthly_income'  => ['nullable', 'integer'],
        'co_applicant_experience'      => ['nullable', 'integer'],
        'created_by'                   => ['nullable', 'integer'],
        'offer_id'                     => ['nullable', 'integer'],
        'pre_created_by'               => ['nullable', 'integer'],
        'applicant_id'                 => ['nullable', 'integer'],
        'co_applicant_id'              => ['nullable', 'integer'],
        
        // Booleans (tinyint(1))
        'co_applicant_required'        => ['nullable', 'boolean'],
        'additional_docs'              => ['nullable', 'boolean'],

        // Dates
        'dob'                          => ['nullable', 'date'],
        'joining_date'                 => ['nullable', 'date'],

        // Standard Strings (varchar 191)
        'name'                         => ['nullable', 'string', 'max:191'],
        'email'                        => ['nullable', 'email', 'max:191'],
        'mobile_number'                => ['nullable', 'string', 'max:191'],
        'purpose'                      => ['nullable', 'string', 'max:191'],
        'loan_amount'                  => ['nullable', 'string', 'max:191'], // Note: Stored as varchar in your DB
        'src_representative_name'      => ['nullable', 'string', 'max:191'],
        'official_email'               => ['nullable', 'email', 'max:191'],
        'facebook_link'                => ['nullable', 'string', 'max:191'],
        'linkedin_link'                => ['nullable', 'string', 'max:191'],
        'current_address_line_1'       => ['nullable', 'string', 'max:191'],
        'current_address_state'        => ['nullable', 'string', 'max:191'],
        'current_address_city'         => ['nullable', 'string', 'max:191'],
        'current_address_pincode'      => ['nullable', 'string', 'max:191'],
        'current_address_landmark'     => ['nullable', 'string', 'max:191'],
        'permanent_address_line_1'     => ['nullable', 'string', 'max:191'],
        'permanent_address_state'      => ['nullable', 'string', 'max:191'],
        'permanent_address_city'       => ['nullable', 'string', 'max:191'],
        'permanent_address_pincode'    => ['nullable', 'string', 'max:191'],
        'permanent_address_landmark'   => ['nullable', 'string', 'max:191'],
        'company_name'                 => ['nullable', 'string', 'max:191'],
        'company_number'               => ['nullable', 'string', 'max:191'],
        'contact_address'              => ['nullable', 'string', 'max:191'],
        'work_address_line_1'          => ['nullable', 'string', 'max:191'],
        'work_address_state'           => ['nullable', 'string', 'max:191'],
        'work_address_city'            => ['nullable', 'string', 'max:191'],
        'work_address_pincode'         => ['nullable', 'string', 'max:191'],
        'work_address_landmark'        => ['nullable', 'string', 'max:191'],
        'co_applicant_name'            => ['nullable', 'string', 'max:191'],
        'co_applicant_relationship'    => ['nullable', 'string', 'max:191'],
        'co_applicant_dob'             => ['nullable', 'string', 'max:191'], // Note: Stored as varchar, unlike primary dob
        'co_applicant_gender'          => ['nullable', 'string', 'max:191'],
        'co_applicant_pan_card'        => ['nullable', 'string', 'max:191'],
        'co_applicant_aadhaar_card'    => ['nullable', 'string', 'max:191'],
        'co_applicant_email'           => ['nullable', 'email', 'max:191'],
        'co_applicant_mobile_number'   => ['nullable', 'string', 'max:191'],
        'co_applicant_address_line_1'  => ['nullable', 'string', 'max:191'],
        'co_applicant_address_state'   => ['nullable', 'string', 'max:191'],
        'co_applicant_address_pincode' => ['nullable', 'string', 'max:191'],
        'co_applicant_address_city'    => ['nullable', 'string', 'max:191'],
        'co_applicant_address_landmark'=> ['nullable', 'string', 'max:191'],
        'state'                        => ['nullable', 'string', 'max:191'],
        'assigned_to'                  => ['nullable', 'string', 'max:191'],
        'credit_score'                 => ['nullable', 'string', 'max:191'],
        'rejection_reason'             => ['nullable', 'string', 'max:191'],
        'misc_info'                    => ['nullable', 'string', 'max:191'],
        'updated_by'                   => ['nullable', 'string', 'max:191'],
        'alt_contact_number'           => ['nullable', 'string', 'max:191'],
        'co_applicant_company_name'    => ['nullable', 'string', 'max:191'],
        'co_applicant_company_number'  => ['nullable', 'string', 'max:191'],

        // Extended Strings
        'src_merchant_name'            => ['nullable', 'string', 'max:200'],
        'pan_card'                     => ['nullable', 'string', 'max:255'],
        'aadhaar_card'                 => ['nullable', 'string', 'max:255'],
        'secondary_status'             => ['nullable', 'string', 'max:100'],
        'additional_docs_list'         => ['nullable', 'string', 'max:1023'],
        'file_income_proof'            => ['nullable', 'string', 'max:1023'],
        'file_bank_statement'          => ['nullable', 'string', 'max:1023'],
        'file_pan_card'                => ['nullable', 'string', 'max:1023'],
        'file_aadhaar_card'            => ['nullable', 'string', 'max:1023'],
        'file_electricity_bill'        => ['nullable', 'string', 'max:1023'],
        
        // Text
        'ckyc_name'                    => ['nullable', 'string'], // TEXT fields don't practically need a strict max for UI

        // Enums
        'gender'                       => ['nullable', 'in:MALE,FEMALE'],
        'marital_status'               => ['nullable', 'in:MARRIED,SINGLE'],
        'current_address_status'       => ['nullable', 'in:RENTED,OWNED,PARENTS HOUSE,Self Owned,Parent Owned,Rented With Family,Rented With Friend,Company Allotted'],
        'permanent_address_status'     => ['nullable', 'in:RENTED,OWNED,PARENTS HOUSE,Self Owned,Parent Owned,Rented With Family,Rented With Friend,Company Allotted'],
        'co_applicant_address_status'  => ['nullable', 'in:RENTED,OWNED,PARENTS HOUSE,Self Owned,Parent Owned,Rented With Family,Rented With Friend,Company Allotted'],
        'employee_status'              => ['nullable', 'in:Self Employed - Professional,Self Employed - Business,UNEMPLOYED,SALARIED,BUSINESS,PENSIONER,HOUSEWIFE'],
        'co_applicant_employee_status' => ['nullable', 'in:UNEMPLOYED,SALARIED,BUSINESS,PENSIONER,HOUSEWIFE'],
    ];

    public $consumerApplicationElementSchemaRules = [
        // --- Foreign Keys & Identifiers (Integers) ---
        'application_id'                 => ['nullable', 'integer'],
        'center_id'                      => ['nullable', 'integer'],
        'bank_id'                        => ['nullable', 'integer'],
        'auto_document_rule_id'          => ['nullable', 'integer'],
        'pre_approval_id'                => ['nullable', 'integer'],
        'collection_advisor'             => ['nullable', 'integer'],
        'avanse_customer_id'             => ['nullable', 'integer'],
        'vendor_id'                      => ['nullable', 'integer'],
        'previous_applied_offer'         => ['nullable', 'integer'],

        // --- Core Integers (int / tinyint) ---
        'industry'                       => ['nullable', 'integer'],
        'profession_type'                => ['nullable', 'integer'],
        'co_applicant_industry'          => ['nullable', 'integer'],
        'co_applicant_profession_type'   => ['nullable', 'integer'],
        'negative_profile'               => ['nullable', 'integer'],
        'co_applicant_for_signing'       => ['nullable', 'integer'],
        'co_applicant_for_income'        => ['nullable', 'integer'],
        'amount_over_due'                => ['nullable', 'integer'],
        'total_amount_due'               => ['nullable', 'integer'],
        'emi_paid'                       => ['nullable', 'integer'],
        'emi_pending'                    => ['nullable', 'integer'],
        'agreement_version'              => ['nullable', 'integer'],
        'withhold_adjusted'              => ['nullable', 'integer'],
        'onfido_skip'                    => ['nullable', 'integer'],
        'agreement_resign'               => ['nullable', 'integer'],
        'nominee_gender'                 => ['nullable', 'integer'],
        'soft_lead'                      => ['nullable', 'integer'],
        'co_app_onfido_skip'             => ['nullable', 'integer'],
        'is_co_app_consent'              => ['nullable', 'integer'],
        'principal_due'                  => ['nullable', 'integer'],
        'total_principal_due'            => ['nullable', 'integer'],
        'repayment_type'                 => ['nullable', 'integer'],
        'inverter_monthly_power_bill'    => ['nullable', 'integer'],
        'inverter_gross_project_amount'  => ['nullable', 'integer'],
        'inverter_subsidy_amount'        => ['nullable', 'integer'],
        'foreclosure_amount_sent'        => ['nullable', 'integer'],
        'foreclosure_link_sent_by'       => ['nullable', 'integer'],
        'type_of_customer'               => ['nullable', 'integer'],
        'verify_risk_category'           => ['nullable', 'integer'],
        'decision_reason'                => ['nullable', 'integer'],
        'initial_applied_tenure'         => ['nullable', 'integer'],
        'linked_status'                  => ['nullable', 'integer'],
        'co_linked_status'               => ['nullable', 'integer'],
        'solar_power_type'               => ['nullable', 'integer'],

        // --- Booleans (tinyint(1) / tinyint flags) ---
        'is_auto_approved'               => ['nullable', 'boolean'],
        'is_reviewed'                    => ['nullable', 'boolean'],
        'is_payout'                      => ['nullable', 'boolean'],
        'disbursement_sent'              => ['nullable', 'boolean'],
        'is_consent'                     => ['nullable', 'boolean'],
        'is_bnpl'                        => ['nullable', 'boolean'],
        'advance_payment_verified'       => ['nullable', 'boolean'],

        // --- Dates (Native Date Columns) ---
        'foreclosure_date'               => ['nullable', 'date'],
        'last_emi_date'                  => ['nullable', 'date'],

        // --- Double / Floats ---
        'pf_discount'                    => ['nullable', 'numeric'], // double(4,2)

        // --- Standard Strings (varchar 191) ---
        'gst_number'                     => ['nullable', 'string', 'max:191'],
        'designation'                    => ['nullable', 'string', 'max:191'],
        'department'                     => ['nullable', 'string', 'max:191'],
        'contact'                        => ['nullable', 'string', 'max:191'],
        'product_name'                   => ['nullable', 'string', 'max:191'],
        'preferred_language'             => ['nullable', 'string', 'max:191'],
        'product_id'                     => ['nullable', 'string', 'max:191'],
        'payment_transfer_date'          => ['nullable', 'string', 'max:191'], // Stored as varchar in DB
        'hold_amount'                    => ['nullable', 'string', 'max:191'],
        'reason_for_loan'                => ['nullable', 'string', 'max:191'],
        'reference_name_1'               => ['nullable', 'string', 'max:191'],
        'reference_name_2'               => ['nullable', 'string', 'max:191'],
        'reference_contact_1'            => ['nullable', 'string', 'max:191'],
        'reference_contact_2'            => ['nullable', 'string', 'max:191'],
        'reference_relation_1'           => ['nullable', 'string', 'max:191'],
        'reference_relation_2'           => ['nullable', 'string', 'max:191'],
        'nominee_full_name'              => ['nullable', 'string', 'max:191'],
        'nominee_relationship'           => ['nullable', 'string', 'max:191'],
        'nominee_mobile_number'          => ['nullable', 'string', 'max:191'],
        'video_kyc'                      => ['nullable', 'string', 'max:191'],
        'reference_number'               => ['nullable', 'string', 'max:191'],
        'merchant_representative_name'   => ['nullable', 'string', 'max:191'],
        'merchant_representative_mobile' => ['nullable', 'string', 'max:191'],
        'merchant_representative_email'  => ['nullable', 'email', 'max:191'],
        'unique_id_number'               => ['nullable', 'string', 'max:191'],
        'co_applicant_designation'       => ['nullable', 'string', 'max:191'],
        'admission_status'               => ['nullable', 'string', 'max:191'],
        'father_name'                    => ['nullable', 'string', 'max:191'],
        'co_applicant_father_name'       => ['nullable', 'string', 'max:191'],
        'inverter'                       => ['nullable', 'string', 'max:191'],
        'inverter_model_description'     => ['nullable', 'string', 'max:191'],
        'inverter_KW_installation'       => ['nullable', 'string', 'max:191'], // DB is varchar
        'inverter_power_savings'         => ['nullable', 'string', 'max:191'], // DB is varchar
        'panel'                          => ['nullable', 'string', 'max:191'],
        'type_of_customer_sub_category'  => ['nullable', 'string', 'max:191'],
        'discount_by_cf'                 => ['nullable', 'string', 'max:191'],
        'login_id_of_installer'          => ['nullable', 'string', 'max:191'],
        'password'                       => ['nullable', 'string', 'max:191'],
        'website_link'                   => ['nullable', 'string', 'max:191'],
        'discom_service_provider'        => ['nullable', 'string', 'max:191'],
        'other_discom_service_provider'  => ['nullable', 'string', 'max:191'],
        'installation_address_line_1'    => ['nullable', 'string', 'max:191'],
        'installation_address_state'     => ['nullable', 'string', 'max:191'],
        'installation_address_city'      => ['nullable', 'string', 'max:191'],
        'installation_address_landmark'  => ['nullable', 'string', 'max:191'],
        'installation_address_status'    => ['nullable', 'string', 'max:191'],
        'installation_address_pincode'   => ['nullable', 'string', 'max:191'],
        'education_level'                => ['nullable', 'string', 'max:191'],
        'mother_name'                    => ['nullable', 'string', 'max:191'],
        'applicant_caste'                => ['nullable', 'string', 'max:191'],
        'loan_type'                      => ['nullable', 'string', 'max:191'],
        'applicant_religion'             => ['nullable', 'string', 'max:191'],
        'tax_residency_app'              => ['nullable', 'string', 'max:191'],
        'tax_residency_co_app'           => ['nullable', 'string', 'max:191'],
        'risk_category'                  => ['nullable', 'string', 'max:191'],
        'type_of_customer_application'   => ['nullable', 'string', 'max:191'],
        'type_of_entity'                 => ['nullable', 'string', 'max:191'],
        'bank_account_type'              => ['nullable', 'string', 'max:191'],

        // --- Extended & Specialized Strings ---
        'work_email'                     => ['nullable', 'email', 'max:255'],
        'decision_reason_other'          => ['nullable', 'string', 'max:200'],
        'current_address_lat_long'       => ['nullable', 'string', 'max:100'],
        'permanent_address_lat_long'     => ['nullable', 'string', 'max:100'],
        'duration'                       => ['nullable', 'string', 'max:20'],
        'nominee_dob'                    => ['nullable', 'string', 'max:10'], // Stored as varchar
        'nominee_salutation'             => ['nullable', 'string', 'max:3'],

        // --- Text & LongText Fields ---
        'current_address_text'           => ['nullable', 'string'],
        'current_formatted_text'         => ['nullable', 'string'],
        'permanent_address_text'         => ['nullable', 'string'],
        'permanent_formatted_text'       => ['nullable', 'string'],
        'telecom_response'               => ['nullable', 'string'],
        'mandatory_document_list'        => ['nullable', 'string'],
        'mandatory_details_list'         => ['nullable', 'string'],
        'credit_approval_video'          => ['nullable', 'string'],
        'existing_customer'              => ['nullable', 'string'],
        'disb_query_reasons'             => ['nullable', 'string'], // longtext
        'multi_tranche_exception_list'   => ['nullable', 'string'], // longtext

        // --- JSON ---
        'merchant_risk_mitigation'       => ['nullable', 'json'],
    ];
    private $cwFactory;

    public function __construct(Request $request){
        $this->request = $request;
        $this->cwFactory = new CloudWatchLoggerFactory();
    }

    public function getBureauData()
    {
        return $this->request->all();
    }

    public function getOffers(){
        $emiCalculation = new EMICalculation($this->request);
        $emiCalculation->merchant_id = $this->request->get('merchant_id');
        $emiCalculation->product_id = explode(',', $this->request->get('product_id'));
        $emiCalculation->loan_amount = $this->request->get('loan_amount');
        return response()->json(['status' => 'OK', 'data' => $emiCalculation->getEMIsByMerchant()]);
    }

    public function runAutoDecision(Request $request)
    {
        try {

            $application_id = $request->query('application_id');
            $hashids = new Hashids('Creditfair by CS', 20);
            $application_unhashed_id = $hashids->decode($application_id);
            $grade = new GradeController($request);
            // $__grade = $grade->ApprovalCheckV1($application_unhashed_id);
            // $_grade = $__grade->getOutput();

            (new Slack(new Request(['title' => 'Run auto decision API', 'fields' => ['application_id' => $application_unhashed_id[0]], 'group' => Slack::$STAGE_TESTING])))->send();
            $applicationDetails = ConsumerApplication::with('merchant', 'creditReport')->where('id', $application_unhashed_id[0])->first();
            $tableOfOffers = $applicationDetails->merchant->table_of_offers ?? false;
            if (count($applicationDetails->creditReport) > 0) {
                $is_bureau_generated = $applicationDetails->creditReport[0]->id;
            }

            if (!$tableOfOffers) {
                $this->updateStatus($application_unhashed_id[0], 'waiting for decision');
                return response()->json(['status' => 'OK', 'message' => 'Not Approved']);
            }
            if (isset($is_bureau_generated)) {

                $request['id'] = $application_unhashed_id[0];
                $gradeController = new GradeController($request);
                $_grade = $gradeController->ApprovalCheckV2($request->get('id'));
                (new Slack(new Request(['title' => 'saveDecisionTable API', 'fields' => ['application_id' => $application_unhashed_id[0]], 'group' => Slack::$STAGE_TESTING])))->send();
                $approvalStatus = $gradeController->saveDecisionInTable($applicationDetails,$_grade);
                if ($approvalStatus) {
                    $this->updateStatus($request->get('id'), 'cf approved');
                    return response()->json(['status' => 'OK', 'message' => 'Approved']);
                }
                else if($gradeController->autoReject($_grade, $request->get('id'))){
                    $this->updateStatus($request->get('id'), 'rejected');
                    return response()->json(['status' => 'OK', 'message' => 'Rejected']);
                }
                else {
                    $this->updateStatus($request->get('id'), 'waiting for decision');
                    return response()->json(['status' => 'OK', 'message' => 'Not Approved']);
                }
            }else{
                return response()->json(['status' => 'OK', 'message' => 'Bureau not generated']);

            }
        } catch (\Exception $e) {
            return response()->json(['status' => 'OK', 'message' => 'Exception occurred while running auto decesion']);

            (new Slack(new Request(['title' => 'Run auto decision API', 'group' => Slack::$STAGE_TESTING])))->send();

        }
    }

    public function updateStatus($id, $status){
        $consumer_application = ConsumerApplication::find($id);
        $consumer_application->state = $status;
        if($status == 'rejected') {
            $consumer_application->approved_amount = 0;
        }
        $consumer_application->save();
        StatusLogs::insert([
            'application_id' => $id,
            'user_id' => 107,
            'status' => $status,
            'created_at' => Carbon::now()->toDateTimeString()
        ]);
    }

    public function getAgreement(Request $request)
    {
        try {
            $application_id = $request->query('application_id');
            $type = $request->query('type');

            $hashids = new Hashids('Creditfair by CS', 20);
            $application_unhashed_id = $hashids->decode($application_id);

            $request->merge(['type' => 'Loan Agreement']);

            $consumerdocument = new ConsumerDocument($request);
            $__consumerdocument = $consumerdocument->getDocument($application_unhashed_id[0]);
            $data = $__consumerdocument->getData();
            $snappypdf = App::make('snappy.pdf.wrapper');
            $snappypdf->setOption("footer-right", "Page [page] from [topage]");
            $snappypdf->setOption('footer-font-size',10);
            $snappypdf->setOption('margin-bottom', 30);
            $snappypdf->setOption('footer-html', view('admin.editor.footer',['type'=>"Loan Agreement Esign",'lender'=> $__consumerdocument['lender']])->render());
            // $snappypdf->setTemporaryFolder(storage_path()."/")->setOption("enable-local-file-access", true);

            if ($data['lender']['id'] == \App\Avanse\Services\AvanseServices::$lender_id) {
                $view = view('admin.documents.avanse.loan_agreement_v2', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == \App\ABFL\Services\Services::$lender_id) {
                $pdf = 1;
                $data['pdf'] = $pdf;
                $view = view('admin.documents.abfl.combine_loan_agreement', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == JMServices::$lender_id) {
                $pdf = 1;
                $snappypdf->setOption('header-html', (new ConsumerDocument($request))->getPDFHeaderView());
                $data['pdf'] = $pdf;
                $view = view('admin.documents.jm.loan_agreement_v2', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == Utkarsh::$lender_id) {
                $pdf = 1;
                $snappypdf->setOption('header-html', (new ConsumerDocument($request))->getPDFHeaderView(Utkarsh::$lender_id));
                $data['pdf'] = $pdf;
                $view = view('admin.documents.utkarsh.loan_agreement_v3', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == Vivriti::$lender_id) {
                $pdf = 1;
                $data['pdf'] = $pdf;
                $view = view('admin.documents.vivriti.loan_agreement_v2', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == KMGP2P::$lender_id) {
                $pdf = 1;
                $data['pdf'] = $pdf;
                $view = view('admin.documents.kmgp2p.borrower_agreement', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['lender']['id'] == \App\LendBox::$lender_id) {
                $pdf = 1;
                $data['pdf'] = $pdf;
                $view = view('admin.documents.lendbox.borrower_agreement', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } elseif ($data['is_bnpl']) {
                $view = view('admin.documents.bnpl.service_agreement', $data)->render();
                if ($type == 'pdf') {
                    $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                    return response()->json(['status' => 'OK', 'message' => $pdfView]);
                }
                return response()->json(['status' => 'OK', 'message' => $view]);
                // return $view;
            } else {
                if ($data['user']['agreement_version'] == 2) {
                    if ($data['lender']['id'] == 2) {
                        $pdf = 1;
                        $data['pdf'] = $pdf;
                        $view = view('admin.documents.borrower_loan_agreement_esign_v_two_v2', $data)->render();
                        if ($type == 'pdf') {
                            $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                            // $snappypdf->setOption("footer-right", "Page [page] from [topage]");
                            // $snappypdf->setOption('footer-font-size',10);
                            // $snappypdf->setOption('margin-bottom', 30);
                            // $snappypdf->setOption('footer-html', view('admin.editor.footer',['type'=>"Loan Agreement Esign",'lender'=> $__consumerdocument['lender']])->render());
                            return response()->json(['status' => 'OK', 'message' => $pdfView]);
                        }
                        return response()->json(['status' => 'OK', 'message' => $view]);
                        // return $view;
                    } else {
                        $view = view('admin.documents.borrower_loan_agreement_esign_v_two', $data)-> render();
                        if ($type == 'pdf') {
                            $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                            return response()->json(['status' => 'OK', 'message' => $pdfView]);
                        }
                        return response()->json(['status' => 'OK', 'message' => $view]);
                        // return $view;
                    }
                } else {
                    $view = view('admin.documents.borrower_loan_agreement', $data)->render();
                    if ($type == 'pdf') {
                        $pdfView = base64_encode($snappypdf->loadHTML($view)->output());
                        return response()->json(['status' => 'OK', 'message' => $pdfView]);
                    }
                    return response()->json(['status' => 'OK', 'message' => $view]);
                    // return $view;
                }
            }


        } catch (\Exception $e) {
            $this->cwFactory->logger(json_encode(['application_id' => $application_unhashed_id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
        }
    }

    public function signAgreement(Request $request) {
        try {
            $application_id = $request->get('application_id');
            $load_time = $request->get('load_time');
            $click_time = $request->get('click_time');
            $hashids = new Hashids('Creditfair by CS', 20);
            $application_unhashed_id = $hashids->decode($application_id);
            $isExist = DigitalSignDetails::where('application_id', $application_unhashed_id[0])->where('applicant', 1)->first(['id']);
            if (!isset($isExist)) {
                $digital_sign = new DigitalSignDetails();
                $digital_sign->application_id = $application_unhashed_id[0];
                $digital_sign->applicant = 1;
                $digital_sign->load_time = date('Y-m-d H:i:s',strtotime($load_time));
                $digital_sign->click_time = date('Y-m-d H:i:s',strtotime($click_time));
                $digital_sign->isaddress =  'UNKNOWN';
                $digital_sign->isagreementsigned = 1;
                $digital_sign->language = 'ENGLISH';
                $digital_sign->type = "consumer";
                $digital_sign->save();
                $agreementsigning = (new TestingController())->generateEsignLoanAgreement($application_unhashed_id[0]);
                if ($agreementsigning == true) {
                    // $payload = [
                    //     'payload' => json_encode(array_merge(['id' => $application_unhashed_id[0], 'status' => 'approved', 'previous_status' => 'cf approved', 'auth_user_id' => 107, 'lender_id' => 2, "residing" => "0", "linkedin" => "", "facebook" => "", "tele_verification" => "0", "contact" => "", "address_document_mapping_permanent_address" => "", "address_document_mapping_current_address" => "", "product_verification" => "0", "product_verification_reason" => "", "next_status" => "Approved", "exception_doc_list" => "[]", "approved_reason_list" => ""])),
                    //     'from' => 'statusChange',
                    //     'application_id' => $application_unhashed_id[0],
                    //     'available_at' => Carbon::now()->toDateTimeString(),
                    //     'created_at' => Carbon::now()->toDateTimeString()
                    // ];
                    $payload = [
                        'payload' => json_encode(array_merge(['id' => $application_unhashed_id[0], 'status' => 'approved', 'previous_status' => 'cf approved', 'auth_user_id' => 107, 'lender_id' => 2, "documents" => "[pro_forma_invoice, sanction_letter]"])),
                        'from' => 'emiCheckoutGenerateDocuments',
                        'application_id' => $application_unhashed_id[0],
                        'available_at' => Carbon::now()->toDateTimeString(),
                        'created_at' => Carbon::now()->toDateTimeString()
                    ];
                    JobProvider::insert($payload);
                    return response()->json(['status' => 'OK', 'message' => 'Agreement Signed Successfully']);
                }
                return response()->json(['status' => 'FAIL', 'message' => 'Agreement Signed Failed']);
            } else {
                return response()->json(['status' => 'OK', 'message' => 'Agreement Already Signed']);
            }

        } catch (\Exception $e) {
            $this->cwFactory->logger(json_encode(['application_id' => $application_unhashed_id, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
        }
    }

    public function getLink(){
        $this->user = $this->getUser();
        if (!$this->user){
            return response()->json(['id' => 0, 'message' => 'Unauthorized'], 401);
        }
        $id = $this->request->get('application_id');
        try {
            $data = [];
            if ($this->request->get('link_type') == "esign_link" && $this->request->get('application_id')) {
                $esignLink = (new ConsumerDocument($this->request))->getEsignLink($id);
                $data['link'] = $esignLink['esign'];
            } else if ($link = $this->getLinkByType($id, $this->request->get('link_type'))) {
                $data['link'] = $link;
            }

            if (!isset($data['link']) && (isset($data['link']) && empty($data['link']))) {
                $id = 0;
                $message = "Application Id or Data is incorrect";
            } else {
                $message = $this->request->get('link_type') . ": " . $data['link'];
            }
        }catch (\Exception $e){
            $message = "Application Id or Data is incorrect";
            $id = 0;
        }

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

    public function getLinkByType($id, $link_type){

        $user = ConsumerApplication::with('proFormaInvoice', 'lender', 'emi', 'merchant', 'activeOffer')->where('id', $id)->first(['id', 'approved_amount', 'merchant_id', 'offer_id', 'lender_id', 'name', 'mobile_number', 'email', 'co_applicant_name', 'co_applicant_mobile_number', 'co_applicant_email', 'state']);

        if(!isset($user->id)){
            return false;
        }

        $application = new ConsumerApplicationController();
        $disbursementController = new DisbursementController($this->request);
        if ($link_type == "processing_fee_link" && isset($user->emi->processing_fee) && $user->emi->processing_fee > 0) {
            $process['proFormaInvoice'] = $user->proFormaInvoice;
            $process['processing_fee_first_emi'] = $user->activeOffer->processing_fee_first_emi ?? '';
            $process['merchant_processing_collected'] = isset($user->merchant->is_collected) && $user->merchant->is_collected == 1 ? $user->merchant->is_collected : (isset($user->proFormaInvoice) && $user->proFormaInvoice->processing_fee_by_merchant == 1 ? $user->proFormaInvoice->processing_fee_by_merchant : 0);
            if ((new ConsumerDocument($this->request))->isProcessingFeeCollected($process)) {
                if (!($application)->isProcessingFeeApplicable($user->id)) {
                    $processingFeeData = $process;
                    $processingFeeData['lender'] = $user->lender;
                    return $application->sendProcessingFeeLink($processingFeeData, $user);
                }
            }
        }else if ($link_type == 'insurance_link' && $insurance_fee_amount = $disbursementController->isCustomerPayingInsuranceFee($user)) {
            return $application->sendInsuranceFeeLink($insurance_fee_amount, $user);
        }else if ($link_type == 'advance_payment_link' && $cf_advance_amount = $disbursementController->isCFCollectingAdvance($user)) {
            return $application->sendAdvanceAmountLink($cf_advance_amount, $user);
        }

        return false;
    }

    public function createLoan() {
        try {
            $this->user = $this->getUser();
            if (!$this->user) {
                return response()->json(['id' => 0, 'message' => 'Unauthorized'], 401);
            }
            $application_id = $this->request->has('application_id') ? $this->request->get('application_id') : null;
            $isUpdateRequest = isset($application_id) && $application_id != "" ? true : false;

            $rawMessage = $this->request->input('text', '');
            $textData = json_decode(
                html_entity_decode($rawMessage),
                true
            );
            if (is_array($textData)) {
                // Structured JSON payload from the LLM
                if (
                    isset($textData['consumer_application']) ||
                    isset($textData['consumer_application_element'])
                ) {
                    // Un-Structured JSON format
                    $this->parsedData = array_merge(
                        $textData['consumer_application'] ?? [],
                        $textData['consumer_application_element'] ?? []
                    );
                } else {
                    $this->parsedData = $textData;
                }
                // Remove empty fields (null / empty string) so they don't overwrite existing data
                $this->parsedData = array_filter(
                    $this->parsedData,
                    function ($value) {
                        return $value !== null && $value !== '';
                    }
                );
            } else {
                // Raw "key:: value" text (not JSON) — parse the body directly
                $this->bodyParser();
            }
            $this->loadAdditionalAttributes($isUpdateRequest);
            $this->simplyAttributes();

            if (!$this->parsedData['merchant_id']) {
                return response()->json(['id' => 0, 'message' => 'Merchant not found, Please whitelist the merchant'], 200);
            }

            // if (isset($this->parsedData['inverter_kw_installation'])) {
            //     $this->parsedData['inverter_kw_installation'] = (float)preg_replace('/[^0-9.]/', '', (string)$this->parsedData['inverter_kw_installation']);
            //     $calpowersaving = $this->parsedData['inverter_kw_installation'] * 1000;
            //     $this->parsedData['inverter_power_savings'] = $calpowersaving;
            // }

            // foreach (['dob', 'co_applicant_dob'] as $dobField) {
            //     if (!empty($this->parsedData[$dobField])) {
            //         try {
            //             $this->parsedData[$dobField] = Carbon::createFromFormat('d/m/Y', $this->parsedData[$dobField])->format('Y-m-d');
            //         } catch (\Exception $e) {
            //             $this->parsedData[$dobField] = null;
            //         }
            //     }
            // }

            // $this->parsedData = $this->filterInvalidDataTypes($this->parsedData);

            // $mobileFields = ['mobile_number', 'co_applicant_mobile_number', 'alt_contact_number'];
            // foreach ($mobileFields as $field) {
            //     if (!empty($this->parsedData[$field])) {
            //         $val = str_replace(' ', '', (string)$this->parsedData[$field]);
            //         if (strlen($val) == 11) {
            //             $val = substr($val, 1);
            //         } elseif (strlen($val) == 12) {
            //             $val = substr($val, 2);
            //         }
            //         $this->parsedData[$field] = $val;
            //     }
            // }

            if ($isUpdateRequest) {

                $application = ConsumerApplication::with('merchant')->find((int)$application_id);

                if (!$application) {
                    return response()->json(['id' => 0, 'message' => 'Application not found'], 200);
                }

                if ((new ApiController())->checkEligibility(new Request([
                    'pan' => $this->request->get('pan_card'),
                    'email' => $this->request->get('email'),
                    'mobile_number' => $this->request->get('mobile_number')
                ]))) {
                    return response()->json([
                        'id' => 0, 
                        'message' => 'Duplicate Customer found',
                        'merchant_slug' => $application->merchant->slug
                    ], 200);
                }

                $allowedStatuses = ['form completed', 'in-process', 'waiting for documents','incomplete form'];
                if (!in_array(strtolower($application->state), $allowedStatuses)) {
                    return response()->json([
                        'id' => $application->id,
                        'message' => "Cannot update application in status: {$application->state}"
                    ], 400);
                }
                $application->fill($this->parsedData);
                $application->save();

                $this->cwFactory->logger([
                    'title' => 'Whatsapp create loan',
                    'action' => 'updated',
                    'application_id' => $application->id,
                    'raw_message' => $rawMessage,
                ]);

                StatusLogs::insert([
                    'application_id' => $application->id,
                    'user_id' => 107, // Hardcoded as per your requirement
                    'status' => $application->state,
                    'created_at' => Carbon::now()->toDateTimeString()
                ]);

                $applicationElement = ConsumerApplicationElement::where('application_id', $application->id)->first();
                if (!$applicationElement) {
                    $applicationElement = new ConsumerApplicationElement();
                    $applicationElement->application_id = $application->id;
                }

                if ($elementAttributes = $this->getPropertiesForElement($applicationElement->fillable)) {
                    $applicationElement->fill($elementAttributes);
                }
                $applicationElement->save();

                $missingFields = $this->checkMandatoryFields($application->id);
                if($missingFields == '') {
                    $message = "Application updated successfully with id: " . $application->id . " \n\n Thank you \n " . $missingFields;
                } else {
                    $message = "Application updated successfully with id: " . $application->id . " \n\n Please provide the following fields to proceed \n " . $missingFields;
                }

                $merchant_slug = $application->merchant->slug ?? '';

                return response()->json(['id' => $application->id, 'message' => $message, 'merchant_slug' => $merchant_slug], 200);

            } else {

                // Creating New Application
                if ((new ApiController())->checkEligibility(new Request([
                    'pan' => $this->request->get('pan_card'),
                    'email' => $this->request->get('email'),
                    'mobile_number' => $this->request->get('mobile_number')
                ]))) {
                    return response()->json(['id' => 0, 'message' => 'Duplicate Customer found'], 200);
                }

                if (empty($this->parsedData['pan_card']) || empty($this->parsedData['mobile_number']) || empty($this->parsedData['name'])) {
                    return response()->json(['id' => null, 'message' => 'Please share valid Name, PAN Card, and Mobile Number to create application'], 400);
                }

                $customer = (new ConsumerApplication())->saveCustomer($this->parsedData);
                $application = new ConsumerApplication();
                $application->fill($this->parsedData);
                $application->applicant_id = $customer->applicant_id;
                $application->state = 'in-process';
                $application->save();

                $application->load('merchant');

                $this->cwFactory->logger([
                    'title' => 'Whatsapp create loan',
                    'action' => 'created',
                    'application_id' => $application->id,
                    'raw_message' => $rawMessage,
                ]);

                StatusLogs::insert([
                    'application_id' => $application->id,
                    'user_id' => 107, // Hardcoded as per your requirement
                    'status' => $application->state,
                    'created_at' => Carbon::now()->toDateTimeString()
                ]);

                $applicationElement = new ConsumerApplicationElement();
                $this->parsedData['application_id'] = $application->id;
                $elementProperties = [];

                if ($elementAttributes = $this->getPropertiesForElement($applicationElement->fillable)) {
                    $elementProperties = array_merge($elementProperties, $elementAttributes);
                }
                $applicationElement->fill($elementProperties);
                $applicationElement->save();

                (new ConsumerApplicationController())->sendMessageBeforeBureauPull($application->id); // consent part added as per request from Neha

                $missingFields = $this->checkMandatoryFields($application->id);
                if($missingFields == '') {
                    $message = "Application created successfully with id: " . $application->id . " \n\n Thank you \n " . $missingFields;
                } else {
                    $message = "Application created successfully with id: " . $application->id . " \n\n Please provide the following fields to proceed \n " . $missingFields;
                }
                
                return response()->json(['id' => $application->id, 'message' => $message, 'merchant_slug' => $application->merchant->slug], 200);
            }
        } catch (\Exception $e) {
            $this->cwFactory->logger(['title' => 'Whatsapp create loan', 'error' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]);
            
            (new Slack(new Request([
                'title' => 'Exception in Whatsapp create loan',
                'fields' => [
                    'error' => $e->getMessage(),
                    'line' => $e->getLine(),
                    'file' => $e->getFile()
                ],
                'group' => Slack::$PROD_TECH_BUG
            ])))->send();

            return response()->json(['id' => 0, 'message' => 'Please connect with the tech support team'], 200);
        }
    }

    public function filterInvalidDataTypes(array $data)
    {
        $allRules = array_merge($this->consumerApplicationSchemaRules, $this->consumerApplicationElementSchemaRules);

        foreach ($data as $key => $value) {
            if (isset($allRules[$key])) {
                $validator = \Illuminate\Support\Facades\Validator::make(
                    [$key => $value],
                    [$key => $allRules[$key]]
                );

                if ($validator->fails()) {
                    unset($data[$key]);
                }
            }
        }

        return $data;
    }

    public function fetchLoanStatus() {
        try {
            $user = $this->getUser();
            if ($user == false) {
                return response()->json(['status' => 'FAIL', 'message' => 'Unauthorized'], 401);
            }

            $merchant_id = $this->getMerchantByGroup();
            if(!$merchant_id) {
                return response()->json(['status' => 'FAIL', 'message' => 'Merchant not found, Please whitelist the merchant'], 401);
            }

            $application_id = $this->request->get('application_id');
            $mobile_number = $this->request->get('mobile_number');
            $loan_application_number = $this->request->get('loan_application_number');

            $application = null;

            if ($application_id && $merchant_id) {
                $application = ConsumerApplication::where('id', $application_id)->where('merchant_id', $merchant_id)->whereNull('is_deleted')->first();
            } else if ($loan_application_number && $merchant_id) {
                $proforma = ProFormaInvoice::where('loan_application_no', $loan_application_number)->first(['application_id']);
                if ($proforma) {
                    $application = ConsumerApplication::where('id', $proforma->application_id)->where('merchant_id', $merchant_id)->whereNull('is_deleted')->first();
                }
            } else if ($mobile_number && $merchant_id) {
                if (strlen($mobile_number) == 12 && substr($mobile_number, 0, 2) == "91") {
                    $mobile_number = substr($mobile_number, 2, 10);
                }
                $application = ConsumerApplication::where('mobile_number', $mobile_number)->where('merchant_id', $merchant_id)->whereNull('is_deleted')->orderBy('id', 'desc')->first();
            }

            if (!$application) {
                return response()->json(['status' => 'FAIL', 'message' => 'Application not found'], 404);
            }

            $status_to_fetch = $application->state == 'nach registered' ? 'disbursed' : $application->state;
            $payload = (new ConsumerApplicationController())->getMConnectPayload($application->id, $status_to_fetch);
            if (empty((array)$payload)  ) {
                $payload = (array) $payload;
                $payload['application_status'] = $status_to_fetch;
                $payload['application_id'] = $application->id;
            } else {
                unset($payload['application-status']);
                if ($application->state == 'approved') {
                    unset($payload['offer_id'], $payload['up_front_from_customer'], $payload['bre_approved']);
                } elseif ($application->state == 'cf approved') {
                    $payload['message'] = 'Application at CF Approved stage (Soft Approved)';
                }
                elseif ($application->state == 'ready for disbursement') {
                    unset($payload['disbursed_amount']);
                } 
                if (isset($payload['bre_approved'])) {
                    unset($payload['bre_approved']);
                }
                $payload['application_status'] = $status_to_fetch;
                $payload['application_id'] = $application->id;
            }
            $payload['applicant_name'] = $application->name ?? '';
            $latest_comment = Comments::where('application_id', $application->id)
                ->where('show_merchant', 1)
                ->orderBy('id', 'desc')
                ->first(['comment']);

            if ($latest_comment && !in_array($application->state, ['nach registered', 'disbursed'])) {
                $payload['latest_comment'] = $latest_comment->comment;
            }

            return response()->json(['status' => 'OK', 'data' => $payload, 'message' => 'Application status fetched successfully']);
        } catch (\Exception $e) {
            $this->cwFactory->logger(json_encode(['title' => 'Whatsapp Fetch Status', 'message' => $e->getMessage(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString()]));
            return response()->json(['status' => 'FAIL', 'message' => 'Please connect with the tech support team'], 500);
        }
    }


    public function getPropertiesForElement($fillable){
        $element_properties = [];
        foreach($this->parsedData as $key => $value) {
            if (in_array($key, $fillable)){
                $element_properties[$key] = $value;
            }
        }

        return $element_properties;
    }

    public function uploadDocumentBase(){
        $this->user = $this->getUser();
        if (!$this->user){
            return response()->json(['id' => 0, 'message' => 'Unauthorized'], 401);
        }
        $s3 = Storage::disk('s3');

        $file = base64_decode($this->request->get('image')[0]['base64']);
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_buffer($finfo, $file);

        $mimeToExtension = [
            'image/jpeg' => 'jpg',
            'image/png' => 'png',
        ];

        $extension = isset($mimeToExtension[$mimeType]) ? $mimeToExtension[$mimeType] : '';
        if (empty($extension)) {
            preg_match('/^data:image\/(\w+);base64,/', $file, $matches);
            $extension = isset($matches[1]) ? $matches[1] : '';
        }

        $path = '/' . $this->request->get('application_id') . '/' . $this->request->get('doc_type') . '.' . $extension;

        $s3->put($path, $file);

        $consumer_application_file = new ConsumerApplicationFiles();
        $consumer_application_file->consumer_application_id = $this->request->get('application_id');
        $consumer_application_file->file_type = $this->request->get('doc_type');
        $consumer_application_file->bank_name = '';
        $consumer_application_file->password = '';
        $consumer_application_file->accounttype = '';
        $consumer_application_file->statementtype = '';
        $consumer_application_file->statemenfilettype = '';
        $consumer_application_file->customer_id = '';
        $consumer_application_file->provider = '';
        $consumer_application_file->finbit_analysis_date = '';
        $consumer_application_file->bp_number = '';
        $consumer_application_file->accountUID = '';
        $consumer_application_file->file_path = $path;
        $consumer_application_file->created_by = $this->user;
        $consumer_application_file->image_score = '';
        $consumer_application_file->m_generated = 1;
        $consumer_application_file->applicant_type = 1;
        $consumer_application_file->bureau_report_type = '';
        $consumer_application_file->bureau_report_score = '';
        $consumer_application_file->is_masked = 0;
        $consumer_application_file->save();

        return response()->json(['id' => $this->request->get('application_id'), 'message' => ucfirst(strtolower($this->request->get('doc_type')))." Document received"], 200);
    }

    public function generateOTP(){
        try {
            $api = new ApiController();
            \request()->merge(['mp' => $this->request->get('mobile')]);
            $data = $api->checkStatusLogin();
            $api->isSystemByPass = true;
            $res = $data->getData();
            return response()->json(['id' => $res->status == 'OK' ? 1 : 0, 'message' => $res->error ?? ''], 200);
        }catch (\Exception $e){
            return response()->json(['id' => 0, 'message' => 'Something went wrong'], 200);
        }
    }

    public function checkMandatoryFields($application_id)
    {
        // Map display name => column name
        $mandatoryFields = [
            'Name' => 'name',
            'Gender' => 'gender',
            'Pan Number' => 'pan_card',
            'Loan Amount' => 'loan_amount',
            'DOB' => 'dob',
            'Mobile number' => 'mobile_number',
            'Monthly Income' => 'monthly_income',
            'Merchant' => 'merchant_id',
            'Tenure' => 'tenure',
            'Main Purpose category' => 'purpose',
            'Solar financing for' => 'type_of_customer',
            'Solar power type' => 'solar_power_type',
            'Net loan amount' => 'loan_amount',
            'Permanent Address Line 1' => 'permanent_address_line_1',
            'Permanent City' => 'permanent_address_city',
            'Permanent Pincode' => 'permanent_address_pincode',
            'Permanent State' => 'permanent_address_state',
            'KW installation' => 'inverter_KW_installation',
        ];

        // Fetch application row
        $application = DB::table('consumer_application')
            ->where('id', $application_id)
            ->first();

        // Fetch application element row (if exists)
        $applicationElement = DB::table('consumer_application_element')
            ->where('application_id', $application_id)
            ->first();

        $missingFields = [];

        foreach ($mandatoryFields as $label => $column) {
            $value = null;

            // Check in applications first
            if ($application && property_exists($application, $column)) {
                $value = $application->$column;
            }

            // If not found there, check in application_element
            if ((is_null($value) || $value === '') && $applicationElement && property_exists($applicationElement, $column)) {
                $value = $applicationElement->$column;
            }

            // If still null/empty => add to missing fields
            if (is_null($value) || $value === '') {
                $missingFields[] = $label;
            }
        }

        $missingFieldsString = implode(", \n", $missingFields);
        if (empty($missingFieldsString)) {
            return "";
        }
        return $missingFieldsString;
    }

    public function verifyOTP(){
        $api = new ApiController();
        $response = $api->verifyOtp(new Request(['mobile_number' => $this->request->get('mobile'), 'otp' => $this->request->get('otp'), 'page_lp_event' => true]));
        if ($response->getData()->message == 'OTP successfully verified') {
            return response()->json(['id' => 1, 'message' => 'verified'], 200);
        }
        return response()->json(['id' => 0, 'message' => 'failed'], 200);
    }

    public function getUser(){
        if ($this->request->get('user_identifier')){
            $user = User::where('mobile_number', $this->request->get('user_identifier'))->where('user_type', '>=', 5)->first(['id']);
            return $user->id ?? false;
        }
        return false;
    }

    public function bodyParser(){
        $this->parsedData = [];

        // Parse raw WhatsApp message text when sent as a single "text" field.
        // Expected line format:  key:: value
        // The :: delimiter avoids ambiguity with commas/dashes inside addresses or amounts.
        $rawText = $this->request->get('text');
        if ($rawText) {
            $skipPatterns = ['create loan', 'new loan', 'create application', 'new application', 'update loan', 'update application'];
            $parsedFromText = [];
            foreach (preg_split('/\r?\n/', $rawText) as $line) {
                $line = trim($line);
                if ($line === '') {
                    continue;
                }
                // Skip header lines like "Create loan", "New application", etc.
                $lineLower = strtolower($line);
                $isHeader = false;
                foreach ($skipPatterns as $pattern) {
                    if (strpos($lineLower, $pattern) !== false) {
                        $isHeader = true;
                        break;
                    }
                }
                if ($isHeader) {
                    continue;
                }
                if (strpos($line, '::') !== false) {
                    [$key, $value] = explode('::', $line, 2);
                    $key = $this->normaliseWhatsappTextValue($key);
                    // Strip inline comments — everything from # onwards is hint text for the merchant.
                    // e.g. "gender:: Male # Male / Female"  →  value = "Male"
                    // e.g. "gender::  # Male / Female"      →  value = "" (line skipped below)
                    if (($commentPos = strpos($value, '#')) !== false) {
                        $value = substr($value, 0, $commentPos);
                    }
                    $value = $this->normaliseWhatsappTextValue($value);
                    // Strip trailing parenthetical hint text preceded by 2+ spaces,
                    // e.g. "12/04/1998      (format DD/MM/YYYY, e.g. 25/01/1990)" → "12/04/1998"
                    $value = $this->normaliseWhatsappTextValue(preg_replace('/[\s\p{Z}]{2,}\([^)]+\)\s*$/u', '', $value));
                    // If the entire value is a hint placeholder like "(Male / Female)", treat as empty
                    if (preg_match('/^\([^)]+\)$/', $value)) {
                        $value = '';
                    }
                    if ($key !== '' && $value !== '') {
                        $parsedFromText[$key] = $value;
                    }
                }
            }
            if (!empty($parsedFromText)) {
                $this->request->merge($parsedFromText);
            }
        }

        // $attributes = [
        //     'name' => ['pt name', 'applicant name', 'name', 'Applicant Name'], 'loan_amount' => ['loan_amount', 'amount', 'loan amount'], 'mobile_number' => ['number', 'pt number', 'mobile', 'contact number', 'Mobile No', 'Mobile number'], 'merchant_id' => ['merchant_id'],
        //     'monthly_income' => ['salary', 'monthly income', 'Monthly Income'], 'company_name' => ['company name'], 'email' => ['email', 'mail', 'email id', 'Mail id'], 'dob' => ['dob', 'date of birth'],
        //     'mother_name' => ['mother_name', 'Mother name'], 'Spouse_name' => ['spouse Name', 'spouse_name'], 'tenure' => ['Tenure']
        // ];
        $attributes = [
            // --- Personal & Contact Details ---
            'name' => ['name', 'applicant name', 'Applicant Name', 'full name', 'pt name'],
            'email' => ['email', 'mail', 'email id', 'Mail id', 'email address'],
            'mobile_number' => ['mobile_number', 'mobile', 'number', 'contact number', 'Mobile No', 'Mobile number', 'pt number'],
            'dob' => ['dob', 'date of birth', 'birth date'],
            'gender' => ['gender'],
            'marital_status' => ['marital_status', 'marital status'],
            'pan_card' => ['pan_card', 'pan', 'pan number', 'PAN'],
            'aadhaar_card' => ['aadhaar_card', 'aadhaar', 'aadhaar number', 'Aadhaar'],
            'alt_contact_number' => ['alt_contact_number', 'alternate contact', 'alternate number', 'secondary number'],
            'mother_name' => ['mother_name', 'Mother name', 'mother\'s name'], // From your example

            // --- Loan & Merchant Details ---
            'merchant_id' => ['merchant_id', 'merchant id'],
            'loan_amount' => ['loan_amount', 'amount', 'loan amount', 'requested amount'],
            'tenure' => ['tenure', 'Tenure', 'loan tenure', 'repayment period', 'emi months'],
            'purpose' => ['purpose', 'loan purpose', 'category'],
            'approved_amount' => ['approved_amount', 'approved amount', 'sanctioned amount'],
            'lender_id' => ['lender_id', 'lender id'],
            'offer_id' => ['offer_id', 'offer id'],

            // --- Employment & Income Details ---
            'monthly_income' => ['monthly_income', 'monthly income', 'Monthly Income', 'salary', 'income'],
            'company_name' => ['company_name', 'company name', 'employer', 'employer name'],
            'employee_status' => ['employee_status', 'employment status', 'employment type'],
            'company_number' => ['company_number', 'company contact', 'office number', 'company phone'],
            'experience' => ['experience', 'work experience', 'total experience'],

            // --- Address Details (Current) ---
            'current_address_line_1' => ['current_address_line_1', 'current address', 'address', 'address line 1'],
            'current_address_state' => ['current_address_state', 'current state', 'state'],
            'current_address_city' => ['current_address_city', 'current city', 'city'],
            'current_address_pincode' => ['current_address_pincode', 'current pincode', 'pincode', 'zipcode'],
            'current_address_landmark' => ['current_address_landmark', 'current landmark', 'landmark'],
            'current_address_status' => ['current_address_status', 'current address status'],
            
            // --- Address Details (Permanent) ---
            'permanent_address_line_1' => ['permanent_address_line_1', 'permanent address', 'permanent address line 1'],
            'permanent_address_state' => ['permanent_address_state', 'permanent state'],
            'permanent_address_city' => ['permanent_address_city', 'permanent city'],
            'permanent_address_pincode' => ['permanent_address_pincode', 'permanent pincode'],
            'permanent_address_landmark' => ['permanent_address_landmark', 'permanent landmark'],
            'permanent_address_status' => ['permanent_address_status', 'permanent address status'],

            // --- Address Details (Work & Contact) ---
            'work_address_line_1' => ['work_address_line_1', 'work address', 'office address'],
            'work_address_state' => ['work_address_state', 'work state', 'office state'],
            'work_address_city' => ['work_address_city', 'work city', 'office city'],
            'work_address_pincode' => ['work_address_pincode', 'work pincode', 'office pincode'],
            'work_address_landmark' => ['work_address_landmark', 'work landmark', 'office landmark'],
            'contact_address' => ['contact_address', 'contact address'],

            // --- Co-Applicant Details ---
            'co_applicant_name' => ['co_applicant_name', 'co applicant name', 'co-applicant name', 'Spouse_name', 'spouse Name'],
            'co_applicant_relationship' => ['co_applicant_relationship', 'co applicant relationship', 'relationship'],
            'co_applicant_dob' => ['co_applicant_dob', 'co applicant dob', 'co-applicant date of birth'],
            'co_applicant_gender' => ['co_applicant_gender', 'co applicant gender'],
            'co_applicant_pan_card' => ['co_applicant_pan_card', 'co applicant pan', 'co-applicant pan'],
            'co_applicant_aadhaar_card' => ['co_applicant_aadhaar_card', 'co applicant aadhaar', 'co-applicant aadhaar'],
            'co_applicant_email' => ['co_applicant_email', 'co applicant email'],
            'co_applicant_mobile_number' => ['co_applicant_mobile_number', 'co applicant mobile'],
            'co_applicant_required' => ['co_applicant_required', 'is co-applicant required'],
            
            // --- Co-Applicant Address ---
            'co_applicant_address_line_1' => ['co_applicant_address_line_1', 'co applicant address'],
            'co_applicant_address_state' => ['co_applicant_address_state', 'co applicant state'],
            'co_applicant_address_pincode' => ['co_applicant_address_pincode', 'co applicant pincode'],
            'co_applicant_address_city' => ['co_applicant_address_city', 'co applicant city'],
            'co_applicant_address_landmark' => ['co_applicant_address_landmark', 'co applicant landmark'],
            'co_applicant_address_status' => ['co_applicant_address_status', 'co applicant address status'],

            // --- Co-Applicant Employment ---
            'co_applicant_employee_status' => ['co_applicant_employee_status', 'co applicant employment status'],
            'co_applicant_monthly_income' => ['co_applicant_monthly_income', 'co applicant monthly income', 'co applicant salary'],
            'co_applicant_company_name' => ['co_applicant_company_name', 'co applicant company'],
            'co_applicant_company_number' => ['co_applicant_company_number', 'co applicant company number'],
            'co_applicant_experience' => ['co_applicant_experience', 'co applicant experience'],
            
            // --- Application Status & Processing ---
            'state' => ['state', 'status', 'application status'],
            'completed_stage' => ['completed_stage', 'stage', 'application stage'],
            'credit_score' => ['credit_score', 'credit score', 'cibil', 'cibil score'],
            'rejection_reason' => ['rejection_reason', 'rejection reason'],

            // --- Source & Lead Details ---
            'src_merchant_name' => ['src_merchant_name', 'source merchant name', 'src merchant name'],
            'src_representative_name' => ['src_representative_name', 'source representative name', 'representative name'],
            'lead_src_email' => ['lead_src_email', 'lead source email'],
            'lead_src_phone' => ['lead_src_phone', 'lead source phone', 'lead source number'],

            // --- File & Document Fields ---
            'additional_docs_list' => ['additional_docs_list', 'additional documents list'],
            'additional_docs' => ['additional_docs', 'additional documents'],
            'file_income_proof' => ['file_income_proof', 'income proof'],
            'file_bank_statement' => ['file_bank_statement', 'bank statement'],
            'file_pan_card' => ['file_pan_card', 'pan card file'],
            'file_aadhaar_card' => ['file_aadhaar_card', 'aadhaar card file'],
            'file_electricity_bill' => ['file_electricity_bill', 'electricity bill'],

            // --- System & Miscellaneous Fields ---
            'id' => ['id', 'application_id', 'application id', 'consumer_application_id'],
            'user_id' => ['user_id', 'user id'],
            'applicant_id' => ['applicant_id', 'applicant id'],
            'co_applicant_id' => ['co_applicant_id', 'co applicant id'],
            'assigned_to' => ['assigned_to', 'assigned to'],
            'updated_by' => ['updated_by', 'updated by'],
            'pre_created_by' => ['pre_created_by', 'pre created by'],
            'misc_info' => ['misc_info', 'miscellaneous info', 'notes'],
            'long_link' => ['long_link', 'long link', 'url'],
            'created_at' => ['created_at', 'creation date', 'created on'],
            'updated_at' => ['updated_at', 'last updated', 'updated on'],

            // --- Application Element  ---
            'application_id' => ['application_id', 'application id'],

            // --- Applicant Profession & Industry ---
            'industry' => ['industry', 'applicant industry', 'industry sector'],
            'profession_type' => ['profession_type', 'profession type', 'applicant profession type'],

            // --- Co-Applicant Profession & Industry ---
            'co_applicant_industry' => ['co_applicant_industry', 'co applicant industry', 'co-applicant industry'],
            'co_applicant_profession_type' => ['co_applicant_profession_type', 'co applicant profession type', 'co-applicant profession type'],

            // --- Merchant & Center Details ---
            'center_id' => ['center_id', 'center id', 'merchant location id'],

            // --- Address (Current) ---
            'current_address_text' => ['current_address_text', 'current address text'],
            'current_formatted_text' => ['current_formatted_text', 'current formatted text'],

            // --- Address (Permanent) ---
            'permanent_address_text' => ['permanent_address_text', 'permanent address text'],
            'permanent_formatted_text' => ['permanent_formatted_text', 'permanent formatted text'],

            // --- Auto Approval ---
            'is_auto_approved' => ['is_auto_approved', 'auto approved flag', 'auto approval'],

            // --- Employment Details ---
            'designation' => ['designation', 'employment designation'],
            'department' => ['department', 'employment department'],
            'contact' => ['contact', 'employment contact', 'work contact'],

            // --- Product & Language ---
            'product_name' => ['product_name', 'product name', 'product id'],
            'preferred_language' => ['preferred_language', 'preferred language'],

            // --- Co-Applicant Flags ---
            'co_applicant_for_signing' => ['co_applicant_for_signing', 'co applicant for signing', 'co-applicant for signing'],
            'co_applicant_for_income' => ['co_applicant_for_income', 'co applicant for income', 'co-applicant for income'],

            // --- Banking & Documents ---
            'bank_id' => ['bank_id', 'bank id'],
            'mandatory_document_list' => ['mandatory_document_list', 'mandatory document list'],

            // --- Customer & Solar Details ---
            'type_of_customer' => ['type_of_customer', 'type of customer'],
            'solar_power_type' => ['solar_power_type', 'solar power type'],

            // --- Risk & Inverter Details ---
            'risk_category' => ['risk_category', 'risk category'],
            'inverter' => ['inverter', 'inverter brand'],
            'inverter_model_description' => ['inverter_model_description', 'inverter model description'],
            'inverter_monthly_power_bill' => ['inverter_monthly_power_bill', 'inverter monthly power bill'],
            'inverter_kw_installation' => ['inverter_kw_installation', 'inverter kw installation', 'kw installation'],
            'inverter_power_savings' => ['inverter_power_savings', 'inverter power savings', 'estimated power savings'],
            // --- Payment Overdue ---
            'amount_over_due' => ['amount_over_due', 'amount overdue', 'overdue amount'],
        ];

        $requestData = $this->request->all();

        // If keys like consumer_application or consumer_application_element exist, flatten them
        if (isset($requestData['consumer_application']) && is_array($requestData['consumer_application'])) {
            $requestData = array_merge($requestData, $requestData['consumer_application']);
            unset($requestData['consumer_application']);
        }

        if (isset($requestData['consumer_application_element']) && is_array($requestData['consumer_application_element'])) {
            $requestData = array_merge($requestData, $requestData['consumer_application_element']);
            unset($requestData['consumer_application_element']);
        }

        $this->request->replace($requestData);
        // Now $requestData is always flat like:
        // ['name' => 'Sunil', 'dob' => '...', 'loan_amount' => '...', ...]
        foreach ($requestData as $key => $value) {
            foreach ($attributes as $attribute => $attributeValue) {
                $this->strPosArray($key, $attribute, $attributeValue);
            }
        }

        // Strip trailing non-numeric text from tenure (e.g. "60 months" → "60")
        // so simplyAttributes() can match against MerchantOffers.tenure correctly.
        if (isset($this->parsedData['tenure']) && $this->parsedData['tenure'] !== null) {
            $this->parsedData['tenure'] = preg_replace('/[^0-9]/', '', (string) $this->parsedData['tenure']);;
        }

        if (isset($this->parsedData['loan_amount']) && $this->parsedData['loan_amount'] !== null) {
            $this->parsedData['loan_amount'] = preg_replace('/[^0-9]/', '', (string) $this->parsedData['loan_amount']);;
        }

        if (isset($this->parsedData['monthly_income']) && $this->parsedData['monthly_income'] !== null) {
            $this->parsedData['monthly_income'] = preg_replace('/[^0-9]/', '', (string) $this->parsedData['monthly_income']);;
        }

        // Map human-readable strings to the integer values the DB expects.
        // Source of truth: context.txt enum definitions.
        $enumMaps = [
            'gender' => [
                'male'   => 'MALE',
                'female' => 'FEMALE',
                'm'      => 'MALE',
                'f'      => 'FEMALE',
            ],
            'co_applicant_gender' => [
                'male'   => 'MALE',
                'female' => 'FEMALE',
                'm'      => 'MALE',
                'f'      => 'FEMALE',
            ],
            'marital_status' => [
                'married' => 'MARRIED',
                'single'  => 'SINGLE',
            ],
            'co_applicant_employee_status' => [
                'unemployed' => 'UNEMPLOYED',
                'salaried'   => 'SALARIED',
                'business'   => 'BUSINESS',
                'pensioner'  => 'PENSIONER',
                'housewife'  => 'HOUSEWIFE',
            ],
            'current_address_status' => [
                'rented'               => 'RENTED',
                'owned'                => 'OWNED',
                'parents house'        => 'PARENTS HOUSE',
                'self owned'           => 'Self Owned',
                'parent owned'         => 'Parent Owned',
                'rented with family'   => 'Rented With Family',
                'rented with friend'   => 'Rented With Friend',
                'company allotted'     => 'Company Allotted',
            ],
            'permanent_address_status' => [
                'rented'               => 'RENTED',
                'owned'                => 'OWNED',
                'parents house'        => 'PARENTS HOUSE',
                'self owned'           => 'Self Owned',
                'parent owned'         => 'Parent Owned',
                'rented with family'   => 'Rented With Family',
                'rented with friend'   => 'Rented With Friend',
                'company allotted'     => 'Company Allotted',
            ],
            'co_applicant_address_status' => [
                'rented'               => 'RENTED',
                'owned'                => 'OWNED',
                'parents house'        => 'PARENTS HOUSE',
                'self owned'           => 'Self Owned',
                'parent owned'         => 'Parent Owned',
                'rented with family'   => 'Rented With Family',
                'rented with friend'   => 'Rented With Friend',
                'company allotted'     => 'Company Allotted',
            ],
            'solar_power_type' => [
                'ongrid'  => 1,
                'offgrid' => 2,
                'hybrid'  => 3,
            ],
            'type_of_customer' => [
                'residential'              => 1,
                'rural c&i msme'           => 2,
                'urban c&i msme'           => 3,
                'housing society'          => 4,
                'schools & universities'   => 5,
                'schools and universities' => 5,
            ],
            'industry' => [
                'services'      => 0,
                'manufacturing' => 1,
                'trading'       => 2,
            ],
            'co_applicant_industry' => [
                'services'      => 0,
                'manufacturing' => 1,
                'trading'       => 2,
            ],
            'profession_type' => [
                'private limited'          => 0,
                'sole proprietorship'      => 1,
                'unregistered partnership' => 2,
                'registered partnership'   => 3,
                'huf/aop'                  => 4,
                'unlisted public limited'  => 5,
                'listed public limited'    => 6,
            ],
            'co_applicant_profession_type' => [
                'private limited'          => 0,
                'sole proprietorship'      => 1,
                'unregistered partnership' => 2,
                'registered partnership'   => 3,
                'huf/aop'                  => 4,
                'unlisted public limited'  => 5,
                'listed public limited'    => 6,
            ],
        ];

        foreach ($enumMaps as $field => $map) {
            if (isset($this->parsedData[$field]) && is_string($this->parsedData[$field])) {
                $normalised = strtolower($this->normaliseWhatsappTextValue($this->parsedData[$field]));
                $this->parsedData[$field] = array_key_exists($normalised, $map) ? $map[$normalised] : null;
            }
        }

        if (isset($this->parsedData['employee_status'])) {
            $empStatus = strtolower($this->normaliseWhatsappTextValue($this->parsedData['employee_status']));
            if ($empStatus === 'self employed') {
                $this->parsedData['employee_status'] = 'Self Employed - Business';
            }
        }

        // Merge normalised field names back onto the request so that code in
        // createLoan() that reads directly from $this->request (e.g. checkEligibility)
        // can find the canonical keys (pan_card, mobile_number, etc.).
        $this->request->merge($this->parsedData);

        return;
    }

    private function normaliseWhatsappTextValue($value)
    {
        if (!is_string($value)) {
            return $value;
        }

        // WhatsApp messages can contain non-breaking spaces, BOM, or zero-width
        // characters that PHP trim() does not remove.
        $value = str_replace(["\xC2\xA0", "\xE2\x80\x87", "\xE2\x80\xAF"], ' ', $value);
        $value = preg_replace('/[\x{FEFF}\x{200B}-\x{200D}]/u', '', $value);
        $normalised = preg_replace('/^[\s\p{Z}]+|[\s\p{Z}]+$/u', '', $value);

        return is_null($normalised) ? trim($value) : $normalised;
    }

    public function getGroups(){
        if(is_null($this->groups)){
            $filePath = _env('GROUPS_JSON_PATH', '/whatsapp/groups.json');
            try {
                $s3 = Storage::disk('s3');
                if ($s3->exists($filePath)) {
                    $content = $s3->get($filePath);
                    return json_decode($content, true);
                }
            } catch (\Exception $e) {
                $this->cwFactory->logger(json_encode([
                    'title' => 'GroupsS3Error',
                    'error' => $e->getMessage(),
                    'file_path' => $filePath
                ], JSON_UNESCAPED_UNICODE));
            }
            return [];
        }
        return $this->groups;
    }

    private function getGroupNameByApplication($application_id) {
        $application = ConsumerApplication::where('id', $application_id)->first(['merchant_id']);
        if (!isset($application->merchant_id)) {
            return null;
        }

        // Whitelist check
        $whitelist = _env('WHATSAPP_BOT_MERCHANT_WHITELIST', '');
        if ($whitelist !== '') {
            $allowed = array_map('trim', explode(',', $whitelist));
            if (!in_array((string) $application->merchant_id, $allowed)) {
                return null;
            }
        }

        $groups = $this->getGroups();
        if (empty($groups)) {
            return null;
        }

        foreach ($groups as $name => $merchantId) {
            if ($merchantId == $application->merchant_id) {
                return $name;
            }
        }

        return null;
    }

    /**
     * Generic Narad API caller
     */
    private function sendNaradRequest($endpoint, $payload, $errorTitle) {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL            => _env('NARAD_HOST') . $endpoint,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST  => 'POST',
            CURLOPT_POSTFIELDS     => json_encode($payload),
            CURLOPT_HTTPHEADER     => [
                'Content-Type: application/json',
                'CF_ACCESS_KEY: ' . _env('NARAD_CF_ACCESS_KEY'),
                'CF_SECRET_KEY: ' . _env('NARAD_CF_SECRET_KEY'),
            ],
        ]);

        $response = curl_exec($curl);
        $error    = curl_error($curl);
        curl_close($curl);

        if ($error) {
            $this->cwFactory->logger(json_encode([
                'title'    => $errorTitle,
                'error'    => $error,
                'payload'  => $payload,
                'response' => $response,
            ], JSON_UNESCAPED_UNICODE));
        }

        return $response;
    }

    public function sendGroupStatusNotification($application_id, $status) {
        if (strtolower($status) !== 'waiting for documents') {
            $priorCount = StatusLogs::where('application_id', $application_id)
                ->where('status', $status)
                ->count();
            if ($priorCount > 1) {
                return;
            }
        }

        $groupName = $this->getGroupNameByApplication($application_id);
        if (!$groupName) return;

        $application = ConsumerApplication::find($application_id);
        $customerInfo = $application ? "Customer Name: " . $application->name . "\nMobile Number: " . $application->mobile_number . "\n" : "";

        $message     = $customerInfo . "Application ID: " . $application_id . "\nStatus: " . $status;
        $lowerStatus = strtolower($status);

        if ($lowerStatus === 'waiting for decision') {
            $message .= "\nCase is under review with Credit Team, we will provide decision soon.";
        } elseif ($lowerStatus === 'rejected') {
            $message .= "\nCase is rejected, Does not meet policy criteria";
        } elseif (in_array($lowerStatus, ['approved', 'waiting for documents'])) {
            $mconnect = (new ConsumerApplicationController())->getMConnectPayload($application_id, $lowerStatus);
            
            if ($lowerStatus === 'approved' && !empty($mconnect['esign'])) {
                $message .= "\nPost Approval Link: " . $mconnect['esign'];
            } elseif ($lowerStatus === 'waiting for documents' && !empty($mconnect['docs'])) {
                $message .= "\nPending Documents:\n- " . implode("\n- ", $mconnect['docs']);
            }
        }

        $payload = [
            'group_name'     => $groupName,
            'application_id' => (string) $application_id,
            'status'         => $status,
            'message'        => $message,
        ];

        $this->sendNaradRequest('/_admin/send-group-status', $payload, 'GroupStatusNotificationError');
    }

    public function sendGroupCommentNotification($application_id, $comment, $commenter_name) {
        $groupName = $this->getGroupNameByApplication($application_id);
        if (!$groupName) return;

        $application = ConsumerApplication::find($application_id);

        $payload = [
            'group_name'     => $groupName,
            'application_id' => (string) $application_id,
            'comment'        => $comment,
            'commenter_name' => $commenter_name,
        ];

        if ($application) {
            $payload['customer_name'] = $application->name;
            $payload['mobile_number'] = $application->mobile_number;
        }

        $this->sendNaradRequest('/_admin/send-group-comment', $payload, 'GroupCommentNotificationError');
    }

    public function getPaymentLink($value){
        try {
            $idType = $this->request->get('id_type', 'application_id');
            $merchant_id = $this->getMerchantByGroup();
            if (!$merchant_id) {
                return response()->json(['status' => 'FAIL', 'message' => 'Merchant not found, Please whitelist the merchant'], 401);
            }

            //For testing in production on a specific merchant/merchant group
            $whitelist = _env('WHATSAPP_BOT_MERCHANT_WHITELIST', '');
            if ($whitelist !== '') {
                $allowed = array_map('trim', explode(',', $whitelist));
                if (!in_array((string) $merchant_id, $allowed)) {
                    return response()->json(['status' => 'FAIL', 'message' => 'Feature not available for this merchant'], 403);
                }
            }

            $application = $this->resolveApplication($value, $idType, $merchant_id);
            if (!$application) {
                return response()->json(['status' => 'FAIL', 'message' => 'Application not found'], 404);
            }
            if ($application->lender_id != 2) {
                return response()->json(['status' => 'OK', 'data' => ['total_payment_link' => 'This case is not of K. M. Global Credit Private Limited']]);
            }
            $fees = (new FrontController())->getFeesData($application->id);
            $link = $fees['total_payment_link'] ?? null;
            if ($link) {
                return response()->json(['status' => 'OK', 'data' => ['total_payment_link' => $link]]);
            }
            return response()->json(['status' => 'OK', 'data' => ['total_payment_link' => null], 'message' => 'No pending payment for this application']);
        } catch (\Exception $e) {
            return response()->json(['status' => 'FAIL', 'message' => $e->getMessage()], 500);
        }
    }

    public function getAccountStatementByIdentifier($value){
        $idType = $this->request->get('id_type', 'application_id');
        $merchant_id = $this->getMerchantByGroup();
        if (!$merchant_id) {
            return response()->json(['status' => 'FAIL', 'message' => 'Merchant not found, Please whitelist the merchant'], 401);
        }

        //For testing in production on a specific merchant/merchant group
        $whitelist = _env('WHATSAPP_BOT_MERCHANT_WHITELIST', '');
        if ($whitelist !== '') {
            $allowed = array_map('trim', explode(',', $whitelist));
            if (!in_array((string) $merchant_id, $allowed)) {
                return response()->json(['status' => 'FAIL', 'message' => 'Feature not available for this merchant'], 403);
            }
        }

        $application = $this->resolveApplication($value, $idType, $merchant_id);
        if (!$application) {
            return response()->json(['status' => 'FAIL', 'message' => 'Application not found'], 404);
        }
        if ($application->lender_id != 2) {
            return response()->json(['status' => 'FAIL', 'message' => 'This is Lender case, please connect to Advisor for SOA'], 403);
        }
        return (new ConsumerApplicationController())->getAccountStatement($application->id);
    }

    private function resolveApplication($value, $idType, $merchant_id){
        if (!$idType || $idType === 'application_id') {
            return ConsumerApplication::where('id', $value)
                ->where('merchant_id', $merchant_id)
                ->whereNull('is_deleted')
                ->first(['id', 'lender_id']);
        }
        if ($idType === 'mobile_number') {
            if (strlen($value) == 12 && substr($value, 0, 2) == '91') {
                $value = substr($value, 2, 10);
            }
            return ConsumerApplication::where('mobile_number', $value)
                ->where('merchant_id', $merchant_id)
                ->whereNull('is_deleted')
                ->orderBy('id', 'desc')
                ->first(['id', 'lender_id']);
        }
        if ($idType === 'loan_application_number') {
            $proforma = ProFormaInvoice::where('loan_application_no', $value)->first(['application_id']);
            if ($proforma) {
                return ConsumerApplication::where('id', $proforma->application_id)
                    ->where('merchant_id', $merchant_id)
                    ->whereNull('is_deleted')
                    ->first(['id', 'lender_id']);
            }
        }
        return null;
    }

    public function getMerchantByGroup(){
        $groupIdentifier = $this->request->get('group_identifier');
        if($groupIdentifier){
            $groups = $this->getGroups();
            return isset($groups[$groupIdentifier]) ? $groups[$groupIdentifier] : false;
        }
        return false;
    }


    public function simplyAttributes(){
        if($this->parsedData['merchant_id']) {
            foreach ($this->parsedData as $key => $value) {
                if ($key == 'tenure') {
                    $merchantOffer = MerchantOffers::where('merchant_id', $this->parsedData['merchant_id'])->where('tenure', $value)->first(['id']);
                    $this->parsedData['tenure'] = $value;
                    if(isset($merchantOffer->id)) {
                        $this->parsedData['offer_id'] = $merchantOffer->id;
                    } else {
                        $this->parsedData['offer_id'] = null;
                    }
                }
            }
        }
    }

    public function loadAdditionalAttributes($isUpdateRequest = false){
        if($isUpdateRequest) {
            $this->parsedData['merchant_id'] = $this->getMerchantByGroup();
            $this->parsedData['updated_by'] = 'WhatsApp';
            $this->parsedData['lender_id'] = 20;
        } else {
            $this->parsedData['lender_id'] = 20;
            $this->parsedData['created_by'] = $this->user;
            $this->parsedData['updated_by'] = 'WhatsApp';
            $this->parsedData['state'] = 'incomplete form';
            $this->parsedData['merchant_id'] = $this->getMerchantByGroup();
            $merchant = Merchant::where('id', $this->parsedData['merchant_id'])->first(['category_id']);
            if (isset($merchant->category_id)){
                $this->parsedData['purpose'] = $merchant->category_id;
            }
        }
    }

   public function strPosArray($key, $baseAttribute, $attributes, $type = 'consumer_application')
    {
        foreach ($attributes as $attribute) {
            if (strtolower($key) == strtolower($attribute)) {
                if($this->request->has($type . '.' . $key)) {
                    // If the key exists in the request, use its value
                    $value = $this->request->input($type . '.' . $key);
                } else {
                    // If not, check if the key exists in the request without the type prefix
                    $value = $this->request->input($key, null);
                }
                // $value = $this->request->input($type . '.' . $key, null);

                $this->parsedData[$baseAttribute] = $this->normaliseWhatsappTextValue($value);
            }
        }
    }

    //Temporary Code - due to cors error
    public function prodMiddleware($name){

        $id = 0;
        $url = 'https://creditfair.in/beta/'.$name;

        $headers = array(
            'Content-Type: application/json',
            'cf-x-client: '._env('CF_X_CLIENT_PRD'),
            'cf-x-client-secret: '._env('CF_X_CLIENT_SECRET_PRD')
        );

        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->request->all()));

        $response = curl_exec($curl);

        if ($response === false) {
            $error = curl_error($curl);
            $message =  'cURL error: ' . $error;
        } else {
            $data = json_decode($response, true);

            if ($data === null) {
                $message =  'Error decoding JSON: ' . json_last_error_msg();
            } else {
                $id = $data['id'] ?? 0;
                $message = $data['message'] ?? '';
            }
        }
        curl_close($curl);

        return response()->json(['id' => $id, 'message' => $message]);

    }

    public function getPincodeDetails(){
        $url = 'https://creditfair.in/api/get-pincode-details-v1?pincode'.$this->request->get('pincode');

        $headers = array(
            'Content-Type: application/json'
        );

        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->request->all()));

        $response = curl_exec($curl);

        $data = array();
        if ($response === false) {
            $error = curl_error($curl);
            $message =  'cURL error: ' . $error;
        } else {
            $data = json_decode($response, true);
        }
        curl_close($curl);

        return response()->json($data, 200);

    }

    public function updateUtkarshWebhook(){

    }

    public function processEmailTracker($tracking_id){
        $sms_logs = SMSLogs::where('tracking_id', $tracking_id)->where('read', 0)->first(['id']);
        if (isset($sms_logs->id)) {
            SMSLogs::where('id', $sms_logs->id)->update(['read' => 1, 'read_time' => Carbon::now()->toDateTimeString()]);
        }
    }
}
