<?php

namespace App\Http\Controllers\Web;

use App\Bank;
use App\Category;
use App\Coupon;
use App\Evaluate;
use App\CoursesBill;
use App\Favorite;
use App\Helpers\ImageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\EvaluateRequest;
use App\Jobs\BillJob;
use App\Order;
use App\Product;
use App\ProductOrder;
use App\UserCourse;
use App\UsersNotification;
use http\Env\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class EyeStoreController extends Controller
{
    private $viewDirectory = 'web.eye_stores.';

    public function index()
    {
        $title = __('products.eye_store');
        $categories = Category::withDescription('products');
        $products = Product::withDescription();

        return view($this->viewDirectory.'index', compact( 'title', 'categories', 'products'));
    }

    public function show(Product $product)
    {

        if ($product->status == 'non_active'){
            return redirect()->route('eyeStore.index')->with('alert_pop_up', __('products.product_not_available_now'));
        }

        $title = __('products.product_details');
        $product = $product::withDescription(null, null, [$product->id])->first();
        $comments = Evaluate::withoutTrashed()
                ->where('evaluates.status', 1)->where('product_id', $product->id)
                ->join('users', 'users.id', 'evaluates.user_id')
                ->select(['evaluates.*', 'users.photo as user_photo'])
                ->cursor() ?? [];

        return view($this->viewDirectory.'show', compact('product', 'comments', 'title'));
    }

    public function productSearch(Request $request)
    {
        if ($request->ajax()){
            $products = Product::withDescription(
                $request->category_id ? [$request->category_id] : [],
                $request->name ?? null
            );
            return view($this->viewDirectory.'product_search', compact('products'));
        }
    }

    public function addToFavorite(Product $product)
    {
        if (!Auth::check()){
            return response()->json(['errors' => __('products.pleas_login_to_add_favorite')]);
        }

        $user = Auth::user();

        if ($user->role != 'user'){
            return response()->json(['errors' => __('products.member_not_allowed_favorite')]);
        }

        $hasFavorite = Favorite::where('user_id', $user->id)->where('product_id', $product->id)->first();

        if ($hasFavorite){
            $hasFavorite->delete();
            return response()->json(['errors' => __('products.deleted_from_favorite')]);
        }

        Favorite::create([
            'user_id' => $user->id,
            'product_id' => $product->id,
        ]);

        return response()->json(['message' => __('products.add_favorite_successfully')]);

    }

    public function addToCart(Product $product)
    {
        if (!Auth::check()){
            return response()->json(['errors' => __('products.pleas_login_to_add_cart')]);
        }

        $user = Auth::user();

        if ($user->role != 'user'){
            return response()->json(['errors' => __('products.member_not_allowed_cart')]);
        }

        if ($product->status == 'non_active'){
            return response()->json(['errors' => __('products.product_not_available_now')]);
        }

        $hasCart = Order::with('productOrder')
            ->where('orders.user_id', '=', $user->id)
            ->where('orders.status', '=', 'charge')
            ->first();

        if ($hasCart){
            // check if product in product list or not
            $productOrders = $hasCart->productOrder->pluck('product_id')->toArray();
            if (in_array($product->id, $productOrders)){
                return response()->json(['errors' => __('products.added_to_cart_before')]);
            }
            $productOrder = ProductOrder::create([
                'order_id' => $hasCart->id,
                'product_id' => $product->id,
            ]);

//            $product = $productOrder->product;
//            $product->update(['amount' => $product->amount-1]);

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

        $order = Order::create([
            'user_id' => $user->id,
            'status' => 'charge',
        ]);

        $productOrder = ProductOrder::create([
            'order_id' => $order->id,
            'product_id' => $product->id,
        ]);

//        $product = $productOrder->product;
//        $product->update(['amount' => $product->amount-1]);

        return response()->json(['message' => __('products.add_cart_successfully')]);

    }

    public function favorites()
    {
        $user = Auth::user();
        if ($user->role != 'user'){
            return redirect()->route('home');
        }
        $favoritesIds = $user->favorites()->pluck('product_id')->toArray();
        $favorites = [];
        if (count($favoritesIds)){
            $favorites = Product::withDescription(null, null, $favoritesIds);
        }
        return view($this->viewDirectory.'favorites', compact('favorites'));
    }

    public function carts()
    {
        $user = Auth::user();
        $orders = Order::where('orders.user_id', '=', $user->id)
            ->where('orders.status', '=', 'charge')
            ->join('product_orders', 'product_orders.order_id','orders.id')
            ->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([
                'products.image',
                'products.price',
                'products.discount',
                'pd.name',
                'product_orders.id',
                'product_orders.amount',
            ])->cursor();

//        dd($orders->pluck('discount')->toArray());

        $bankAccounts = Bank::withDescription();

        $points = $user->points/25;


        return view($this->viewDirectory.'carts', compact('orders', 'points', 'bankAccounts'));
    }

    public function deleteProductFromCart(Request $request, ProductOrder $productOrder)
    {
        if (request()->ajax()){
            $product = $productOrder->product;
            $user = Auth::user();
            $price = [];
            $discount = null;
            $lastTotal = null;

            $orders = Order::getUserOrder($user->id);

            foreach ($orders as $order) {
                if ($productOrder->id == $order->id){
                    continue;
                }
                $price[] = $order->price*$order->product_order_amount;
            }

            $price = array_sum($price);
            $addedValue = ($price*settings('added_Value'))/100;
            $total = $price+$addedValue;

            if ($request->coupon){
                $check = $this->checkCoupon($request);
                if ($check['errors']){
                    return response()->json($check);
                }

                $productHaveCoupon = $check['product'];
                $coupon = $check['coupon'];
                $discount = (($productHaveCoupon->price*$productHaveCoupon->product_order_amount)*($coupon->discount))/100;
                $lastTotal = $total-$discount;

                if (!count($orders)){
                    $discount = null;
                    $lastTotal = null;
                }

                if ($productOrder->id == $productHaveCoupon->id){
                    $productOrder->delete();
                    $discount = null;
                    $lastTotal = null;
                }

            }

            $productOrder->delete();

            session()->put(['price' => $lastTotal ?? $price]);
            return response()->json([
                'success' => true,
                'errors' => __('products.deleted_from_cart'),
                'price' => $price,
                'added_value' => $addedValue,
                'discount' => $discount,
                'total' => $total,
                'last_total' => $lastTotal,
                'item_quantity' => $productOrder->amount ?? null,
                'item_price' => ($product->price*$productOrder->amount) ?? null,
            ]);
        }
    }

    public function editAmount(Request $request)
    {
        if ($request->ajax()){
            $productOrder = ProductOrder::find($request->order_id);
            if (!$productOrder){
                return response()->json(['errors' => __('products.not_found')]);
            }
            $product = $productOrder->product;
            if ($product && $request->amount > $product->amount){
                return response()->json(['errors' => __('products.product_not_enough')]);
            }
            if ($product && $product->amount == 0){
                return response()->json(['errors' => __('products.product_out_of_stock')]);
            }

            if ($request->minus){
                $productOrder->update(['amount' => $productOrder->amount-1]);
            }
            if ($request->plus){
                $productOrder->update(['amount' => $productOrder->amount+1]);
            }

            $user = Auth::user();
            $price = [];
            $discount = null;
            $lastTotal = null;

            $orders = Order::getUserOrder($user->id);

            foreach ($orders as $order) {
                $price[] = $order->price*$order->product_order_amount;
            }

            $price = array_sum($price);

            $addedValue = ($price*settings('added_Value'))/100;
            $total = $price+$addedValue;

            if ($request->coupon){
                $check = $this->checkCoupon($request);
                if ($check['errors']){
                    return response()->json($check);
                }

                $productHaveCoupon = $check['product'];
                $coupon = $check['coupon'];
                $addedValueForProductHaveCoupon = ($productHaveCoupon->price*$productHaveCoupon->product_order_amount*settings('added_Value'))/100;
                $discount = ((($productHaveCoupon->price*$productHaveCoupon->product_order_amount)+$addedValueForProductHaveCoupon)*($coupon->discount))/100;
                $lastTotal = $total-$discount;

                if (!count($orders)){
                    $discount = null;
                    $lastTotal = null;
                }
            }

            session()->put(['price' => $lastTotal ?? $price]);
            return response()->json([
                'success' => true,
                'price' => $price,
                'added_value' => $addedValue,
                'discount' => $discount,
                'total' => $total,
                'last_total' => $lastTotal,
                'item_quantity' => $productOrder->amount,
                'item_price' => $product->price*$productOrder->amount,
            ]);
        }
    }

    public function productEvaluate(EvaluateRequest $request)
    {

        if (! Auth::check()){
            return response()->json(['errors' => __('courses.pleas_login')]);
        }

        $user = Auth::user();
        $orders = Order::where('orders.user_id', '=', $user->id)
            ->where('orders.status', 'done')
//            ->join('coupons', 'orders.coupon_id', 'coupons.id')
            ->join('product_orders', 'product_orders.order_id','orders.id')
            ->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',
//                'coupons.code',
                'products.price',
                'products.discount',
                'products.image',
                'pd.name',
                'product_orders.amount',
                'product_orders.product_id',
            ])
            ->selectSub("SELECT code FROM coupons WHERE coupons.id = orders.coupon_id", 'coupon')
            ->cursor();

        $productsIds = $orders->pluck('product_id')->toArray();

        if (!in_array($request->product_id, $productsIds)){
            return response()->json(['errors' => __('products.product_not_purchased')]);
        }

        $evaluate = Evaluate::where('product_id', $request->product_id)->where('user_id', $user->id)->first();

        if ($evaluate){
            $evaluate->forceDelete();
        }

        Evaluate::create([
            'user_name' => $user->name,
            'comment' => $request->comment,
            'evaluate' => $request->evaluate,
            'user_id' => $user->id,
            'product_id' => $request->product_id,
        ]);

        return response()->json(['message' => __('products.comment_successfully')]);

    }

    public function checkProductsPrice(Request $request)
    {
        if ($request->ajax()){
            $user = Auth::user();
            $price = [];
            $discount = null;
            $lastTotal = null;

            $orders = Order::getUserOrder($user->id);

            foreach ($orders as $order) {
                $price[] = $order->price*$order->product_order_amount;
                if ($order->product_amount < $order->product_order_amount){
                    return response()->json(['errors' => '('.$order->name.' )' . __('products.product_not_enough')]);
                }
                if ($order->product_amount == 0){
                    return response()->json(['errors' => '('.$order->name.' )' . __('products.product_out_of_stock')]);
                }
            }

            $price = array_sum($price);

            $addedValue = ($price*settings('added_Value'))/100;
            $total = $price+$addedValue;

            if ($request->coupon){
                $check = $this->checkCoupon($request);
                if ($check['errors']){
                    return response()->json($check);
                }
                $coupon = $check['coupon'];
                $productHaveCoupon = $check['product'];
                $addedValueForProductHaveCoupon = ($productHaveCoupon->price*$productHaveCoupon->product_order_amount*settings('added_Value'))/100;
                $discount = ((($productHaveCoupon->price*$productHaveCoupon->product_order_amount)+$addedValueForProductHaveCoupon)*($coupon->discount))/100;
                $lastTotal = $total-$discount;

                if (!count($orders)){
                    $discount = null;
                    $lastTotal = null;
                }
            }

            session()->put(['price' => $lastTotal ?? $price]);
            return response()->json([
                'success' => true,
                'price' => $price,
                'added_value' => $addedValue,
                'discount' => $discount,
                'total' => $total,
                'last_total' => $lastTotal,
            ]);

        }
    }

    public function checkCoupon(Request $request)
    {
        $validation = Validator::make($request->all(), [
            'coupon' => 'required|exists:coupons,code'
        ], [], [
            'coupon' => __('courses.coupon')
        ]);

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

        $coupon = Coupon::where('type', 'products')->where('code', $request->coupon)->first();

        if (!$coupon){
            return ['errors' => __('courses.invalid_coupon')];
        }

        if ($coupon->status == 0){
            return ['errors' => __('courses.invalid_coupon')];
        }

        if ($coupon->type != 'products' ){
            return ['errors' => __('courses.invalid_coupon')];
        }

        if ($coupon->used_count >= $coupon->available_users){
            return ['errors' => __('courses.invalid_coupon')];
        }

        if ($coupon->type == 'products' && $coupon->start_date > date('Y-m-d')){
            return ['errors' => __('courses.coupon_not_allow_before_date') . $coupon->start_date];
        }

        if ($coupon->type == 'products' && $coupon->end_date < date('Y-m-d')){
            return ['errors' => __('courses.invalid_coupon')];
        }

        $user = Auth::user();
        $orders = Order::getUserOrder($user->id);

        $orderFound = null;
        foreach ($orders as $order) {
            if ($order->product_id == $coupon->product_id){
                $orderFound = $order;
            }
        }

        if (!$orderFound){
            return ['errors' => __('products.not_invalid_with_any_product')];
        }

        return ['product' => $orderFound, 'coupon' => $coupon, 'errors' => false];
    }

    public function payNow(Request $request)
    {
        if ($request->ajax()){
            session()->forget(['pay_way', 'points', 'coupon', 'price', 'orders', 'order']);

            if (!$request->has('pay_way') && !$request->coupon && !$request->has('points')){
                return response()->json(['errors' => __('courses.choose_pay_way')]);
            }

            $user = Auth::user();
            $price = [];
            $discount = null;
            $lastTotal = null;
            $coupon_id = null;

            $orders = Order::getUserOrder($user->id);

            foreach ($orders as $order) {
                $price[] = $order->price*$order->product_order_amount;
            }

            $price = array_sum($price);

            $addedValue = ($price*settings('added_Value'))/100;
            $total = $price+$addedValue;
            $userOrder = Order::where('user_id', $user->id)->where('status', 'charge')->first();

            if ($request->coupon && !$request->pay_way){

                $check = $this->checkCoupon($request);
                if ($check['errors']){
                    return $check;
                }


                $productHaveCoupon = $check['product'];
                $coupon = $check['coupon'];
                $discount = ((($productHaveCoupon->price*$productHaveCoupon->product_order_amount)+$addedValue)*($coupon->discount))/100;
                $lastTotal = $total-$discount;

                if ($lastTotal > 0){
                    if (!$request->has('pay_way')){
                        return response()->json(['errors' => __('courses.choose_pay_way_with_coupon')]);
                    }
                }

                if (!count($orders)){
                    $discount = null;
                    $lastTotal = null;
                }

                $coupon->update(['used_count' => $coupon->used_count+1]);
                if($coupon->used_count == $coupon->available_users){
                    $coupon->update(['status' => 0]);
                }

                $coupon_id = $coupon->id;

                foreach ($orders as $order) {
                    $product = Product::find($order->product_id);
                    $product->update(['amount' => ($product->amount-$order->product_order_amount)]);
                }

                $productsIds = $orders->pluck('product_id')->toArray();

                $userOrder->update([
                    'status' => 'done',
                    'coupon_id' => $coupon_id,
                ]);

                UsersNotification::create([
                    'title' => __('productRequests.your_request_changed') . __('productRequests.delivery'),
                    'message' => __('productRequests.your_request_changed') . __('productRequests.number') .
                        ' ('.$userOrder->id.') '. __('productRequests.to') .
                        __('productRequests.delivery'),
                    'send_to' => 'user',
                    'user_id' =>  $userOrder->user_id,
                ]);

                $bill = self::createBill($userOrder->id, $productsIds, $lastTotal ?? $total);

                if ($bill){
                    try{
                        self::sendEmailWithBill($bill, $orders);
                    } catch (\Exception $e) {

                    }
                }


                return response()->json([
                    'url' => route('user.profile'),
                    'message' => __('products.Product_purchased_complete')
                ]);

            }

            if (in_array($request->pay_way, ['bank'])){

                if (!$request->has('payment_receipt')){
                    return response()->json(['errors' => __('courses.payment_receipt_required')]);
                }

                if ($request->coupon){
                    $check = $this->checkCoupon($request);
                    if ($check['errors']){
                        return response()->json($check);
                    }

                    $productHaveCoupon = $check['product'];
                    $coupon = $check['coupon'];
                    $discount = ((($productHaveCoupon->price*$productHaveCoupon->product_order_amount)+$addedValue)*($coupon->discount))/100;
                    $lastTotal = $total-$discount;

                    if (!count($orders)){
                        $discount = null;
                        $lastTotal = null;
                    }

                    $coupon->update(['used_count' => $coupon->used_count+1]);
                    if($coupon->used_count == $coupon->available_users){
                        $coupon->update(['status' => 0]);
                    }

                    $coupon_id = $coupon->id;
                }


                foreach ($orders as $order) {
                    $product = Product::find($order->product_id);
                    $product->update(['amount' => ($product->amount-$order->product_order_amount)]);
                }

                $paymentReceipt = ImageHelper::upload($request->payment_receipt, 'payment_receipt');
                $productsIds = $orders->pluck('product_id')->toArray();

                $userOrder->update([
                    'status' => 'progress',
                    'pay_way' => 'bank',
                    'coupon_id' => $coupon_id,
                    'payment_receipt' => $paymentReceipt,
                ]);

                $bill = self::createBill($userOrder->id, $productsIds, $lastTotal ?? $total);

                if ($bill){
                    try{
                        self::sendEmailWithBill($bill, $orders);
                    } catch (\Exception $e) {

                    }
                }


                return response()->json([
                    'url' => route('user.profile'),
                    'message' => __('products.Product_purchased_complete')
                ]);

            }

            if (in_array($request->pay_way, ['mada', 'visa', 'mastercard'])){

                $request->pay_way == 'mada' ? session()->put(['pay_way' => 6]) : session()->put(['pay_way' => 2]);
                $user = Auth::user();
                $price = [];
                $discount = null;
                $lastTotal = null;
                $coupon = null;

                $orders = Order::getUserOrder($user->id);

                foreach ($orders as $order) {
                    $price[] = $order->price*$order->product_order_amount;
                }

                $price = array_sum($price);

                $addedValue = ($price*settings('added_Value'))/100;
                $total = $price+$addedValue;

                if ($request->coupon){

                    $check = $this->checkCoupon($request);
                    if ($check['errors']){
                        return response()->json($check);
                    }

                    $productHaveCoupon = $check['product'];
                    $coupon = $check['coupon'];
                    $addedValueForProductHaveCoupon = ($productHaveCoupon->price*$productHaveCoupon->product_order_amount*settings('added_Value'))/100;
                    $discount = ((($productHaveCoupon->price*$productHaveCoupon->product_order_amount)+$addedValueForProductHaveCoupon)*($coupon->discount))/100;
                    $lastTotal = $total-$discount;

                    if (!count($orders)){
                        $discount = null;
                        $lastTotal = null;
                    }

                }

                session()->put([
                    'coupon' => $coupon,
                    'price' => round($lastTotal) ?? round($total),
                    'orders' => $orders,
                    'order' => $userOrder
                ]);

                $userOrder->update(['coupon_id' => $coupon->id]);

                return response()->json(['url' =>route('productPay') ]);
            }

        }

    }

    public static function createBill($order_id, array $product_id, $price)
    {
        $user = Auth::user();
        $bill = CoursesBill::create([
            'user_id' => $user->id,
            'order_id' => $order_id,
            'product_id' => $product_id,
            'bill_date' => date('Y-m-d'),
            'tax_number' => array_key_exists('tax_number', settings()) ? settings('tax_number') : null,
            'course_price' => $price,
            'added_value' => array_key_exists('added_value', settings()) ? settings('added_value') : null,
        ]);

        return $bill ?? null;
    }

    public static function sendEmailWithBill($bill, $orders)
    {

        $data = [
            'direction' => getCurrentLocale() == 'ar' ? 'rtl' : 'ltr',
            'bill_id' => $bill->id,
            'bill_date' => $bill->created_at,
            'tax_number' => $bill->tax_number,
            'email' => $bill->user_email,
            'phone' => $bill->phone,
            'user_name' => $bill->user_name,
            'added_value' => $bill->added_value,
            'orders' => $orders,
        ];

        BillJob::dispatch($data, 'web.eye_stores.emails.bill_email');

    }

}
