<?php

namespace App\Http\Controllers\Api\V1;

use App\CentralLogics\Helpers;
use App\CentralLogics\ProductLogic;
use App\Http\Controllers\Controller;
use App\Models\BusinessSetting;
use App\Models\Item;
use App\Models\ItemCampaign;
use App\Models\Order;
use App\Models\OrderDetail;
use App\Models\ParcelCategory;
use App\Models\Store;
use App\Models\StoreSchedule;
use App\Models\User;
use App\Models\Zone;
use Grimzy\LaravelMysqlSpatial\Types\Point;
use Illuminate\Http\Request;
use App\Models\ApiSubscription;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class ApiSubscriptionController extends Controller
{
    public function getItems(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $request->validate([
                'api_key'    => 'required|string',
                'secret_key' => 'required|string',
            ]);

            $subscription = ApiSubscription::where('api_key', $request->api_key)
                ->where('secret_key', $request->secret_key)
                ->first();

            if (!$subscription) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Invalid API credentials.',
                ], 401);
            }

            $today = now()->toDateString();

            if ($subscription->status != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is inactive!',
                ], 403);
            }

            if ($subscription->start_date > $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription has not started yet!',
                ], 403);
            }

            if ($subscription->end_date < $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is expired!',
                ], 403);
            }

            if ($subscription->get_items != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your current subscription plan does not include access to retrieve items!',
                ], 403);
            }

            $items = Item::where('status', 1)
                ->whereHas('store', function($query){
                    $query->where('status', 1);
                })
                ->orderBy('id', 'ASC')
                ->paginate(50);

            $storage = [];

            foreach($items as $item) {

                $category_id = '';
                $sub_category_id = '';
                $enCategory = '';
                $enSubCategory = '';
                $catID = '';
                $subCatID = '';
                foreach(json_decode($item->category_ids, true) as $category)
                {
                    if($category['position']==1)
                    {
                        $enCategory = DB::table('categories')->where('id', $category['id'])->first()->name ?? '';
                        $category_id = DB::table('translations')
                            ->where('translationable_type', 'App\Models\Category')
                            ->where('translationable_id', $category['id'])
                            ->where('locale', 'ar')
                            ->where('key', 'name')->first();
                        $catID = $category['id'];
                        if($category_id) $category_id = $category_id->value;
                        if(!$category_id) {
                            $category_id = $enCategory;
                        }
                    }
                    else if($category['position']==2)
                    {
                        $enSubCategory = DB::table('categories')->where('id', $category['id'])->first()->name ?? '';
                        $sub_category_id = DB::table('translations')
                            ->where('translationable_type', 'App\Models\Category')
                            ->where('translationable_id', $category['id'])
                            ->where('locale', 'ar')
                            ->where('key', 'name')->first();
                        $subCatID = $category['id'];
                        if($sub_category_id) $sub_category_id = $sub_category_id->value;
                        if(!$sub_category_id) {
                            $sub_category_id = $enSubCategory;
                        }
                    }
                }

                $name = DB::table('translations')
                    ->where('translationable_type', 'App\Models\Item')
                    ->where('translationable_id', $item->id)
                    ->where('locale', 'ar')
                    ->where('key', 'name')->first()->value ?? $item->name;
                $description = DB::table('translations')
                    ->where('translationable_type', 'App\Models\Item')
                    ->where('translationable_id', $item->id)
                    ->where('locale', 'ar')
                    ->where('key', 'description')->first()->value ?? $item->description;

                $dayNames = [
                    0 => 'sunday',
                    1 => 'monday',
                    2 => 'tuesday',
                    3 => 'wednesday',
                    4 => 'thursday',
                    5 => 'friday',
                    6 => 'saturday',
                ];

                $storeSchedules = StoreSchedule::where('store_id', $item->store_id)
                    ->orderBy('day')
                    ->orderBy('opening_time')
                    ->get()
                    ->groupBy('day')
                    ->mapWithKeys(function ($group, $day) use ($dayNames) {
                        $dayIndex = (int) $day;
                        $key = $dayNames[$dayIndex] ?? $day; // لو صار شي غير متوقع، يرجع المفتاح الأصلي
                        $value = $group->map(function ($item) {
                            return [
                                'id' => $item->id,
                                'start_time' => substr($item->opening_time, 0, 5),
                                'end_time' => substr($item->closing_time, 0, 5),
                            ];
                        })->values();
                        return [ $key => $value ];
                    });

                $storage[] = [
                    'id' => $item->id,
                    'en_name' => $item->name,
                    'ar_name' => $name,
                    'en_description' => $item->description,
                    'ar_description' => $description,
                    'image' => 'https://postajji.com/storage/app/public/product/' . $item->image,
                    'category_id'=>$catID,
                    'ar_category'=>$category_id,
                    'en_category' => $enCategory,
                    'sub_category_id' => $subCatID,
                    'ar_sub_category' => $sub_category_id,
                    'en_sub_category' => $enSubCategory,
                    'price' => $item->price,
                    'discount' => $item->discount,
                    'discount_type' => $item->discount_type,
                    'store_id' => $item->store_id,
                    'store_name' => $item->store->name ?? '',
                    'en_store_name' => $item->store->en_name ?? '',
                    'tax_percentage' => $item->store->tax,
                    'store_lat' => $item->store->latitude,
                    'store_lng' => $item->store->longitude,
                    'ar_store_address' => $item->store->address,
                    'en_store_address' => $item->store->en_address,
                    'store_logo' => $item->store->logo != null ? ('https://postajji.com/storage/app/public/store/' . $item->store->logo) : null,
                    'store_cover_photo' => $item->store->logo != null ? ('https://postajji.com/storage/app/public/store/cover/' . $item->store->cover_photo) : null,
                    'store_expected_delivery_time' => $item->store->delivery_time,
                    'module_id' => $item->store->module_id,
                    'module_name' => $item->store->module->module_name,
                    'store_schedules' => $storeSchedules,
                    'item_schedules' => $item->item_schedules,
                ];
            }

            return response()->json([
                'status' => true,
                'total'   => $items->total(),
                'data'   => $storage,
            ], 200);

        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'status'  => false,
                'message' => 'Validation error.',
                'errors'  => $e->errors(),
            ], 422);

        } catch (\Exception $e) {
            Log::error('API Error in getItems: ' . $e->getMessage());

            return response()->json([
                'status'  => false,
                'message' => 'An unexpected error occurred. Please try again later.',
            ], 500);
        }
    }

    public function delivery(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $request->validate([
                'api_key'    => 'required|string',
                'secret_key' => 'required|string',
                'client_first_name' => 'required|string',
                'client_last_name' => 'nullable|string',
                'phone' => [
                    'required',
                    'string',
                    'regex:/^\+9639\d{8}$/'
                ],
                'source_address' => 'required',
                'source_latitude' => 'required',
                'source_longitude' => 'required',
                'receiver_address' => 'required',
                'receiver_latitude' => 'required',
                'receiver_longitude' => 'required',
                'order_description' => 'required',
            ]);

            $subscription = ApiSubscription::where('api_key', $request->api_key)
                ->where('secret_key', $request->secret_key)
                ->first();

            if (!$subscription) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Invalid API credentials.',
                ], 401);
            }

            $today = now()->toDateString();

            if ($subscription->status != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is inactive!',
                ], 403);
            }

            if ($subscription->start_date > $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription has not started yet!',
                ], 403);
            }

            if ($subscription->end_date < $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is expired!',
                ], 403);
            }

            if ($subscription->delivery != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your current subscription plan does not include access to delivery!',
                ], 403);
            }

            return $this->createParcelOrder($request, $subscription);

        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'status'  => false,
                'message' => 'Validation error.',
                'errors'  => $e->errors(),
            ], 422);

        } catch (\Exception $e) {
            Log::error('API Error in delivery: ' . $e->getMessage());

            return response()->json([
                'status'  => false,
                'message' => 'An unexpected error occurred. Please try again later.' . $e->getMessage(),
            ], 500);
        }
    }

    public function getUser($request)
    {
        $user = User::where('phone', $request->phone)->first();

        if (!$user) {
            $user = User::create([
                'f_name'     => $request->client_first_name,
                'l_name'     => $request->client_last_name,
                'phone'    => $request->phone,
                'password' => bcrypt(Str::random(10)),
                'platform' => 'DeliveryAPI',
                'app_version' => 0,
                'last_login' => now(),
            ]);
        }

        return $user;
    }

    public function createParcelOrder($request, $subscription): \Illuminate\Http\JsonResponse
    {
        $paymentMethod = 'cash_on_delivery';
        $orderType = 'parcel';
        $parcelCategoryId = 4;
        $chargePayer = 'receiver';
        $userId = $this->getUser($request)->id;
        $extraCharges = 0;

        $address = [
            'contact_person_name' => trim($request->client_first_name . ' ' . ($request->client_last_name ?? '')),
            'contact_person_number' => $request->phone,
            'address_type' => 'Delivery',
            'address' => $request->source_address,
            'floor' => null,
            'road' => null,
            'house' => null,
            'longitude' => (string)$request->source_longitude,
            'latitude' => (string)$request->source_latitude,
        ];
        $receiverDetails = [
            'id' => null,
            'address_type' => 'others',
            'contact_person_name' => trim($request->client_first_name . ' ' . ($request->client_last_name ?? '')),
            'contact_person_number' => $request->phone,
            'address' => $request->receiver_address,
            'additional_address' => null,
            'latitude' => $request->receiver_latitude,
            'longitude' => $request->receiver_longitude,
            'zone_id' => null,
            'zone_ids' => null,
            '_method' => null,
            'area_ids' => null,
            'road' => null,
            'house' => null,
            'floor' => null,
        ];

        /*$currentOrder = Order::where('user_id', $userId)->whereIn('order_status', ['pending', 'accepted', 'confirmed', 'processing', 'handover'])->first();
        if($currentOrder){
            return response()->json([
                'status'  => false,
                'message' => 'You have an active order now!',
            ], 406);
        }*/

        $zone = null;
        if ($request->receiver_latitude && $request->receiver_longitude) {
            $point = new Point($request->receiver_latitude, $request->receiver_longitude);
            $zone = Zone::contains('coordinates', $point)->latest()->first();
            if (!$zone) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Out of coverage!',
                ], 403);
            }
        }

        //Calc distance
        $mapApiKeyServer = BusinessSetting::where(['key'=>'map_api_key_server'])->first();
        $mapApiKeyServer = $mapApiKeyServer ? $mapApiKeyServer->value : null;
        $mapApiKey = $mapApiKeyServer;
        $response = Http::get('https://maps.googleapis.com/maps/api/distancematrix/json?origins='.$request['source_latitude'].','.$request['source_longitude'].'&destinations='.$request['receiver_latitude'].','.$request['receiver_longitude'].'&key='.$mapApiKey.'&mode=driving');
        $response = json_decode($response);
        $distance = $response->rows[0]->elements[0]->distance->value;
        $distance = (double) str_replace('.', '', sprintf('%.1f', $distance / 1000 ) . '00' );
        $distance = $distance / 1000;

        //Calc order amount & delivery charge
        $parcelCategory = ParcelCategory::findOrFail($parcelCategoryId);
        if ($parcelCategory->parcel_per_km_shipping_charge && $parcelCategory->parcel_minimum_shipping_charge) {
            $parcelPerKmShippingCharge = $parcelCategory->parcel_per_km_shipping_charge;
            $parcelMinimumShippingCharge = $parcelCategory->parcel_minimum_shipping_charge;
        } else {
            $parcelPerKmShippingCharge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
            $parcelMinimumShippingCharge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
        }
        $originalDeliveryCharge = ($distance * $parcelPerKmShippingCharge > $parcelMinimumShippingCharge) ? $distance * $parcelPerKmShippingCharge + $extraCharges : $parcelMinimumShippingCharge;

        //Fix price
        $originalDeliveryCharge = $this->fixPrice($originalDeliveryCharge);
        $deliveryCharge = $originalDeliveryCharge;

        $order = new Order();
        $order->id = Order::generateOrderId();
        $order->user_id = $userId;
        $order->payment_status = 'unpaid';
        $order->order_status = 'pending';
        $order->coupon_code = null;
        $order->payment_method = $paymentMethod;
        $order->transaction_reference = null;
        $order->order_note = null;
        $order->order_type = $orderType;
        $order->store_id = null;
        $order->delivery_charge = round($deliveryCharge, config('round_up_to_digit')) ?? 0;
        $order->original_delivery_charge = round($originalDeliveryCharge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = now();
        $order->scheduled = 0;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : 1;
        $order->module_id = 3;
        $order->parcel_category_id = $parcelCategoryId;
        $order->receiver_details = $receiverDetails;
        $order->dm_vehicle_id = null;
        $order->pending = now();
        $order->order_attachment = null;
        $order->distance = $distance;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = $chargePayer;
        $order->is_read = 0;
        $order->admin_id = 0;
        $order->general_store_id = null;
        $order->coupon_info = null;
        $order->dm_tips = 0;
        $order->order_amount = round($order->delivery_charge, config('round_up_to_digit'));
        $order->coupon_created_by = null;
        $order->coupon_discount_title = '';
        $order->free_delivery_by = null;
        $order->order_description = $request->order_description;
        $order->api_subscription_id = $subscription->id;
        $order->api_subscription_info = json_encode($subscription);

        try {
            DB::beginTransaction();
            $order->save();
            $customer = $this->getUser($request);
            $customer->zone_id = $order->zone_id;
            $customer->save();
            DB::commit();
            Helpers::send_order_notification($order);
            return response()->json([
                'status'  => true,
                'message' => 'Your order has been sent successfully, Your order will not begin delivery until it is approved from one of the postajjieen.',
                'order_id' => $order->id,
                'total_amount' => $order->order_amount
            ], 200);
        } catch (\Exception $e) {
            Log::info($e);
            DB::rollBack();
            return response()->json([
                'status'  => false,
                'message' => $e,
            ], 403);
        }
    }

    public function fixPrice($price){
        if($price % 1000 == 0) return $price;
        $price = $price / 500;
        $price = ((int)$price) + 1;
        if($price % 2 != 0){
            $price += 1;
        }
        return $price * 500;
    }

    public function deliverItems(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $request->validate([
                'api_key'    => 'required|string',
                'secret_key' => 'required|string',
                'items'      => 'required|array|min:1',
                'items.*.id' => 'required|integer|distinct',
                'items.*.quantity' => 'required|integer|min:1',
                'client_first_name' => 'required|string',
                'client_last_name' => 'nullable|string',
                'phone' => [
                    'required',
                    'string',
                    'regex:/^\+9639\d{8}$/'
                ],
                'receiver_address' => 'required',
                'receiver_latitude' => 'required',
                'receiver_longitude' => 'required',
            ], [
                'items.required' => 'The items field is required.',
                'items.array' => 'The items field must be an array.',
                'items.*.id.required' => 'Each item must have an ID.',
                'items.*.id.integer' => 'Each item ID must be a number.',
                'items.*.id.distinct' => 'Duplicate item IDs are not allowed.',
                'items.*.quantity.required' => 'Each item must have a quantity.',
                'items.*.quantity.integer' => 'The quantity must be a number.',
                'items.*.quantity.min' => 'The quantity must be at least 1.',
            ]);

            $subscription = ApiSubscription::where('api_key', $request->api_key)
                ->where('secret_key', $request->secret_key)
                ->first();

            if (!$subscription) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Invalid API credentials.',
                ], 401);
            }

            $today = now()->toDateString();

            if ($subscription->status != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is inactive!',
                ], 403);
            }

            if ($subscription->start_date > $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription has not started yet!',
                ], 403);
            }

            if ($subscription->end_date < $today) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your subscription is expired!',
                ], 403);
            }

            if ($subscription->delivery != 1) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Your current subscription plan does not include access to delivery!',
                ], 403);
            }

            return $this->createItemsOrder($request, $subscription);

        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'status'  => false,
                'message' => 'Validation error.',
                'errors'  => $e->errors(),
            ], 422);

        } catch (\Exception $e) {
            Log::error('API Error in delivery: ' . $e->getMessage());

            return response()->json([
                'status'  => false,
                'message' => 'An unexpected error occurred. Please try again later.' . $e->getMessage(),
            ], 500);
        }
    }

    public function createItemsOrder($request, $subscription): \Illuminate\Http\JsonResponse
    {
        $paymentMethod = 'cash_on_delivery';
        $orderType = 'delivery';
        $chargePayer = 'receiver';
        $userId = $this->getUser($request)->id;
        $extraCharges = 0;
        $itemsArray = $request->items;
        $schedule_at = now();

        $itemIdsArray = collect($itemsArray)->pluck('id')->toArray();
        $items = Item::active()->whereIn('id', $itemIdsArray)->get();
        if ($items->count() !== count($itemIdsArray)) {
            return response()->json(['error' => 'Some items not exists or not active!'], 404);
        }
        $storeIds = $items->pluck('store_id')->unique();
        if ($storeIds->count() > 1) {
            return response()->json(['error' => 'Items are not all from the same store!'], 400);
        }
        $storeId = $storeIds->first();
        $store = Store::with('discount')->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open')->where('id', $storeId)->first();
        if (!$store) {
            return response()->json(['error' => 'Store not found!'], 404);
        }
        if ($store->open == false) {
            return response()->json(['error' => 'Store is closed at order time!'], 406);
        }
        $moduleId = $store->module_id;
        $address = [
            'contact_person_name' => trim($request->client_first_name . ' ' . $request->client_last_name),
            'contact_person_number' => $request->phone,
            'address_type' => 'Delivery',
            'address' => $store->address,
            'floor' => null,
            'road' => null,
            'house' => null,
            'longitude' => (string)$store->longitude,
            'latitude' => (string)$store->latitude,
        ];
        $receiverDetails = [
            'id' => null,
            'address_type' => 'others',
            'contact_person_name' => trim($request->client_first_name . ' ' . $request->client_last_name),
            'contact_person_number' => $request->phone,
            'address' => $request->receiver_address,
            'additional_address' => null,
            'latitude' => $request->receiver_latitude,
            'longitude' => $request->receiver_longitude,
            'zone_id' => null,
            'zone_ids' => null,
            '_method' => null,
            'area_ids' => null,
            'road' => null,
            'house' => null,
            'floor' => null,
        ];

        /*$currentOrder = Order::where('user_id', $userId)->whereIn('order_status', ['pending', 'accepted', 'confirmed', 'processing', 'handover'])->first();
        if($currentOrder){
            return response()->json([
                'status'  => false,
                'message' => 'You have an active order now!',
            ], 406);
        }*/

        $zone = null;
        if ($request->receiver_latitude && $request->receiver_longitude) {
            $point = new Point($request->receiver_latitude, $request->receiver_longitude);
            $zone = Zone::contains('coordinates', $point)->latest()->first();
            if (!$zone) {
                return response()->json([
                    'status'  => false,
                    'message' => 'Out of coverage!',
                ], 403);
            }
        }

        //Calc distance
        $mapApiKeyServer = BusinessSetting::where(['key'=>'map_api_key_server'])->first();
        $mapApiKeyServer = $mapApiKeyServer ? $mapApiKeyServer->value : null;
        $mapApiKey = $mapApiKeyServer;
        $response = Http::get('https://maps.googleapis.com/maps/api/distancematrix/json?origins='.$store->latitude.','.$store->longitude.'&destinations='.$request['receiver_latitude'].','.$request['receiver_longitude'].'&key='.$mapApiKey.'&mode=driving');
        $response = json_decode($response);
        $distance = $response->rows[0]->elements[0]->distance->value;
        if (!$response) {
            return response()->json([
                'status' => false,
                'message' => 'Could not calculate delivery distance. Please check the coordinates.',
            ], 500);
        }
        $distance = (double) str_replace('.', '', sprintf('%.1f', $distance / 1000 ) . '00' );
        $distance = $distance / 1000;

        //Calc delivery charge
        $parcelCategory = ParcelCategory::findOrFail(5);
        if ($parcelCategory->parcel_per_km_shipping_charge && $parcelCategory->parcel_minimum_shipping_charge) {
            $perKmShippingCharge = $parcelCategory->parcel_per_km_shipping_charge;
            $minimumShippingCharge = $parcelCategory->parcel_minimum_shipping_charge;
        } else {
            $perKmShippingCharge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
            $minimumShippingCharge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
        }
        $originalDeliveryCharge = ($distance * $perKmShippingCharge > $minimumShippingCharge) ? $distance * $perKmShippingCharge + $extraCharges : $minimumShippingCharge;

        //Fix price
        $originalDeliveryCharge = $this->fixPrice($originalDeliveryCharge);
        $deliveryCharge = $originalDeliveryCharge;

        $product_price = 0;
        $store_discount_amount = 0;
        $product_data = [];
        $order_details = [];

        $orderId = Order::generateOrderId();

        $order = new Order();
        $order->id = $orderId;
        $order->user_id = $userId;
        $order->payment_status = 'unpaid';
        $order->order_status = 'pending';
        $order->coupon_code = null;
        $order->payment_method = $paymentMethod;
        $order->transaction_reference = null;
        $order->order_note = null;
        $order->order_type = $orderType;
        $order->store_id = $storeId;
        $order->delivery_charge = round($deliveryCharge, config('round_up_to_digit')) ?? 0;
        $order->original_delivery_charge = round($originalDeliveryCharge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = now();
        $order->scheduled = 0;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : 1;
        $order->module_id = $moduleId;
        $order->parcel_category_id = 5;
        $order->receiver_details = $receiverDetails;
        $order->dm_vehicle_id = null;
        $order->pending = now();
        $order->order_attachment = null;
        $order->distance = $distance;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = $chargePayer;
        $order->is_read = 0;
        $order->admin_id = 0;
        $order->general_store_id = null;
        $order->coupon_info = null;
        $order->dm_tips = 0;
        $order->coupon_created_by = null;
        $order->coupon_discount_title = '';
        $order->free_delivery_by = null;
        $order->api_subscription_id = $subscription->id;
        $order->api_subscription_info = json_encode($subscription);

        foreach ($itemsArray as $c) {
            $product = Item::with('module')->active()->find($c['id']);
            if ($product) {
                $price = $product['price'];
                $product->tax = $store->tax;
                $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                $or_d = [
                    'item_id' => $c['id'],
                    'item_campaign_id' => null,
                    'item_details' => json_encode($product),
                    'quantity' => $c['quantity'],
                    'price' => round($price, config('round_up_to_digit')),
                    'tax_amount' => round(Helpers::tax_calculate($product, $price), config('round_up_to_digit')),
                    'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store),
                    'discount_type' => 'discount_on_product',
                    'variant' => '""',
                    'variation' => '[]',
                    'add_ons' => '[]',
                    'total_add_on_price' => 0,
                    'created_at' => now(),
                    'updated_at' => now()
                ];
                $product_price += $price * $or_d['quantity'];
                $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                $order_details[] = $or_d;

            } else {
                return response()->json(['error' => 'Some items not exists or not active!'], 404);
            }
        }
        $order->discount_on_product_by = 'vendor';
        $store_discount = Helpers::get_store_discount($store);
        if (isset($store_discount)) {
            $order->discount_on_product_by = 'admin';
        }

        $tax = ($store->tax > 0) ? $store->tax : 0;
        $order->tax_status = 'excluded';

        $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ?  BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0;
        if ($tax_included ==  1) {
            $order->tax_status = 'included';
        }

        $total_tax_amount = Helpers::product_tax(($product_price - $store_discount_amount), $tax, $order->tax_status == 'included');

        $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount;

        if ($store->minimum_order > $product_price) {
            return response()->json(['error' => 'You need to order at least ' . $store->minimum_order], 406);
        }

        $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value;
        if (isset($free_delivery_over)) {
            if ($free_delivery_over <= $product_price - $store_discount_amount) {
                $order->delivery_charge = 0;
                $free_delivery_by = 'admin';
            }
        }
        $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit'));
        $order->total_tax_amount = round($total_tax_amount, config('round_up_to_digit'));
        $order->order_amount = round(($product_price - $store_discount_amount), config('round_up_to_digit'));

        foreach ($order_details as $key => $item) {
            $name = item::where('id',$order_details[$key]['item_id'])->first();
            $translate = DB::table('translations')->where('translationable_type', 'App\Models\Item')->where('translationable_id', $name['id'])->where('key', 'name')->first();
            $arName = isset($translate->value) ? $translate->value : $name->name;
            $order_items[] = $arName;
        }
        $order->order_description=  implode(",",$order_items);

        try {
            DB::beginTransaction();
            $order->save();

            foreach ($order_details as $key => $item) {
                $order_details[$key]['order_id'] = $order->id;
            }
            OrderDetail::insert($order_details);
            if (count($product_data) > 0) {
                foreach ($product_data as $item) {
                    ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save();
                }
            }
            $store->increment('total_order');

            $customer = $this->getUser($request);
            $customer->zone_id = $order->zone_id;
            $customer->save();
            DB::commit();
            Helpers::send_order_notification($order);
            return response()->json([
                'status'  => true,
                'message' => 'Your order has been sent successfully, Your order will not begin delivery until it is approved from one of the postajjieen.',
                'order_id' => $order->id,
                'sub_total' => $product_price,
                'discount' => $store_discount_amount,
                'tax' => $order->total_tax_amount,
                'delivery_fee' => $deliveryCharge,
                'total_amount' => $order->order_amount + $order->total_tax_amount + $deliveryCharge,
            ], 200);
        } catch (\Exception $e) {
            Log::info($e);
            DB::rollBack();
            return response()->json([
                'status'  => false,
                'message' => $e,
            ], 403);
        }
    }

    public function orderDetails(Request $request): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'api_key'    => 'required|string',
            'secret_key' => 'required|string',
            'order_id' => 'required|numeric',
        ]);

        $subscription = ApiSubscription::where('api_key', $request->api_key)
            ->where('secret_key', $request->secret_key)
            ->first();

        if (!$subscription) {
            return response()->json([
                'status'  => false,
                'message' => 'Invalid API credentials.',
            ], 401);
        }

        $today = now()->toDateString();

        if ($subscription->status != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is inactive!',
            ], 403);
        }

        if ($subscription->start_date > $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription has not started yet!',
            ], 403);
        }

        if ($subscription->end_date < $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is expired!',
            ], 403);
        }

        if ($subscription->delivery != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your current subscription plan does not include access to delivery!',
            ], 403);
        }

        $order_id = $request->order_id;

        $order = Order::select('id', 'order_status', 'total_tax_amount', 'delivery_charge', 'pending', 'accepted', 'delivered', 'canceled', 'cancellation_reason', 'distance', 'order_description')->where('id', $order_id)->where('api_subscription_id', $subscription->id)->first();
        if($order){
            return response()->json([
                'status'  => true,
                'order' => $order,
            ], 200);
        }else{
            return response()->json([
                'status'  => false,
                'message' => 'Order not found!',
            ], 404);
        }
    }

    public function ordersList(Request $request): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'api_key'    => 'required|string',
            'secret_key' => 'required|string',
        ]);

        $subscription = ApiSubscription::where('api_key', $request->api_key)
            ->where('secret_key', $request->secret_key)
            ->first();

        if (!$subscription) {
            return response()->json([
                'status'  => false,
                'message' => 'Invalid API credentials.',
            ], 401);
        }

        $today = now()->toDateString();

        if ($subscription->status != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is inactive!',
            ], 403);
        }

        if ($subscription->start_date > $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription has not started yet!',
            ], 403);
        }

        if ($subscription->end_date < $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is expired!',
            ], 403);
        }

        if ($subscription->delivery != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your current subscription plan does not include access to delivery!',
            ], 403);
        }

        $orders = Order::select('id', 'order_status', 'total_tax_amount', 'delivery_charge', 'pending', 'accepted', 'delivered', 'canceled', 'cancellation_reason', 'distance', 'order_description')->where('api_subscription_id', $subscription->id)->get();

        if ($orders->isEmpty()) {
            return response()->json([
                'status'  => false,
                'message' => 'No orders found!',
            ], 404);
        }

        return response()->json([
            'status' => true,
            'orders' => $orders,
        ]);
    }

    public function checkCoordinates(Request $request): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'api_key'    => 'required|string',
            'secret_key' => 'required|string',
            'receiver_latitude' => 'required',
            'receiver_longitude' => 'required',
        ]);

        $subscription = ApiSubscription::where('api_key', $request->api_key)
            ->where('secret_key', $request->secret_key)
            ->first();

        if (!$subscription) {
            return response()->json([
                'status'  => false,
                'message' => 'Invalid API credentials.',
            ], 401);
        }

        $today = now()->toDateString();

        if ($subscription->status != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is inactive!',
            ], 403);
        }

        if ($subscription->start_date > $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription has not started yet!',
            ], 403);
        }

        if ($subscription->end_date < $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is expired!',
            ], 403);
        }

        $zone = null;
        $point = new Point($request->receiver_latitude, $request->receiver_longitude);
        $zone = Zone::contains('coordinates', $point)->latest()->first();
        if (!$zone) {
            return response()->json([
                'status'  => false,
                'message' => 'Out of coverage!',
            ], 403);
        }

        return response()->json([
            'status'  => true,
            'message' => 'We cover this address.',
        ], 200);
    }

    public function cancelOrder(Request $request): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'api_key'    => 'required|string',
            'secret_key' => 'required|string',
            'order_id' => 'required|numeric',
            'reason' => 'required|max:255'
        ]);

        $subscription = ApiSubscription::where('api_key', $request->api_key)
            ->where('secret_key', $request->secret_key)
            ->first();

        if (!$subscription) {
            return response()->json([
                'status'  => false,
                'message' => 'Invalid API credentials.',
            ], 401);
        }

        $today = now()->toDateString();

        if ($subscription->status != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is inactive!',
            ], 403);
        }

        if ($subscription->start_date > $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription has not started yet!',
            ], 403);
        }

        if ($subscription->end_date < $today) {
            return response()->json([
                'status'  => false,
                'message' => 'Your subscription is expired!',
            ], 403);
        }

        if ($subscription->delivery != 1) {
            return response()->json([
                'status'  => false,
                'message' => 'Your current subscription plan does not include access to delivery!',
            ], 403);
        }

        $order_id = $request->order_id;

        $order = Order::select('id', 'order_status', 'total_tax_amount', 'delivery_charge', 'pending', 'accepted', 'delivered', 'canceled', 'cancellation_reason', 'distance', 'order_description')->where('id', $order_id)->where('api_subscription_id', $subscription->id)->first();
        if($order){
            if ($order->order_status == 'pending' || $order->order_status == 'failed'|| $order->order_status == 'canceled') {
                if (count($order->details) > 0) {
                    foreach ($order->details as $detail) {
                        $variant = json_decode($detail['variation'], true);
                        $item = $detail->item;
                        if ($detail->campaign) {
                            $item = $detail->campaign;
                        }
                        ProductLogic::update_stock($item, -$detail->quantity, count($variant) ? $variant[0]['type'] : null)->save();
                    }
                }
                $order->order_status = 'canceled';
                $order->canceled = now();
                $order->cancellation_reason = $request->reason;
                $order->canceled_by = 'customer';
                $order->save();
                Helpers::send_order_notification($order);
                return response()->json([
                    'status'  => true,
                    'message'  => 'Order canceled successfully.',
                ], 200);
            }else{
                return response()->json([
                    'status'  => false,
                    'message'  => 'Can not cancel order not pending!',
                ], 403);
            }
        }else{
            return response()->json([
                'status'  => false,
                'message' => 'Order not found!',
            ], 404);
        }
    }

}
