<?php

namespace App\Http\Controllers\Admin;

use App\ApplicationEMICalculation;
use App\ApplicationEMICalculationLock;
use App\ConsumerApplication;
use App\ConsumerApplicationElement;
use App\ConsumerApplicationFiles;
use App\RiskBasedPricingCalculation;
use App\RiskBasedPricingCalculationLog;
use App\CreditReport;
use App\EmiPayment;
use App\Http\Controllers\Controller;
use App\RiskBasedConfiguration;
use App\RiskBasedConfigurationLogs;
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;

class RiskController extends Controller{

    private $request;

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

    public function getRiskBasedView(){
        $riskBasedConfiguration = RiskBasedConfiguration::get();
        $riskBasedConfigurationLogs = RiskBasedConfigurationLogs::orderBy('created_at', 'desc')->get();
        return view('admin.merchant.risk.edit', ['riskBasedConfiguration' => $riskBasedConfiguration, 'range' => $riskBasedConfigurationLogs]);
    }

    public function updateRiskBasedPricing(Request $request){
        $user_id = (int)$this->request->get('user_id');
        $range = $this->request->get('data');

        if(count($range) > 0){
            foreach($range as $details){
                $row_id = (int)$details['row_id'];

                $min = (int)$details['min_range'];
                $max = (int)$details['max_range'];
                $increase_pf_percent = $details['increase_pf_percent'];
                $discount_pf_percent = $details['discount_pf_percent'];
                if($row_id > 0){
                    RiskBasedConfiguration::where('id', $row_id)->update([
                        'min' => $min,
                        'max' => $max,
                        'increase_pf_percent' => $increase_pf_percent,
                        'discount_pf_percent' => $discount_pf_percent,
                        'updated_by' => $user_id,
                    ]);
                } else{
                    $riskBasedConfiguration = new RiskBasedConfiguration();
                    $riskBasedConfiguration->min = $min;
                    $riskBasedConfiguration->max = $max;
                    $riskBasedConfiguration->increase_pf_percent = $increase_pf_percent;
                    $riskBasedConfiguration->discount_pf_percent = $discount_pf_percent;
                    $riskBasedConfiguration->updated_by = $user_id;
                    $riskBasedConfiguration->created_at = Carbon::now()->toDateTimeString();
                    $riskBasedConfiguration->save();

                    $row_id = $riskBasedConfiguration->id;
                }

                $log_data = [
                    'config_id' => $row_id,
                    'min' => $min,
                    'max' => $max,
                    'increase_pf_percent' => $increase_pf_percent,
                    'discount_pf_percent' => $discount_pf_percent,
                    'updated_by' => $user_id,
                    'created_at' => Carbon::now()->toDateTimeString()
                ];

//                array_push($log_data, ['min' => $min]);
//                array_push($log_data, ['max' => $max]);
//                array_push($log_data, ['increase_pf_percent' => $increase_pf_percent]);
//                array_push($log_data, ['discount_pf_percent' => $discount_pf_percent]);

                RiskBasedConfigurationLogs::insert($log_data);
            }
        }

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

    /* Fetch the final PF amount */
    public function getProcessingFee($id, $pf = 0, $discount=0, $internal = false)
    {
        $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 ($internal) {
//            $pf = $application->emi->processing_fee;
//        }

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

        if($bureau_date && Carbon::parse($bureau_date)->toDateTimeString() >= '2024-08-09 15:00:00'){
            // if ($discount != 0) {
            //     $application->application_element->pf_discount = $discount;
            // }

            if (isset($application->id) && isset($application->merchant->id)) {
                if ($application->merchant->pf_surcharge_active == 1) {
                    $pf_surcharge_percent = $this->getIncreasedPFFromMerchantLevel($id);
                    $pf_surcharge_percent = $pf_surcharge_percent['surcharge'];
                    // if ($application->application_element->pf_discount > 0) {
                    //     $pf_surcharge_percent = (float)$pf_surcharge_percent - (float)$application->application_element->pf_discount;
                    // }

                    $pf_surcharge_amount = round($this->calculateIncreasedPF($id, $pf_surcharge_percent));
                    $pf_surcharge_gst = 0;
                    if ($pf_surcharge_percent > 0) {
                        $pf_surcharge_gst = $pf_surcharge_amount * 18 / 100;
                    }


                    if ($pf_surcharge_amount > 0) {
                        $final_pf_amount = round($pf + $pf_surcharge_amount + $pf_surcharge_gst);
                        $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_surcharge_percent' => $pf_surcharge_percent,
                                'pf_surcharge_amount' => $pf_surcharge_amount, 'pf_surcharge_gst' => $pf_surcharge_gst, 'final_pf_amount' => $final_pf_amount];
                        }
                    }
                } else{
                    $this->updateSurcharge($id, 0, 0, 0, $pf, $application->approved_amount);
                }
            }
        }else{
            if (!$internal) {
                return $pf;
            } else {
                return ['id' => $id, 'pf_surcharge_percent' => 0, 'pf_surcharge_amount' => 0, 'pf_surcharge_gst' => 0, 'final_pf_amount' => $pf];
            }
        }
        return $pf;
    }

    public function getProcessingFeesForNetLoanAmount($id, $pf = 0, $discount=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']);

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

        if($bureau_date && Carbon::parse($bureau_date)->toDateTimeString() >= '2024-08-09 15:00:00'){
            // if ($discount != 0) {
            //     $application->application_element->pf_discount = $discount;
            // }

            if (isset($application->id) && isset($application->merchant->id)) {
                if ($application->merchant->pf_surcharge_active == 1) {
                    $pf_surcharge_percent = $this->getIncreasedPFFromMerchantLevel($id);
                    $pf_surcharge_percent = $pf_surcharge_percent['surcharge'];
                    // if ($application->application_element->pf_discount > 0) {
                    //     $pf_surcharge_percent = (float)$pf_surcharge_percent - (float)$application->application_element->pf_discount;
                    // }

                    $pf_surcharge_amount = round($this->calculateIncreasedPF($id, $pf_surcharge_percent));
                    $pf_surcharge_gst = 0;
                    if ($pf_surcharge_percent > 0) {
                        $pf_surcharge_gst = $pf_surcharge_amount * 18 / 100;
                    }

                    if ($pf_surcharge_amount > 0) {
                        $final_pf_amount = round($pf + $pf_surcharge_amount + $pf_surcharge_gst);
                        $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 $total_surcharge_amount;
                    }
                }
            }
        }
        return $total_surcharge_amount;
    }

    /*  */
    public function getIncreasedPFFromMerchantLevel($id){
        $surcharge = 0;
        $score = $this->getBureauScore($id);
        $response = RiskBasedConfiguration::where('min', '<=', $score)->where('max', '>=', $score)->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)->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', 'desc')->first(['created_at']);
            if (isset($file->created_at)){
                return $file->created_at;
            }
        }
        return 0;
    }

    /* update the net surcharge for application */
    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_amount != $pf_surcharge_amount)) {
            $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();
            $comment_exist = DB::selectOne("SELECT id from comments WHERE application_id = $id AND comment = 'Risk Based Pricing Surcharge Added'"); // Check if comment already exists
            if (!isset($comment_exist->id) && $pf_surcharge_amount > 0) {
                (new GradeController(new Request))->addComment($id, 107, 'Risk Based Pricing Surcharge Added'); // Comment for Risk Based Pricing Surcharge
            }
            $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]);
        $data = $this->getProcessingFee($id, 0, $discount, true);
        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;
    }
}
