<?php

namespace App\Http\Controllers\Web;

use App\Country;
use App\Helpers\ImageHelper;
use App\Http\Requests\RegisterRequest;
use App\Http\Requests\UserUpdateProfileRequest;
use App\Jobs\VerifyEmail;
use App\Order;
use App\ProductOrder;
use App\State;
use App\User;
use App\UsersNotification;
use App\Verification;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
use PHPUnit\Framework\Constraint\Count;

class UserController extends Controller
{

    protected $view = 'web.users.';

    /**
     * User profile
     * @return Factory|View
     * @throws \Exception
     */
    public function index()
    {
        $user = Auth::user();
        $country = Country::withDescription($user->country_id);
        $state = State::withDescription(null, $user->state_id);
        $countries = Country::withDescription();
        $states = State::withDescription($user->country_id);

        if (!in_array($user->role, ['user'])){
            return redirect()->route('home');
        }
        $notifications = UsersNotification::orderBy('id', 'DESC')
            ->where('user_id', $user->id)
            ->orWhere('user_id', null)
            ->cursor();

        $notificationsCount = [];

        $allNotifications = $notifications->pluck('is_read')->toArray();

        foreach ($allNotifications as $allNotification) {
            if (is_array($allNotification) && !in_array($user->id, $allNotification)){
                $notificationsCount[] = true;
            }
            if (!is_array($allNotification)){
                $notificationsCount[] = true;
            }

        }

        $notificationsCount = count($notificationsCount);

        $carts = Order::getUserOrder($user->id)->groupBy('status')->toArray();

        return view($this->view.'profile', compact(
            'user',
            'notifications',
            'notificationsCount',
            'countries',
            'country',
            'state',
            'states',
            'carts'
        ));
    }

    public function productRequests()
    {
        $user = Auth::user();

        $orders = Order::where('orders.user_id', '=', $user->id)
//            ->join('product_orders', 'product_orders.order_id','orders.id')
//            ->orderBy('product_orders.id', 'desc')
//            ->join('products', 'products.id', 'product_orders.product_id')
//            ->join('product_descriptions as pd', 'products.id', 'pd.product_id')
//            ->where('pd.language_id', currentLanguage()->id)
            ->select([
                'orders.id',
                'orders.pay_way',
//                'orders.created_at',
                'orders.status',
//                'products.price',
//                'products.discount',
//                'product_orders.amount',
//                'products.image',
//                'pd.name',
            ])->cursor()->groupBy('status')->toArray();

//        dd($orders);

        $addedValue = array_key_exists('added_value', settings()) ? settings('added_value') : 15;

        return view($this->view.'product_requests', compact('orders', 'addedValue'));
    }

    public function requestDetails(Order $order)
    {
        $user = Auth::user();
        $ordersIds = $user->orders()->pluck('id')->toArray();

        if (!in_array($order->id, $ordersIds)){
            return redirect()->route('home');
        }

        $orders = Order::where('orders.id', $order->id)
            ->where('orders.user_id', '=', $user->id)
//            ->join('coupons', 'orders.coupon_id', 'coupons.id')
            ->join('product_orders', 'product_orders.order_id','orders.id')
            ->orderBy('product_orders.id', 'desc')
            ->join('products', 'products.id', 'product_orders.product_id')
            ->join('product_descriptions as pd', 'products.id', 'pd.product_id')
            ->where('pd.language_id', currentLanguage()->id)
            ->select([
                'orders.id',
                'products.file',
                'orders.pay_way',
                'orders.created_at',
                'orders.status',
//                'coupons.code',
                'products.id as product_id',
                'products.price',
                'products.discount',
                'products.image',
                'pd.name',
                'product_orders.amount',
            ])
            ->selectSub("SELECT code FROM coupons WHERE coupons.id = orders.coupon_id", 'code')
            ->selectSub("SELECT discount FROM coupons WHERE coupons.id = orders.coupon_id", 'coupon_discount')
            ->selectSub("SELECT product_id FROM coupons WHERE coupons.id = orders.coupon_id", 'product_with_coupon')
            ->cursor();

        $price = $orders->pluck('price')->toArray();
//        $total = array_sum($price);
        $addedValue = array_key_exists('added_value', settings()) ? settings('added_value') : 15;
//        $totalAddedValue = ($total*$addedValue)/100;
//        $totalWithAddedValue = $total+$totalAddedValue;
        $taxNumber =array_key_exists('tax_number', settings()) ? settings('tax_number') : 0;
        $orderBill = CoursesBill::where('order_id', $order->id)->first();

        $siteAddress = array_key_exists('site_address', settings()) ? settings('site_address') : null;
        $phone = array_key_exists('site_phone', settings()) ? settings('site_phone') : null;
        $phone_2 = array_key_exists('site_phone_2', settings()) ? settings('site_phone_2') : null;
        $siteEmail = array_key_exists('site_email', settings()) ? settings('site_email') : null;

        return view($this->view.'request_details', compact(
            'orders',
            'addedValue',
            'user',
            'orderBill',
            'siteAddress',
            'phone',
            'phone_2',
            'siteEmail',
            'taxNumber'
        ));
    }

    public function refreshNotification(Request $request)
    {
        if ($request->ajax()){
            $user = Auth::user();
            $courses = $user->courses()->pluck('course_id')->toArray();
            $notifications = UsersNotification::orderBy('id', 'DESC')
                    ->orWhere('user_id', $user->id)
                    ->orWhereIn('send_to', ['all_users'])
                    ->orWhereIn('course_id', $courses)
                    ->cursor() ?? [];
            $notificationsCount = $notifications->count();
            return view($this->view.'refresh_notification', compact('notifications', 'notificationsCount', 'user'));
        }
    }

    public function markAsRead()
    {
        $user = Auth::user();
        $notifications = UsersNotification::orderBy('id', 'DESC')
            ->where('user_id', $user->id)
            ->orWhere('user_id', null)
            ->cursor();

        foreach ($notifications as $notification) {
            $isRead = $notification->is_read;
            if (is_array($isRead)){
                if (!in_array($user->id, $isRead)){
                    array_push($isRead, $user->id);
                }
            } else {
                $isRead = [$user->id];
            }
            $notification->update(['is_read' => $isRead]);
        }

        return response()->json(['success' => true]);
    }

    public function updateProfile(UserUpdateProfileRequest $request, User $user)
    {
        $data = $request->all();
        $data['password'] = $request->password ? bcrypt($request->password) : $user->password;
        if ($request->has('photo')){
            if (file_exists(public_path().'/'.$user->photo)){
                File::delete(public_path().'/'.$user->photo);
            }
            $data['photo'] = ImageHelper::upload($request->photo, 'users/profile');
        }

        $data['phone'] = '00966'.$request->phone;
        $user->update($data);

        return response()->json(['message' => __('members.save_successfully')]);
    }



    /**
     * Show login form for all users type
     * @return Factory|RedirectResponse|View
     */
    public function login()
    {
        if (Auth::check() && in_array(Auth::user()->role, ['user'])){
//            return redirect()->route('home');
        } else {
            Auth::logout();
        }
        $title = __('main.login');
        return view($this->view.'login', compact('title'));
    }

    /**
     * Do login for all users
     * @param LoginRequest $loginRequest
     * @return RedirectResponse|Redirector
     */
    public function doLogin(LoginRequest $loginRequest)
    {
        $user = User::whereIn('role', ['user'])
            ->where('email', $loginRequest->email)->first();

        if ($user && !$user->status){
            return response()->json(['errors' => __('members.account_disabled_by_admin')]);
        }
        if ($user && Hash::check($loginRequest->password, $user->password)) {
            Auth::login($user);
            $hasGuestCart = Session::get('cart_mode');
            if ($hasGuestCart){
                $isCreateGuestOrder = $this->createGuestOrder($hasGuestCart);
                if ($isCreateGuestOrder){
                    Session::forget(['cart_mode']);
                    return response()->json(['url' => route('product.cart')]);
                }
            }

            return response()->json(['url' => route('user.profile')]);
        } else {
            return response()->json(['errors' => __('auth.failed')]);
        }
    }

    private function createGuestOrder($guestCart)
    {
//        $user = \App\User::find(4);
//        Auth::login($user);
        $user = Auth::user();
        $addedValue = array_key_exists('added_value', settings()) ? settings('added_Value') : 15;
        $shippingValue = array_key_exists('shipping_value', settings()) ? settings('shipping_value') : 15; // shipping value by SAR no percentage
        $net_total = [];
        $order_total = [];

        $oldCart = Order::where('orders.user_id', $user->id)
            ->where('orders.status', 'cart_mode')
            ->first();

        if ($oldCart){
            foreach ($guestCart['products'] as $productId => $product) {
                $data = [
                    'order_id' => $oldCart->id,
                    'product_id' => $product['product_id'],
                    'color' => $product['color'],
                    'amount' => $product['amount'],
                    'price' => $product['price'],
                ];

                $productOrders = ProductOrder::where('order_id', $oldCart->id)
                    ->where('color', $product['color'])
                    ->where('product_id', $product['product_id'])->first();

                if ($productOrders){
                    $productOrders->update($data);
                } else {
                    ProductOrder::create($data);
                }


            }

            foreach ($oldCart->productOrder as $product) { // push new orders price to calc order total and net total

                $netTotal = $product->amount*$product->price;
                $net_total[] = $netTotal;
                $order_total[] = $netTotal+(($netTotal*$addedValue)/100);
            }

            // update order with new total
            $net_total = array_sum($net_total);
            $order_total = array_sum($order_total)+$shippingValue;

            $oldCart->update([
                'net_total' => $net_total,
                'order_total' => $order_total,
            ]);


        } else { // if user have not old card
            $order = Order::create([
                'user_id' => $user->id,
                'order_total' => $guestCart['order_total']+$shippingValue,
                'net_total' => $guestCart['net_total'],
                'status' => 'cart_mode',
            ]);

            foreach ($guestCart['products'] as $productId => $product) {
                ProductOrder::create([
                    'order_id' => $order->id,
                    'product_id' => $product['product_id'],
                    'color' => $product['color'],
                    'amount' => $product['amount'],
                    'price' => $product['price'],
                ]);
            }
        }
        return true;
    }


    /**
     * Show register form for user
     * @return Factory|RedirectResponse|View
     */
    public function register()
    {
        $countries = Country::withDescription();
        return view($this->view.'register', compact('countries'));
    }

    public function getState(Request $request)
    {
        if ($request->ajax()){
            $states = State::withDescription($request->country_id);
            if (count($states)){
                return response()->json(['states' => $states]);
            } else {
                return response()->json(['states' => false]);
            }
        }
    }

    /**
     * Register new user
     * @param RegisterRequest $registerRequest
     * @return JsonResponse
     */
    public function doRegister(RegisterRequest $registerRequest)
    {
        $data = $registerRequest->all();
        $data['password'] = bcrypt($registerRequest->password);
        $data['role'] = 'user';
        $data['phone'] = '00966'.$registerRequest->phone;

        $phone = User::where('phone',  $data['phone'])->first();

        if ($phone){
            return  response()->json(['errors' => __('members.phone_already_exists')]);
        }

        $data['status'] = 1;
        $user = User::create($data);
        Auth::login($user);
        return response()->json(['url' =>route('home')]);
    }



    /**
     * Show forget password form way
     * @return Factory|View
     */
    public function forgetPasswordForm()
    {
        $title = strip_tags(__('users.forget_password'));
        return view($this->view.'password.forget_password_form', compact('title'));
    }

    /**
     * Check forget password way whether by phone or email
     * @param Request $request
     * @return array|bool|JsonResponse
     */
    public function sendForgetPasswordCode(Request $request)
    {
        $validation = Validator::make($request->all(), [
            'email' => 'required|email|exists:users,email'
        ], [
            'email.exists' => __('auth.failed')
        ], [
            'email' => __('users.email')
        ]);
        if ($validation->fails()){
            return response()->json(['errors' => $validation->errors()->first()]);
        }

        $generateCode = $this->generateCode($request->email);

        if ($generateCode['errors']){
            return $generateCode;
        }

        session(['forgetPasswordEmail' => $request->email]);
        return response()->json(['url' => route('user.typeForgetPasswordCode')]);
    }

    public function typeForgetPasswordCode()
    {
        if (!session('forgetPasswordEmail')){
            return redirect()->route('home');
        }

        return view($this->view.'password.type_forget_password_code_form');
    }

    /**
     * Check code verification for new register or reset password
     * @param Request $request
     * @return JsonResponse
     */
    public function codeVerification(Request $request)
    {
        if (getCurrentLocale() == 'ar'){
            $code = array_reverse($request->code);
        } else {
            $code = $request->code;
        }
        $code = implode('',  $code);
        if (mb_strlen($code) < 4){
            return response()->json(['errors' => __('members.enter_full_code')]);
        }

        $verification = Verification::where('code', $code)->where('email', session('forgetPasswordEmail'))->first();
        if ($verification){
            session()->put(['code' => $code]);
            return response()->json(['url' => route('user.newPasswordForm')]);
        }
        return response()->json(['errors' => __('members.invalid_code')]);
    }

    /**
     * Show type new password form
     * @return Factory|View
     */
    public function newPasswordForm()
    {
        if (!session('forgetPasswordEmail')){
            return redirect()->route('home');
        }
        return view($this->view.'password.new_password_form');
    }

    /**
     * Reset password
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function resetPassword(Request $request)
    {
        $validation = Validator::make($request->all(),
            ['password' => 'required|confirmed',], //regex:/^(?=.*[a-zA-Z0-9])[a-zA-Z\d]{6,}$/
            ['password.regex' => __('users.password_regex')],
            ['password' => __('users.password')]);

        if ($validation->fails()){
            return response()->json(['errors' => $validation->errors()->first()]);
        }

        $code = session('code');
        $code = Verification::where('code', $code)->where('email', session('forgetPasswordEmail'))->first();

        if (!$code){
            return response()->json(['errors' => __('members.not_allowed_to_change_password')]);
        }


//        $user = $code->user()->withTrashed()->first();
        $user = $code->user()->where('status', 1)->first();
        if($user){
            $password = bcrypt($request->password);
            $user->update(['password' => $password]);
            $code->delete();
            Auth::login($user);
            session()->forget(['code', 'forgetPasswordEmail']);
            return response()->json(['url' => route('home')]);
        } else {
            session()->forget(['code', 'forgetPasswordEmail']);
            return response()->json(['errors' => __('members.account_disabled_by_admin')]);
        }
    }

    /**
     * Generate code
     * @param $email
     * @return array|bool
     */
    protected function generateCode($email)
    {
        $registerRoute = preg_match('/register/', Route::getCurrentRoute()->uri);

        if ($registerRoute){
            $type = 'register';
        } else {
            $type = 'password';
        }

        $user = User::where('status', 1)->where('email', $email)->first();

        if (!$user){
            return ['errors' => __('members.account_disabled_by_admin')];
        }

        $code = rand(1111,9999);
        if (count($user->verifications) > 0){
            $user->verifications->first()->delete();
        }

        Verification::create([
            'user_id' => $user->id,
            'email' => $email,
            'type' => $type,
            'code' => $code
        ]);

        $data = [
            'user' => $user->name,
            'email' => $user->email,
            'code' => $code,
        ];

        if ($type == 'register'){
            $data['title'] = 'Account Verification';
            $data['details'] = 'Verify Email';

        } else {
            $data['title'] = 'Forget password';
            $data['details'] = 'Reset password';
        }

        VerifyEmail::dispatch($data, 'web.users.emails.verification_email');

//        if ($request['active_way'] == 'phone'){
//            $message = 'عزيز العميل مرحبا بك في منصة عين المبدع، كود التفعيل الخاص بك هو ';
//            $message .= $code;
//            $phone = ltrim($user->phone, 0);
//            $sms = Sms::send($phone, $message);
//            if ($sms){
//                return true;
//            } else {
//                return  false;
//            }
//        }

        return ['errors' => false];
    }



    /**
     * Logout for all users
     * @return RedirectResponse
     */
    public function logout()
    {
        Auth::logout();
        session()->forget('http_referer');
        return redirect()->route('home');
    }


    //    public function downloadFile(PaperApplication $file)
//    {
//        if (request()->ajax()){
//            $fileName = $file::withDescription()->first();
//            if($file->file != null && strpos($file->file, '.pdf')){
//                $headers = ['Content-Type:application/pdf'];
//                return response()->download(public_path().$file->file, $fileName->name, $headers);
//            }
//
//            if ($file->file != null){
//                $headers = ['Content-Type: image/jpeg'];
//                return response()->make($file->file, 200)->withHeaders($headers);
//            }
//        }
//    }

}
