<?php

namespace App\Http\Controllers\Api\V1;

ini_set('memory_limit', '-1');

use App\CentralLogics\Helpers;
use App\CentralLogics\OrderLogic;
use App\CentralLogics\SMS_module;
use App\Http\Controllers\Controller;
use App\Models\AccountTransaction;
use App\Models\Admin;
use App\Models\AdminWallet;
use App\Models\BusinessSetting;
use App\Models\Conversation;
use App\Models\DeliveryHistory;
use App\Models\DeliveryMan;
use App\Models\DeliveryManBonus;
use App\Models\DMBoost;
use App\Models\DMLog;
use App\Models\DMMonthlySubscription;
use App\Models\Message;
use App\Models\Order;
use App\Models\Notification;
use App\Models\Store;
use App\Models\Translation;
use App\Models\UserNotification;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;

// Carbon::setWeekStartsAt(Carbon::SUNDAY);
// Carbon::setWeekEndsAt(Carbon::SATURDAY);


class DeliverymanController extends Controller
{

    public function get_profile(Request $request)
    {
        $dm = DeliveryMan::with(['rating'])->where(['auth_token' => $request['token']])->first();
        $dm['avg_rating'] = (double)(!empty($dm->rating[0])?$dm->rating[0]->average:0);
        $dm['rating_count'] = (double)(!empty($dm->rating[0])?$dm->rating[0]->rating_count:0);
        $dm['order_count'] =(integer)$dm->orders->count();
        $dm['todays_order_count'] =(integer)$dm->todaysorders->count();
        $dm['this_week_order_count'] =(integer)$dm->this_week_orders->count();
        $dm['member_since_days'] =(integer)$dm->created_at->diffInDays();
        $dm['cash_in_hands'] =$dm->wallet?$dm->wallet->collected_cash:0;
        $dm['balance'] = $dm->wallet?$dm->wallet->total_earning - $dm->wallet->total_withdrawn:0;
        //Added DM TIPS
        $dm['todays_earning'] =(float)($dm->todays_earning()->sum('original_delivery_charge') + $dm->todays_earning()->sum('dm_tips'));
        $dm['this_week_earning'] =(float)($dm->this_week_earning()->sum('original_delivery_charge') + $dm->this_week_earning()->sum('dm_tips'));
        $dm['this_month_earning'] =(float)($dm->this_month_earning()->sum('original_delivery_charge') + $dm->this_month_earning()->sum('dm_tips'));

        $totalEarning = [
            'total' => number_format(DeliveryMan::getTotalEarning($dm, '', ''), config('round_up_to_digit')),
            'today' => number_format(DeliveryMan::getTotalEarning($dm, date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')), config('round_up_to_digit')),
            'month' => number_format(DeliveryMan::getTotalEarning($dm, date('Y-m-01 00:00:00'), date('Y-m-t 23:59:59')), config('round_up_to_digit')),
        ];
        $ordersCount = [
            'total' => (string)DeliveryMan::getCountOfOrders($dm, '', ''),
            'today' => (string)DeliveryMan::getCountOfOrders($dm, date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')),
            'month' => (string)DeliveryMan::getCountOfOrders($dm, date('Y-m-01 00:00:00'), date('Y-m-t 23:59:59')),
        ];
        $companyDues = [
            'total' => number_format(DeliveryMan::getTheRemainingBalanceForDeliveryMan($dm, '', ''), config('round_up_to_digit')),
            'today' => number_format(DeliveryMan::getTheRemainingBalanceForDeliveryMan($dm, date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')), config('round_up_to_digit')),
            'month' => number_format(DeliveryMan::getTheRemainingBalanceForDeliveryMan($dm, date('Y-m-01 00:00:00'), date('Y-m-t 23:59:59')), config('round_up_to_digit')),
        ];

        $dm['total_earning'] = $totalEarning;
        $dm['orders_count'] = $ordersCount;
        $dm['company_dues'] = $companyDues;

        $DMMonthlySubscriptionAmount = BusinessSetting::where('key', 'd_m_monthly_subscription_amount')->first();
        $isHaveActiveMonthlySubscription = DeliveryMan::isHaveActiveMonthlySubscription($dm->id);
        $dm['subscription_amount'] = $DMMonthlySubscriptionAmount->value;
        $dm['is_have_active_monthly_subscription'] = (bool)$isHaveActiveMonthlySubscription;
        $dm['subscription_start_at'] = null;
        $dm['subscription_end_at'] = null;
        if($isHaveActiveMonthlySubscription){
            $currentTime = Carbon::now();
            $getSubscriptionInfo = DMMonthlySubscription::where('delivery_man_id', $dm->id)
                ->where('start_at', '<=', $currentTime)
                ->where('end_at', '>=', $currentTime)
                ->first();
            if($getSubscriptionInfo){
                $dm['subscription_start_at'] = $getSubscriptionInfo->start_at;
                $dm['subscription_end_at'] = $getSubscriptionInfo->end_at;
            }
        }

        unset($dm['orders']);
        unset($dm['rating']);
        unset($dm['todaysorders']);
        unset($dm['this_week_orders']);
        unset($dm['wallet']);
        return response()->json($dm, 200);
    }

    public function update_profile(Request $request)
    {
        $dm = DeliveryMan::with(['rating'])->where(['auth_token' => $request['token']])->first();
        $validator = Validator::make($request->all(), [
            'f_name' => 'required',
            'l_name' => 'required',
            'email' => 'nullable|unique:delivery_men,email,'.$dm->id,
            'password'=>'nullable|min:6',
        ], [
            'f_name.required' => 'First name is required!',
            'l_name.required' => 'Last name is required!',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

//        $image = $request->file('image');

//        if ($request->has('image')) {
//            $imageName = Helpers::update('delivery-man/', $dm->image, 'png', $request->file('image'));
//        } else {
//            $imageName = $dm->image;
//        }

        if ($request['password'] != null && strlen($request['password']) > 5) {
            $pass = bcrypt($request['password']);
        } else {
            $pass = $dm->password;
        }

        $dm->vehicle_id = $request->vehicle_id ??  $dm->vehicle_id ?? null;

        $dm->f_name = $request->f_name;
        $dm->l_name = $request->l_name;
        $dm->email = $request->email;
//        $dm->image = $imageName;
        $dm->password = $pass;
        $dm->updated_at = now();
        $dm->save();

        if($dm->userinfo) {
            $userinfo = $dm->userinfo;
            $userinfo->f_name = $request->f_name;
            $userinfo->l_name = $request->l_name;
            $userinfo->email = $request->email;
//            $userinfo->image = $imageName;
            $userinfo->save();
        }

        return response()->json(['message' => 'successfully updated!'], 200);
    }

    public function activeStatus(Request $request)
    {
        $dm = DeliveryMan::with(['rating'])->where(['auth_token' => $request['token']])->first();
        $dm->active = $dm->active?0:1;
        $dm->save();
        return response()->json(['message' => translate('messages.active_status_updated')], 200);
    }

    public function get_current_orders(Request $request)
    {
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();
        $orders = Order::with(['customer', 'store','parcel_category','details'])
            ->whereIn('order_status', ['accepted','confirmed','pending', 'processing', 'picked_up', 'handover'])
            ->where(['delivery_man_id' => $dm['id']])
            ->orderBy('accepted')
            ->orderBy('schedule_at', 'desc')
            ->dmOrder()
            ->get();
        $orders= Helpers::order_data_formatting($orders, true);
        return response()->json($orders, 200);
    }

    public function get_latest_orders(Request $request)
    {
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $orders = Order::with(['customer', 'store','parcel_category','details']);

        if($dm->type == 'zone_wise')
        {
            $orders = $orders->where('zone_id', $dm->zone_id);
            //->where(function($query){
            //    $query->whereNull('store_id')->orWhereHas('store',function($q){
            //        $q->where('self_delivery_system','0');
            //    });
            //});
        }
        else
        {
            $orders = $orders->where('store_id', $dm->store_id);
        }

        if(config('order_confirmation_model') == 'deliveryman' && $dm->type == 'zone_wise')
        {
            $orders = $orders->whereIn('order_status', ['pending', 'confirmed','processing','handover']);
        }
        else
        {
            $orders = $orders->where(function($query){
                $query->whereIn('order_status', ['confirmed','processing','handover'])->orWhere('order_type','parcel');
            });
        }
        if(isset($dm->vehicle_id )){
            //$orders = $orders->where('dm_vehicle_id',$dm->vehicle_id);
        }
        $orders = $orders//->dmOrder()
            ->Notpos()
            ->OrderScheduledIn(30)
            ->whereNull('delivery_man_id')
            ->orderBy('schedule_at', 'desc')
            ->get();
        $orders = Helpers::order_data_formatting($orders, true);
        return response()->json($orders, 200);
    }

    public function accept_order(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required|exists:orders,id',
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $dm=DeliveryMan::where(['auth_token' => $request['token']])->first();
        $order = Order::where('id', $request['order_id'])
            // ->whereIn('order_status', ['pending', 'confirmed'])
            ->whereNull('delivery_man_id')
            ->dmOrder()
            ->first();
        if(!$order)
        {
            return response()->json([
                'errors' => [
                    ['code' => 'order', 'message' => translate('messages.can_not_accept')]
                ]
            ], 404);
        }
        //if($dm->current_orders >= config('dm_maximum_orders'))
        if(DeliveryMan::getCurrentOrdersCount($dm) >= config('dm_maximum_orders'))
        {
            return response()->json([
                'errors'=>[
                    ['code' => 'dm_maximum_order_exceed', 'message'=> translate('messages.dm_maximum_order_exceed_warning')]
                ]
            ], 405);
        }
        //Check if the delivery man account is enabled
        if($dm->status == '0')
        {
            return response()->json([
                'errors'=>[
                    ['code' => 'dm_suspended', 'message'=> translate('messages.your_account_is_suspended')]
                ]
            ], 405);
        }
        //Check if the Remaining balance > 0 in the delivery man account
        if((DeliveryMan::getTheRemainingBalanceForDeliveryMan($dm, '', '') >= 0 && $dm->earning == '1') && !DeliveryMan::isHaveActiveMonthlySubscription($dm->id))
        {
            return response()->json([
                'errors'=>[
                    ['code' => 'dm_remaining_balance', 'message'=> translate('messages.please_contact_with_administrator_to_pay_the_financial_dues')]
                ]
            ], 405);
        }
        if($order->order_type == 'parcel' && $order->order_status=='confirmed')
        {
            $order->order_status = 'handover';
            $order->handover = now();
            $order->processing = now();
        }
        else{
            $order->order_status = in_array($order->order_status, ['pending', 'confirmed'])?'accepted':$order->order_status;
        }

        if(isset($request->distance_between_dm_and_source_location) and !empty($request->distance_between_dm_and_source_location)){
            $order->distance_between_dm_and_source_location = $request->distance_between_dm_and_source_location;
        }

        $order->delivery_man_id = $dm->id;
        $order->accepted = now();
        $order->save();

        DMBoost::getBoost($dm, $order->id);

        $dm->current_orders = $dm->current_orders+1;
        $dm->save();

        $value = Helpers::order_status_update_message('accepted',$order->module->module_type,$order->customer?
            $order->customer->current_language_key:'ar');

        Order::sendSystemMessages($request['order_id']);

        $dm->increment('assigned_order_count');

        $fcm_token=$order->customer->cm_firebase_token;
        try {
            if($value)
            {
                $conversationId = Message::where('order_id', $order->id)->first()->conversation_id;
                $data = [
                    'title' => translate('messages.first_step'),
                    'description' => $value,
                    'order_id' => $order->id,
                    'image' => '',
                    'message' => json_encode($value),
                    'type' => 'message',
                    'conversation_id' => $conversationId,
                    'sender_type' => 'delivery_man'
                ];
                Helpers::send_push_notif_to_device($fcm_token, $data);
            }

        } catch (\Exception $e) {

        }

        //Send notification to store for new order
        if(isset($order->store) && !empty($order->store_id)) {
            Store::acceptOrderFromStore($order, false);
            Helpers::sendOrderNotificationToStore($order, 'طلب جديد', 'هناك طلب جديد، يرجى متابعته.');
        }

        return response()->json(['message' => translate('messages.order_accepted_successfully')], 200);

    }

    public function record_location_data(Request $request)
    {
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();
        DB::table('delivery_histories')->insert([
            'delivery_man_id' => $dm['id'],
            'longitude' => $request['longitude'],
            'latitude' => $request['latitude'],
            'time' => now(),
            'location' => $request['location'],
            'created_at' => now(),
            'updated_at' => now()
        ]);
        return response()->json(['message' => 'location recorded'], 200);
    }

    public function get_order_history(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $history = DeliveryHistory::where(['order_id' => $request['order_id'], 'delivery_man_id' => $dm['id']])->get();
        return response()->json($history, 200);
    }

    public function update_order_status(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required',
            'status' => 'required|in:confirmed,canceled,picked_up,delivered,handover',
            'reason' =>'required_if:status,canceled',
        ]);

        $validator->sometimes('otp', 'required', function ($request) {
            return (Config::get('order_delivery_verification')==1 && $request['status']=='delivered');
        });

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $order = Order::where(['id' => $request['order_id'], 'delivery_man_id' => $dm['id']])->dmOrder()->first();

        if($request['status'] =="confirmed" && config('order_confirmation_model') == 'store')
        {
            return response()->json([
                'errors' => [
                    ['code' => 'order-confirmation-model', 'message' => translate('messages.order_confirmation_warning')]
                ]
            ], 403);
        }

        if($request['status'] == 'canceled' && !config('canceled_by_deliveryman'))
        {
            return response()->json([
                'errors' => [
                    ['code' => 'status', 'message' => translate('messages.you_can_not_cancel_a_order')]
                ]
            ], 403);
        }

        if($order->confirmed && $request['status'] == 'canceled')
        {
            return response()->json([
                'errors' => [
                    ['code' => 'delivery-man', 'message' => translate('messages.order_can_not_cancle_after_confirm')]
                ]
            ], 403);
        }

        if(Config::get('order_delivery_verification')==1 && $order->payment_method=='cash_on_delivery' && $order->charge_payer=='sender' && $request['status']=='picked_up' && $order->otp != $request['otp'])
        {
            return response()->json([
                'errors' => [
                    ['code' => 'otp', 'message' => 'Not matched']
                ]
            ], 406);
        }

        if(Config::get('order_delivery_verification')==1 && $order->payment_method=='cash_on_delivery' &&  $request['status']=='delivered' && $order->otp != $request['otp'])
        {
            return response()->json([
                'errors' => [
                    ['code' => 'otp', 'message' => 'Not matched']
                ]
            ], 406);
        }

        try{

            if ($request->status == 'delivered')
            {
                if($order->transaction == null)
                {
                    $reveived_by = $order->payment_method == 'cash_on_delivery'?($dm->type != 'zone_wise'?'store':'deliveryman'):'admin';

                    if(OrderLogic::create_transaction($order,$reveived_by, null))
                    {
                        $order->payment_status = 'paid';
                    }
                    else
                    {
                        return response()->json([
                            'errors' => [
                                ['code' => 'error', 'message' => translate('messages.faield_to_create_order_transaction')]
                            ]
                        ], 406);
                    }
                }
                if($order->transaction)
                {
                    $order->transaction->update(['delivery_man_id'=>$dm->id]);
                }

                $order->details->each(function($item, $key){
                    if($item->food)
                    {
                        $item->food->increment('order_count');
                    }
                });
                $order->customer->increment('order_count');

                $dm->current_orders = $dm->current_orders>1?$dm->current_orders-1:0;
                $dm->save();

                $dm->increment('order_count');
                if($order->store)
                {
                    $order->store->increment('order_count');
                }
                if($order->parcel_category)
                {
                    $order->parcel_category->increment('orders_count');
                }

                $newLine = '
';
                $ratingMessage = 'تم توصيل طلبك رقم #' . $order->id . $newLine;

                if($order->order_type == 'parcel'){
                    $serviceTitle = 'اسم الخدمة: ';
                    $parcelCategoryId = $order->parcel_category_id;
                    $parcelCategoryName = Translation::where('translationable_type', 'App\Models\ParcelCategory')
                    ->where('translationable_id', $parcelCategoryId)
                    ->where('locale', 'ar')
                    ->where('key', 'name')
                    ->first();
                    if($parcelCategoryName){
                        $serviceName = $parcelCategoryName->value;
                    }else{
                        $serviceName = $order->parcel_category ? $order->parcel_category->name : 'توصيل';
                    }
                }else{
                    if($order->module_id == '1'){
                        $serviceTitle = 'اسم المطعم: ';
                    }else if($order->module_id == '50'){
                        $serviceTitle = 'اسم الماركت: ';
                    }else{
                        $serviceTitle = 'اسم المتجر: ';
                    }

                    $serviceName = $order->store->name ?? '------';
                }
                $ratingMessage .= $serviceTitle . $serviceName . $newLine;
                $ratingMessage .= 'تقييمك للخدمة يهمنا.. 💛' . $newLine;
                $ratingMessage .= 'ممتازة 🤩' . $newLine;
                $ratingMessage .= 'جيدة 😄' . $newLine;
                $ratingMessage .= 'سيئة ☹ ولماذا؟' . $newLine;
                $ratingMessage .= 'ماهو تقييمك للمندوب؟.. 💛' . $newLine;
                $ratingMessage .= 'ممتاز 🤩' . $newLine;
                $ratingMessage .= 'جيد 😄' . $newLine;
                $ratingMessage .= 'سيء☹ ولماذا؟' . $newLine;
                $ratingMessage .= $newLine;
                $ratingMessage .= 'هل واجهت أي مشكلة عند تجربتك للخدمة؟..💛';

                SMS_module::whatsApp($order->customer->phone, $ratingMessage);

            }
            else if($request->status == 'canceled')
            {
                if($order->delivery_man)
                {
                    $dm = $order->delivery_man;
                    $dm->current_orders = $dm->current_orders>1?$dm->current_orders-1:0;
                    $dm->save();
                }
                $order->cancellation_reason = $request->reason;
                $order->canceled_by = 'deliveryman';
            }
            else if($order->order_type == 'parcel' && $request->status == 'handover')
            {
                $order->confirmed = now();
                $order->processing = now();
            }

            $order->order_status = $request['status'];
            $order[$request['status']] = now();
            $order->save();

            if ($request->status == 'delivered') {
                DeliveryManBonus::addBonusForDeliveryMan($dm);
                Helpers::sendDeliveryChargeToCompaniesSystem($order->id);
            }

            $orderNotificationTitle = translate('messages.order_status_updated');
            $orderNotificationDescription = Helpers::order_status_update_message($order->order_status,$order->module->module_type,$order->customer?
                $order->customer->current_language_key:'ar') ?? '';
            $conversationId = Message::where('order_id', $order->id)->first()->conversation_id;

            if(in_array($order->order_status, ['accepted', 'confirmed'])){
                $orderNotificationTitle = 'المرحلة الأولى';
                if($order->order_type == 'parcel') {
                    $data = [
                        'title' => $orderNotificationTitle,
                        'description' => $orderNotificationDescription,
                        'order_id' => $order->id,
                        'image' => '',
                        'message' => json_encode($orderNotificationDescription),
                        'type' => 'message',
                        'conversation_id' => $conversationId,
                        'sender_type' => 'delivery_man'
                    ];
                }else{
                    $data = [
                        'title' => $orderNotificationTitle,
                        'description' => $orderNotificationDescription,
                        'order_id' => $order->id,
                        'module_id' => $order->module_id,
                        'order_type' => $order->order_type,
                        'image' => '',
                        'type' => 'new_order',
                        'sender_type' => 'delivery_man'
                    ];
                }
            }else if(in_array($order->order_status, ['processing', 'handover', 'picked_up'])){
                $orderNotificationTitle = 'المرحلة الثانية';
                $data = [
                    'title' => $orderNotificationTitle,
                    'description' => $orderNotificationDescription,
                    'order_id' => $order->id,
                    'image' => '',
                    'message' => json_encode($orderNotificationDescription),
                    'type' => 'message',
                    'conversation_id' => $conversationId,
                    'sender_type' => 'delivery_man'
                ];
            }else{ //($order->order_status == 'delivered'){
                $orderNotificationTitle = 'المرحلة الثالثة';
                //$data = [
                //    'title' => $orderNotificationTitle,
                //    'description' => $orderNotificationDescription,
                //    'order_id' => $order->id,
                //    'image' => '',
                //    'type' => 'order_status',
                //];
                $data = [
                    'title' => $orderNotificationTitle,
                    'description' => $orderNotificationDescription,
                    'order_id' => $order->id,
                    'image' => '',
                    'message' => json_encode($orderNotificationDescription),
                    'type' => 'message',
                    'conversation_id' => $conversationId,
                    'sender_type' => 'delivery_man'
                ];
            }

            Helpers::send_push_notif_to_device($order->customer->cm_firebase_token, $data);
            Helpers::sendNotificationToAPISubscriptionServer($order);
            DB::table('user_notifications')->insert([
                'data' => json_encode($data),
                'user_id' => $order->user_id,
                'created_at' => now(),
                'updated_at' => now()
            ]);

        }catch (\Exception $exception){
            return response()->json([
                'errors' => [
                    ['code' => 'error', 'message' => $exception->getMessage()]
                ]
            ], 406);
        }

        return response()->json(['message' => translate('messages.order_status_updated')], 200);
    }

    public function get_order_details(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        //$dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();
        $order = Order::with(['details'])->where('id',$request['order_id'])->where(function($query) use($dm){
            $query->WhereNull('delivery_man_id')
                ->orWhere('delivery_man_id', $dm['id']);
        })->Notpos()->first();
        if(!$order)
        {
            return response()->json([
                'errors' => [
                    ['code' => 'order', 'message' => translate('messages.not_found')]
                ]
            ], 404);
        }
        if(in_array($order->order_type, ['Whatsapp', 'Water', 'Store'])){
            $order->receiver_details = json_decode($order->receiver_details);
        }
        $details = isset($order->details)?$order->details:null;
        if ($details != null && $details->count() > 0) {
            $details = $details = Helpers::order_details_data_formatting($details);
            return response()->json($details, 200);
        } else if (in_array($order->order_type , ['parcel', 'Whatsapp', 'Water', 'Store']) || $order->prescription_order == 1) {
            $order->delivery_address = json_decode($order->delivery_address, true);
            return response()->json(($order), 200);
        }

        return response()->json([
            'errors' => [
                ['code' => 'order', 'message' => translate('messages.not_found')]
            ]
        ], 404);
    }

    public function get_order(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $order = Order::with(['customer', 'store','details','parcel_category'])->where(['delivery_man_id' => $dm['id'], 'id' => $request['order_id']])->Notpos()->first();
        if(!$order)
        {
            return response()->json([
                'errors' => [
                    ['code' => 'order', 'message' => translate('messages.not_found')]
                ]
            ], 204);
        }
        return response()->json(Helpers::order_data_formatting($order), 200);
    }

    public function get_any_order(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $order = Order::with(['customer', 'store', 'details','parcel_category'])->where(['id' => $request['order_id']])->Notpos()->first();
        if(!$order)
        {
            return response()->json([
                'errors' => [
                    ['code' => 'order', 'message' => translate('messages.not_found')]
                ]
            ], 204);
        }
        return response()->json(Helpers::order_data_formatting($order), 200);
    }

    public function get_all_orders(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'limit' => 'required',
            'offset' => 'required',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $paginator = Order::with(['customer', 'store', 'parcel_category','details'])
//        $paginator = Order::with(['customer' =>function($query){
//        $query->select('id',DB::raw("SUBSTRING(f_name, 1, 1) as f_name"),DB::raw("SUBSTRING(l_name, 1, 1) as l_name"),
//            'phone','email','image','is_phone_verified','email_verified_at',
//            'created_at','updated_at','cm_firebase_token','status','order_count',
//            'login_medium','social_id','zone_id','wallet_balance','loyalty_point',
//            'ref_code','current_language_key','ref_by','temp_token');}, 'store', 'parcel_category','details'])
            ->where(['delivery_man_id' => $dm['id']])
            ->whereIn('order_status', ['delivered','canceled','refund_requested','refunded','failed'])
            ->orderBy('schedule_at', 'desc')
            //->dmOrder()
            ->paginate($request['limit'], ['*'], 'page', $request['offset']);
        $orders= Helpers::order_data_formatting($paginator->items(), true);
        $data = [
            'total_size' => $paginator->total(),
            'limit' => $request['limit'],
            'offset' => $request['offset'],
            'orders' => $orders
        ];
        return response()->json($data, 200);
    }

    public function get_last_location(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $last_data = DeliveryHistory::whereHas('delivery_man.orders', function($query) use($request){
            return $query->where('id',$request->order_id);
        })->latest()->first();
        return response()->json($last_data, 200);
    }

    public function order_payment_status_update(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required',
            'status' => 'required|in:paid'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        if (Order::where(['delivery_man_id' => $dm['id'], 'id' => $request['order_id']])->dmOrder()->first()) {
            Order::where(['delivery_man_id' => $dm['id'], 'id' => $request['order_id']])->update([
                'payment_status' => $request['status']
            ]);
            return response()->json(['message' => 'Payment status updated'], 200);
        }
        return response()->json([
            'errors' => [
                ['code' => 'order', 'message' => 'not found!']
            ]
        ], 404);
    }

    public function update_fcm_token(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'fcm_token' => 'required'
        ]);
        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        DeliveryMan::where(['id' => $dm['id']])->update([
            'fcm_token' => $request['fcm_token']
        ]);

        return response()->json(['message'=>'successfully updated!'], 200);
    }

    public function get_notifications(Request $request){

        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        $notifications = Notification::active()->where(function($q) use($dm){
            $q->whereNull('zone_id')->orWhere('zone_id', $dm->zone_id);
        })->where('tergat', 'deliveryman')->where('created_at', '>=', \Carbon\Carbon::today()->subDays(7))->get();

        $user_notifications = UserNotification::where('delivery_man_id', $dm->id)->where('created_at', '>=', \Carbon\Carbon::today()->subDays(7))->get();

        $notifications->append('data');

        $notifications =  $notifications->merge($user_notifications);
        try {
            return response()->json($notifications, 200);
        } catch (\Exception $e) {
            return response()->json([], 200);
        }
    }

    public function remove_account(Request $request)
    {
        $dm = DeliveryMan::where(['auth_token' => $request['token']])->first();

        if(Order::where('delivery_man_id', $dm->id)->whereIn('order_status', ['pending','accepted','confirmed','processing','handover','picked_up'])->count())
        {
            return response()->json(['errors'=>[['code'=>'on-going', 'message'=>translate('messages.user_account_delete_warning')]]],203);
        }

        if($dm->wallet && $dm->wallet->collected_cash > 0)
        {
            return response()->json(['errors'=>[['code'=>'on-going', 'message'=>translate('messages.user_account_wallet_delete_warning')]]],203);
        }

        if (Storage::disk('public')->exists('delivery-man/' . $dm['image'])) {
            Storage::disk('public')->delete('delivery-man/' . $dm['image']);
        }

        foreach (json_decode($dm['identity_image'], true) as $img) {
            if (Storage::disk('public')->exists('delivery-man/' . $img)) {
                Storage::disk('public')->delete('delivery-man/' . $img);
            }
        }
        /*if($dm->userinfo){

            $dm->userinfo->delete();
        }
        $dm->delete();*/

        $dm->userinfo->phone = $dm->userinfo->phone . '-Deleted';
        $dm->userinfo->password = 'Deleted';
        $dm->userinfo->save();

        $dm->phone = $dm->phone . '-Deleted';
        $dm->password = 'Deleted';
        $dm->save();

        return response()->json([]);
    }

    public function add_order_invoice(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'order_id' => 'required',
            'total_invoice' => 'required',
            'invoice_picture' => 'required|image',
        ]);

        $orderId = $request['order_id'];

        $order = Order::where('id', $orderId)->first();

        if(isset($order)){

            if ($request->hasFile('invoice_picture')) {
                $ext = $request->file('invoice_picture')->getClientOriginalExtension();
                $path = storage_path("app/public/invoices");
                $name = time() . '.' . $ext;
                $request->file('invoice_picture')->move($path, $name);
                $order->invoice_picture = $name;

                //Copy invoice picture to conversations folder
                $invoicePic = storage_path("app/public/conversation/") . $name;
                if(file_exists($path . '/' . $name)) {
                    File::copy($path . '/' . $name, $invoicePic);
                }
            }
            $order->total_invoice = $request->total_invoice;
            $order->save();

            //Send invoice to conversation
            $getOrderMessage = Message::where('order_id', $orderId)->orderBy('id', 'DESC')->first();
            if($getOrderMessage) {
                $conversationId = $getOrderMessage->conversation_id;
                $conversationInfo = Conversation::where('id', $conversationId)->first();
                if($conversationInfo) {
                    $deliveryManId = $conversationInfo->sender_type == 'delivery_man' ? $conversationInfo->sender_id : $conversationInfo->receiver_id;
                    if (isset($invoicePic) && isset($name)) {
                        $message = new Message();
                        $message->conversation_id = $conversationId;
                        $message->sender_id = $deliveryManId;
                        $message->order_id = $orderId;
                        $message->message = null;
                        $message->file = json_encode([$name]);
                        $message->is_seen = 0;
                        $message->is_visible_to_dm = 1;
                        $message->is_visible_to_customer = 1;
                        $message->save();
                    }
                    Order::sendInvoiceMessage($orderId, $conversationId);
                }
            }

            return response()->json(['message' => translate('messages.invoice_placed_successfully')
                ,'Your Order' => $order ], 200);
        }

        else {
            return response()->json(['errors' => translate('messages.Please enter your order ID correctly')],404);

        }
    }

    public function getEmployedDeliveryMen()
    {
        $deliveryMen = DeliveryMan::where('earning', '0')->get();
        return response()->json($deliveryMen);
    }

    public function getInfo(Request $request): \Illuminate\Http\JsonResponse
    {
        $result = [
            'status' => 0,
            'deliveryManId' => 0,
            'countOfOrders' => 0,
            'balance' => 0,
        ];

        $normalizedPhone = $this->normalizePhone($request->phone);
        $deliveryMan = DeliveryMan::where('phone', $normalizedPhone)->first();

        if (!$deliveryMan) {
            return response()->json($result);
        }

        $result['status'] = 1;
        $result['deliveryManId'] = $deliveryMan->id;
        $result['balance'] = DeliveryMan::getTheRemainingBalanceForDeliveryMan($deliveryMan, '', '');

        $fromDate = $request->filled('from_date') ? $request->from_date : Carbon::today()->toDateString();
        $toDate = $request->filled('to_date') ? $request->to_date : Carbon::today()->toDateString();

        $countOfOrders = Order::where('order_status', 'delivered')
            ->where('delivery_man_id', $deliveryMan->id)
            ->whereBetween('delivered', ["$fromDate 00:00:00", "$toDate 23:59:59"])
            ->count();

        $result['countOfOrders'] = $countOfOrders;

        return response()->json($result);
    }

    private function normalizePhone($phone)
    {
        $phone = preg_replace('/\D+/', '', $phone);
        if (strpos($phone, '0') === 0 && strlen($phone) === 10) {
            return '+963' . substr($phone, 1);
        }
        if (strpos($phone, '963') === 0) {
            return '+' . $phone;
        }
        return $phone;
    }

    public function receiveAnAmountFromDm(Request $request)
    {
        $deliveryManId = $request->delivery_man_id;
        $amount = $request->amount;
        $type = 'deliveryman';
        $method = 'تلقائية';
        $ref = 'استلام مبلغ من المندوب عن طريق سيستم الشركات من السيد: ' . $request->admin_name;

        $data = DeliveryMan::findOrFail($deliveryManId);
        $currentBalance = $data->wallet ? $data->wallet->collected_cash : 0;

        $account_transaction = new AccountTransaction();
        $account_transaction->from_type = $type;
        $account_transaction->from_id = $deliveryManId;
        $account_transaction->method = $method;
        $account_transaction->ref = $ref;
        $account_transaction->amount = $amount;
        $account_transaction->current_balance = $currentBalance;
        $account_transaction->transaction_date = null;
        $account_transaction->admin_id = null;

        DMLog::createLog($data->id, $ref, $amount, null);

        try
        {
            DB::beginTransaction();
            $account_transaction->save();
            AdminWallet::where('admin_id', Admin::where('role_id', 1)->first()->id)->increment('manual_received', $request['amount']);
            DB::commit();
        }
        catch(\Exception $e)
        {
            DB::rollBack();
            return response()->json(['errors' => $e->getMessage()]);
        }

        return response()->json(200);
    }

    public function sendPayment(Request $request): \Illuminate\Http\JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'phone' => 'required',
            'payment_value' => 'required',
            'note' => 'required',
        ]);

        $type = 'deliveryman';
        $method = 'تلقائية';
        $amount = $request->payment_value;
        $ref = $request->note;

        $data = DeliveryMan::where('phone', $request->phone)->first();
        $currentBalance = 0;

        if ($validator->fails()) {
            Log::error('Validation error');
            return response()->json(['errors' => Helpers::error_processor($validator)]);
        }

        $account_transaction = new AccountTransaction();
        $account_transaction->from_type = $type;
        $account_transaction->from_id = $data->id;
        $account_transaction->method = $method;
        $account_transaction->ref = $ref;
        $account_transaction->amount = $amount;
        $account_transaction->current_balance = $currentBalance;
        $account_transaction->transaction_date = isset($request->transaction_date) ? $request->transaction_date : null;
        $account_transaction->admin_id = null;

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

            if(!empty($request->dm_log_message)) {
                if(!empty($getDMLogMessage)) {
                    DMLog::createLog($data->id, $ref, $amount, null);
                }
            }

            AdminWallet::where('admin_id', Admin::where('role_id', 1)->first()->id)->increment('manual_received', $amount);
            //DB::commit();
        }catch (\Exception $exception){
            Log::channel('PaymentRequestsForFreeDMLog')->error('Transaction insert failed', ['error' => $exception->getMessage()]);
            return response()->json(['errors' => $exception->getMessage()]);
        }

        if($data->status == '0'){
            $theRemainingBalance = DeliveryMan::getTheRemainingBalanceForDeliveryMan($data, '', '');
            if($theRemainingBalance < 0) {
                $data->status = 1;
                $data->save();
            }
        }

        return response()->json(200);
    }

}
