<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Frontend\WebsiteController;
use App\Jobs\SendGeneralEmail;
use App\Traits\SendNotification;
use App\User;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Modules\Certificate\Entities\Certificate;
use Modules\Certificate\Entities\CertificateRecord;
use Modules\Certificate\Http\Controllers\CertificateController;
use Modules\CourseSetting\Entities\Course;
use Modules\CourseSetting\Entities\CourseCanceled;
use Modules\CourseSetting\Entities\CourseEnrolled;
use Modules\Payment\Entities\InstructorPayout;
use Modules\Payment\Entities\InstructorTotalPayout;
use Modules\Payment\Entities\Withdraw;
use Modules\Subscription\Entities\SubscriptionCheckout;
use Modules\Subscription\Entities\SubscriptionCourse;
use Yajra\DataTables\DataTables;

class AdminController extends Controller
{
    use SendNotification;

    public function enrollLogs(Request $request)
    {
        $courseId = $request->get('course', '');
        $start = !empty($request->start_date) ? date('Y-m-d', strtotime($request->start_date)) : '';
        $end = !empty($request->end_date) ? date('Y-m-d', strtotime($request->end_date)) : '';

        try {
            $enrolls = [];
            $course_query = Course::where('status', 1);

            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $course_query->whereHas('user', function ($q) {
                    $q->where('organization_id', Auth::id());
                    $q->orWhere('id', Auth::id());
                });
            }

            $courses = $course_query->select('id', 'title', 'type')->get();

            $query = User::where('role_id', 3);
            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $query->where('organization_id', Auth::id());
                $query->orWhere('id', Auth::id());
            }
            $students = $query->get();
            return view('backend.student.enroll_student', compact('courseId', 'start', 'end', 'enrolls', 'courses', 'students'));

        } catch (\Exception $e) {
            Toastr::error(trans('common.Operation failed'), trans('common.Failed'));
            return redirect()->back();
        }
    }

    public function cancelLogs(Request $request)
    {
        $courseId = $request->get('course', '');
        $start = !empty($request->start_date) ? date('Y-m-d', strtotime($request->start_date)) : '';
        $end = !empty($request->end_date) ? date('Y-m-d', strtotime($request->end_date)) : '';

        try {
            $enrolls = [];
            $course_query = Course::where('status', 1);

            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $course_query->whereHas('user', function ($q) {
                    $q->where('organization_id', Auth::id());
                    $q->orWhere('id', Auth::id());
                });
            }

            $courses = $course_query->select('id', 'title', 'type')->get();

            $query = User::where('role_id', 3);
            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $query->where('organization_id', Auth::id());
                $query->orWhere('id', Auth::id());
            }
            $students = $query->get();
            return view('backend.student.cancel_student', compact('courseId', 'start', 'end', 'enrolls', 'courses', 'students'));

        } catch (\Exception $e) {
            Toastr::error(trans('common.Operation failed'), trans('common.Failed'));
            return redirect()->back();
        }
    }

    public function enrollFilter(Request $request)
    {

        try {
            $courseId = $request->get('course', '');
            $start = !empty($request->start_date) ? date('Y-m-d', strtotime($request->start_date)) : '';
            $end = !empty($request->end_date) ? date('Y-m-d', strtotime($request->end_date)) : '';


            $courses = Course::all();
            $query = User::where('role_id', 3);
            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $query->where('organization_id', Auth::id());
            }
            $students = $query->get();
            return view('backend.student.enroll_student', compact('courseId', 'start', 'end', 'courses', 'students'));


        } catch (\Exception $e) {
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());
        }
    }

    public function reveuneList()
    {
        try {
            $courses = Course::with('enrolls', 'user')->withCount('enrolls')->get();
            return view('payment::admin_revenue', compact('courses'));
        } catch (\Exception $e) {
            return response()->json(['error' => trans("lang.Oops, Something Went Wrong")]);


        }
    }

    public function reveuneListInstructor(Request $request)
    {
        try {
            $search_instructor = $request->get('instructor', '');
            $search_month = $request->get('month', '');
            $search_year = empty($request->year) ? date('Y') : $request->year;
            $query = CourseEnrolled::with('course', 'user', 'course.user');

            if (!empty($search_month)) {
                $from = date($search_year . '-' . $search_month . '-1');
                $to = date($search_year . '-' . $search_month . '-31');
                $query->whereBetween('created_at', [$from, $to]);
            }

            if (Auth::user()->role_id == 2) {
                $query->whereHas('course', function ($q) {
                    $q->where('user_id', Auth::user()->id);
                });
            }
            if (!empty($request->instructor)) {
                $query->whereHas('course', function ($q) {
                    $q->where('user_id', \request('instructor'));
                });
            }

            $enrolls = $query->whereHas('course.user', function ($query) {
                $query->where('id', '!=', 1);
            })->latest()->get();


            $query2 = DB::table('subscription_courses')
                ->select('subscription_courses.*')
                ->selectRaw("SUM(revenue) as total_price");
            if (Auth::user()->role_id == 2) {
                $query2->where('user_id', '=', Auth::user()->id);
            }


            if (isModuleActive('Subscription')) {
                $subscriptionsData = $query2->groupBy('checkout_id')
                    ->latest()->get();;
                $subscriptions = [];
                foreach ($subscriptionsData as $key => $data) {
                    $subscriptions[$key]['checkout_id'] = $data->checkout_id;
                    $subscriptions[$key]['date'] = $data->date;
                    $subscriptions[$key]['price'] = $data->total_price;
                    $user = User::where('id', $data->instructor_id)->first();
                    $subscriptions[$key]['instructor'] = $user->name ?? '';

                    $plan = SubscriptionCheckout::where('id', $data->checkout_id)->first();

                    $subscriptions[$key]['plan'] = $plan->plan->title ?? '';
                }


            } else {
                $subscriptions = [];
            }
            $instructors = User::where('role_id', 2)->get();
            return view('payment::instructor_revenue_report', compact('search_instructor', 'search_month', 'search_year', 'instructors', 'enrolls', 'subscriptions'));
        } catch
        (\Exception $e) {
            return response()->json(['error' => trans("lang.Oops, Something Went Wrong")]);
        }

    }

    public function sortByDiscount(Request $request)
    {

        $rules = [
            'discount' => 'required',
            'id' => 'required'
        ];

        $this->validate($request, $rules, validationMessage($rules));

        try {
            $id = $request->id;
            $val = $request->discount;
            $start = date('Y-m-d', strtotime($request->start_date));
            $end = date('Y-m-d', strtotime($request->end_date));
            $method = $request->methods;
            if ((isset($request->end_date)) && (isset($request->start_date))) {

                if ($val == 10) {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '>', 0)->whereDate('created_at', '>=', $start)->whereDate('created_at', '<=', $end)->latest()->with('user')->get();
                } else {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '=', 0)->whereDate('created_at', '>=', $start)->whereDate('created_at', '<=', $end)->latest()->with('user')->get();

                }
            } elseif (is_null($request->start_date) && is_null($request->end_date)) {

                if ($val == 10) {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '>', 0)->with('user', 'course')->latest()->get();
                } else {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '=', 0)->with('user', 'course')->latest()->get();

                }
            } elseif (isset($request->start_date) && is_null($request->end_date)) {


                if ($val == 10) {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '>', 0)->with('user', 'course')->whereDate('created_at', '>=', $start)->latest()->get();
                } else {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '=', 0)->with('user', 'course')->whereDate('created_at', '>=', $start)->latest()->get();

                }

            } elseif (isset($request->end_date) && is_null($start)) {

                if ($val == 10) {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '>', 0)->with('user', 'course')->whereDate('created_at', '<=', $end)->latest()->get();
                } else {

                    $logs = CourseEnrolled::where('course_id', $id)->where('discount_amount', '=', 0)->with('user', 'course')->whereDate('created_at', '<=', $end)->latest()->get();

                }
            }
            $course_id = $request->id;
            return view('payment::enroll_log', compact('logs', 'course_id'));
        } catch (\Exception $e) {
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());

        }
    }


    public function courseEnrolls($id)
    {

        try {
            $logs = CourseEnrolled::where('course_id', $id)->with('user', 'course')->latest()->get();
            $course_id = $id;
            return view('payment::enroll_log', compact('logs', 'course_id'));
        } catch (\Exception $e) {
            return response()->json(['error' => trans("lang.Oops, Something Went Wrong")]);


        }
    }

    public function instructorPayout(Request $request)
    {
        $instructors = User::where('role_id', 2)->get(['id', 'name']);

        $next_pay = InstructorPayout::where('instructor_id', Auth::user()->id)->whereStatus('0')->sum('reveune');
        if (isModuleActive('Subscription')) {
            $subscriptionPay = SubscriptionCourse::where('instructor_id', Auth::user()->id)->whereStatus('0')->sum('revenue');
            $next_pay = $next_pay + $subscriptionPay;
        }


        $user = Auth::user();

        $instructorTotal = InstructorTotalPayout::where('instructor_id', $user->id)->first();
        if (!$instructorTotal) {
            $instructorTotal = new InstructorTotalPayout();
            $instructorTotal->instructor_id = $user->id;
        }
        $instructorTotal->amount = $instructorTotal->amount + $next_pay;
        $instructorTotal->save();

        $remaining = $instructorTotal->amount;

        InstructorPayout::where('instructor_id', $user->id)->whereStatus('0')->update(['status' => 1]);
        if (isModuleActive('Subscription')) {
            SubscriptionCourse::where('instructor_id', $user->id)->whereStatus('0')->update(['status' => 1]);
        }

        return view('payment::instructor_payout', compact('remaining', 'instructors'));
    }

    public function instructorRequestPayout(Request $request)
    {
        try {
            $minAmount = (int)Settings('minimum_payout_amount');
            $user = Auth::user();
            $totalPayout = InstructorTotalPayout::where('instructor_id', $user->id)->first();
            $maxAmount = $totalPayout->amount;
            $amount = $request->amount;

            if ($maxAmount < $amount) {
                Toastr::error(trans('payment.Max Limit is').' ' . getPriceFormat($maxAmount), trans('common.Error'));
                return redirect()->back();
            }
                if ($minAmount!=0 && $minAmount > $amount) {
                Toastr::error(trans('payment.Minimum Amount is').' ' . getPriceFormat($minAmount), trans('common.Error'));
                return redirect()->back();
            }

            $withdraw = new Withdraw();
            $withdraw->instructor_id = Auth::user()->id;
            $withdraw->amount = $amount;
            $withdraw->issueDate = Carbon::now();
            $withdraw->method = Auth::user()->payout;
            $withdraw->save();
            $totalPayout->amount = $totalPayout->amount - $amount;
            $totalPayout->save();


            if (Auth::user()->role_id != 1) {
                $admins = User::where('role_id', 1)->get();
                foreach ($admins as $user) {
                    SendGeneralEmail::dispatch($user, 'PayoutRequest', [
                        'admin' => $user->name,
                        'amount' => $amount,
                        'instructor' => Auth::user()->name,
                    ]);
                    send_browser_notification($user, 'PayoutRequest', [
                            'admin' => $user->name,
                            'amount' => $amount,
                            'instructor' => Auth::user()->name,
                        ]
                    );
                }
            }

            Toastr::success(trans('lang.Payment request has been successfully submitted'), trans('common.Success'));
            return redirect()->back();
        } catch (\Exception $e) {
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());
        }
    }

    public function instructorCompletePayout(Request $request)
    {
        try {
            DB::beginTransaction();
            $withdraw = Withdraw::whereId($request->withdraw_id)->whereInstructorId($request->instructor_id)->first();
            $instractor = User::find($request->instructor_id);
            $withdraw->status = 1;
            $withdraw->save();
            $instractor->balance += $withdraw->amount;
            $instractor->save();
            DB::commit();
            Toastr::success(trans('lang.Payment request has been Approved'), trans('common.Success'));
            return redirect()->back();
        } catch (\Exception $e) {
            DB::rollback();
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());
        }
    }

    public function enrollDelete(Request $request)
    {

        $request->validate([
            'id' => 'required',
//           'reason'=>'required',
        ]);


        if (demoCheck()) {
            return redirect()->back();
        }

        $id = $request->id;

        if (isset($request->cancel)) {
            $deleteEnroll = $enroll = CourseCanceled::with('course', 'user')->findOrFail($id);
        } else {
            $deleteEnroll = $enroll = CourseEnrolled::with('course', 'user')->findOrFail($id);

        }

        $student = $enroll->user;

        if (isset($request->refund)) {
            $student->balance = $student->balance + $enroll->purchase_price;
            $student->save();
            $act = 'Enroll_Refund';
            $status = 1;
        } else {
            $act = 'Enroll_Rejected';
            $status = 0;
        }
        $reason = $request->reason;
        if (!isset($request->cancel)) {
            $this->courseCanceled($enroll->user_id, $enroll->course_id, $enroll->purchase_price, $status, $reason);
            $deleteEnroll->delete();
        } else {
            $deleteEnroll->refund = $status;
            $deleteEnroll->save();
        }

        $this->sendNotification($act, $enroll->user, [
            'course' => $enroll->course->getTranslation('title', $enroll->user->language_code ?? config('app.fallback_locale')),
            'time' => now(),
            'reason' => $reason
        ], [
            'actionText' => trans('common.View'),
            'actionUrl' => courseDetailsUrl(@$enroll->course->id, @$enroll->course->type, @$enroll->course->slug)
        ]);
        $this->sendNotification($act, $enroll->course->user, [
            'course' => $enroll->course->getTranslation('title', $enroll->course->user->language_code ?? config('app.fallback_locale')),
            'time' => now(),
            'reason' => $reason
        ], [
            'actionText' => trans('common.View'),
            'actionUrl' => courseDetailsUrl(@$enroll->course->id, @$enroll->course->type, @$enroll->course->slug)
        ]);


        Toastr::success(trans('common.Operation successful'), trans('common.Success'));
        return redirect()->back();
    }

    public function courseCanceled($user_id, $course_id, $price, $status, $reason)
    {
        $user = Auth::user();
        $cancle = new CourseCanceled();
        $cancle->user_id = $user_id;
        $cancle->course_id = $course_id;
        $cancle->purchase_price = (int)$price;
        $cancle->refund = $status;
        $cancle->cancel_by = $user->id;
        $cancle->reason = $reason ?? '';
        $cancle->approved_date = date('Y-m-d');

        $cancle->save();
    }

    public function getEnrollLogsData(Request $request)
    {
        $user = Auth::user();
        $query = CourseEnrolled::select('course_enrolleds.*')->with('user:id,name,image,email', 'course:id,title', 'course.enrolls:id', 'course.certificate_records');


        if ($user->role_id == 2) {
            $query->whereHas('course', function ($query) use ($user) {
                $query->where('user_id', '=', $user->id);
            });

        } else {

            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $query->whereHas('user', function ($q) {
                    $q->where('organization_id', Auth::id());
                    $q->orWhere('id', Auth::id());
                })->orWhereHas('course.user', function ($q) {
                    $q->where('organization_id', Auth::id());
                    $q->orWhere('id', Auth::id());
                });

            }
        }


        if (!empty($request->course)) {
            $query->where('course_id', $request->course);
        }
        if (!empty($request->start_date)) {
            $query->whereDate('created_at', '>=', $request->start_date);
        }
        if (!empty($request->end_date)) {
            $query->whereDate('created_at', '<=', $request->end_date);
        }

        if ($request->start) {
            $query->skip($request->start);
        }
        if ($request->length) {
            $query->limit($request->length);
        }


        return Datatables::of($query)
            ->addIndexColumn()
            ->addColumn('image', function ($query) {
                $image = $query->user->image;
                $user = $query->user->name;
                return view('backend.partials._small_profile_image', compact('image', 'user'));
            })->editColumn('user.name', function ($query) {
                return $query->user->name;

            })->editColumn('user.email', function ($query) {
                return $query->user->email;

            })
            ->editColumn('course.title', function ($query) {
                return $query->course->title;

            })
            ->editColumn('created_at', function ($query) {
                return showDate(@$query->created_at);

            })->editColumn('purchase_price', function ($query) {
                return getPriceFormat(@$query->purchase_price);

            })
            ->addColumn('action', function ($query) {

                return view('backend.student._td_enroll_log', compact('query'));

            })->rawColumns(['image', 'action'])->make(true);
    }

    public function getCancelLogsData(Request $request)
    {
        $user = Auth::user();
        if ($user->role_id == 2) {
            $query = CourseCanceled::with('user', 'course', 'confirmUser')
                ->whereHas('course', function ($query) use ($user) {
                    $query->where('user_id', '=', $user->id);
                });
        } else {
            $query = CourseCanceled::with('user', 'course', 'confirmUser');


            if (isModuleActive('Organization') && Auth::user()->isOrganization()) {
                $query->whereHas('course.user', function ($q) {
                    $q->where('organization_id', Auth::id());
                    $q->orWhere('id', Auth::id());
                });
            }
        }

        if ($request->f_course) {
            $query->where('course_id', $request->f_course);
        }
        if ($request->f_user) {
            $query->where('user_id', $request->f_user);
        }
        if ($request->f_type) {
            $query->where('refund', $request->f_type == 1 ? 1 : 0);
        }

        if ($request->f_status != null) {

            if ($request->f_status == 3) {
                $status = 0;
            } else {
                $status = $request->f_status;
            }
            $query->where('status', $status);
        }

        if ($request->f_date) {
            $query->whereBetween(DB::raw('DATE(created_at)'), formatDateRangeData($request->f_date));
        }


        $query->select('course_canceleds.*');


        return Datatables::of($query)
            ->addIndexColumn()
            ->addColumn('user_name', function ($query) {
                return $query->user->name;

            })
            ->addColumn('confirm_user', function ($query) {
                return $query->confirmUser->name;

            })
            ->addColumn('user_email', function ($query) {
                return $query->user->email;

            })
            ->addColumn('course', function ($query) {
                return $query->course->title;

            })
            ->editColumn('purchase_price', function ($query) {
                return getPriceFormat(@$query->purchase_price);

            })
            ->editColumn('created_at', function ($query) {
                return showDate(@$query->created_at);

            })
            ->editColumn('approved_date', function ($query) {
                if ($query->approved_date && $query->status == 1) {
                    return showDate(@$query->approved_date);
                }
                return '';

            })
            ->editColumn('refund', function ($query) {
                return $query->refund == 1 ? 'Refund' : 'Cancel';
            })
            ->addColumn('total_complete', function ($query) {

                return $query->course->userCourseCompletePercentage($query->user_id) . "%";
            })
            ->editColumn('status', function ($query) {

                if ($query->status == 1) {
                    $status = 'Approved';
                } elseif ($query->status == 0) {
                    $status = 'Pending';
                } else {
                    $status = 'Reject';
                }
                return $status;
            })
            ->addColumn('action', function ($query) {
                return view('backend.student._td_cancel_error_log', compact('query'));
            })
            ->rawColumns(['action'])
            ->make(true);
    }


    public function getPayoutData(Request $request)
    {
        try {
            $query = Withdraw::latest()->with('user');
            if (!empty($request->month)) {
                $query->whereMonth('created_at', '=', $request->month);
            }
            if (!empty($request->year)) {
                $query->whereYear('created_at', '=', $request->year);
            }
            if (!empty($request->instructor)) {
                $query->where('instructor_id', '=', $request->instructor);
            }
            if (Auth::user()->role_id != 1) {
                $query->where('instructor_id', '=', Auth::user()->id);
            }

            return Datatables::of($query)
                ->addIndexColumn()
                ->addColumn('user.name', function ($query) {
                    return $query->user->name;
                })
                ->editColumn('amount', function ($query) {
                    return getPriceFormat($query->amount,false);
                })
                ->addColumn('requested_date', function ($query) {
                    return showDate(@$query->created_at);
                })
                ->editColumn('method', function ($query) {
                    $withdraw = $query;
                    return view('backend.partials._withdrawMethod', compact('withdraw'));
                })
                ->addColumn('status', function ($query) {
                    if ($query->status == 1) {
                        $status = trans('common.Paid');
                    } else {
                        $status = trans('common.Unpaid');
                    }
                    return $status;
                })
                ->addColumn('action', function ($query) {
                    return view('backend.instructor._td_payout_action', compact('query'));
                })
                ->rawColumns(['method', 'user.image', 'action'])
                ->make(true);

        } catch (\Exception $e) {

        }
    }


    public function getUserDate($id)
    {
        $user = User::with('image_media')->find($id);
        $user->dob = getJsDateFormat($user->dob);
        return $user;
    }

    public function removeImageByAjax(Request $request)
    {
        $table = $request->get('table');
        $name = $request->get('name');
        $id = $request->get('id');

        if ($table && $name && $id) {
            DB::table($table)->where('id', $id)->update([
                $name => ''
            ]);
        }
        return true;
    }


    public function generateCertificate(Request $request)
    {
        $enroll = CourseEnrolled::with('course', 'user')->findOrFail($request->id);
        $course = $enroll->course;

        try {
            $certificate = null;
            if (!empty($course->certificate_id)) {
                $certificate = Certificate::find($course->certificate_id);
            }
            if (!$certificate) {
                if ($course->type == 1) {
                    $certificate = Certificate::where('for_course', 1)->first();
                } elseif ($course->type == 2) {
                    $certificate = Certificate::where('for_quiz', 1)->first();
                } elseif ($course->type == 3) {
                    $certificate = Certificate::where('for_class', 1)->first();
                } else {
                    $certificate = null;
                }
            }
            if ($certificate) {
                $websiteController = new WebsiteController();
                $certificate_record = CertificateRecord::where('student_id', $enroll->user_id)->where('course_id', $enroll->course_id)->first();
                if (!$certificate_record) {
                    $certificate_record = new CertificateRecord();
                    $certificate_record->certificate_id = $websiteController->generateUniqueCode();
                    $certificate_record->student_id = $enroll->user_id;
                    $certificate_record->course_id = $enroll->course_id;
                    $certificate_record->created_by = Auth::id();
                    $certificate_record->save();
                }

                request()->certificate_id = $certificate_record->certificate_id;
                request()->course = $course;
                request()->user = $enroll->user;
                $downloadFile = new CertificateController();
                $certificate = $downloadFile->makeCertificate($certificate->id, request())['image'] ?? '';

                $certificate->encode('jpg');

                $certificate->save('public/certificate/' . $certificate_record->id . '.jpg');
            } else {
                Toastr::error(trans('certificate.Certificate Not Found!'), trans('common.Failed'));
                return redirect()->back();
            }
        } catch (\Exception $e) {
            GettingError($e->getMessage(), url()->current(), request()->ip(), request()->userAgent());
        }

        Toastr::success(trans('common.Operation successful'), trans('common.Success'));
        return redirect()->back();
    }

    public function removeCertificate(Request $request)
    {
        $enroll = CourseEnrolled::with('course', 'user')->findOrFail($request->id);
        CertificateRecord::where('student_id', $enroll->user_id)->where('course_id', $enroll->course_id)->delete();
        Toastr::success(trans('common.Operation successful'), trans('common.Success'));
        return redirect()->back();
    }

}
