<?php

namespace App\Http\Controllers;

use App\Constants\Status;
use App\Models\Addon;
use App\Models\AdminNotification;
use App\Models\Advertisement;
use App\Models\Cart;
use App\Models\Category;
use App\Models\Food;
use App\Models\Frontend;
use App\Models\Language;
use App\Models\Location;
use App\Models\Page;
use App\Models\Restaurant;
use App\Models\Subscriber;
use App\Models\SupportMessage;
use App\Models\SupportTicket;
use App\Models\VariantItem;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Session;

class SiteController extends Controller
{
    public function index()
    {
        $pageTitle = 'Home';
        $sections = Page::where('tempname', activeTemplate())->where('slug', '/')->first();
        $seoContents = $sections->seo_content;
        $seoImage = @$seoContents->image ? getImage(getFilePath('seo') . '/' . @$seoContents->image, getFileSize('seo')) : null;
        return view('Template::home', compact('pageTitle', 'sections', 'seoContents', 'seoImage'));
    }

    public function pages($slug)
    {
        $page = Page::where('tempname', activeTemplate())->where('slug', $slug)->firstOrFail();
        $pageTitle = $page->name;
        $sections = $page->secs;
        $seoContents = $page->seo_content;
        $seoImage = @$seoContents->image ? getImage(getFilePath('seo') . '/' . @$seoContents->image, getFileSize('seo')) : null;
        return view('Template::pages', compact('pageTitle', 'sections', 'seoContents', 'seoImage'));
    }

    public function allRestaurants()
    {
        $pageTitle   = "All Restaurants";
        $restaurants = Restaurant::whereHas('foods')->with('plan', 'location');
        $restaurants = sortRestaurants($restaurants);
        $restaurants = customPaginate($restaurants, getPaginate());
        return view('Template::restaurants', compact('pageTitle', 'restaurants'));
    }

    public function popularRestaurants()
    {
        $pageTitle   = "Popular Restaurants";
        $restaurants = Restaurant::whereHas('foods')->featured()->with('plan', 'location');
        $restaurants = sortRestaurants($restaurants);
        $restaurants = customPaginate($restaurants, getPaginate());
        return view('Template::restaurants', compact('pageTitle', 'restaurants'));
    }

    public function topRatedRestaurants()
    {
        $pageTitle   = "Top Rated Restaurants";
        $restaurants = Restaurant::active()
            ->whereHas('foods')
            ->with('location')
            ->whereHas('reviews')
            ->withCount('reviews')
            ->withAvg('reviews', 'rating')
            ->orderByDesc('reviews_avg_rating')
            ->paginate(getPaginate());
        return view('Template::restaurants', compact('pageTitle', 'restaurants'));
    }

    public function favoriteRestaurants()
    {
        $pageTitle   = "Favorite Restaurants";
        $user        = auth()->user();
        if (!$user) {
            $notify[] = ['error', 'Please login to see your favorite restaurants '];
            return back()->withNotify($notify);
        }
        $restaurants = sortRestaurants($user->restaurants());
        $restaurants = customPaginate($restaurants, getPaginate());
        return view('Template::favorite_restaurants', compact('pageTitle', 'restaurants'));
    }

    public function categoryFoods($slug)
    {
        $category  = Category::where('slug', $slug)->where('restaurant_id', Status::ADMIN_CATEGORIES)->firstOrFail();
        $pageTitle = $category->name;
        $foods     = $category->foods()->paginate(getPaginate(21));
        return view('Template::foods', compact('pageTitle', 'foods'));
    }

    public function search(Request $request)
    {
        $pageTitle   = "Restaurants";
        $locations   = Location::active()->get();
        $categories  = Category::active()->where('restaurant_id', Status::ADMIN_CATEGORIES)->orderBy('sort_order')->get();
        $type        = $request->type ?? 'restaurant';
        abort_if($type != 'restaurant' && $type != 'food', 404);

        if ($request->category) {
            $category = $categories->where('slug', $request->category)->firstOrFail();
        }

        if ($request->location) {
            $location = $locations->where('slug', $request->location)->firstOrFail();
        }

        if ($type == 'restaurant') {
            $data = $this->filterRestaurantData($request, @$category, @$location);
        } elseif ($type == 'food') {
            $data = $this->filterFoodData($request, @$category, @$location);
        }

        if ($request->sort) {
            $events = $this->sort($request->sort, $data, $type);
        }

        $resultCount = $data->count();
        $data = $data->paginate(getPaginate(18));

        return view('Template::search', compact('pageTitle', 'locations', 'categories', 'type', 'data', 'resultCount'));
    }

    protected function filterRestaurantData($request, $category = null, $location = null)
    {
        $restaurant = Restaurant::active()->whereHas('foods');

        if ($category) {
            $categoryId = $category->id;
            $restaurant = $restaurant->whereHas('foods', function ($food) use ($categoryId) {
                $food->whereHas('categories', function ($categories) use ($categoryId) {
                    $categories->where('categories.id', $categoryId);
                });
            });
        }

        if ($location) {
            $restaurant = $restaurant->where('location_id', $location->id);
        }

        return $restaurant->searchable(['restaurant_name', 'foods:name']);
    }

    protected function filterFoodData($request, $category = null, $location = null)
    {
        $food = Food::whereHas('restaurant', function ($query) {
            $query->active();
        })->published();



        if ($category) {
            $categoryId = $category->id;
            $food = $food->whereHas('categories', function ($categories) use ($categoryId) {
                $categories->where('categories.id', $categoryId);
            });
        }


        if ($location) {
            $locationId = $location->id;
            $food = $food->whereHas('restaurant', function ($query) use ($locationId) {
                $query->where('location_id', $locationId);
            });
        }

        return $food->searchable(['name', 'restaurant:restaurant_name']);
    }

    protected function sort($sort, $data, $type)
    {
        if ($sort == 'newestToOldest') {
            $data = $data->orderBy('created_at', 'desc');
        }

        if ($sort == 'oldestToNewest') {
            $data = $data->orderBy('created_at', 'asc');
        }

        if ($type == 'food') {
            if ($sort == 'priceLowToHigh') {
                $data = $data->orderBy('price', 'asc');
            }
            if ($sort == 'priceHighToLow') {
                $data = $data->orderBy('price', 'desc');
            }
            if ($sort == 'restaurant') {
                $data = $data->orderBy('restaurant_id', 'desc');
            }
        }

        if ($type == 'restaurant') {
            if ($sort == 'restaurant') {
                $data = $data->orderBy('id', 'desc');
            }
            if ($sort == 'location') {
                $data = $data->orderBy('location_id', 'desc');
            }

            if ($sort == 'ratingHighToLow') {
                $data = $data->select('restaurants.*')
                    ->selectSub(function ($query) {
                        $query->selectRaw('CEIL(AVG(rating))')
                            ->from('reviews')
                            ->whereColumn('restaurant_id', 'restaurants.id');
                    }, 'averageRating')
                    ->orderByDesc('averageRating')
                    ->get();
            }

            if ($sort == 'ratingLowToHigh') {
                $data = $data->select('restaurants.*')
                    ->selectSub(function ($query) {
                        $query->selectRaw('CEIL(AVG(rating))')
                            ->from('reviews')
                            ->whereColumn('restaurant_id', 'restaurants.id');
                    }, 'averageRating')
                    ->orderBy('averageRating')
                    ->get();
            }
        }

        return $data;
    }

    public function contact()
    {
        $pageTitle = "Contact Us";
        $user = auth()->user();
        $sections = Page::where('tempname', activeTemplate())->where('slug', 'contact')->first();
        $seoContents = $sections->seo_content;
        $seoImage = @$seoContents->image ? getImage(getFilePath('seo') . '/' . @$seoContents->image, getFileSize('seo')) : null;
        return view('Template::contact', compact('pageTitle', 'user', 'sections', 'seoContents', 'seoImage'));
    }


    public function contactSubmit(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required',
            'subject' => 'required|string|max:255',
            'message' => 'required',
        ]);

        $request->session()->regenerateToken();

        if (!verifyCaptcha()) {
            $notify[] = ['error', 'Invalid captcha provided'];
            return back()->withNotify($notify);
        }

        $random = getNumber();

        $ticket = new SupportTicket();
        $ticket->user_id = auth()->id() ?? 0;
        $ticket->name = $request->name;
        $ticket->email = $request->email;
        $ticket->priority = Status::PRIORITY_MEDIUM;


        $ticket->ticket = $random;
        $ticket->subject = $request->subject;
        $ticket->last_reply = Carbon::now();
        $ticket->status = Status::TICKET_OPEN;
        $ticket->save();

        $adminNotification = new AdminNotification();
        $adminNotification->user_id = auth()->user() ? auth()->user()->id : 0;
        $adminNotification->title = 'A new contact message has been submitted';
        $adminNotification->click_url = urlPath('admin.ticket.view', $ticket->id);
        $adminNotification->save();

        $message = new SupportMessage();
        $message->support_ticket_id = $ticket->id;
        $message->message = $request->message;
        $message->save();

        $notify[] = ['success', 'Ticket created successfully!'];

        return to_route('ticket.view', [$ticket->ticket])->withNotify($notify);
    }

    public function policyPages($slug)
    {
        $policy = Frontend::where('slug', $slug)->where('data_keys', 'policy_pages.element')->firstOrFail();
        $pageTitle = $policy->data_values->title;
        $seoContents = $policy->seo_content;
        $seoImage = @$seoContents->image ? frontendImage('policy_pages', $seoContents->image, getFileSize('seo'), true) : null;
        return view('Template::policy', compact('policy', 'pageTitle', 'seoContents', 'seoImage'));
    }

    public function changeLanguage($lang = null)
    {
        $language = Language::where('code', $lang)->first();
        if (!$language) {
            $language = Language::where('code', 'en')->first();
            $lang     = $language->code;
        } else {
            $lang = $language->code;
        }
        session()->put('lang', $lang);
        return back();
    }

    public function blogDetails($slug)
    {
        $blog = Frontend::where('slug', $slug)->where('data_keys', 'blog.element')->firstOrFail();
        $pageTitle = $blog->data_values->title;
        $seoContents = $blog->seo_content;
        $seoImage = @$seoContents->image ? frontendImage('blog', $seoContents->image, getFileSize('seo'), true) : null;
        return view('Template::blog_details', compact('blog', 'pageTitle', 'seoContents', 'seoImage'));
    }

    public function subscribe(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email|unique:subscribers,email',
        ], [
            'email.unique' => "You have already subscribed",
        ]);

        if ($validator->fails()) {
            return response()->json([
                'error'   => $validator->errors()->all(),
                'success' => false,
            ]);
        }

        $subscribe        = new Subscriber();
        $subscribe->email = $request->email;
        $subscribe->save();

        return response()->json([
            'message' => "Thank you for subscribing us",
            'success' => true,
        ]);
    }

    public function changeTheme(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'mode' => 'required|in:dark,light',
        ]);

        session()->put('theme', $request->mode);

        return response()->json([
            'message' => "Theme changed successfully",
            'success' => true,
        ]);
    }


    public function cookieAccept()
    {
        Cookie::queue('gdpr_cookie', gs('site_name'), 43200);
    }

    public function cookiePolicy()
    {
        $cookieContent = Frontend::where('data_keys', 'cookie.data')->first();
        abort_if($cookieContent->data_values->status != Status::ENABLE, 404);
        $pageTitle = 'Cookie Policy';
        $cookie = Frontend::where('data_keys', 'cookie.data')->first();
        return view('Template::cookie', compact('pageTitle', 'cookie'));
    }

    public function placeholderImage($size = null)
    {
        $imgWidth = explode('x', $size)[0];
        $imgHeight = explode('x', $size)[1];
        $text = $imgWidth . '×' . $imgHeight;
        $fontFile = realpath('assets/font/solaimanLipi_bold.ttf');
        $fontSize = round(($imgWidth - 50) / 8);
        if ($fontSize <= 9) {
            $fontSize = 9;
        }
        if ($imgHeight < 100 && $fontSize > 30) {
            $fontSize = 30;
        }

        $image     = imagecreatetruecolor($imgWidth, $imgHeight);
        $colorFill = imagecolorallocate($image, 100, 100, 100);
        $bgFill    = imagecolorallocate($image, 255, 255, 255);
        imagefill($image, 0, 0, $bgFill);
        $textBox = imagettfbbox($fontSize, 0, $fontFile, $text);
        $textWidth  = abs($textBox[4] - $textBox[0]);
        $textHeight = abs($textBox[5] - $textBox[1]);
        $textX      = ($imgWidth - $textWidth) / 2;
        $textY      = ($imgHeight + $textHeight) / 2;
        header('Content-Type: image/jpeg');
        imagettftext($image, $fontSize, 0, $textX, $textY, $colorFill, $fontFile, $text);
        imagejpeg($image);
        imagedestroy($image);
    }

    public function maintenance()
    {
        $pageTitle = 'Maintenance Mode';
        if (gs('maintenance_mode') == Status::DISABLE) {
            return to_route('home');
        }
        $maintenance = Frontend::where('data_keys', 'maintenance.data')->first();
        return view('Template::maintenance', compact('pageTitle', 'maintenance'));
    }

    public function restaurantDetails($slug)
    {
        $pageTitle    = 'Restaurant Details';
        $restaurant   = Restaurant::where('slug', $slug)->active()->with('reviews')->firstOrFail();
        $restaurantId = $restaurant->id;

        $categories = Category::whereHas('foods', function ($query) use ($restaurantId) {
            $query->where('restaurant_id', $restaurantId);
        })->with(['foods' => function ($query) use ($restaurantId) {
            $query->where('restaurant_id', $restaurantId)->with('variations', 'variations.items', 'addons', 'restaurant');
        }])->get();

        if (!Session::get('session_id')) {
            Session::put('session_id', getNumber());
        }


        $user = auth()->user();
        $sessionId = $user ? 0 : Session::get('session_id');

        $cartItemsQuery = Cart::with('user', 'restaurant', 'food');
        if ($user) {
            $cartItemsQuery->where('user_id', $user->id);
        } else {
            $cartItemsQuery->where('session_id', $sessionId);
        }
        $cartItems = $cartItemsQuery->get();

        return view('Template::restaurant_details', compact('pageTitle', 'restaurant', 'categories', 'cartItems'));
    }

    public function addToCart(Request $request)
    {
        $validation = Validator::make($request->all(), [
            'food_id'          => 'required|numeric|gt:0',
            'restaurant_id'    => 'required|numeric|gt:0',
            'quantity'         => 'required|numeric|gt:0',
            'additional_notes' => 'nullable|string',
            'variation'        => ['nullable', 'array'],
            'variation.*'      => ['required', 'numeric', 'gt:0'],
            'addon'            => ['nullable', 'array'],
            'addon.*'          => ['required', 'numeric', 'gt:0'],
        ]);

        if ($validation->fails()) {
            return response()->json([
                'success' => false,
                'message' => $validation->errors()->all()
            ]);
        }

        if (authRestaurant()) {
            return response()->json([
                'success' => false,
                'message' => 'You are currently logged in as restaurant. Please login as a user to add to cart.'
            ]);
        }

        $user = auth()->user();
        $sessionId = $user ? 0 : Session::get('session_id');

        if (!$user && !$sessionId) {
            Session::put('session_id', getNumber());
        }

        $food = Food::where('id', $request->food_id)->published()->firstOrFail();
        $restaurant = Restaurant::where('id', $request->restaurant_id)->active()->firstOrFail();

        $cartQuery = Cart::where('restaurant_id', '!=', $request->restaurant_id);
        if ($user) {
            $cartQuery->where('user_id', $user->id);
        } else {
            $cartQuery->where('session_id', $sessionId);
        }

        $carts = $cartQuery->first();
        if ($carts) {
            return response()->json([
                'success' => false,
                'modal' => true,
            ]);
        }

        $cart = new Cart();

        if ($request->variation) {
            foreach ($request->variation as $variationId => $variationItemId) {
                $variationItem = VariantItem::where('id', $variationItemId)->first();
                if (!$variationItem) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Variation not found'
                    ]);
                }
                if (@$variationItem->variant->food->id != $food->id) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Variation is invalid'
                    ]);
                }
            }
            $cart->variations = $request->variation;
        }

        if ($request->addon) {
            foreach ($request->addon as $addonId) {
                $addon = Addon::where('id', $addonId)->first();
                if (!$addon) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Addon not found'
                    ]);
                }
                if (@$addon->food->id != $food->id) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Addon is invalid'
                    ]);
                }
            }
            $cart->addons = $request->addon;
        }

        // Store either user ID or session ID in the cart
        $cart->user_id          = $user ? $user->id : 0;
        $cart->session_id       = $sessionId;
        $cart->food_id          = $food->id;
        $cart->restaurant_id    = $restaurant->id;
        $cart->quantity         = $request->quantity;
        $cart->additional_notes = $request->additional_notes;
        $cart->save();

        $cartItemsQuery = Cart::with('restaurant', 'food');
        if ($user) {
            $cartItemsQuery->where('user_id', $user->id);
        } else {
            $cartItemsQuery->where('session_id', $sessionId);
        }

        $cartItems = $cartItemsQuery->get();

        return response()->json([
            'success' => true,
            'message' => 'Added to cart',
            'cart_count' => $cartItems->count(),
            'view' => view('Template::partials.cart', compact('cartItems'))->render(),
        ]);
    }

    public function changeQuantity(Request $request)
    {
        $validation  = Validator::make($request->all(), [
            'cartId'           => 'required|numeric|gt:0',
            'quantity'         => 'nullable|numeric|gte:0',
            'type'             => 'nullable|string',
        ]);

        if ($validation->fails()) {
            return response()->json([
                'success' => false,
                'message' => $validation->errors()->all()
            ]);
        }

        if (!isset($request->quantity) && !isset($request->type)) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid Request'
            ]);
        }

        $user = auth()->user();
        $sessionId = $user ? 0 : Session::get('session_id');

        // Check if the user or session ID exists
        $cartItemQuery = Cart::where('id', $request->cartId);
        if ($user) {
            $cartItemQuery->where('user_id', $user->id);
        } else {
            $cartItemQuery->where('session_id', $sessionId);
        }

        $cartItem = $cartItemQuery->first();
        if (!$cartItem) {
            return response()->json([
                'success' => false,
                'message' => 'Cart item not found'
            ]);
        }

        $quantity = $cartItem->quantity;
        if ($request->type) {
            if ($request->type == '+') {
                $quantity++;
            } elseif ($request->type == '-') {
                $quantity--;
            }
        }

        if ($request->quantity) {
            $quantity = $request->quantity < 0 ? 1 : $request->quantity;
        }

        // Remove the item from the cart if the quantity is zero
        if ($quantity == 0) {
            $cartItem->delete();

            // Check if user is authenticated and get the cart items accordingly
            $cartItemsQuery = Cart::with('user', 'restaurant', 'food');
            if ($user) {
                $cartItemsQuery->where('user_id', $user->id);
            } else {
                $cartItemsQuery->where('session_id', $sessionId);
            }

            $cartItems = $cartItemsQuery->get();

            return response()->json([
                'success' => true,
                'cart_count' => $cartItems->count(),
                'message' => 'Item removed from cart',
                'view'    => view('Template::partials.cart', compact('cartItems'))->render()
            ]);
        }

        // Update the quantity of the cart item
        $cartItem->quantity = $quantity;
        $cartItem->save();

        // Check if user is authenticated and get the cart items accordingly
        $cartItemsQuery = Cart::with('user', 'restaurant', 'food');
        if ($user) {
            $cartItemsQuery->where('user_id', $user->id);
        } else {
            $cartItemsQuery->where('session_id', $sessionId);
        }

        $cartItems = $cartItemsQuery->get();

        return response()->json([
            'success'   => true,
            'message'   => 'Item updated in cart',
            'cart_count' => $cartItems->count(),
            'view'      => view('Template::partials.cart', compact('cartItems'))->render()
        ]);
    }

    public function removeOtherRestaurantsFood(Request $request)
    {
        $validation  = Validator::make($request->all(), [
            'restaurant_id' => 'required',
        ]);

        if ($validation->fails()) {
            return response()->json([
                'success' => false,
                'message' => $validation->errors()->all()
            ]);
        }

        $user = auth()->user();
        $sessionId = $user ? 0 : Session::get('session_id');

        // Delete items based on user or session ID
        $cartQuery = Cart::where('restaurant_id', '!=', $request->restaurant_id);
        if ($user) {
            $cartQuery->where('user_id', $user->id);
        } else {
            $cartQuery->where('session_id', $sessionId);
        }
        $cartQuery->delete();

        return response()->json([
            'success' => true,
            'message' => 'Foods removed successfully',
        ]);
    }

    public function setFavoriteFood($foodId)
    {
        $user = auth()->user();

        if (authRestaurant()) {
            return returnResponse('Please login as user to add food to favorites');
        }

        if (!$user) {
            return returnResponse('Please login to add food to favorites');
        }

        $food = Food::published()->find($foodId);

        if (!$food) {
            return returnResponse('Food not found');
        }

        if ($user->isFavoriteFood($food)) {
            $user->foods()->detach($food);
            return returnResponse('Food removed from favorites', 'success');
        } else {
            $user->foods()->attach($food);
            return returnResponse('Food added to favorites', 'success');
        }
    }

    public function setFavoriteRestaurant($restaurantId)
    {
        $user                = auth()->user();
        if (authRestaurant()) return returnResponse('Please login as user to add restaurant to favorites');
        if (!$user)           return returnResponse('Please login to add restaurant to favorites');
        $restaurant          = Restaurant::active()->find($restaurantId);
        if (!$restaurant)    return returnResponse('Restaurant not found');

        if ($user->isFavoriteRestaurant($restaurant)) {
            $user->restaurants()->detach($restaurant);
            return returnResponse('Restaurant removed from favorites', 'success');
        } else {
            $user->restaurants()->attach($restaurant);
            return returnResponse('Restaurant added to favorites', 'success');
        }
    }

    function adRedirect($hash)
    {
        try {
            $id = decrypt($hash);
        } catch (\Throwable $th) {
            return returnBack('Invalid request');
        }

        $advertisement = Advertisement::find($id);
        if (!$advertisement) {
            return returnBack('Advertisement not found');
        }

        $advertisement->click += 1;
        $advertisement->save();

        return redirect($advertisement->redirect_url);
    }
}
