<?php

namespace App\Http\Controllers\Admin;

use App\ApplicationEMICalculation;
use App\ApplicationEMICalculationLock;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\ConsumerApplicationFiles;
use App\PincodeClassification;
use App\RiskBasedPricingCalculation;
use App\RiskBasedPricingCalculationLog;
use App\CreditReport;
use App\EmiPayment;
use App\Http\Controllers\Controller;
use App\RiskBasedConfiguration;
use App\RiskBasedConfigurationLogs;
use App\MerchantCategory;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Grade\GradeController;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use App\MerchantCategoryLogs;
use Illuminate\Support\Facades\Session;
use App\Comments;
class RiskController extends Controller{

    private $request;

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

    /**
     * Resolve the final automated pricing mode for a selected offer.
     *
     * PF and ROI are evaluated independently first. The offer-tenure rule is
     * used only when both automated components are eligible. Manual PF and ROI
     * are intentionally not part of this decision.
     */
    public function getAutomatedRiskPricingEligibility($applicationId, $offer, $baseRoi = 0){
        $tenure = (int) ($offer->tenure ?? 0);
        $roiData = $this->getAutomatedROI($applicationId, $baseRoi);
        $extraPfPercent = 0;
        if ($baseRoi == 0 && isset($roiData['is_risky_pincode']) && $roiData['is_risky_pincode']) {
            $extraPfPercent = 1;
            $roiData['bureau_roi_percentage'] = 0.0;
            $roiData['pincode_roi_percentage'] = 0.0;
            $roiData['applied_roi_percentage'] = 0.0;
            $roiData['final_system_roi'] = 0.0;
            $roiData['status'] = 'suppressed_due_to_zero_roi';
        }
        $roiEligible = isset($roiData['status'])
            && $roiData['status'] === 'success'
            && ($roiData['applied_roi_percentage'] ?? 0) > 0;

        $pfEligibility = $this->getAutomatedPFSurchargeEligibility($applicationId, $extraPfPercent);
        $pfAllowed = $pfEligibility['eligible'];
        $roiAllowed = $roiEligible;

        if ($pfEligibility['eligible'] && $roiEligible) {
            $pfAllowed = $tenure <= 12;
            $roiAllowed = $tenure > 12;
        }

        return [
            'offer_tenure' => $tenure,
            'automated_pf_eligible' => $pfEligibility['eligible'],
            'automated_roi_eligible' => $roiEligible,
            'automated_pf_allowed' => $pfAllowed,
            'automated_roi_allowed' => $roiAllowed,
            'automated_pf_data' => $pfEligibility,
            'automated_roi_data' => $roiData,
        ];
    }

    /**
     * Determine PF surcharge eligibility without updating EMI or lock rows.
     */
    public function getAutomatedPFSurchargeEligibility($id, $extraPfPercent = 0){
        $result = [
            'eligible' => false,
            'pf_surcharge_percent' => 0,
            'pf_surcharge_amount' => 0,
            'pf_surcharge_gst' => 0,
        ];

        $application = ConsumerApplication::with('merchant')->where('id', $id)
            ->first(['id', 'merchant_id', 'approved_amount', 'loan_amount']);
        if (!isset($application->id) || !isset($application->merchant->id) || $application->merchant->pf_surcharge_active != 1) {
            return $result;
        }

        $pfSurchargePercent = 0;
        $pfSurchargePercent += (float) ($this->getIncreasedPFFromMerchantLevel($id)['surcharge'] ?? 0);
        $pfSurchargePercent = max($pfSurchargePercent, $extraPfPercent);
        if ($pfSurchargePercent <= 0) {
            return $result;
        }

        $pfSurchargeAmount = round($this->calculateIncreasedPF($id, $pfSurchargePercent));
        if ($pfSurchargeAmount <= 0) {
            return $result;
        }

        return [
            'eligible' => true,
            'pf_surcharge_percent' => $pfSurchargePercent,
            'pf_surcharge_amount' => $pfSurchargeAmount,
            'pf_surcharge_gst' => $pfSurchargeAmount * 18 / 100,
            'extra_pf_percent' => $extraPfPercent,
        ];
    }

    public function getRiskBasedView(){
        $riskBasedConfiguration = RiskBasedConfiguration::get();
        $riskBasedConfigurationLogs = RiskBasedConfigurationLogs::orderBy('created_at', 'desc')->get();
        $merchantCategories = MerchantCategory::orderBy('name')->get(['id', 'name', 'risky_pincode_roi', 'is_risky_pincode_active']);

        return view('admin.merchant.risk.edit', [
            'riskBasedConfiguration' => $riskBasedConfiguration,
            'range' => $riskBasedConfigurationLogs,
            'merchantCategories' => $merchantCategories,
        ]);
    }

    public function updateRiskBasedPricing(Request $request){
        $request->validate([
            'data' => 'nullable|array',
            'data.*.row_id' => 'nullable|integer|min:0',
            'data.*.min_range' => 'required|integer|min:0',
            'data.*.max_range' => 'required|integer|min:0',
            'data.*.increase_pf_percent' => 'required|numeric|min:0',
            'data.*.discount_pf_percent' => 'required|numeric|min:0',
            'data.*.risky_roi_percentage' => 'required|numeric|min:0',
            'data.*.is_risky_pf_active' => 'required|boolean',
            'data.*.is_risky_roi_active' => 'required|boolean',
            'data.*.status' => 'required|boolean',
            'deleted_band_ids' => 'nullable|array',
            'deleted_band_ids.*' => 'integer|min:1',
            'merchant_category_id' => 'nullable|array',
            'merchant_category_id.*' => 'integer|exists:merchant_category,id',
            'risky_pincode_roi' => 'nullable|numeric|min:0',
            'is_risky_pincode_active' => 'nullable|boolean',
        ]);

        $userId = Auth::id() ?: (int)$request->get('user_id');

        $hasBureauUpdatePermission = \Illuminate\Support\Facades\Session::has('Bureau_Configuration_Update|-2-0');
        $hasPincodeUpdatePermission = \Illuminate\Support\Facades\Session::has('Risky_Pincode_Update|-2-1');

        if (!$hasBureauUpdatePermission) {
            $request->request->remove('data');
            $request->request->remove('deleted_band_ids');
        }

        if (!$hasPincodeUpdatePermission) {
            $request->request->remove('merchant_category_id');
            $request->request->remove('risky_pincode_roi');
            $request->request->remove('is_risky_pincode_active');
        }

        if (!$request->filled('data') && !$request->filled('deleted_band_ids') && !$request->filled('merchant_category_id')) {
            abort(403, 'You do not have permission to perform this action or no valid data was provided.');
        }
        $range = $request->get('data', []);
        $deletedBandIds = collect($request->get('deleted_band_ids', []))->map(function ($id) {
            return (int)$id;
        })->unique()->values()->all();

        DB::transaction(function () use ($request, $range, $deletedBandIds, $userId) {
            foreach ($deletedBandIds as $bandId) {
                $configuration = RiskBasedConfiguration::find($bandId);
                if (!$configuration) {
                    continue;
                }

                $this->logRiskBasedConfiguration($configuration, $userId, 'delete');
                $configuration->delete();
            }

            foreach ($range as $details) {
                $rowId = (int)$details['row_id'];
                $values = [
                    'min' => (int)$details['min_range'],
                    'max' => (int)$details['max_range'],
                    'increase_pf_percent' => (float)$details['increase_pf_percent'],
                    'discount_pf_percent' => (float)$details['discount_pf_percent'],
                    'risky_roi_percentage' => (float)$details['risky_roi_percentage'],
                    'is_risky_pf_active' => (int)$details['is_risky_pf_active'],
                    'is_risky_roi_active' => (int)$details['is_risky_roi_active'],
                    'status' => (int)$details['status'],
                    'updated_by' => $userId,
                ];

                if ($values['min'] > $values['max']) {
                    abort(422, 'The minimum bureau score cannot exceed the maximum bureau score.');
                }

                $configuration = $rowId > 0 ? RiskBasedConfiguration::findOrFail($rowId) : new RiskBasedConfiguration();
                $event = $this->getRiskBasedConfigurationEvent($configuration, $values, $rowId === 0);

                $configuration->fill($values);
                $configuration->save();
                $this->logRiskBasedConfiguration($configuration, $userId, $event);
            }

            $this->validateRiskBasedConfigurationRanges();

            if ($request->filled('merchant_category_id')) {
                $merchantCategoryIds = (array) $request->get('merchant_category_id');
                $riskyPincodeRoi = (float)$request->get('risky_pincode_roi', 0);
                $isRiskyPincodeActive = $request->get('is_risky_pincode_active', 1) ? 1 : 0;

                MerchantCategory::whereIn('id', $merchantCategoryIds)->update([
                    'risky_pincode_roi' => $riskyPincodeRoi,
                    'is_risky_pincode_active' => $isRiskyPincodeActive,
                ]);

                $userId = $request->get('user_id') ?? (\Auth::check() ? \Auth::id() : null);
                $now = now();
                $logs = [];
                foreach ($merchantCategoryIds as $categoryId) {
                    $logs[] = [
                        'merchant_category_id' => $categoryId,
                        'risky_pincode_roi' => $riskyPincodeRoi,
                        'is_risky_pincode_active' => $isRiskyPincodeActive,
                        'updated_by' => $userId,
                        'created_at' => $now,
                        'updated_at' => $now,
                    ];
                }
                MerchantCategoryLogs::insert($logs);
            }
        });

        return response()->json(['status' => 'OK', 'message' => 'Risk based pricing successfully saved']);
    }

    private function getRiskBasedConfigurationEvent(RiskBasedConfiguration $configuration, array $values, $isNew)
    {
        if ($isNew) {
            return 'create';
        }

        if ((int)$configuration->status !== (int)$values['status']) {
            return (int)$values['status'] === 1 ? 'activate' : 'deactivate';
        }

        return 'update';
    }

    private function logRiskBasedConfiguration(RiskBasedConfiguration $configuration, $userId, $event)
    {
        RiskBasedConfigurationLogs::create([
            'config_id' => $configuration->id,
            'min' => $configuration->min,
            'max' => $configuration->max,
            'increase_pf_percent' => $configuration->increase_pf_percent,
            'discount_pf_percent' => $configuration->discount_pf_percent,
            'risky_roi_percentage' => $configuration->risky_roi_percentage,
            'is_risky_pf_active' => $configuration->is_risky_pf_active,
            'is_risky_roi_active' => $configuration->is_risky_roi_active,
            'status' => $configuration->status,
            'event' => $event,
            'updated_by' => $userId,
        ]);
    }

    private function validateRiskBasedConfigurationRanges()
    {
        $previousRange = null;

        foreach (RiskBasedConfiguration::orderBy('min')->orderBy('max')->get(['min', 'max']) as $range) {
            if ($previousRange !== null && $range->min <= $previousRange->max) {
                abort(422, 'Bureau score bands cannot overlap.');
            }

            $previousRange = $range;
        }
    }

    /* Fetch the final PF amount */
    public function getProcessingFee($id, $pf = 0, $discount=0, $internal = false, $automatedPfAllowed = true, $persistSurcharge = true, $extraPfPercent = 0)
    {
        $application = ConsumerApplication::with([
            'merchant' => function ($query) {
                $query->select('id', 'pf_surcharge_active');
            }, 'emi' => function ($query) {
                $query->select('application_id', 'processing_fee');
            }, 'application_element' => function ($query) {
                $query->select('application_id', 'pf_discount');
            }
        ])->where('id', $id)->first(['id', 'merchant_id', 'approved_amount']);

        if (!$automatedPfAllowed) {
            if ($persistSurcharge && isset($application->id)) {
                $this->updateSurcharge($id, 0, 0, 0, $pf, $application->approved_amount);
            }

            return $internal ? [
                'id' => $id,
                'pf' => $pf,
                'pf_surcharge_percent' => 0,
                'pf_surcharge_amount' => 0,
                'pf_surcharge_gst' => 0,
                'final_pf_amount' => $pf,
            ] : $pf;
        }

//        if ($internal) {
//            $pf = $application->emi->processing_fee;
//        }

        $bureau_date = $this->getBureauPullDate($id);
        $pf_surcharge_percent = 0;

        if (isset($application->id) && isset($application->merchant->id) && $application->merchant->pf_surcharge_active == 1) {
            $bureau_surcharge = $this->getIncreasedPFFromMerchantLevel($id);
            $pf_surcharge_percent += (float) $bureau_surcharge['surcharge'];
            $pf_surcharge_percent = max($pf_surcharge_percent, (float) $extraPfPercent);
        }

        if ($pf_surcharge_percent > 0) {
            $pf_surcharge_amount = round($this->calculateIncreasedPF($id, $pf_surcharge_percent));
            $pf_surcharge_gst = 0;
            if ($pf_surcharge_amount > 0) {
                $pf_surcharge_gst = $pf_surcharge_amount * 18 / 100;
                $final_pf_amount = round($pf + $pf_surcharge_amount + $pf_surcharge_gst);
                
                if ($persistSurcharge) {
                    $this->updateSurcharge($id, $pf_surcharge_percent, $pf_surcharge_amount, $pf_surcharge_gst, $final_pf_amount, $application->approved_amount);
                }
                if (!$internal) {
                    return $final_pf_amount;
                } else {
                    return ['id' => $id, 'pf' => $pf, 'pf_surcharge_percent' => $pf_surcharge_percent,
                        'pf_surcharge_amount' => $pf_surcharge_amount, 'pf_surcharge_gst' => $pf_surcharge_gst, 'final_pf_amount' => $final_pf_amount];
                }
            }
        }

        if ($persistSurcharge && isset($application->id)) {
            $this->updateSurcharge($id, 0, 0, 0, $pf, $application->approved_amount);
        }
        if (!$internal) {
            return $pf;
        } else {
            return ['id' => $id, 'pf' => $pf, 'pf_surcharge_percent' => 0, 'pf_surcharge_amount' => 0, 'pf_surcharge_gst' => 0, 'final_pf_amount' => $pf];
        }
    }

    public function getProcessingFeesForNetLoanAmount($id, $pf = 0, $discount=0, $automatedPfAllowed = true, $internal = false, $persistSurcharge = true, $extraPfPercent = 0)
        {
        $total_surcharge_amount = 0;
        $application = ConsumerApplication::with([
            'merchant' => function ($query) {
                $query->select('id', 'pf_surcharge_active');
            }, 'application_element' => function ($query) {
                $query->select('application_id', 'pf_discount');
            }
        ])->where('id', $id)->first(['id', 'merchant_id', 'approved_amount']);

        if (!$automatedPfAllowed) {
            if ($persistSurcharge && isset($application->id)) {
                $this->updateSurcharge($id, 0, 0, 0, $pf, $application->approved_amount);
            }
            return $internal ? [
                'pf_surcharge_percent' => 0,
                'pf_surcharge_amount' => 0,
                'pf_surcharge_gst' => 0,
                'total_surcharge_amount' => 0,
            ] : 0;
        }

        $pf_surcharge_percent = 0;

        if (isset($application->id) && isset($application->merchant->id) && $application->merchant->pf_surcharge_active == 1) {
            $bureau_surcharge = $this->getIncreasedPFFromMerchantLevel($id);
            $pf_surcharge_percent += (float) $bureau_surcharge['surcharge'];
            $pf_surcharge_percent = max($pf_surcharge_percent, (float) $extraPfPercent);
        }

        if ($pf_surcharge_percent > 0) {
            $pf_surcharge_amount = round($this->calculateIncreasedPF($id, $pf_surcharge_percent));
            $pf_surcharge_gst = 0;
            if ($pf_surcharge_amount > 0) {
                $pf_surcharge_gst = $pf_surcharge_amount * 18 / 100;
                $final_pf_amount = round($pf + $pf_surcharge_amount + $pf_surcharge_gst);
                if ($persistSurcharge) {
                    $this->updateSurcharge($id, $pf_surcharge_percent, $pf_surcharge_amount, $pf_surcharge_gst, $final_pf_amount, $application->approved_amount);
                }
                $total_surcharge_amount = $pf_surcharge_amount + $pf_surcharge_gst;
                return $internal ? [
                    'pf_surcharge_percent' => $pf_surcharge_percent,
                    'pf_surcharge_amount' => $pf_surcharge_amount,
                    'pf_surcharge_gst' => $pf_surcharge_gst,
                    'total_surcharge_amount' => $total_surcharge_amount,
                ] : $total_surcharge_amount;
            }
        }

        if ($persistSurcharge && isset($application->id)) {
            $this->updateSurcharge($id, 0, 0, 0, $pf, $application->approved_amount);
        }
        return $internal ? [
            'pf_surcharge_percent' => 0,
            'pf_surcharge_amount' => 0,
            'pf_surcharge_gst' => 0,
            'total_surcharge_amount' => 0,
        ] : $total_surcharge_amount;
    }

    /*  */
    public function getIncreasedPFFromMerchantLevel($id){
        $surcharge = 0;
        $score = $this->getBureauScore($id);
        $response = RiskBasedConfiguration::where('min', '<=', $score)
            ->where('max', '>=', $score)
            ->where('status', 1)
            ->where('is_risky_pf_active', 1)
            ->first();
        if(isset($response->id)){
            $surcharge = (float)$response->increase_pf_percent ?? 0;
        }
        return ['surcharge' => $surcharge];
    }

    /* Fetch applicant's bureau score to match bands */
    public function getBureauScore($id){
        $creditReport = CreditReport::where('application_id', $id)->where('applicant_type', 1)->first(['Score']);
        if(isset($creditReport->Score) && $creditReport->Score > -2){
            return $creditReport->Score == -1 ? 0 : $creditReport->Score;
        }else{
            $file = ConsumerApplicationFiles::where('consumer_application_id', $id)->where('file_type', 'equifax_report')->whereNull('deleted_at')->orderBy('created_at', 'desc')->first(['bureau_report_score']);
            if (isset($file->bureau_report_score)){
                return $file->bureau_report_score == -1 ? 0 : $file->bureau_report_score;
            }
        }
        return false;
    }

    /* Fetch applicant's bureau score to match bands */
    public function getBureauPullDate($id){
        $creditReport = CreditReport::where('application_id', $id)
            ->where('applicant_type', 1)
            ->orderBy('created_at', 'asc')
            ->first(['created_at']);
        if(isset($creditReport->created_at)){
            return $creditReport->created_at;
        }else{
            $file = ConsumerApplicationFiles::where('consumer_application_id', $id)->where('file_type', 'equifax_report')->whereNull('deleted_at')->orderBy('created_at', 'asc')->first(['created_at']);
            if (isset($file->created_at)){
                return $file->created_at;
            }
        }
        return 0;
    }

    /**
     * Calculate and return the automated risk-based ROI parameters for an application.
     */
    public function getAutomatedROI($application_id, $base_roi = 0)
    {
        $bureau_loading = 0.0;
        $pincode_loading = 0.0;
        $is_risky_pincode = false;

        $application = ConsumerApplication::with(['merchant', 'category', 'application_element'])->find($application_id);

        if (!$application || !$application->merchant) {
            return [
                'bureau_roi_percentage' => 0.0,
                'pincode_roi_percentage' => 0.0,
                'applied_roi_percentage' => 0.0,
                'final_system_roi' => (float)$base_roi,
                'is_risky_pincode' => false,
                'status' => 'merchant_not_found'
            ];
        }

        if (!$application->merchant->pf_surcharge_active) {
            return [
                'bureau_roi_percentage' => 0.0,
                'pincode_roi_percentage' => 0.0,
                'applied_roi_percentage' => 0.0,
                'final_system_roi' => (float)$base_roi,
                'is_risky_pincode' => false,
                'status' => 'merchant_risk_pricing_disabled'
            ];
        }

        $pullDate = $this->getBureauPullDate($application_id);
        $thresholdDate = '2026-09-02 23:00:00';

        // Gate the entire Automated ROI feature behind the rollout date
        if (!$pullDate || $pullDate < $thresholdDate) {
            return [
                'bureau_roi_percentage' => 0.0,
                'pincode_roi_percentage' => 0.0,
                'applied_roi_percentage' => 0.0,
                'final_system_roi' => (float)$base_roi,
                'is_risky_pincode' => false,
                'status' => 'bureau_pull_date_too_old'
            ];
        }

        // 1. Resolve Bureau-Score ROI Loading
        $score = $this->getBureauScore($application_id);

        if ($score !== false) {
            $band = RiskBasedConfiguration::where('min', '<=', $score)
                ->where('max', '>=', $score)
                ->where('status', 1)
                ->where('is_risky_roi_active', 1)
                ->first();

            if ($band) {
                $bureau_loading = (float)$band->risky_roi_percentage;
            }
        }

        // 2. Resolve Risky-Pincode ROI Loading
        $pincodesToCheck = [];
        if (!empty($application->current_address_pincode)) {
            $pincodesToCheck[] = $application->current_address_pincode;
        }
        if ($application->application_element && !empty($application->application_element->installation_address_pincode)) {
            $pincodesToCheck[] = $application->application_element->installation_address_pincode;
        }

        foreach (array_unique($pincodesToCheck) as $pincode) {
            $riskyMatch = PincodeClassification::risky()
                ->pincode($pincode)
                ->whereNull('deleted_at')
                ->first();

            if ($riskyMatch) {
                $is_risky_pincode = true;
                break;
            }
        }

        if ($is_risky_pincode && $application->category && $application->category->is_risky_pincode_active == 1) {
            $pincode_loading = (float)$application->category->risky_pincode_roi;
        }

        // 3. Priority Math
        $applied_loading = max($bureau_loading, $pincode_loading);

        return [
            'bureau_roi_percentage' => $bureau_loading,
            'pincode_roi_percentage' => $pincode_loading,
            'applied_roi_percentage' => $applied_loading,
            'final_system_roi' => round((float)$base_roi + $applied_loading, 4),
            'is_risky_pincode' => $is_risky_pincode,
            'status' => 'success'
        ];
    }

    /* update the net surcharge for application */
    public function ensureAutomatedPFSurchargeComment($id, $pfSurchargeAmount){
        if ($pfSurchargeAmount <= 0) {
            return false;
        }

        $bureauSurchargePercent = 0;
        $bureauSurchargePercent = (float) ($this->getIncreasedPFFromMerchantLevel($id)['surcharge'] ?? 0);

        $extraPfPercent = 0;
        $application = ConsumerApplication::with('activeOffer')->find($id);
        if ($application && $application->activeOffer && $application->activeOffer->interest_rate == 0) {
            $pricingEligibility = $this->getAutomatedRiskPricingEligibility($id, $application->activeOffer, 0);
            $extraPfPercent = (float) ($pricingEligibility['automated_pf_data']['extra_pf_percent'] ?? 0);
        }

        $commentText = 'Risk Based Pricing Surcharge Added';
        if ($bureauSurchargePercent > 0 && $extraPfPercent > 0) {
            $commentText = 'Risk Based Pricing Surcharge and 1% pf due to Zero-ROI evaluated (Maximum applied)';
        } elseif ($extraPfPercent > 0) {
            $commentText = '1% Risk Based PF Surcharge added due to Zero-ROI offer';
        }

        $existingComment = Comments::where('application_id', $id)
            ->whereIn('comment', [
                'Risk Based Pricing Surcharge Added',
                'Risk Based Pricing Surcharge and 1% pf due to Zero-ROI evaluated (Maximum applied)',
                '1% Risk Based PF Surcharge added due to Zero-ROI offer'
            ])
            ->exists();

        if (!$existingComment) {
            (new GradeController(new Request))->addComment($id, 107, $commentText);
        }
        return true;
    }

    public function updateSurcharge($id, $pf_surcharge_percent, $pf_surcharge_amount, $pf_surcharge_gst, $final_pf_amount, $approved_amount){
        $app = ApplicationEMICalculation::where('application_id', $id)->first();
        if(isset($app->id) && (
            $app->pf_surcharge_percent != $pf_surcharge_percent ||
            $app->pf_surcharge_amount != $pf_surcharge_amount ||
            $app->pf_surcharge_gst != $pf_surcharge_gst
        )) {
            $app->pf_surcharge_percent = $pf_surcharge_percent;
            $app->pf_surcharge_amount = $pf_surcharge_amount;
            $app->pf_surcharge_gst = $pf_surcharge_gst;
            //$app->processing_fee = $final_pf_amount;
            $app->save();
            $this->ensureAutomatedPFSurchargeComment($id, $pf_surcharge_amount);
            $applicationEMICalculationLock = ApplicationEMICalculationLock::where('application_id', $id)->orderBy('created_at', 'desc')->first(['id']);

            if (!isset($applicationEMICalculationLock->id)) {

                $updatedUser = ApplicationEMICalculation::find($app->id)->toArray();

                $applicationLock = new ApplicationEMICalculationLock();
                $applicationLock->fill($updatedUser);
                $applicationLock->approved_amount = $approved_amount ?? 0;
                $applicationLock->pf_surcharge_percent = $pf_surcharge_percent;
                $applicationLock->pf_surcharge_amount = $pf_surcharge_amount;
                $applicationLock->pf_surcharge_gst = $pf_surcharge_gst;
                //$applicationLock->processing_fee = $final_pf_amount;
                $applicationLock->created_at = Carbon::now()->toDateTimeString();
                $applicationLock->re_scheduled_type = 0;
                $applicationLock->re_scheduled_by = isset(Auth::user()->id) ? Auth::user()->id : 0;
                $applicationLock->save();
            }else{
                $appLock = ApplicationEMICalculationLock::find($applicationEMICalculationLock->id);
                $appLock->approved_amount = $approved_amount ?? 0;
                $appLock->pf_surcharge_percent = $pf_surcharge_percent;
                $appLock->pf_surcharge_amount = $pf_surcharge_amount;
                $appLock->pf_surcharge_gst = $pf_surcharge_gst;
                $appLock->save();
            }
            return true;
        }
    }

    /* update the provided discount for application */
    public function updateDiscount($id, $discount){
        ConsumerApplicationElement::where('application_id', $id)->update(['pf_discount' => $discount]);
        $application = ConsumerApplication::with('activeOffer')->find($id);
        $pricingEligibility = $application && $application->activeOffer
            ? $this->getAutomatedRiskPricingEligibility($id, $application->activeOffer, $application->activeOffer->interest_rate)
            : ['automated_pf_allowed' => false];
        $data = $this->getProcessingFee(
            $id, 
            0, 
            $discount, 
            true, 
            $pricingEligibility['automated_pf_allowed'], 
            true, 
            $pricingEligibility['automated_pf_data']['extra_pf_percent'] ?? 0
        );
        return $discount;
    }

    /* Calculate the increase in existing PF amount */
    public function calculateIncreasedPF($id, $increased_pf_percentage){
        $application = ConsumerApplication::where('id', $id)->first(['loan_amount', 'approved_amount']);
        $calculationLoanAmount = empty($application->approved_amount) ? $application->loan_amount : $application->approved_amount;
        if ((new \App\EMICalculation())->checkAgreementSigned($id)) {
            $calculationLoanAmount = EMICalculation::getLoanAmountWithInsuranceAmount($id); // get loan amount including insurance amount or not
        }
        return $calculationLoanAmount * ($increased_pf_percentage / 100);
    }

    public function saveRiskBasedPricingCalculation($record_details) {
        $rbpCalculation = new RiskBasedPricingCalculation();
        $rbpCalculation->application_id = $record_details['application_id'];
        $rbpCalculation->payment_type = $record_details['payment_type'];
        $rbpCalculation->adjustment_enabled = 1;
        $rbpCalculation->adjustment_type = $record_details['adjust_type'];
        $rbpCalculation->adjustment_value = $record_details['pf_increase_value'];
        $rbpCalculation->adjustment_value_type = $record_details['value_type'];
        $rbpCalculation->total_amount = (float)$record_details['pf_summary_value'];
        $rbpCalculation->deleted_at = null;
        $rbpCalculation->save();
        // $this->saveRiskBasedPricingCalculationLog($record_details);
        return true;
    }

    public function saveRiskBasedPricingCalculationLog($data) {
        $rbpLog = new RiskBasedPricingCalculationLog();
        $rbpLog->application_id = $data['application_id'];
        $rbpLog->payment_type = $data['payment_type'];
        $rbpLog->adjustment_enabled = 1;
        $rbpLog->adjustment_type = $data['adjust_type'];
        $rbpLog->adjustment_value = $data['pf_increase_value'];
        $rbpLog->adjustment_value_type = $data['value_type'];
        $rbpLog->total_amount = (float)$data['pf_summary_value'];
        $rbpLog->updated_by = Auth::user() ? Auth::user()->id : 107;
        $rbpLog->deleted_at = null;
        $rbpLog->save();
    }

    public function riskBasedCalculationSavingValidation($id) {
        $riskBasedCalculation = DB::selectOne("SELECT id, adjustment_type, adjustment_value_type, adjustment_value from risk_based_pricing_calculation where application_id = $id");
        if (Input::has('pf_details') && Input::get('pf_details')) {
            $pf_details = Input::get('pf_details');
            $pf_details['application_id'] = $id;
            $pf_details['payment_type'] = 'processing_fee';
        }
        if (isset($pf_details) && isset($riskBasedCalculation->id)) {
            DB::table('risk_based_pricing_calculation')
                ->where('application_id', $id)
                ->update([
                    'adjustment_type' => $pf_details['adjust_type'],
                    'adjustment_value' => $pf_details['pf_increase_value'],
                    'adjustment_value_type' => $pf_details['value_type'],
                    'total_amount' => $pf_details['pf_summary_value'],
                    'updated_at' => Carbon::now(),
                    'deleted_at' => null
                ]);
            $this->saveRiskBasedPricingCalculationLog($pf_details);
        } else if (isset($pf_details) && !isset($riskBasedCalculation->id)) {
            // new entry
            $result = $this->saveRiskBasedPricingCalculation($pf_details);
        } else {
            // delete condition
            if (isset($riskBasedCalculation->id)) {
                DB::table('risk_based_pricing_calculation')
                    ->where('application_id', $id)
                    ->update([
                        'deleted_at' => Carbon::now()
                    ]);
            }
        }
    }

    public function updateDetailsOnReviseDocuments($id) {
        $processingFee = DB::selectOne("SELECT processing_fee from emi_calculation where application_id = ?", [$id])->processing_fee;
        $riskBasedCalculation = DB::selectOne("SELECT id,adjustment_type,adjustment_value,adjustment_value_type,total_amount from risk_based_pricing_calculation WHERE application_id = ? and deleted_at is null", [$id]);
        if (isset($riskBasedCalculation->id)) {
            $log_data = [
                'application_id' => $id,
                'payment_type' => 'processing_fee',
                'adjust_type' => $riskBasedCalculation->adjustment_type,
                'pf_increase_value' => $riskBasedCalculation->adjustment_value,
                'value_type' => $riskBasedCalculation->adjustment_value_type,
                'pf_summary_value' => round($riskBasedCalculation->total_amount)
            ];
            // Update the risk based calculation table
            DB::table('risk_based_pricing_calculation')
                ->where('application_id', $id)
                ->update([
                    'total_amount' => round($processingFee),
                    'updated_at' => Carbon::now()
                ]);
            // Insert into risk based calculation logs table
            $this->saveRiskBasedPricingCalculationLog($log_data);

        }
    }

    public function getRiskBasedPFCalculation($id, $baseProcessingFee) {
        $riskBasedCalculation = DB::selectOne("SELECT id,adjustment_type,adjustment_value,adjustment_value_type,total_amount from risk_based_pricing_calculation WHERE application_id = ? and deleted_at is null", [$id]);
        if (isset($riskBasedCalculation->id)) {
            $baseProcessingFee = ($baseProcessingFee == 0 && $riskBasedCalculation->adjustment_value_type == 'percent') ? 1 : $baseProcessingFee; // to avoid zero division error
            $amount = $riskBasedCalculation->adjustment_value_type == 'percent' ? $baseProcessingFee * ($riskBasedCalculation->adjustment_value/100) : $riskBasedCalculation->adjustment_value;
            $returnValue = $riskBasedCalculation->adjustment_type == 'increase' ? round($amount) : -round($amount);
            return $returnValue;
        }
        return 0;
    }

    // Reset the rbpc entry and add a comment for PF change due to offer change or approved amount change and the rbp component was for decerease
    public function resetRiskBasedPFOnOfferChange($id, $basePF) {
        DB::table('emi_calculation')->where('application_id', $id)->update(['processing_fee' => $basePF]);
        $creditPerson = DB::selectOne("SELECT u.id, u.name from users u inner join status_logs s on u.id = s.user_id WHERE s.application_id = ? and s.status = 'approved' order by s.created_at desc limit 1", [$id]);
        $advisor = DB::selectOne("SELECT u.id, u.name from users u inner join consumer_application ca on u.id = ca.created_by where ca.id = ?", [$id]);
        $creditPersonTag = '@'.$creditPerson->id.'-'.$creditPerson->name;
        $advisorTag = '@'.$advisor->id.'-'.$advisor->name;
        (new GradeController(new Request))->addComment($id, 107, $creditPersonTag.' '.$advisorTag.' The application PF has been revised. Please check the Risk Based Pricing Surcharge details.');
        DB::table('risk_based_pricing_calculation')
            ->where('application_id', $id)
            ->update([
                'deleted_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ]);
    }

    public function getOfferLinkedPF($application) {
        $emiCalculation = new \App\EMICalculation();
        $checkAgreementSigned = (new \App\EMICalculation())->checkAgreementSigned($application->id);
        if ($checkAgreementSigned) {
            $pfCalculationloanAmount = EMICalculation::getLoanAmountWithInsuranceAmount($application->id);
        } else {
            $pfCalculationloanAmount = $application->loan_amount;
        }
        if ($application->merchant->processing_fee_on_advance_amount && $application->activeOffer->processing_fee_type == 'percentage') {
            $pfCalculationloanAmount -= $application->emi->upfront_from_customer;
            $offer_linked_pf = $pfCalculationloanAmount * ($application->activeOffer->processing_fee / 100);
        } else {
            $offer_linked_pf = $emiCalculation->setProcessingFeeType($application->activeOffer->processing_fee_type)->setLoanAmount((float)$pfCalculationloanAmount)->setProcessingFee($application->activeOffer->processing_fee, true);
        }
        return $offer_linked_pf;
    }
}
