<?php

namespace App\Http\Controllers\Api;

use App\Helpers\ApiResponse;
use App\Helpers\Message;
use App\Http\Controllers\Controller;

use App\Http\Controllers\RestaurantController;
use App\Http\Resources\CategoryCollection;
use App\Http\Resources\CategoryResource;
use App\Models\Category;
use App\Models\DeviceSection;
use App\Models\Item;
use App\Models\Language;
use App\Models\Order;
use App\Models\OrderDetail;
use App\Models\Restaurant;
use App\Models\RestaurantDevice;
use App\Models\Section;
use App\Models\Setting;
use App\Models\Status;
use App\Models\Table;
use App\Models\TableNotification;
use App\Models\User;
use App\Models\UserWorkSession;
use App\Models\WaiterNotification;
use App\Models\WaiterSessionSection;
use App\Models\WaiterWorkSession;
use Illuminate\Http\Request;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;


class ApiMainController extends Controller
{

    public function employeeLogin(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'username' => 'required|string',
            'password' => 'required|string'],
            [
                'required' => 'The :attribute field is required.',
                'string' => 'The :attribute field must be a string',
//                'email' => 'The username must be an email',
            ]);
        if ($validator->fails())
        {
            foreach ($validator->messages() as $message) {
                return response(['success' => false, 'message' => $message], 422);
            }
        }
        $user = User::query()->where('username', strtolower($request->username))->first();
        if ($user) {
            if (!$user->is_active) {
                $response = ["message" => "User is not active", 'success' => false];
                return response($response, 422);
            }else{
                if(Hash::check($request->password, $user->password)){
                    $reg_id = $request->reg_id;
                    $device_id = $request->device_id;
                    $updateData = [
                        "reg_id" => $reg_id,
                        "device_id" => $device_id
                    ];
                    if($user->remember_token == null){
                        $token = Str::random(60);
                        $updateData["token"] = $token;
                        $updateData["remember_token"] = $token;
                        $updateData["token_gen_date"] = date('Y-m-d H:i:s');
                    }else{
                        $token = $user->remember_token;
                    }
                    $user->update($updateData);
                    $first_login = true;
                    $response = [
                        'token' => $token,
                        'user' => User::getDecryptedData($user->full_name),
                        'success' => true,
                    ];
                    return response($response, 200);
                }else {
                    $response = ["message" => "Password mismatch", 'success' => false];
                    return response($response, 422);
                }
            }

        } else {
            $response = ["message" =>'User does not exist', 'success' => false];
            return response($response, 422);
        }
    }

    public function employeeLogout(Request $request)
    {
        $user = $this->checkRestaurantDevice($request);
        if ($user) {
            $result = User::closeEmployeeSession($user, $request->location);
            $user->update([
                "token" => null,
                "reg_id" => null,
                "device_id" => null
            ]);
            return response(["success" => true, "message" => "Logged out successfully"], 200);
        }else {
            $response = ["message" =>'User does not exist', 'success' => false];
            return response($response, 422);
        }
    }

    private function checkRestaurantDevice(Request $request)
    {
        $token = $request->bearerToken();
        return User::getUserByToken($token);
    }

    public function changePassword(Request $request)
    {
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
        if($user === false)
            return response(["success" => false, "message" => "Not Allowed"], 200);

        $oldPassword = $request->current_password;
        $newPassword = $request->new_password;
        if(Hash::check($oldPassword, $user->password)){
            $user->password = Hash::make($newPassword);
            $user->save();
            $response = [
                'success' => true,
                "message" => __("Password changed successfully")
            ];
            return response($response, 200);
        }else{
            $response = ["message" => "Password mismatch", 'success' => false];
            return response($response, 422);
        }
    }

    public function startWorkSession(Request $request)
    {
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
        if($user === false)
            return response(["success" => false, "message" => "Not Allowed"], 200);

        $start_time = date('Y-m-d H:i:s');
        $start_location = $request->location;
        $currentSession = UserWorkSession::query()->where('user_id', $user->id)
//            ->whereNull('end_date')
            ->whereDate('start_date', date('Y-m-d'))
            ->first();
        if($currentSession != null && $currentSession->count() > 0){
            // return there is an active session, you must close it first
            $response = [
                'message' => __("You already have open session"),
                'start_time' => $currentSession->start_date != null ? $currentSession->start_date->format("H:i"):"N/A",
                'end_time' => $currentSession->end_date != null ? $currentSession->end_date->format("H:i"):"N/A",
                'session_id' => $currentSession->id,
                'success' => false,
            ];
        }else{
            $sessionId = UserWorkSession::insertGetId([
                "user_id" => $user->id,
                "start_date" => $start_time,
                "start_location" => $start_location,
                "start_online" => 1,
                "created_at" => $start_time,
                "created_user" => $user->device_name
            ]);
            $response = [
                'session_id' => $sessionId,
                'start_time' => date("H:i"),
                'end_time' => "N/A",
                'message' => __("Your Session started successfully"),
                'success' => true,
            ];
        }
        return response($response, 200);
    }

    public function finishWorkSession(Request $request)
    {
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
//        $user = RestaurantDevice::find(1);
        if($user === false)
            return response(["success" => false, "message" => "Not Allowed"], 200);

        $end_time = date('Y-m-d H:i:s');
        $end_location = $request->location;
        $currentSession = UserWorkSession::query()->where('user_id', $user->id)
            ->whereDate('start_date', date('Y-m-d'))
//            ->whereNull('end_date')
            ->first();
        if($currentSession != null && $currentSession->count() > 0 && $currentSession->end_date == null){
            $startTime = $currentSession->start_date != null ? $currentSession->start_date->format('H:i:s'):"N/A";
            $currentSession->update([
                "end_date" => $end_time,
                "end_location" => $end_location,
                "end_online" => 1,
                "updated_at" => $end_time
            ]);
            $response = [
                'success' => true,
                'start_time' => $startTime,
                'end_time' => date("H:i"),
                'session_id' => $currentSession->id,
                'message' => __("Your Session end successfully")
            ];
        }else{
            // return no active session
            $response = [
                'message' => __("You have no active session, please sync your data first"),
                'start_time' => ($currentSession != null && $currentSession->start_date) != null ? $currentSession->start_date->format("H:i"):"N/A",
                'end_time' => ($currentSession != null && $currentSession->end_date != null) ? $currentSession->end_date->format("H:i"):"N/A",
                'session_id' => ($currentSession != null) ? $currentSession->id:"",
                'success' => false,
            ];
        }
        return response($response, 200);
    }

    public function syncOfflineSession(Request $request)
    {
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
        $start_time = date('Y-m-d H:i:s');
//        $user = RestaurantDevice::find(1);
        if($user === false)
            return response(["success" => false, "message" => "Not Allowed"], 200);

        $sessions = $request->sessions;
        $sessionId = "";
        if(is_array($sessions) && count($sessions) > 0){
            foreach ($sessions as $session) {
                if(isset($session['startTime']) && $session['startTime'] != null && strtotime($session['date']) <= strtotime(date('Y-m-d'))){
                    $daySession = UserWorkSession::query()->where('user_id', $user->id)
                        ->whereDate('start_date', $session['date'])
                        ->first();
                    if($daySession != null){
                        $daySession->update([
                            "start_date" => $session['date'].' '.$session['startTime'],
                            "end_date" => (isset($session['endTime']) && $session['endTime'] != 'N/A') ? $session['date'].' '.$session['endTime']:null,
                            "start_location" => isset($session['startLocation']) ? $session['startLocation']:null,
                            "end_location" => isset($session['endLocation']) ? $session['endLocation']:null,
                            "start_online" => isset($session['startOnline']) ? $session['startOnline']:null,
                            "end_online" => isset($session['endOnline']) ? $session['endOnline']:null,
                            "updated_at" => $start_time,
                            "updated_user"=> $user->id
                        ]);
                        $sessionId = $daySession->id;
                    }else{
                        $sessionId = UserWorkSession::query()->insertGetId(
                            [
                                "user_id" => $user->id,
                                "start_date" => isset($session['startTime']) ? $session['date'].' '.$session['startTime']:null,
                                "end_date" => (isset($session['endTime']) && $session['endTime'] != 'N/A') ? $session['date'].' '.$session['endTime']:null,
                                "start_location" => isset($session['startLocation']) ? $session['startLocation']:null,
                                "end_location" => isset($session['endLocation']) ? $session['endLocation']:null,
                                "start_online" => isset($session['startOnline']) ? $session['startOnline']:null,
                                "end_online" => isset($session['endOnline']) ? $session['endOnline']:null,
//                                "start_location" => isset($session['start_location']) ? $session['start_location']:null,
//                                "end_location" => isset($session['end_location']) ? $session['end_location']:null,
                                "created_at" => $start_time,
                                "created_user" => $user->id
                            ]);
                    }
                }
            }
            $response = [
                'success' => true,
                'sessionId' => $sessionId,
                'message' => __("Your Sessions synced successfully")
            ];
            return response($response, 200);
        }else{
            print_r($sessions);
            return response(["success" => false, "message" => "Nothing to sync"], 200);
        }


    }

    public function getWorkSessions(Request $request)
    {
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
        if($user == null){
            $response = [
                'message' => "Not Allowed, please logout and login",
                'success' => false
            ];
            return response($response, 200);
        }
        $sessions = UserWorkSession::query()->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->limit(10)->get()->each(function($row) {
                $row->date = $row->start_date != null ? $row->start_date->format('Y-m-d'):"";
                $row->day = $row->start_date != null ? $row->start_date->format('l'):"";
                $row->start_time = $row->start_date != null ? $row->start_date->format('H:i:s'):null;
                $row->end_time = $row->end_date != null ? $row->end_date->format('H:i:s'):null;
            });

        $response = [
            'message' => "",
            'success' => true,
            'sessions'  => $sessions,
            'last_update_time' => date('Y-m-d H:i:s')
        ];
        return response($response, 200);
    }

    public function getUserSessions(Request $request){

        $update = $request->last_update;
        $token = $request->bearerToken();
        $user = User::getUserByToken($token);
        if($user == null){
            $response = [
                'message' => "Not Allowed, please logout and login",
                'success' => false
            ];
            return response($response, 200);
        }
        if($user->restaurant_id == null){
            $response = [
                'message' => "Authentication Failed",
                'success' => false,
                'orders'  => []
            ];
            return response($response, 200);
        }
        $userAllowedSections = $this->getActiveSectionsForDevice($user->id);
        if ($update == null){
            $orders = Order::query()->with(['status'])
//                ->where('updated_at', '>=' , date('Y-m-d'))
                ->whereIn('status_id', Status::STATUS_LIVE_ORDERS)
                ->where('restaurant_id', $user->restaurant->id)
                ->whereIn('table_id', function ($qu) use($userAllowedSections) {
                    $qu->select('id')->from((new Table())->getTable())->whereIn('section_id', $userAllowedSections)->get();
                })
                ->orderBy('order_date', 'desc')
                ->get()
//                ->paginate(19)
                ->each(function ($items) {
                    $items->status_name = $items->status->defaultLang->name;
                    $items->restaurant_name = $items->restaurant->defaultLang->name;
                    $items->makeHidden(['status', 'table', 'item', 'created_at', 'updated_at']);
                    $items->table_no = $items->table_id != null ? $items->table->table_no:"";
                    $items->section = $items->table_id != null ? $items->table->section->defaultLang->name:"";
                    $items->order_text = Order::generateOrderMessage($items->id);
                    $items->payment_method = __($items->payment_method);
                    $items->items = OrderDetail::query()->where('order_id', $items->id)->get()->each(function ($it) {
//                        dd($it->order_detail_modifiers);
                        if($it->order_detail_modifiers->count() > 0){
                            foreach ($it->order_detail_modifiers as $key => $order_detail_modifier) {
                                $it->order_detail_modifiers[$key]['modifier_name'] = $order_detail_modifier->item_modifier->modifier->defaultLang->name;
                            }
                        }else{
                            $it->modifier_name = '';
                        }
                        $it->makeHidden(['item', 'item_modifier', 'created_at', 'updated_at']);
                    });
                });
        }
        else{
            $orders = Order::query()->with(['status'])
                ->whereIn('status_id', Status::STATUS_WAITER_ORDERS)
                ->where('restaurant_id', $user->restaurant->id)
                ->whereIn('table_id', function ($qu) use($userAllowedSections) {
                    $qu->select('id')->from((new Table())->getTable())->whereIn('section_id', $userAllowedSections)->get();
                })
                ->where('updated_at', '>=' , $update)
                ->get()
                ->each(function ($items) {
                    $items->status = $items->status->defaultLang->name;
                });
        }
        $response = [
            'message' => "",
            'success' => true,
            'orders'  => $orders,
            'last_update_time' => date('Y-m-d H:i:s')
        ];
        return response($response, 200);
    }

    private function checkUserDevice(Request $request)
    {
        $token = $request->bearerToken();
        return User::getUserByToken($token);
    }

    public function getMenuSettings(Request $request)
    {
//        dd(Session::token());
//        $rest_id = $request->id;
        $slug = $request->id;
        $restaurant = Restaurant::query()->select(['id', 'email', 'slug', 'country_id', 'city_id', 'phone', 'mobile', 'logo', 'currency'])
            ->where('slug', $slug)->first();

        if($restaurant == null)
            abort(404);
        $rest_id = $restaurant->id;
        Restaurant::setTimeZone($rest_id);
        $table_id = $request->table;
        $table = false;
        if($table_id != null) {
            $table = Table::query()
                ->select(['id', 'table_no'])
                ->where('id', $table_id)
                ->whereIn('section_id', function ($q) use($rest_id){
                    $q->select('id')->from((new Section())->getTable())
                        ->where('restaurant_id', $rest_id)->get();
                })->first();
            if($table == null || $table->count() == 0) {
                $table = false;
            }else{
                $table->table_name = $table->defaultLang->name;
                $table->makeHidden(['defaultLang']);
            }
        }

        $categories = Category::query()
            ->select(['id', 'parent_id', 'is_active', 'category_image', 'sort'])
            ->where('is_active', 1)
            ->where('restaurant_id', $rest_id)
            ->where('is_active', 1)
            ->whereNull('parent_id')
            ->orderBy('category.sort')
            ->get()
            ->each(function($item) {
                $item->category_name = $item->defaultLang->category_name;
                $item->makeHidden(['defaultLang']);
            });
//        $categories = new CategoryCollection($categories);
        $categories = CategoryResource::collection($categories);

        //get first category data
        if($categories->count() > 0){
            $category = $categories[0];
            $category_id = $category->id;
            $category_child = Category::query()->where('parent_id', $category_id)
                ->where('is_active', 1)
                ->orderBy('category.sort')
                ->get();
            $items = Item::query()
                ->select(['id', 'category_id', 'image', 'is_active', 'price', 'sort'])
                ->where('category_id', $category_id)
                ->where('is_active', 1)
                ->orderBy('item.sort')
                ->get()
                ->each(function($item) {
                    $item->item_name = $item->defaultLang->item_name;
                    $item->item_description = $item->defaultLang->item_description;
                    $item->makeHidden(['defaultLang', 'category', 'category.restaurant']);
                });


//            compact('items', 'category_child', 'category_id')
        }
        $menu_service_buttons = Setting::getMenuServiceButtons($rest_id);
        $menu_url_buttons = Setting::getMenuUrlButtons($rest_id);
        $menu_settings = Setting::getMenuSettings($rest_id);
        $enableSelfOrder = false;
        $enableSelfOrder = $menu_settings[Setting::SETTING_ENABLE_SELF_ORDER];
        if($table === false && $enableSelfOrder == "1"){
            $themeSettings[Setting::SETTING_ENABLE_SELF_ORDER] = "0";
        }
        $payment_methods = Setting::getMenuPaymentMethods($rest_id);
        return ApiResponse::response(compact('rest_id', 'restaurant', 'categories', 'category_id', 'payment_methods',
            'category_child', 'items', 'menu_url_buttons', 'menu_service_buttons', 'table', 'menu_settings'));
//        return response()->json(compact('rest_id', 'restaurant', 'categories', 'category_id',
//            'category_child', 'items', 'menu_url_buttons', 'menu_service_buttons', 'table', 'menu_settings'));

    }
}
