<?php

namespace App\Http\Controllers\Reciption;

use App\Exports\CustomerExport;
use App\Http\Controllers\Controller;
use App\Http\Requests\Manager\StoreEmployeeRequest;
use App\Http\Requests\Reciption\StoreOrderRequest;
use App\Models\Brand;
use App\Models\CanceledOrdersNotes;
use App\Models\Customer;
use App\Models\Device;
use App\Models\Order;
use App\Models\StockNotes;
use Carbon\Carbon;
use Cassandra\Custom;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use Maatwebsite\Excel\Facades\Excel;
use Yajra\DataTables\DataTables;

class ReciptionController extends Controller
{
    protected $image_url;

    public function home()
    {
        return view('reciption.index');
    }

    public function getOrdersForScreen()
    {
        $data = Order::whereIn('state', [1, 2, 3])
            ->where('isVisible', true)
            ->with('employee')
            ->with('customer')
            ->with('customer.device')
            ->latest()->paginate(8);
        return $data;
    }

    //satistics
    public function stat()
    {
        $orders = Order::all();
        $wait = $orders->where('state', 1)->count();
        $working = $orders->where('state', 2)->count();
        $done = $orders->where('state', 3)->count();
        $delv = $orders->where('state', 4)->count();
        $canceled = $orders->where('state', 6)->count();
        $stock = $orders->where('state', 7)->count();
        $customers = Customer::all()->count();
        $mobile = \App\Models\Request::where('current_state', 3)->where('work_type', 1)->count();
        $swc = \App\Models\Request::where('current_state', 2)->where('work_type', 1)->count();
        $hdc = \App\Models\Request::where('current_state', 1)->where('work_type', 1)->count();
        return view('reciption.stat', compact('wait', 'working', 'done', 'delv', 'canceled', 'stock', 'customers', 'mobile', 'swc', 'hdc'));
    }

    public function index(Request $request)
    {
        if ($request->isMethod('POST')) {
            // if request is = 0 then return oll orders
            if ($request->pageState == 0) {
                $data = Order::where('state', '!=', 7)
                    ->with(['updatedEmployee' => function ($q) {
                        return $q->select('id', 'name');
                    }])
                    ->with('employee')
                    ->with('canceledOrder')
                    ->with('customer')
                    ->with('customer.device')
                    ->with('requests.user')
                    ->latest()
                    ->paginate(8);
            } else {
                // return results based on order state
                $data = Order::where('state', '!=', 7)
                    ->where('state', $request->pageState)
                    ->with(['updatedEmployee' => function ($q) {
                        return $q->select('id', 'name');
                    }])
                    ->with('employee')
                    ->with('canceledOrder')
                    ->with('customer')
                    ->with('customer.device')
                    ->with('requests.user')
                    ->paginate(8);
            }
            return $data;
        } else
            return view('reciption.orders.orders');
    }

    //Get Search Result
    public function searchResult(Request $request)
    {
        $searchResult = Customer::whereHas('device', function ($q) {
            $q->where('state', '1');
        })
            ->where('name', 'LIKE', "%{$request->name}%")
            ->orWhere('phone', 'LIKE', "%{$request->name}%")
            ->with('order.employee')
//           ->with('order.requests.user')
            ->with('device')
            ->with('order.canceledOrder')
            ->paginate(8);
        return $searchResult;
    }


    // store new order or return new order view form
    public function NewOrder(StoreOrderRequest $storeOrderRequest)
    {
        // IF method request is get then return add order view
        if ($storeOrderRequest->isMethod('GET')) {
            return view('reciption.orders.new_order');
        } elseif ($storeOrderRequest->isMethod('POST')) {
            try {
                DB::beginTransaction();

                $order = Order::create([
                    'notice' => $storeOrderRequest->notice,
                    'proccess_type' => $storeOrderRequest->proccess_type,
                    'priority' => $storeOrderRequest->priority,
                    'created_employee' => null,
                    'updated_employee' => null,
                    'created_at' => now(),
                ]);
                if ($storeOrderRequest->photo) {
                    $position = strpos($storeOrderRequest->photo, ';');
                    $sub = substr($storeOrderRequest->photo, 0, $position);
                    $ext = explode('/', $sub)[1];
                    $photo = time() . "." . $ext;
                    $img = Image::make($storeOrderRequest->photo);
                    $upload_path = 'uploads/images/';
                    $this->image_url = $upload_path . $photo;
                    $img->save($this->image_url);
//                    $this->photoName =  time().'.'.$storeOrderRequest->file('photo')->extension();
//                    $storeOrderRequest->file('photo') ? $storeOrderRequest->file('photo')->move('uploads/images/' , $this->photoName) : '#'
                }
//                $mac = $this->getMacFormat($storeOrderRequest->device_type, $storeOrderRequest->serial);
//                if(is_null($storeOrderRequest->serial)){
//                    $mac = $this->getMacFormat($storeOrderRequest->device_type, $storeOrderRequest->serial);
//
//                }else $mac = $this->getMacFormat($storeOrderRequest->device_type, $storeOrderRequest->serial);
                $device = Device::create([
                    'serial' => $this->getMacFormat(),
                    'brand' => $storeOrderRequest->input('brand'),
                    'type' => $storeOrderRequest->device_type,
                    'extentions' => $storeOrderRequest->extentions,
                    'photo' => $this->image_url,
                    'notice' => $storeOrderRequest->input('notice'),
                    'color' => $storeOrderRequest->input('color'),
                ]);
                $customer = Customer::create([
                    'name' => $storeOrderRequest->input('name'),
                    'phone' => $storeOrderRequest->input('phone'),
                    'order_id' => (int)$order->id,
                    'device_id' => (int)$device->id
                ]);

//                session()->flash('success', 'تم إدخال الطلب بنجاح');
                $device_type = ['', 'كومبيوتر', 'موبايل', 'لابتوب'];
                $dataPrinted = [
                    'name' => $customer->name,
                    'phone' => $customer->phone,
                    'serial' => $device->serial,
                    'device_type' => $device->type,
                    'brand' => $device->brand,
                    'extentions' => $device->extentions,
                    'note' => $order->notice,
//                    'color' =>$device->color,
                    'created_at' => $device->created_at->toDateTimeString()
                ];
                DB::commit();
//                session()->flash('dataPrinted',$dataPrinted);
                return response()->json($dataPrinted, 200);
//                return redirect()->route('rec.new-order')->with('dataPrinted',$dataPrinted);
            } catch (\Exception $exception) {
//                session()->flash('error', $exception->getMessage());
                return $exception->getMessage();
            }
        }

    }

    public function updateOrder(StoreOrderRequest $storeOrderRequest)
    {
        $customer = Customer::findOrFail($storeOrderRequest->id);
        $customerDevice = Device::where('id', $customer->device_id)->firstOrFail();
        $customerOrder = Order::where('id', $customer->order_id)->firstOrFail();
        // if order state not in pending then can not update the order
        if ($customerOrder->state !== 1) {
            abort(301);
        }
        try {
            DB::beginTransaction();
            $customer->update([
                'name' => $storeOrderRequest->input('name'),
                'phone' => $storeOrderRequest->input('phone')
            ]);
//            return file_exists($storeOrderRequest->photo) ? 'yes' : 'no';
            if (!file_exists($storeOrderRequest->photo) && $storeOrderRequest->photo !== '#') {
                $position = strpos($storeOrderRequest->photo, ';');
                $sub = substr($storeOrderRequest->photo, 0, $position);
                $ext = explode('/', $sub)[1];
                $photo = time() . "." . $ext;
                $img = Image::make($storeOrderRequest->photo);
                $image_url = 'uploads/images/' . $photo;
                $this->photoName = $image_url;
                $img->save($image_url);
                File::delete($customerDevice->photo);
                $customerDevice->update([
                    'photo' => $this->photoName,
                ]);
            }
            $customerDevice->update([
//                'serial' => $storeOrderRequest->input('serial'),
                'brand' => $storeOrderRequest->input('brand'),
                'type' => $storeOrderRequest->input('device_type'),
                'notice' => $storeOrderRequest->input('notice'),
                'color' => $storeOrderRequest->input('color'),
                'extentions' => $storeOrderRequest->extentions,
            ]);
            $customerOrder->update([
                'notice' => $storeOrderRequest->input('notice'),
                'proccess_type' => $storeOrderRequest->input('proccess_type'),
                'priority' => $storeOrderRequest->priority,
                'updated_employee' => auth()->user()->id
            ]);
            DB::commit();
            return 'updated';
        } catch (\Exception $exception) {
            return $exception->getMessage();
        }
    }

    // add new notice after repairing finished
    public function doneNotice(Request $request)
    {

        $order = Order::findOrFail($request->order);
        DB::beginTransaction();
        $order->update([
            'isVisible' => $request->isVisible,
            'updated_employee' => auth()->user()->id
        ]);
        $order->customer->device->update([
            'done_notice' => $request->doneNotice
        ]);
        DB::commit();
        return response()->json(['message' => 'ok'], 200);
    }

    public function print(Request $request)
    {
        $array = array_slice(explode(',', $request->extentions), 0, 4);
        return view('reciption.print', [
            'name' => $request->name,
            'phone' => $request->phone,
            'type' => $request->type,
            'brand' => $request->brand,
            'serial' => $request->serial,
            'note' => $request->note,
            'extentions' => $array,
            'date' =>  $request->date
        ]);
    }


    public function print2(Request $request)
    {
        return view('reciption.print2', [
            'name' => $request->name,
            'phone' => $request->phone,
        ]);
    }


    // Cancel Order recived id => order_id
    public function cancelOrder(Request $request)
    {

        $order = Order::findOrFail($request->id);
        if ($order->state === 4 || $order->state === 3) {
            return response()->json(['message' => 'لايمكن إلغاء الطلب يبدو أن الجهاز تمت صيانته أو تم تسليمه للعميل'], 302);
        }
        $request->validate([
            'notes' => 'required'
        ], ['notes.required' => 'يجب إدخال سبب إلغاء الطلب']);
        try {
            DB::beginTransaction();
            $order_notes = DB::table('canceled_orders_notes')->where('order_id', $request->id)->get();
            if (count($order_notes)) {
                CanceledOrdersNotes::where('order_id', $request->id)->update([
                    'notes' => $request->notes,
                ]);
            } else {
                CanceledOrdersNotes::create([
                    'notes' => $request->notes,
                    'order_id' => $request->id
                ]);
            }
            $order->update([
                'state' => 6,
                'updated_employee' => auth()->user()->id
            ]);
            DB::commit();
        } catch (\Exception $exception) {
            return $exception->getMessage();
        }
    }

    // Delivered Order
    public function deleviredOrder(Request $request)
    {
        $order = Order::findOrFail($request->order);
        if ($order->state === 3 || $order->state === 7) {
            $order->update([
                'state' => 4,
                'discount' => $request->discount,
                'updated_employee' => auth()->user()->id
            ]);
            return $order;
        } else {
            return response()->json(['message' => 'لايمكن تسليم الجهاز في الوقت الحالي, تم تسليم الجهاز أو مازال في الانتظار أو الصيانة!'], 302);
        }
    }

    // view order details THIS FUNCTION NOT USED ***********
    public function viewOrderDetails(Request $request)
    {
        $order = Order::where('id', $request->id)
            ->with('stockNotes')
            ->with('canceledOrder')
            ->with('employee')
            ->with('updatedEmployee')
            ->with('customer.device')
            ->with('requests.user')
            ->first();
        return $order;
    }

    public function ordersSotck(Request $request)
    {
        return view('reciption.orders.stock');
    }

    public function ordersSotckDevices(Request $request)
    {
        switch ($request->pageState) {
            case 0:
                $order = Order::orderBy('created_at', 'asc')->whereIn('state', [3])
                    ->with('employee')
                    ->with('updatedEmployee')
                    ->with('customer.device')
                    ->with('requests.user')
                    ->paginate(8);
                break;
            case 1:
                $order = Order::whereIn('state', [3])
                    ->whereDate('created_at', '<=', Carbon::now()->subDays(7))
                    ->with('employee')
                    ->with('updatedEmployee')
                    ->with('customer.device')
                    ->with('requests.user')
                    ->paginate(8);
                break;
            case 2:
                $order = Order::whereIn('state', [3])
                    ->whereDate('created_at', '<=', Carbon::now()->subDays(15))
                    ->with('employee')
                    ->with('updatedEmployee')
                    ->with('customer.device')
                    ->with('requests.user')
                    ->paginate(8);
                break;
        }

        return $order;
    }

    public function toStock(Request $request)
    {
        $request->validate([
            'note' => 'required'
        ]);
        $order = Order::where('id', $request->order)->first();
        if ($order->state === 3) {
            DB::beginTransaction();
            $order->update([
                'state' => 7,
                'updated_employee' => auth()->user()->id
            ]);
            $order->customer->device->update([
                'state' => 2
            ]);
            StockNotes::create([
                'order_id' => $order->id,
                'note' => $request->note
            ]);

            DB::commit();
            return response()->json(['message' => 'ok'], 201);
        } else {
            abort(302);
        }
    }

    public function mainStock(Request $request)
    {
        if ($request->isMethod('POST')) {
            $order = Order::where('state', 7)
                ->with('employee')
                ->with('stockNotes')
                ->with('updatedEmployee')
                ->with('customer.device')
                ->with('requests.user')
                ->latest()
                ->paginate(8);
            return $order;
        } else {
            return view('reciption.orders.main_stock');
        }
    }

    public function excel()
    {

        return Excel::download(new CustomerExport(), 'customers.xlsx');
    }

    //brands view + store brand
    public function brands(Request $request)
    {
        //Post methos is to store new brand
        if ($request->isMethod('POST')) {
            $validated = $request->validate([
                'name' => 'required',
                'type' => 'required|in:1,2,3'
            ], [
                'name.required' => 'إسم الماركة مطلوبة',
                'type.required' => 'نوع الجهاز مطلوب',
                'type.in' => 'يجب إختيار نوع الجهاز من القائمة'
            ]);
            Brand::create($validated);
            return response()->json(['message' => 'ok'], 200);
        } //update brand
        elseif ($request->isMethod('put')) {
            $brand = Brand::findOrFail($request->id);
            $validated = $request->validate([
                'name' => 'required',
                'type' => 'required|in:1,2,3'
            ], [
                'name.required' => 'إسم الماركة مطلوبة',
                'type.required' => 'نوع الجهاز مطلوب',
                'type.in' => 'يجب إختيار نوع الجهاز من القائمة'
            ]);
            $brand->update($validated);
            return response()->json(['message' => 'ok'], 201);
        } else
            return view('reciption.brands.brands');
    }

    // get all brands
    public function getBrands(Request $request)
    {
        $brands = Brand::latest()->paginate(5);
        return $brands;
    }

    public function getBrandsType(Request $request)
    {
        if ($request->type) {
            $brands = Brand::where('type', $request->type)->get();
            return $brands;
        } else return null;
    }

    public function getMacFormat()
    {
        $number = mt_rand(10000001, 99999999);
        if ($this->checkNumberExist($number)) {
            return $this->getMacFormat();
        }
        return $number;
    }

    function checkNumberExist($number)
    {
        return Device::whereSerial($number)->exists();
    }

    public function reset_print(Request $request){
        return view('/reciption.reset_print', ['name' => $request->name, 'serial' => $request->serial, 'phone' =>  $request->phone]);
    }
}
