<?php

namespace Modules\Installment\Http\Controllers;

use App\Http\Controllers\PaymentController;
use App\Traits\ImageStore;
use Brian2694\Toastr\Facades\Toastr;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Modules\CourseSetting\Entities\Course;
use Modules\Installment\Entities\InstallmentCart;
use Modules\Installment\Entities\InstallmentPlan;
use Modules\Installment\Entities\InstallmentPurchasePayment;
use Modules\Installment\Entities\InstallmentPurchaseRequest;
use Modules\Installment\Entities\InstallmentVerificationAttachment;
use Modules\Payment\Entities\Cart;

class InstallmentPurchaseController extends Controller
{
    use ImageStore;

    function installmentOverviewData($topic_id, $plan_id)
    {
        try {

            $data = [];
            $upfront = 0;
            $total_installment_count = 0;
            $total_installment_amount = 0;
            $installment_duration = 0;


            $plan = InstallmentPlan::where('id', $plan_id)->where('status', 1)
                ->with('plan_specific_item', 'features', 'paymentSteps')
                ->where('start_datetime', '<=', date('Y-m-d H:i:s'))
                ->first();
            $topic = Course::find($topic_id);
            if (!$plan || !$topic) {
                return redirect()->back()->send()->with('error', _trans('installment::Plan Not Found'));
            }
            if ($topic->discount_price != null) {
                $topic_price = $topic->discount_price;
            } else {
                $topic_price = $topic->price;
            }
            $upfront_setup = $plan->paymentSteps->where('payment_title', 'Upfront')->first();
            if ($upfront_setup->amount_type == 'percent') {
                $upfront = ($topic_price * $upfront_setup->payment_amount) / 100;
            } else {
                $upfront = $upfront_setup->payment_amount;
            }
            $installment_setups = $plan->paymentSteps->where('payment_title', '!=', 'Upfront');
            $total_installment_count = $installment_setups->count();
            foreach ($installment_setups as $key => $installment_setup) {
                if ($installment_setup->amount_type == 'percent') {
                    $total_installment_amount += ($topic_price * $installment_setup->payment_amount) / 100;
                } else {
                    $total_installment_amount += $installment_setup->payment_amount;
                }
            }
            $installment_duration = $plan->paymentSteps->where('payment_title', '!=', 'Upfront')->last()->payment_deadline ?? null;

            $data['installment_overview'] = [
                'upfront' => $upfront,
                'upfront_amount' => $upfront,
                'total_installment_count' => $total_installment_count,
                'total_installment_amount' => $total_installment_amount,
                'total_payable_amount' => $upfront + $total_installment_amount,
                'installment_duration' => $installment_duration,
            ];
            $data['installment_page_title'] = _trans('installment.Review and confirm installments');

            $data['plan'] = $plan;
            $data['topic'] = $topic;
            return $data;
        } catch (\Throwable $th) {
            return false;
        }
    }

    public function purchase($topic_id, $plan_id)
    {
        try {

            $data = [];
            $data = $this->installmentOverviewData($topic_id, $plan_id);

            return view(theme('pages.installment_overview'), compact('data'));
        } catch (\Throwable $th) {
            return false;
        }
    }

    public function submitRequest(Request $request)
    {
        try {
            if (!Auth::check()) {
                Toastr::error(_trans('common.You must login'), trans('common.Error'));
                return \redirect()->route('login');
            }
            $course = Course::find($request->topic_id);
            if (!$course) {
                Toastr::error(trans('frontend.Course not found'), trans('common.Failed'));
                return redirect()->back();
            }
            if ($course->isLoginUserEnrolled) {
                Toastr::error(trans('frontend.Course already enrolled'), trans('common.Failed'));
                return redirect()->back();
            }
            if (isModuleActive('Org')) {
                $type = $course->required_type;
                if ($type == 1) {
                    Toastr::error(trans('org.Unable to add cart'), trans('common.Failed'));
                    return redirect()->back();
                }
            }

            $user = Auth::user();
            $installmentOvervie = $this->installmentOverviewData($course->id, $request->plan_id);
            if (Auth::check() && ($user->role_id != 1)) {
                DB::beginTransaction();

                $exist = Cart::where('user_id', $user->id)->where('course_id', $course->id)->first();
                $oldCart = Cart::where('user_id', $user->id)->when(isModuleActive('Appointment'), function ($query) {
                    $query->whereNotNull('course_id');
                })->first();

                if (isset($exist)) {
                    Toastr::error(trans('frontend.Course already added in your cart'), trans('common.Failed'));
                    return redirect()->route('CheckOut');
                } else {


                    if (isset($oldCart)) {

                        $cart = new Cart();
                        $cart->user_id = $user->id;
                        $cart->instructor_id = $course->user_id;
                        $cart->course_id = $course->id;
                        $cart->tracking = $oldCart->tracking;
                        $cart->price = $installmentOvervie['installment_overview']['upfront_amount'];
                        $cart->is_installment = 1;
                        $cart->plan_id = $request->plan_id;
                        $cart->installment_type = 'upfront';
                        $cart->save();
                    } else {
                        $cart = new Cart();
                        $cart->user_id = $user->id;
                        $cart->instructor_id = $course->user_id;
                        $cart->course_id = $course->id;
                        $cart->tracking = getTrx();
                        $cart->price = $installmentOvervie['installment_overview']['upfront_amount'];
                        $cart->is_installment = 1;
                        $cart->installment_type = 'upfront';
                        $cart->plan_id = $request->plan_id;
                        $cart->save();
                    }
                    $installment_cart = new InstallmentCart();
                    $installment_cart->user_id = $user->id;
                    $installment_cart->instructor_id = $course->user_id;
                    $installment_cart->course_id = $course->id;
                    $installment_cart->tracking = $cart->tracking;
                    $installment_cart->price = $cart->price;
                    $installment_cart->plan_id = $request->plan_id;
                    $installment_cart->save();

                    if ($cart->price == 0) {
                        $paymentController = new PaymentController();
                        $paymentController->directEnroll($cart->course_id, $cart->tracking);
                    }
                    $installment_purchase = $this->installmentCartProcess($request, $cart, $installmentOvervie);
                    $installment_cart->purchase_id = $installment_purchase->id;
                    $installment_cart->save();

                    $cart->purchase_id = $installment_purchase->id;
                    $cart->save();
                    DB::commit();
                    Toastr::success(trans('frontend.Item Added to your cart'), trans('common.Success'));
                    return redirect()->route('CheckOut')->with('back', courseDetailsUrl(@$course->id, @$course->type, @$course->slug));
                }
            } else {
                Toastr::error(trans('frontend.You logged in as admin so can not add cart'), trans('common.Failed'));
                return redirect()->back();
            }
        } catch (\Exception $e) {
            DB::rollback();
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());
        }
    }

    function priceNumber($price)
    {
        return   preg_replace('/[^0-9.]/', '', $price);
    }

        public function installmentCartProcess($request, $cart, $data)
    {
        try {

            $installment_purchase = new InstallmentPurchaseRequest();
            $installment_purchase->user_id = Auth::user()->id;
            $installment_purchase->topic_id = $request->topic_id;
            $installment_purchase->plan_id = $request->plan_id;
            $installment_purchase->tracking = $cart->tracking;
            $installment_purchase->cart_data = json_encode($cart);
            $installment_purchase->total_installment = $data['installment_overview']['total_installment_count'];
            $installment_purchase->paid_installment = 0;
            $installment_purchase->remaining_installment = $data['installment_overview']['total_installment_count'];
            $installment_purchase->paid_amount = $data['installment_overview']['upfront_amount'];
            $installment_purchase->remaining_amount = $this->priceNumber($data['installment_overview']['total_installment_amount']);
            $installment_purchase->total_amount = $this->priceNumber($data['installment_overview']['total_payable_amount']);
            $installment_purchase->purchase_date = date('Y-m-d');
            $installment_purchase->payment_status = 'incomplete';
            $installment_purchase->save();

            $plan_info = InstallmentPlan::where('id', $installment_purchase->plan_id)->with('paymentSteps')->first();
            $upload_path = 'public/uploads/installment/verification';
            if (isset($request->file)) {
                foreach ($request->file as $key => $file) {
                    $installment_purchase_file = new InstallmentVerificationAttachment();
                    $installment_purchase_file->installment_purchase_id = $installment_purchase->id;
                    $installment_purchase_file->title = $request->title[$key] ?? null;
                    $installment_purchase_file->file = $this->saveFile($file, $upload_path);
                    $installment_purchase_file->save();
                }
            }
            foreach ($plan_info->paymentSteps as $key => $installment) {
                $installment_amount = 0;
                if ($installment->amount_type == 'percent') {
                    $installment_amount = ($installment->payment_amount * $this->priceNumber($installment_purchase->total_amount)) / 100;
                } else {
                    $installment_amount = $installment->payment_amount;
                }
                $due_date = Carbon::now();

                if ($installment->payment_deadline == null) {
                    $due_date = date('Y-m-d');
                } else {
                    $newDate = $due_date->addDays($installment->payment_deadline);
                    $due_date = $newDate->format('Y-m-d');
                }
                $installment_payment = new InstallmentPurchasePayment();
                $installment_payment->installment_purchase_id = $installment_purchase->id;
                $installment_payment->type = $installment->payment_title == 'Upfront' ? 'upfront' : 'step';
                $installment_payment->step_id = $installment->id;
                $installment_payment->amount = $installment_amount;
                $installment_payment->amount_type = $installment->amount_type;
                $installment_payment->percentage = $installment->amount_type == 'percent' ? $installment->payment_amount : 0;
                $installment_payment->due_date = $due_date;
                $installment_payment->payment_date = $installment->payment_title == 'Upfront' ? date('Y-m-d') : null;
                $installment_payment->status = 'unpaid';
                $installment_payment->save();
            }
            $installment_purchase->next_payment_date = $installment_purchase->installmentPayments->where('type', 'step')->first()->due_date ?? '';
            $installment_purchase->save();
            return $installment_purchase;
        } catch (\Throwable $th) {
            return [];
        }
    }

    public function installmentProcessReset($tracking, $checkout_data)
    {
        try {
            $installment_purchases = InstallmentPurchaseRequest::where('tracking', $tracking)->get();

            foreach ($installment_purchases as $key => $installment_purchase) {
                $installment_purchase->payment_status = 'paid';
                $installment_purchase->checkout_data = $checkout_data;

                $installment_purchase->save();

                $installment_purchase->installmentPayments()->delete();
                $plan_info = InstallmentPlan::where('id', $installment_purchase->plan_id)->with('paymentSteps')->first();

                foreach ($plan_info->paymentSteps as $key => $installment) {
                    $installment_amount = 0;
                    if ($installment->amount_type == 'percent') {
                        $installment_amount = ($installment->payment_amount * $this->priceNumber($installment_purchase->total_amount)) / 100;
                    } else {
                        $installment_amount = $installment->payment_amount;
                    }
                    $due_date = Carbon::now();

                    if ($installment->payment_deadline == null) {
                        $due_date = date('Y-m-d');
                    } else {
                        $newDate = $due_date->addDays($installment->payment_deadline);
                        $due_date = $newDate->format('Y-m-d');
                    }
                    $installment_payment = new InstallmentPurchasePayment();
                    $installment_payment->installment_purchase_id = $installment_purchase->id;
                    $installment_payment->type = $installment->payment_title == 'Upfront' ? 'upfront' : 'step';
                    $installment_payment->step_id = $installment->id;
                    $installment_payment->amount = $installment_amount;
                    $installment_payment->amount_type = $installment->amount_type;
                    $installment_payment->percentage = $installment->amount_type == 'percent' ? $installment->payment_amount : 0;
                    $installment_payment->due_date = $due_date;
                    $installment_payment->payment_date = $installment->payment_title == 'Upfront' ? date('Y-m-d') : null;
                    $installment_payment->status = $installment->payment_title == 'Upfront' ? 'paid' : 'unpaid';
                    $installment_payment->save();
                }
                $installment_purchase->next_payment_date = $installment_purchase->installmentPayments->where('type', 'step')->first()->due_date;
                $installment_purchase->save();
            }
            return true;


        } catch (\Throwable $th) {
            return false;
        }
    }

    public function installmentPaymentProcess($purchase_id)
    {
        try {
            DB::beginTransaction();
            $installment_purchases = InstallmentPurchaseRequest::where('id', $purchase_id)
                ->with('installmentPayments')
                ->first();

            $installment_payment = $installment_purchases->installmentPayments->where('status', 'unpaid')->first();
            $installment_payment->status = 'paid';
            $installment_payment->payment_date = date('Y-m-d');
            $installment_payment->save();

            $check_unpaid_installment = $installment_purchases->installmentPayments->where('status', 'unpaid');
            if ($check_unpaid_installment->count() == 0) {
                $installment_purchases->payment_status = 'complete';
                $installment_purchases->save();
            }
            DB::commit();
            return true;
        } catch (\Throwable $th) {
            DB::rollBack();
            return false;
        }
    }
}
