<?php

namespace App\Http\Controllers\Frontend;

use Exception;
use Carbon\Carbon;
use App\Models\Order;
use App\Models\Courier;
use App\Models\Product;
use App\Models\Variant;
use App\Models\Customer;
use App\Models\OrderItem;
use App\Models\OrderSource;
use Illuminate\Support\Str;
use App\Models\ComboProduct;
use App\Services\SmsService;
use Illuminate\Http\Request;
use App\Models\DeliveryCharge;
use App\Models\ProductVariant;
use App\Models\CustomerCashbook;
use App\Models\OrderItemVariant;
use App\Models\SiteConfiguration;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Gloudemans\Shoppingcart\Facades\Cart;

class OrderController extends Controller
{

    public function order(Request $request)
    {
        // return $request->all();
        // return session()->get('order_session_id');
        $request->validate([
            'mobile_no' => 'required|digits:11',
            'name'      => 'required ',
            'address'   => 'nullable',
        ]);


            // $customer = Customer::where('phone', $request->mobile_no)->where('status',1)->first();
            // // $customer = Customer::where('ip', $request->ip())->first();

            // if($customer){
            //     $order = Order::where('customer_id',$customer->id)->select('created_at')->latest()->first();

            //     //====== For Hours========
            //     // if($order){
            //     //     $current_time = Carbon::now()->format('Y-m-d H:00:00');
            //     //     $parse_time   = Carbon::parse($current_time);
            //     //     $different    = $order->created_at->diffInHours($parse_time);
                    
            //     //      if($different < 12){
            //     //         $waiting_time = 12 - $different;
            //     //         return response()->json([
            //     //             'status' => false,
            //     //             'message' => 'For next order, you have to wait '.$waiting_time.' hours.',
            //     //         ]);
            //     //      } 
            //     // }

            //     // ========== For minutes =======
            //     if ($order) {
            //         $current_time = Carbon::now();
            //         $different = $order->created_at->diffInMinutes($current_time);

            //         if ($different < 30) {
            //             $waiting_time = 30 - $different;
            //             return response()->json([
            //                 'status'  => false,
            //                 'message' => 'For next order, you have to wait '.$waiting_time.' minutes.',
            //             ]);
            //         }
            //     }

            // }

        $setting = SiteConfiguration::select('is_pre_stock', 'variant_wise_stock', 'incomplete_order_system')->first();

        if ($setting && $setting->incomplete_order_system == 1) {
            if ($request->status == 12) {
                if (!session()->has('order_session_id')) {
                    session()->put('order_session_id', Str::uuid());
                }
            }
            if ($request->status == 1) {
                if (session()->has('order_session_id')) {
                    $order = Order::where('session_id', session()->get('order_session_id'))
                        ->where('status', 12)
                        ->first();

                    if ($order) {
                        OrderItemVariant::whereIn('order_item_id', OrderItem::where('order_id', $order->id)->pluck('id'))->delete();
                        OrderItem::where('order_id', $order->id)->delete();
                        $order->delete();
                    }
                    session()->forget(['order_session_id', 'online_payment']);
                }
            }
        }

        if (Cart::count() <= 0) {
            return response()->json([
                'status' => false,
                'message' => 'your cart is empty',
            ]);
        }

        $ip = $request->ip();

        $isBlockedByPhone = Customer::where('phone', $request->mobile_no)
            ->where('is_blocked', 0)
            ->exists();

        // Check if IP is blocked (even if it's a different customer)
        $isBlockedByIp = Customer::where('ip_address', $ip)
            ->where('is_blocked',  0)
            ->exists();

        if ($isBlockedByPhone || $isBlockedByIp) {
            return response()->json([
                'status' => false,
                'message' => 'You are not allowed to place an order.',
            ]);
        }
        //=======================set variable =============================
        
        $delivery_charge = 0;
        $discount = 0;

        // Check if any cart item has free delivery
        $cartItems = Cart::content()->values();

        $has_free_delivery = $cartItems->contains(function ($item) {
            return $item->options->is_free_delivery == 1;
        });

        $delivery_charge = 0;

        if ($has_free_delivery == 1) {
            $delivery_charge = 0;
        } else if ($request->shipping_charge) {
            $delivery_charge = $request->shipping_charge;
        } else {
            $delivery_charge = 0;
        }

        // Handle coupon discount
        $coupon_id  = session()->get('coupon_id');
        $discount   = $request->coupon_amount ?? 0;
        // =======================================================================
        # Rule of customer create and update.
        # customer buy product with phone number.
        # when customer info is exit then customer info update
        # when customer not exit then create new customer with customer phone number.
        # customer is authentic.
        //========================================================================

        DB::beginTransaction();
        try {
            $customer = Customer::where('phone', $request->mobile_no)->first();

            if ($customer) {
                $customer->address     = $request->address;
                $customer->name        = $request->name;
                $customer->city_id     = $request->city_id ?? null;
                $customer->sub_city_id = $request->subcity_id ?? null;
                $customer->total_order = ++$customer->total_order;
                $customer->save();
            } else {
                $customer                = new Customer();
                $customer->name          = $request->name;
                $customer->phone         = $request->mobile_no;
                $customer->city_id       = $request->city_id ?? null;
                $customer->sub_city_id   = $request->subcity_id ?? null;
                $customer->password      = Hash::make($request->mobile_no);
                $customer->address       = $request->address ?? null;
                $customer->status        = 1;
                $customer->total_order   = 1;
                $customer->ip_address    = $request->ip();
                $customer->customer_type = 1;
                $customer->save();
                
                $first_name              = explode(' ', trim(strtolower($customer->name)))[0];
                $username                = $first_name;
                $counter                 = 1;

                while (Customer::where('username', $username)->exists()) {
                    $username            = $first_name . $counter;
                    $counter++;
                }
                $customer->username      = $username;
                $customer->save();
            }

            $total = Cart::total();
            //save the order
            $order                  = new Order();
            $order->customer_id     = $customer->id;
            $order->customer_phone  = $request->mobile_no;
            $order->city_id         = $request->city_id ?? null;
            $order->sub_city_id     = $request->subcity_id ?? null;
            $order->invoice_no      = 123;
            $order->order_type      = 1;
            $order->shipping_cost   = $delivery_charge ?? 0;
            $order->discount        = $discount;
            $order->coupon_disocunt = $discount;
            $order->coupon_id       = $coupon_id ?? null;
            $order->note            = $request->note ?? null;
            $order->total           = $total;
            $order->status          = $request->status ?? 1;

            if ($request->status == 12) {
                $order->session_id  = session()->get('order_session_id');
            }

            //default courier
            $courier = Courier::where('is_default', 1)->select('id')->first();
            if (!empty($courier)) {
                $order->courier_id = $courier->id;
            }


            if (!empty($request->order_source) && $request->order_source == 'landing_page') {
                $order->order_source = 4;
                $order->save();
            } else {
                //order source
                $source = OrderSource::where('is_default', 1)->select('id')->first();
                if (!empty($source)) {
                    $order->order_source = $source->id;
                }
                $order->save();
            }

            $affiliate_amount = 0;

            foreach (Cart::content() as $cart) {

              $product = Product::findOrFail($cart->id);

                $orderItem = OrderItem::create([
                    'order_id'   => $order->id,
                    'product_id' => $cart->id,
                    'price'      => $cart->price,
                    'quantity'   => $cart->qty,
                    'total'      => $cart->qty * $cart->price,
                    'purchase_price' => $product->purchase_price
                ]);

                

                if ($product && $product->affiliate_profit > 0) {
                    $affiliate_amount += $product->affiliate_profit;
                }

                if (is_array($cart->options->variants)) {

                    // Iterate through variants if they exist
                    foreach ($cart->options->variants as $attributeName => $variantName) {
                        OrderItemVariant::create([
                            'order_item_id'    => $orderItem->id,
                            'variant_atribute' => $attributeName ?? null,
                            'variant_name'     => $variantName ?? null,
                        ]);
                    }
                }

                /*** checking pre stock order **/
                if ($setting && $setting->is_pre_stock == 1) {

                    $product = Product::findOrFail($cart->id);

                    
                if ($product->is_combo == 1) {

                    $combo_products_id  = ComboProduct::where('combo_product_id', $product->id)->select('general_product_id')->pluck('general_product_id');

                    $combo_products     = Product::whereIn('id', $combo_products_id)->select('id', 'stock', 'product_code')->get();

                        //save purchase price for profit calculation
                    $combo_products_purchase_price  = Product::whereIn('id', $combo_products_id)->sum('purchase_price');

                    $orderItem->purchase_price     = $combo_products_purchase_price;

                        foreach ($combo_products as $item) {

                            if ($setting->variant_wise_stock != 1) {
                                $item->stock = $item->stock - $orderItem->quantity;
                                $item->save();
                            } else {
                                

                                $orderItemVariants = OrderItemVariant::where('order_item_id', $orderItem->id)->get();

                                foreach ($orderItemVariants as $orderItemVariant) {
                                    $variant  = Variant::where('name', $orderItemVariant->variant_name)->select('id', 'name')->first();
                                    if ($variant) {
                                        $productVariant = ProductVariant::where('product_id', $item->id)
                                            ->where('variant_id', $variant->id)
                                            ->first();
                                        if ($productVariant) {
                                            $productVariant->stock = $productVariant->stock - $orderItem->quantity;
                                            $productVariant->save();
                                        }
                                    }
                                }


                            }
                        }                    
                } else {
                        if ($setting->variant_wise_stock != 1) {
                            if ($product) {
                                $product->stock = $product->stock - $cart->qty;
                                $product->save();
                            }
                        } else {
                            if (is_array($cart->options->variants)) {

                                foreach ($cart->options->variants as $attributeName => $variantName) {

                                    $variant = Variant::where('name', $variantName)->select('id', 'name')->first();

                                    if ($variant) {

                                        $productVariant = ProductVariant::where('product_id', $cart->id)
                                            ->where('variant_id', $variant->id)
                                            ->first();

                                        if ($productVariant) {
                                            $productVariant->stock = $productVariant->stock - $cart->qty;
                                            $productVariant->save();
                                        }
                                    }
                                }
                            }
                        }
                        $orderItem->purchase_price = $product->purchase_price;
                        $orderItem->save();
                    }
                }
                
            }
        
            /**** making 6 digit unique invoice no ****/
            if (strlen($order->id) > 3) {
                $order->invoice_no = rand(1, 9) . $order->id . rand(1, 9);
            } else if (strlen($order->id) > 2) {
                $order->invoice_no = rand(11, 99) . $order->id . rand(1, 9);
            } else if (strlen($order->id) > 1) {
                $order->invoice_no = rand(11, 99) . $order->id . rand(11, 99);
            } else {
                $order->invoice_no = rand(111, 999) . $order->id . rand(11, 99);
            }

            

            $order->save();
            $order_amount = ($order->total + $order->shipping_cost) - $order->discount;

            Session::put([
                'online_payment' => [
                    'order_id' => $order->id,
                    'order_invoice' => $order->invoice_no,
                    'order_amount' => $order_amount,
                ]
            ]);

            DB::commit();
            Auth::guard('customer')->loginUsingId($customer->id);
            return response()->json([
                'status' => true,
                'transaction_id' => $order->invoice_no,
                'invoice_no' => $order->invoice_no,
                'shipping' => $order->shipping_cost,
                'coupon' => $coupon->code ?? "",
                'payment' => $request->payment,
                'message' => 'order successfully',
            ]);
        } catch (Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ]);
        }
    }


    public function showOrderSuccess($invoice_no)
    {
        $order = Order::with(['orderItem'])->where('invoice_no', $invoice_no)->first();
        $data = [
            'order' => $order,
        ];
        return view('frontend.pages.order_success', $data);
    }
    public function paymentFail($payment_id)
    {
        $order = Order::where('payment_id', $payment_id)->first();
        return view('frontend.bkash.fail', compact('order'));
    }


    public function index(Request $request)
    {
        return view('frontend.pages.order_tracking');
    }

    public function orderTrack(Request $request)
    {

        $data = $request->validate([
            'invoice_no' => 'required',
        ]);

        $order = Order::with(['customer:id,name,phone,address', 'courier:id,name,status'])->select('id', 'invoice_no', 'customer_id', 'courier_id', 'status', 'customer_phone', 'total', 'created_at','courier_id','tracking_id')->where('invoice_no', $request->invoice_no)->first();
        
        if (!empty($order)) {
            $order_status = '';
            switch ($order->status) {
                case 1:
                    $order_status .= 'New';
                    break;
                case 2:
                    $order_status .= 'Pending';
                    break;

                case 3:
                    $order_status .= 'Approved';
                    break;

                case 4:
                    $order_status .= 'Shipment';
                    break;

                case 5:
                    $order_status .= ' Delivered';
                    break;

                case 6:
                    $order_status .= 'Cancel';
                    break;

                case 7:
                    $order_status .= 'Return';
                    break;

                case 8:
                    $order_status .= 'Packaging Ready';
                    break;

                default:
                    $order_status .= 'Unknown Order';
                    break;
            }
            return response()->json([
                'status' => true,
                'message' => 'order find successfully',
                'courier_name' => @$order->courier->name ?? "",
                'data' => view('frontend.components.order_tracking_content', compact('order', 'order_status'))->render(),
            ]);
        } else {
            return response()->json([
                'status' => false,
                'message' => 'Unknown Order',
            ]);
        }
    }
}
