/**
  * Get items in the Swine Cart
  * [!]AJAX
  *
  * @param  Request $request
  * @return JSON/Array
  */
 public function getSwineCartItems(Request $request)
 {
     if ($request->ajax()) {
         $customer = $this->user->userable;
         $swineCartItems = $customer->swineCartItems()->where('if_requested', 0)->get();
         $items = [];
         foreach ($swineCartItems as $item) {
             $itemDetail = [];
             $product = Product::find($item->product_id);
             $itemDetail['item_id'] = $item->id;
             $itemDetail['product_id'] = $item->product_id;
             $itemDetail['product_name'] = $product->name;
             $itemDetail['product_type'] = $product->type;
             $itemDetail['product_breed'] = Breed::find($product->breed_id)->name;
             $itemDetail['img_path'] = '/images/product/' . Image::find($product->primary_img_id)->name;
             $itemDetail['breeder'] = Breeder::find($product->breeder_id)->users()->first()->name;
             $itemDetail['token'] = csrf_token();
             array_push($items, $itemDetail);
         }
         $itemsCollection = collect($items);
         return $itemsCollection->toJson();
     } else {
         $customer = $this->user->userable;
         $swineCartItems = $customer->swineCartItems()->where('if_rated', 0)->get();
         $products = [];
         $log = $customer->transactionLogs()->get();
         $history = [];
         foreach ($swineCartItems as $item) {
             $itemDetail = [];
             $product = Product::find($item->product_id);
             $reviews = Breeder::find($product->breeder_id)->reviews()->get();
             $itemDetail['request_status'] = $item->if_requested;
             $itemDetail['request_quantity'] = $item->quantity;
             $itemDetail['status'] = $item->reservation_id ? ProductReservation::find($item->reservation_id)->order_status : $product->status;
             $itemDetail['staus'] = $product->status;
             $itemDetail['item_id'] = $item->id;
             $itemDetail['customer_id'] = $customer->id;
             $itemDetail['breeder_id'] = $product->breeder_id;
             $itemDetail['breeder'] = Breeder::find($product->breeder_id)->users()->first()->name;
             $itemDetail['product_id'] = $item->product_id;
             $itemDetail['product_province'] = FarmAddress::find($product->farm_from_id)->province;
             $itemDetail['product_name'] = $product->name;
             $itemDetail['product_type'] = $product->type;
             $itemDetail['product_quantity'] = $product->quantity;
             $itemDetail['product_breed'] = $this->transformBreedSyntax(Breed::find($product->breed_id)->name);
             $itemDetail['product_birthdate'] = $this->transformDateSyntax($product->birthdate);
             $itemDetail['product_age'] = $this->computeAge($product->birthdate);
             $itemDetail['product_adg'] = $product->adg;
             $itemDetail['product_fcr'] = $product->fcr;
             $itemDetail['product_backfat_thickness'] = $product->backfat_thickness;
             $itemDetail['other_details'] = $product->other_details;
             $itemDetail['avg_delivery'] = $reviews->avg('rating_delivery');
             $itemDetail['avg_transaction'] = $reviews->avg('rating_transaction');
             $itemDetail['avg_productQuality'] = $reviews->avg('rating_productQuality');
             if ($item->date_needed == '0000-00-00') {
                 $itemDetail['date_needed'] = '';
             } else {
                 $itemDetail['date_needed'] = $this->transformDateSyntax($item->date_needed);
             }
             $itemDetail['special_request'] = $item->special_request;
             $itemDetail['img_path'] = '/images/product/' . Image::find($product->primary_img_id)->name;
             if ($item->transactionLog) {
                 $itemDetail['status_transactions'] = json_decode($item->transactionLog->status_transactions, true);
             } else {
                 $itemDetail['status_transactions'] = ["requested" => '', "reserved" => '', "on_delivery" => '', "paid" => '', "sold" => '', "rated" => ''];
             }
             array_push($products, (object) $itemDetail);
         }
         $products = collect($products);
         $history = collect($history);
         $token = csrf_token();
         $customerId = $customer->id;
         return view('user.customer.swineCart', compact('products', 'history', 'token', 'customerId'));
     }
 }
 /**
  * Update product status
  *
  * @param  Request      $request
  * @return Array/String
  */
 public function updateStatus(Request $request, Product $product)
 {
     switch ($request->status) {
         case 'reserved':
             // Check if product is available for reservations
             if ($product->quantity) {
                 $customerName = Customer::find($request->customer_id)->users()->first()->name;
                 // Update quantity of product
                 if ($product->type != 's***n') {
                     $product->quantity = 0;
                 }
                 $product->save();
                 // Make a product reservation
                 $reservation = new ProductReservation();
                 $reservation->customer_id = $request->customer_id;
                 $reservation->quantity = $request->request_quantity;
                 $reservation->date_needed = date_format(date_create($request->date_needed), 'Y-n-j');
                 $reservation->special_request = $request->special_request;
                 $reservation->order_status = 'reserved';
                 $product->reservations()->save($reservation);
                 // Update the Swine Cart item
                 $swineCartItem = SwineCartItem::find($request->swinecart_id);
                 $swineCartItem->reservation_id = $reservation->id;
                 $swineCartItem->save();
                 // Update Transaction Log
                 // This must be put in an event for better performance
                 $transactionLog = $reservation->transactionLog()->first();
                 $decodedStatusTransaction = json_decode($transactionLog->status_transactions, true);
                 $decodedStatusTransaction['reserved'] = date('j M Y (D) g:iA', time());
                 $transactionLog->status_transactions = collect($decodedStatusTransaction)->toJson();
                 $transactionLog->save();
                 // Notify reserved customer
                 $reservedCustomerUser = Customer::find($reservation->customer_id)->users()->first();
                 $reservedCustomerUser->notify(new ProductReserved(['description' => 'Product ' . $product->name . ' by ' . $product->breeder->users()->first()->name . ' has been reserved to you', 'time' => $decodedStatusTransaction['reserved'], 'url' => route('cart.items')]));
                 // If product type is not s***n remove other requests to this product
                 $productRequests = SwineCartItem::where('product_id', $product->id)->where('customer_id', '<>', $request->customer_id)->where('reservation_id', 0);
                 if ($product->type != 's***n') {
                     // Notify Customer users that the product has been reserved to another customer
                     foreach ($productRequests->get() as $productRequest) {
                         $customerUser = $productRequest->customer->users()->first();
                         $breederName = Product::find($productRequest->product_id)->breeder->users()->first()->name;
                         $customerUser->notify(new ProductReservedToOtherCustomer(['description' => 'Sorry, product ' . $product->name . ' was reserved by ' . $breederName . ' to another customer', 'time' => $decodedStatusTransaction['reserved'], 'url' => route('cart.items')]));
                     }
                     // Delete requests to this product after notifying Customer users
                     $productRequests->delete();
                 } else {
                     if ($productRequests->count() == 0) {
                         $product->status = 'displayed';
                         $product->save();
                         return ['success', $product->name . ' reserved to ' . $customerName, $reservation->id, (string) Uuid::uuid4(), true];
                     }
                 }
                 // [0] - success/fail operation flag
                 // [1] - toast message
                 // [2] - reservation_id
                 // [3] - generated UUID
                 // [4] - flag for removing the parent product display in the UI component
                 return ['success', $product->name . ' reserved to ' . $customerName, $reservation->id, (string) Uuid::uuid4(), false];
             } else {
                 return ['fail', $product->name . ' is already reserved to another customer'];
             }
         case 'on_delivery':
             $reservation = ProductReservation::find($request->reservation_id);
             $reservation->order_status = 'on_delivery';
             $reservation->save();
             // Update Transaction Log
             // This must be put in an event for better performance
             $transactionLog = $reservation->transactionLog()->first();
             $decodedStatusTransaction = json_decode($transactionLog->status_transactions, true);
             $decodedStatusTransaction['on_delivery'] = date('j M Y (D) g:iA', time());
             $transactionLog->status_transactions = collect($decodedStatusTransaction)->toJson();
             $transactionLog->save();
             // Notify customer
             $reservedCustomerUser = Customer::find($reservation->customer_id)->users()->first();
             $reservedCustomerUser->notify(new ProductReservationUpdate(['description' => 'Product ' . $product->name . ' by ' . $product->breeder->users()->first()->name . ' is on delivery', 'time' => $decodedStatusTransaction['on_delivery'], 'url' => route('cart.items')]));
             return "OK";
         case 'paid':
             $reservation = ProductReservation::find($request->reservation_id);
             $reservation->order_status = 'paid';
             $reservation->save();
             // Update Transaction Log
             // This must be put in an event for better performance
             $transactionLog = $reservation->transactionLog()->first();
             $decodedStatusTransaction = json_decode($transactionLog->status_transactions, true);
             $decodedStatusTransaction['paid'] = date('j M Y (D) g:iA', time());
             $transactionLog->status_transactions = collect($decodedStatusTransaction)->toJson();
             $transactionLog->save();
             // Notify customer
             $reservedCustomerUser = Customer::find($reservation->customer_id)->users()->first();
             $reservedCustomerUser->notify(new ProductReservationUpdate(['description' => 'Product ' . $product->name . ' by ' . $product->breeder->users()->first()->name . ' has been marked as paid', 'time' => $decodedStatusTransaction['paid'], 'url' => route('cart.items')]));
             return "OK";
         case 'sold':
             $reservation = ProductReservation::find($request->reservation_id);
             $reservation->order_status = 'sold';
             $reservation->save();
             // Update Transaction Log
             // This must be put in an event for better performance
             $transactionLog = $reservation->transactionLog()->first();
             $decodedStatusTransaction = json_decode($transactionLog->status_transactions, true);
             $decodedStatusTransaction['sold'] = date('j M Y (D) g:iA', time());
             $transactionLog->status_transactions = collect($decodedStatusTransaction)->toJson();
             $transactionLog->save();
             // Notify reserved customer
             $reservedCustomerUser = Customer::find($reservation->customer_id)->users()->first();
             $reservedCustomerUser->notify(new ProductReservationUpdate(['description' => 'Product ' . $product->name . ' by ' . $product->breeder->users()->first()->name . ' has been marked as sold', 'time' => $decodedStatusTransaction['sold'], 'url' => route('cart.items')]));
             return "OK";
         default:
             return "Invalid operation";
     }
 }