<?php

    namespace App\Http\Controllers\Admin;

    use App\Http\Requests\Subscription\StoreSubscription;
    use App\Library\Tool;
    use App\Models\Plan;
    use App\Models\Subscription;
    use App\Models\User;
    use App\Repositories\Contracts\SubscriptionRepository;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Auth\Access\AuthorizationException;
    use Illuminate\Contracts\Foundation\Application;
    use Illuminate\Contracts\View\Factory;
    use Illuminate\Http\JsonResponse;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\View\View;
    use JetBrains\PhpStorm\NoReturn;

    class SubscriptionController extends AdminBaseController
    {
        protected SubscriptionRepository $subscriptions;

        /**
         * SubscriptionController constructor.
         *
         * @param SubscriptionRepository $subscriptions
         */
        public function __construct(SubscriptionRepository $subscriptions)
        {
            $this->subscriptions = $subscriptions;
        }


        /**
         * @return Application|Factory|View
         * @throws AuthorizationException
         */

        public function index(): Factory|View|Application
        {

            $this->authorize('view subscription');

            $breadcrumbs = [
                ['link' => url(config('app.admin_path') . "/dashboard"), 'name' => __('locale.menu.Dashboard')],
                ['link' => url(config('app.admin_path') . "/dashboard"), 'name' => __('locale.menu.Customer')],
                ['name' => __('locale.menu.Subscriptions')],
            ];

            $subscriptions_stats = $this->subscriptions->getSubscriptionStats();

            return view('admin.subscriptions.index', compact('breadcrumbs', 'subscriptions_stats'));
        }


        /**
         * @param Request $request
         *
         * @return void
         * @throws AuthorizationException
         */
        #[NoReturn] public function search(Request $request): void
        {

            $this->authorize('view subscription');

            $columns = [
                0 => 'responsive_id',
                1 => 'uid',
                2 => 'uid',
                3 => 'name',
                4 => 'subscribed_by',
                5 => 'start_at',
                6 => 'end_at',
                7 => 'status',
                8 => 'action',
            ];

            $totalData = Subscription::count();

            $totalFiltered = $totalData;

            $limit = $request->input('length');
            $start = $request->input('start');
            $order = $columns[$request->input('order.0.column')];
            $dir   = $request->input('order.0.dir');

            if (empty($request->input('search.value'))) {
                $subscriptions = Subscription::offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();
            } else {
                $search = $request->input('search.value');

                $subscriptions = Subscription::whereLike(['uid', 'user.first_name', 'user.last_name', 'plan.name'], $search)
                    ->offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();

                $totalFiltered = Subscription::whereLike(['uid', 'user.first_name', 'user.last_name', 'plan.name'], $search)->count();
            }

            $data = [];
            if ( ! empty($subscriptions)) {
                foreach ($subscriptions as $subscription) {

                    if ($subscription->status == 'active') {
                        $color        = 'success';
                        $status_label = __('locale.labels.active');
                    } else if ($subscription->status == 'new') {
                        $color        = 'primary';
                        $status_label = __('locale.labels.pending');
                    } else {
                        $color        = 'danger';
                        $status_label = __('locale.labels.' . $subscription->status);
                    }

                    if ($subscription->status == 'pending') {
                        $color = 'warning';
                    }

                    if ($subscription->status == 'renew') {
                        $color = 'primary';
                    }

                    $customer_name    = $subscription->user->displayName();
                    $customer_profile = route('admin.customers.show', $subscription->user->uid);

                    if ($subscription->start_at) {
                        $subscribed_on = Tool::formatDateTime($subscription->start_at);
                    } else {
                        $subscribed_on = Tool::formatDateTime($subscription->created_at);
                    }

                    if ($subscription->isEnded()) {
                        $end_at = Tool::dateTime($subscription->end_at)->diffForHumans();
                    } else if ($subscription->cancelled()) {
                        if ($subscription->current_period_ends_at) {
                            $end_at = Tool::dateTime($subscription->current_period_ends_at)->diffForHumans();
                        } else {
                            $end_at = '--';
                        }
                    } else if ($subscription->isRecurring()) {
                        if ($subscription->current_period_ends_at) {
                            $end_at = Tool::dateTime($subscription->current_period_ends_at)->diffForHumans();
                        } else {
                            $end_at = '--';
                        }
                    } else {
                        $end_at = Tool::dateTime($subscription->end_at)->diffForHumans();
                    }


                    $is_active = false;
                    $is_ended  = false;
                    $is_new    = false;

                    if ($subscription->isActive()) {
                        $is_active = true;
                    }

                    if ($subscription->isNew()) {
                        $is_new = true;
                    }

                    if ($subscription->isEnded()) {
                        $is_ended = true;
                    }

                    $nestedData['responsive_id'] = '';
                    $nestedData['avatar']        = route('admin.customers.avatar', $subscription->user->uid);
                    $nestedData['email']         = $subscription->user->email;
                    $nestedData['uid']           = $subscription->uid;
                    $nestedData['name']          = $subscription->plan->name;
                    $nestedData['subscribed_by'] = "<a href='$customer_profile' class='text-primary mr-1'>$customer_name</a>";
                    $nestedData['start_at']      = $subscribed_on;
                    $nestedData['end_at']        = $end_at;
                    $nestedData['logs']          = route('admin.subscriptions.logs', $subscription->uid);
                    $nestedData['logs_label']    = __('locale.subscription.logs');
                    $nestedData['is_active']     = $is_active;
                    $nestedData['is_ended']      = $is_ended;
                    $nestedData['is_new']        = $is_new;
                    $nestedData['approve_label'] = __('locale.labels.approve');
                    $nestedData['cancel_label']  = __('locale.buttons.cancel');
                    $nestedData['delete_label']  = __('locale.buttons.delete');

                    $nestedData['status'] = "<span class='badge bg-$color'>$status_label</span>";
                    $data[]               = $nestedData;

                }
            }

            $json_data = [
                "draw"            => intval($request->input('draw')),
                "recordsTotal"    => $totalData,
                "recordsFiltered" => $totalFiltered,
                "data"            => $data,
            ];

            echo json_encode($json_data);
            exit();

        }


        /**
         * @return Application|Factory|View
         * @throws AuthorizationException
         */

        public function create(): Factory|View|Application
        {
            $this->authorize('new subscription');

            $breadcrumbs = [
                ['link' => url(config('app.admin_path') . "/dashboard"), 'name' => __('locale.menu.Dashboard')],
                ['link' => url(config('app.admin_path') . "/subscriptions"), 'name' => __('locale.menu.Subscriptions')],
                ['name' => __('locale.buttons.new_subscription')],
            ];

            $customers = User::where('status', true)->where('is_customer', true)->cursor();
            $plans     = Plan::where('status', true)->orderBy('price')->cursor();

            return view('admin.subscriptions.create', compact('breadcrumbs', 'customers', 'plans'));
        }


        /**
         * assign new subscription to customer
         *
         * @param StoreSubscription $request
         *
         * @return RedirectResponse
         */
        public function store(StoreSubscription $request): RedirectResponse
        {
            if (config('app.stage') == 'demo') {
                return redirect()->route('admin.subscriptions.index')->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $response = $this->subscriptions->store($request->input());


            if (isset($response->getData()->status) && $response->getData()->status == 'error') {
                return redirect()->route('admin.subscriptions.create')->with([
                    'status'  => 'error',
                    'message' => $response->getData()->message,
                ]);
            }

            return redirect()->route('admin.subscriptions.index')->with([
                'status'  => 'success',
                'message' => __('locale.subscription.subscription_successfully_added'),
            ]);

        }

        /**
         * view specific subscription logs
         *
         * @param Subscription $subscription
         *
         * @return Application|Factory|\Illuminate\Contracts\View\View
         * @throws AuthorizationException
         */
        public function logs(Subscription $subscription): \Illuminate\Contracts\View\View|Factory|Application
        {

            $this->authorize('manage subscription');

            $breadcrumbs = [
                ['link' => url(config('app.admin_path') . "/dashboard"), 'name' => __('locale.menu.Dashboard')],
                ['link' => url(config('app.admin_path') . "/subscriptions"), 'name' => __('locale.menu.Subscriptions')],
                ['name' => __('locale.subscription.logs')],
            ];

            return view('admin.subscriptions.logs', compact('breadcrumbs', 'subscription'));
        }

        /**
         * approve pending subscription
         *
         * @param Subscription $subscription
         *
         * @return JsonResponse
         * @throws AuthorizationException
         */
        public function approvePending(Subscription $subscription): JsonResponse
        {
            if (config('app.stage') == 'demo') {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $this->authorize('manage subscription');

            $this->subscriptions->approvePending($subscription);

            return response()->json([
                'status'  => 'success',
                'message' => __('locale.subscription.subscription_successfully_active'),
            ]);
        }

        /**
         * reject pending subscription
         *
         * @param Subscription $subscription
         *
         * @param Request      $request
         *
         * @return JsonResponse
         * @throws AuthorizationException
         */
        public function rejectPending(Subscription $subscription, Request $request): JsonResponse
        {

            if (config('app.stage') == 'demo') {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $this->authorize('manage subscription');

            if ( ! $request->input('reason')) {
                return response()->json([
                    'status'  => 'error',
                    'message' => __('locale.subscription.reject_reason_required'),
                ]);
            }

            $this->subscriptions->rejectPending($subscription, $request->only('reason'));

            return response()->json([
                'status'  => 'success',
                'message' => __('locale.subscription.subscription_successfully_active'),
            ]);
        }


        /**
         * cancel subscription
         *
         * @param Subscription $subscription
         *
         * @return JsonResponse
         * @throws AuthorizationException
         */
        public function cancel(Subscription $subscription): JsonResponse
        {

            if (config('app.stage') == 'demo') {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $this->authorize('manage subscription');

            $subscription->setEnded(Auth::user()->id);

            return response()->json([
                'status'  => 'success',
                'message' => __('locale.subscription.subscription_successfully_cancelled'),
            ]);
        }


        /**
         * @param Subscription $subscription
         *
         * @return JsonResponse
         *
         * @throws AuthorizationException
         */
        public function destroy(Subscription $subscription): JsonResponse
        {

            if (config('app.stage') == 'demo') {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $this->authorize('delete subscription');

            $this->subscriptions->destroy($subscription);

            return response()->json([
                'status'  => 'success',
                'message' => __('locale.subscription.subscription_successfully_deleted'),
            ]);

        }

        /**
         * Bulk Action with Enable, Disable and Delete
         *
         * @param Request $request
         *
         * @return JsonResponse
         * @throws AuthorizationException
         */

        public function batchAction(Request $request): JsonResponse
        {

            if (config('app.stage') == 'demo') {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            $action = $request->get('action');
            $ids    = $request->get('ids');


            switch ($action) {
                case 'cancel':
                    $this->authorize('manage subscription');

                    $this->subscriptions->batchCancel($ids);

                    return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.subscription.subscriptions_cancelled'),
                    ]);

                case 'delete':
                    $this->authorize('delete subscription');

                    $this->subscriptions->batchDelete($ids);

                    return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.subscription.subscriptions_deleted'),
                    ]);

            }

            return response()->json([
                'status'  => 'error',
                'message' => __('locale.exceptions.invalid_action'),
            ]);

        }

    }
