<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\AdvertisingBanner;
use App\Models\Follow;
use App\Models\Product;
use App\Models\ProductCategory;
use App\Models\ProductFavorite;
use App\Models\ProductOrder;
use App\Models\ProductSelectedFilterOption;
use App\Models\ProductSelectedSpecification;
use App\Models\ProductSpecification;
use App\Models\RewardAccounting;
use App\Models\Sale;
use App\Models\Setting;
use App\Services\ProductCatalogThemeService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class ProductController extends Controller
{

    public function searchLists(Request $request)
    {
        $data = $request->all();

        // Check if this is the Montessori Prints page (category_id = 13)
        $categoryId = !empty($data['category_id']) ? (int)$data['category_id'] : null;
        $isMontessoriPrints = ($categoryId === 13);

        // Get Montessori Prints settings if applicable
        $montessoriPrintsSettings = [];
        $perPage = 9; // Default pagination

        if ($isMontessoriPrints) {
            \Log::info('=== Montessori Prints Page Detected ===');
            \Log::info('Category ID: ' . $categoryId);

            // Clear cache first to ensure fresh data
            cache()->forget('settings.montessori_prints_settings');
            
            // Try to get settings from database
            $montessoriSettings = Setting::where('name', 'montessori_prints_settings')->first();
            \Log::info('Settings Record Found: ' . ($montessoriSettings ? 'Yes (ID: ' . $montessoriSettings->id . ')' : 'No'));

            if (!empty($montessoriSettings)) {
                // Get value - it should use the translated value automatically
                $rawValue = $montessoriSettings->value;
                \Log::info('Raw Value Type: ' . gettype($rawValue));
                \Log::info('Raw Value: ' . (is_string($rawValue) ? substr($rawValue, 0, 200) : json_encode($rawValue)));

                if (!empty($rawValue)) {
                    $decodedValue = is_string($rawValue) ? json_decode($rawValue, true) : $rawValue;
                    if (is_array($decodedValue)) {
                        $montessoriPrintsSettings = $decodedValue;
                        \Log::info('Successfully Decoded Settings');
                    } else {
                        \Log::warning('Failed to decode settings - not an array');
                    }
                } else {
                    \Log::warning('Settings value is empty');
                }

                \Log::info('Final Settings Array: ', $montessoriPrintsSettings);
            } else {
                \Log::warning('No settings record found in database');
            }

            // Get per page from settings
            if (!empty($montessoriPrintsSettings['montessori_prints_per_page'])) {
                $perPage = (int)$montessoriPrintsSettings['montessori_prints_per_page'];
                \Log::info('Per Page from Settings: ' . $perPage);
            } else {
                \Log::info('Using default per page: ' . $perPage);
            }
        }

        $query = Product::where('products.status', Product::$active)
            ->where('ordering', true);

        // Apply Montessori Prints specific filters
        $hasSelectedProducts = false;
        if ($isMontessoriPrints && !empty($montessoriPrintsSettings)) {
            \Log::info('=== Applying Montessori Prints Filters ===');

            // Filter by selected products if set
            $selectedProducts = !empty($montessoriPrintsSettings['montessori_prints_products']) && is_array($montessoriPrintsSettings['montessori_prints_products']) 
                ? $montessoriPrintsSettings['montessori_prints_products'] 
                : [];

            \Log::info('Selected Products Count: ' . count($selectedProducts));
            if (!empty($selectedProducts)) {
                \Log::info('Selected Products IDs: ', $selectedProducts);
            }

            if (!empty($selectedProducts) && count($selectedProducts) > 0) {
                // If products are selected, filter by them ONLY (ignore category filter)
                $query->whereIn('products.id', $selectedProducts);
                $hasSelectedProducts = true;
                \Log::info('Filtering by selected products ONLY - Category filter will be skipped');
            } else {
                // If no products selected, ensure category_id 13 is applied
                \Log::info('No selected products - Will use category filter (category_id=13)');
            }
        }

        // Apply other filters (skip category_id if we have selected products)
        $boundsBaseSnapshot = clone $query;
        $query = $this->handleFilters($request, $query, false, $hasSelectedProducts);

        // Get products with pagination
        $products = $query->with(['selectedFilterOptions'])->paginate($perPage);
        \Log::info('Products Count: ' . $products->total());
        \Log::info('Per Page Used: ' . $perPage);

        $categories = ProductCategory::whereNull('parent_id')
            ->with([
                'subCategories' => function ($query) {
                    $query->orderBy('order', 'asc');
                },
            ])
            ->get();

        $selectedCategory = null;

        if (!empty($data['category_id'])) {
            $selectedCategory = ProductCategory::where('id', $data['category_id'])
                ->with(['filters.options', 'filters'])
                ->first();
        }

        $seoSettings = getSeoMetas('products_lists');
        $pageTitle = $seoSettings['title'] ?? '';
        $pageDescription = $seoSettings['description'] ?? '';
        $pageRobot = getPageRobot('products_lists');

        $payload = [
            'pageTitle' => $pageTitle,
            'pageDescription' => $pageDescription,
            'pageRobot' => $pageRobot,
            'productsCount' => $products->total(),
            'productCategories' => $categories,
            'selectedCategory' => $selectedCategory,
            'products' => $products,
        ];

        return view(getTemplate() . '.products.search', $this->augmentCatalogListing(
            $request,
            $payload,
            'main',
            false,
            $boundsBaseSnapshot,
            $hasSelectedProducts,
            [
                'isMontessoriPrints' => $isMontessoriPrints,
            ]
        ));
    }

    public function handleFilters(Request $request, $query, $isRewardProducts = false, $skipCategoryFilter = false, array $omitFilters = [])
    {
        $isFree = $request->get('free', null);
        $isFreeShipping = $request->get('free_shipping', null);
        $withDiscount = $request->get('discount', null);
        $sort = $request->get('sort', null);
        $type = $request->get('type', null);
        $options = $request->get('options', null);
        $categoryId = $request->get('category_id', null);
        $filterOption = $request->get('filter_option', null);

        if (! empty($isFree) and $isFree == 'on') {
            $query->where(function ($qu) {
                $qu->whereNull('price')
                    ->orWhere('price', '0');
            });
        }

        if (! empty($isFreeShipping) and $isFreeShipping == 'on') {
            $query->where(function ($qu) {
                $qu->whereNull('delivery_fee')
                    ->orWhere('delivery_fee', '0');
            });
        }

        if (! empty($withDiscount) and $withDiscount == 'on') {
            $query->whereHas('discounts', function ($query) {
                $query->where('status', 'active')
                    ->where('start_date', '<', time())
                    ->where('end_date', '>', time());
            });
        }

        if (! empty($type) and count($type)) {
            $query->whereIn('type', $type);
        }

        if (! empty($options) and count($options)) {
            if (in_array('only_available', $options)) {
                $query->where(function ($query) {
                    $query->where('unlimited_inventory', true)
                        ->orWhereHas('productOrders', function ($query) {
                            $query->havingRaw('products.inventory > sum(quantity)')
                                ->whereNotNull('sale_id')
                                ->whereNotIn('status', [ProductOrder::$canceled, ProductOrder::$pending])
                                ->groupBy('product_id');
                        });
                });
            }

            if (in_array('with_point', $options)) {
                $query->whereNotNull('point');
            }
        }

        if (! empty($categoryId) && ! $skipCategoryFilter) {
            $query->where(function ($q) use ($categoryId) {
                $q->where('category_id', $categoryId)
                  ->orWhereHas('categories', function ($q2) use ($categoryId) {
                      $q2->where('category_id', $categoryId);
                  });
            });
        }

        if (! empty($filterOption) and is_array($filterOption)) {
            $productIdsFilterOptions = ProductSelectedFilterOption::whereIn('filter_option_id', $filterOption)
                ->pluck('product_id')
                ->toArray();

            $productIdsFilterOptions = array_unique($productIdsFilterOptions);

            $query->whereIn('products.id', $productIdsFilterOptions);
        }

        $needle = trim((string) $request->get('q', $request->get('search', '')));
        if (! in_array('text_search', $omitFilters) && $needle !== '') {
            $needleLike = '%' . addcslashes($needle, '%_\\') . '%';
            $query->whereTranslationLike('title', $needleLike);
        }

        if (! in_array('price_range', $omitFilters)) {
            $hasMin = $request->filled('min_price');
            $hasMax = $request->filled('max_price');

            if ($hasMin || $hasMax) {
                $minVal = $hasMin ? (float) $request->get('min_price') : null;
                $maxVal = $hasMax ? (float) $request->get('max_price') : null;

                $query->where(function ($outer) use ($minVal, $maxVal, $hasMin, $hasMax) {
                    $outer->where(function ($priced) use ($minVal, $maxVal, $hasMin, $hasMax) {
                        $priced->whereNotNull('products.price')->where('products.price', '>', 0);

                        if ($hasMin && $minVal !== null) {
                            $priced->where('products.price', '>=', $minVal);
                        }

                        if ($hasMax && $maxVal !== null) {
                            $priced->where('products.price', '<=', $maxVal);
                        }
                    });

                    $includeFree = (! $hasMin) || ($minVal !== null && $minVal <= 0);

                    if ($includeFree) {
                        $outer->orWhere(function ($free) {
                            $free->whereNull('products.price')
                                ->orWhere('products.price', '=', 0);
                        });
                    }
                });
            }
        }

        if (! empty($sort) && ! in_array('sort_only', $omitFilters)) {
            if ($sort == 'newest') {
                $query->orderBy('products.id', 'desc');
            }

            if ($sort == 'expensive') {
                if ($isRewardProducts) {
                    $query->orderBy('point', 'desc');
                } else {
                    $query->orderBy('price', 'desc');
                }
            }

            if ($sort == 'inexpensive') {
                if ($isRewardProducts) {
                    $query->orderBy('point', 'asc');
                } else {
                    $query->orderBy('price', 'asc');
                }
            }

            if ($sort == 'bestsellers') {
                $query->leftJoin('product_orders', function ($join) {
                    $join->on('products.id', '=', 'product_orders.product_id')
                        ->whereNotNull('product_orders.sale_id')
                        ->whereNotIn('product_orders.status', [ProductOrder::$canceled, ProductOrder::$pending]);
                })
                    ->select('products.*', DB::raw('sum(product_orders.quantity) as salesCounts'))
                    ->groupBy('product_orders.product_id')
                    ->orderBy('salesCounts', 'desc');
            }

            if ($sort == 'best_rates') {
                $query->leftJoin('product_reviews', function ($join) {
                    $join->on('products.id', '=', 'product_reviews.product_id');
                    $join->where('product_reviews.status', 'active');
                })
                    ->whereNotNull('rates')
                    ->select('products.*', DB::raw('avg(rates) as rates'))
                    ->groupBy('product_reviews.product_id')
                    ->orderBy('rates', 'desc');
            }
        }

        return $query;
    }

    public function listingPriceBounds(Request $request, Builder $startingQuery, bool $isRewardProducts = false, bool $skipCategoryFilter = false): array
    {
        $qb = $this->handleFilters($request, clone $startingQuery, $isRewardProducts, $skipCategoryFilter, ['sort_only', 'price_range', 'text_search']);
        try {
            $minPrice = (clone $qb)->whereNotNull('products.price')->where('products.price', '>', 0)->min('products.price');
            $maxPrice = (clone $qb)->whereNotNull('products.price')->max('products.price');
        } catch (\Throwable $e) {
            return ['min' => 0, 'max' => 0];
        }

        $minPrice = isset($minPrice) && $minPrice !== null ? (float) $minPrice : 0.0;
        $maxPrice = isset($maxPrice) && $maxPrice !== null ? (float) $maxPrice : 0.0;

        if (($maxPrice === 0.0 || $maxPrice === 0) && ($minPrice === 0.0 || $minPrice === 0)) {
            return ['min' => 0, 'max' => 0];
        }

        return ['min' => $minPrice, 'max' => $maxPrice > $minPrice ? $maxPrice : ($minPrice + 1)];
    }

    protected function bestsellerProductIds(): array
    {
        return Cache::remember('imt_products_bestseller_ids_v1', 3600, function () {
            return DB::table('product_orders')
                ->join('products', 'product_orders.product_id', '=', 'products.id')
                ->where('products.status', Product::$active)
                ->where('products.ordering', true)
                ->whereNotNull('product_orders.sale_id')
                ->whereNotIn('product_orders.status', [ProductOrder::$canceled, ProductOrder::$pending])
                ->groupBy('product_orders.product_id')
                ->select('product_orders.product_id', DB::raw('SUM(product_orders.quantity) as sold'))
                ->orderByDesc('sold')
                ->limit(120)
                ->pluck('product_orders.product_id')
                ->map(function ($id) {
                    return (int) $id;
                })
                ->all();
        });
    }

    public function augmentCatalogListing(
        Request $request,
        array $payload,
        string $listingKey,
        bool $isReward,
        Builder $boundsBaseSnapshot,
        bool $skipCategoryForBounds = false,
        array $flags = []
    ): array {
        $selectedCategory = $payload['selectedCategory'] ?? null;
        $productsCount = (int) ($payload['productsCount'] ?? 0);
        $isMontessoriPrints = ! empty($flags['isMontessoriPrints']);

        $svc = app(ProductCatalogThemeService::class);
        $theme = $svc->resolveListingTheme($listingKey, $selectedCategory, $isMontessoriPrints, $isReward);

        $listingContext = [
            'products_count' => $productsCount,
            'listing_key' => $listingKey,
        ];
        $svc->localizedHeroTitles($theme, $selectedCategory, $listingContext);
        $svc->logListingThemeDiagnostics($request, $listingKey, $theme);

        $payload['catalogTheme'] = $theme;

        $payload['priceBounds'] = $this->listingPriceBounds($request, clone $boundsBaseSnapshot, $isReward, $skipCategoryForBounds);

        $payload['favoriteProductIds'] = [];
        if (auth()->check()) {
            $payload['favoriteProductIds'] = ProductFavorite::where('user_id', auth()->id())
                ->pluck('product_id')
                ->map(function ($id) {
                    return (int) $id;
                })
                ->all();
        }

        $payload['bestsellerProductIds'] = $this->bestsellerProductIds();
        $payload['recommendedFilterOptionIds'] = config('product_catalog_themes.recommended_filter_option_ids', []);
        $payload['new_product_days'] = (int) config('product_catalog_themes.new_product_days', 30);
        $payload['is_reward_products_page'] = $isReward;

        return $payload;
    }

    public function quickView($id)
    {
        $product = Product::where('status', Product::$active)
            ->where('ordering', true)
            ->where('id', $id)
            ->with(['category'])
            ->first();

        if (empty($product)) {
            abort(404);
        }

        return view(getTemplate() . '.products.includes.quick_view', [
            'product' => $product,
        ]);
    }

    public function show($slug)
    {
        $user = null;

        if (auth()->check()) {
            $user = auth()->user();
        }

        $product = Product::where('status', Product::$active)
            ->where('slug', $slug)
            ->with([
                'selectedSpecifications' => function ($query) {
                    $query->where('status', ProductSelectedSpecification::$Active);
                    $query->with(['specification']);
                },
                'comments' => function ($query) {
                    $query->where('status', 'active');
                    $query->whereNull('reply_id');
                    $query->with([
                        'user' => function ($query) {
                            $query->select('id', 'full_name', 'role_name', 'role_id', 'avatar');
                        },
                        'replies' => function ($query) {
                            $query->where('status', 'active');
                            $query->with([
                                'user' => function ($query) {
                                    $query->select('id', 'full_name', 'role_name', 'role_id', 'avatar');
                                }
                            ]);
                        }
                    ]);
                    $query->orderBy('created_at', 'desc');
                },
                'files' => function ($query) {
                    $query->where('status', 'active');
                    $query->orderBy('order', 'asc');
                },
                'reviews' => function ($query) {
                    $query->where('status', 'active');
                    $query->with([
                        'comments' => function ($query) {
                            $query->where('status', 'active');
                        },
                        'creator' => function ($qu) {
                            $qu->select('id', 'full_name', 'avatar');
                        }
                    ]);
                },
                'selectedFilterOptions',
            ])
            ->first();

        if (empty($product)) {
            abort(404);
        }

        $selectableSpecifications = $product->selectedSpecifications->where('allow_selection', true)
            ->where('type', 'multi_value');
        $selectedSpecifications = $product->selectedSpecifications->where('allow_selection', false);

        $seller = $product->creator;
        $following = $seller->following();
        $followers = $seller->followers();

        $authUserIsFollower = false;
        if (auth()->check()) {
            $authUserIsFollower = $followers->where('follower', auth()->id())
                ->where('status', Follow::$accepted)
                ->first();
        }

        $advertisingBanners = AdvertisingBanner::where('published', true)
            ->whereIn('position', ['product_show'])
            ->get();


        $pageRobot = getPageRobot('product_show'); // return => index
        $related_products = Product::where('category_id', $product->category_id)->where('id', '!=', $product->id)
            ->where('ordering', true)
            ->with(['selectedFilterOptions'])
            ->take(6)
            ->get();

        $favoriteProductIds = [];
        $productIsFavorited = false;
        if (auth()->check()) {
            $favoriteProductIds = ProductFavorite::where('user_id', auth()->id())
                ->pluck('product_id')
                ->map(function ($id) {
                    return (int) $id;
                })
                ->all();
            $productIsFavorited = ProductFavorite::where('user_id', auth()->id())
                ->where('product_id', $product->id)
                ->exists();
        }

        $data = [
            'pageTitle' => $product->title,
            'pageDescription' => $product->seo_description,
            'pageRobot' => $pageRobot,
            'product' => $product,
            'user' => $user,
            'selectableSpecifications' => $selectableSpecifications,
            'selectedSpecifications' => $selectedSpecifications,
            'seller' => $seller,
            'sellerBadges' => $seller->getBadges(),
            'sellerRates' => $seller->rates(),
            'sellerFollowers' => $following,
            'sellerFollowing' => $followers,
            'authUserIsFollower' => $authUserIsFollower,
            'advertisingBanners' => $advertisingBanners,
            'activeSpecialOffer' => $product->getActiveDiscount(),
            'related_products' => $related_products,
            'favoriteProductIds' => $favoriteProductIds,
            'productIsFavorited' => $productIsFavorited,
            'bestsellerProductIds' => $this->bestsellerProductIds(),
            'recommendedFilterOptionIds' => config('product_catalog_themes.recommended_filter_option_ids', []),
            'new_product_days' => (int) config('product_catalog_themes.new_product_days', 30),
        ];

        return view(getTemplate() . '.products.show', $data);
    }

    public function books(Request $request)
    {
        $storeSettings = \App\Models\Setting::getStoreSettings();

        // Get selected books products from settings
        $selectedBooksProducts = !empty($storeSettings['books_products']) && is_array($storeSettings['books_products']) 
            ? $storeSettings['books_products'] 
            : [];

        if (!empty($selectedBooksProducts)) {
            // Show only selected products
            $query = Product::where('products.status', Product::$active)
                ->where('ordering', true)
                ->whereIn('products.id', $selectedBooksProducts);
        } else {
            // If no products selected, show all active products
            $query = Product::where('products.status', Product::$active)
                ->where('ordering', true);
        }

        $boundsBaseSnapshot = clone $query;
        $query = $this->handleFilters($request, $query);

        $perPage = ! empty($storeSettings['books_per_page']) ? (int) $storeSettings['books_per_page'] : 24;

        $products = $query->with(['selectedFilterOptions'])->paginate($perPage);

        $categories = ProductCategory::whereNull('parent_id')
            ->with([
                'subCategories' => function ($query) {
                    $query->orderBy('order', 'asc');
                },
            ])
            ->get();

        $selectedCategory = null;
        $booksCategoryId = $request->get('category_id', null);
        if (! empty($booksCategoryId)) {
            $selectedCategory = ProductCategory::where('id', $booksCategoryId)
                ->with(['filters.options', 'filters'])
                ->first();
        }

        $seoSettings = getSeoMetas('books');
        $pageTitle = $seoSettings['title'] ?? trans('update.books');
        $pageDescription = $seoSettings['description'] ?? '';
        $pageRobot = getPageRobot('books');

        $payload = [
            'pageTitle' => $pageTitle,
            'pageDescription' => $pageDescription,
            'pageRobot' => $pageRobot,
            'productsCount' => $products->total(),
            'productCategories' => $categories,
            'selectedCategory' => $selectedCategory,
            'products' => $products,
        ];

        return view(getTemplate() . '.products.books', $this->augmentCatalogListing(
            $request,
            $payload,
            'books',
            false,
            $boundsBaseSnapshot,
            false,
            []
        ));
    }

    public function toolsAndPrintables(Request $request)
    {
        $storeSettings = \App\Models\Setting::getStoreSettings();
        $isEnabled = ! empty($storeSettings['tools_and_printables_status']) && $storeSettings['tools_and_printables_status'];

        if (! $isEnabled) {
            abort(404);
        }

        $query = Product::where('products.status', Product::$active)
            ->where('ordering', true);

        $boundsBaseSnapshot = clone $query;

        $query = $this->handleFilters($request, $query);

        $perPage = ! empty($storeSettings['tools_and_printables_per_page']) ? (int) $storeSettings['tools_and_printables_per_page'] : 24;

        $products = $query->with(['selectedFilterOptions'])->paginate($perPage);

        $categories = ProductCategory::whereNull('parent_id')
            ->with([
                'subCategories' => function ($query) {
                    $query->orderBy('order', 'asc');
                },
            ])
            ->get();

        $selectedCategory = null;
        $categoryKey = $request->get('category_id', null);
        if (! empty($categoryKey)) {
            $selectedCategory = ProductCategory::where('id', $categoryKey)
                ->with(['filters.options', 'filters'])
                ->first();
        }

        $seoSettings = getSeoMetas('tools_and_printables');
        $pageTitle = $seoSettings['title'] ?? trans('update.tools_and_printables');
        $pageDescription = $seoSettings['description'] ?? '';
        $pageRobot = getPageRobot('tools_and_printables');

        $payload = [
            'pageTitle' => $pageTitle,
            'pageDescription' => $pageDescription,
            'pageRobot' => $pageRobot,
            'productsCount' => $products->total(),
            'productCategories' => $categories,
            'selectedCategory' => $selectedCategory,
            'products' => $products,
        ];

        return view(getTemplate() . '.products.tools_and_printables', $this->augmentCatalogListing(
            $request,
            $payload,
            'tools_printables',
            false,
            $boundsBaseSnapshot,
            false,
            []
        ));
    }

    public function toolsOfIlmonstery(Request $request)
    {
        // Get settings - clear cache first to ensure fresh data
        cache()->forget('settings.tools_of_ilmonstery_settings');
        
        $storeSettings = \App\Models\Setting::getStoreSettings();
        $toolsSettings = Setting::where('name', 'tools_of_ilmonstery_settings')->first();
        $toolsSettingsValue = [];
        
        if (!empty($toolsSettings) && !empty($toolsSettings->value)) {
            $decodedValue = is_string($toolsSettings->value) ? json_decode($toolsSettings->value, true) : $toolsSettings->value;
            if (is_array($decodedValue)) {
                $toolsSettingsValue = $decodedValue;
            }
        }

        // Check if page is enabled
        $isEnabled = !empty($toolsSettingsValue['tools_of_ilmonstery_status']) && $toolsSettingsValue['tools_of_ilmonstery_status'];
        
        if (!$isEnabled) {
            abort(404);
        }

        $data = $request->all();

        $query = Product::where('products.status', Product::$active)
            ->where('ordering', true);

        // Filter by selected products if set
        $selectedProducts = !empty($toolsSettingsValue['tools_of_ilmonstery_products']) && is_array($toolsSettingsValue['tools_of_ilmonstery_products']) 
            ? $toolsSettingsValue['tools_of_ilmonstery_products'] 
            : [];

        if (!empty($selectedProducts)) {
            $query->whereIn('products.id', $selectedProducts);
        } else {
            // If no products selected, filter by category from settings
            $settingsCategoryId = !empty($toolsSettingsValue['tools_of_ilmonstery_category_id']) ? $toolsSettingsValue['tools_of_ilmonstery_category_id'] : null;
            
            if (!empty($settingsCategoryId)) {
                $query->where(function($q) use ($settingsCategoryId) {
                    $q->where('category_id', $settingsCategoryId)
                      ->orWhereHas('categories', function($q2) use ($settingsCategoryId) {
                          $q2->where('category_id', $settingsCategoryId);
                      });
                });
            }
        }

        $boundsBaseSnapshot = clone $query;
        $query = $this->handleFilters($request, $query);

        $perPage = ! empty($toolsSettingsValue['tools_of_ilmonstery_per_page']) ? (int) $toolsSettingsValue['tools_of_ilmonstery_per_page'] : 24;

        $products = $query->with(['selectedFilterOptions'])->paginate($perPage);

        $categories = ProductCategory::whereNull('parent_id')
            ->with([
                'subCategories' => function ($query) {
                    $query->orderBy('order', 'asc');
                },
            ])
            ->get();

        $selectedCategory = null;
        if (! empty($data['category_id'])) {
            $selectedCategory = ProductCategory::where('id', $data['category_id'])
                ->with(['filters.options', 'filters'])
                ->first();
        }

        $seoSettings = getSeoMetas('tools_of_ilmonstery');
        $pageTitle = $seoSettings['title'] ?? trans('navbar.tools_montessori');
        $pageDescription = $seoSettings['description'] ?? '';
        $pageRobot = getPageRobot('tools_of_ilmonstery');

        $payload = [
            'pageTitle' => $pageTitle,
            'pageDescription' => $pageDescription,
            'pageRobot' => $pageRobot,
            'productsCount' => $products->total(),
            'productCategories' => $categories,
            'selectedCategory' => $selectedCategory,
            'products' => $products,
        ];

        return view(getTemplate() . '.products.tools_of_ilmonstery', $this->augmentCatalogListing(
            $request,
            $payload,
            'tools_ilmonstery',
            false,
            $boundsBaseSnapshot,
            false,
            []
        ));
    }

    public function buyWithPoint(Request $request, $slug)
    {
        if (auth()->check()) {
            $user = auth()->user();
            $data = $request->all();

            $product = Product::where('slug', $slug)
                ->where('status', 'active')
                ->first();

            $product_id = $data['item_id'];
            $specifications = $data['specifications'] ?? null;
            $quantity = $data['quantity'] ?? 1;

            if (!empty($product) and $product_id == $product->id) {
                if (empty($product->point)) {
                    $toastData = [
                        'title' => '',
                        'msg' => trans('update.can_not_buy_this_product_with_point'),
                        'status' => 'error'
                    ];
                    return back()->with(['toast' => $toastData]);
                }

                $availablePoints = $user->getRewardPoints();

                if ($availablePoints < $product->point) {
                    $toastData = [
                        'title' => '',
                        'msg' => trans('update.you_have_no_enough_points_for_this_product'),
                        'status' => 'error'
                    ];
                    return back()->with(['toast' => $toastData]);
                }

                $checkCourseForSale = checkProductForSale($product, $user);

                if ($checkCourseForSale != 'ok') {
                    return $checkCourseForSale;
                }

                $productOrder = ProductOrder::create([
                    'product_id' => $product->id,
                    'seller_id' => $product->creator_id,
                    'buyer_id' => $user->id,
                    'specifications' => $specifications ? json_encode($specifications) : null,
                    'quantity' => $quantity,
                    'status' => 'pending',
                    'created_at' => time()
                ]);

                $sale = Sale::create([
                    'buyer_id' => $user->id,
                    'seller_id' => $product->creator_id,
                    'product_order_id' => $productOrder->id,
                    'type' => Sale::$product,
                    'payment_method' => Sale::$credit,
                    'amount' => 0,
                    'total_amount' => 0,
                    'created_at' => time(),
                ]);

                $productOrder->update([
                    'sale_id' => $sale->id,
                    'status' => $product->isVirtual() ? ProductOrder::$success : ProductOrder::$waitingDelivery,
                ]);

                RewardAccounting::makeRewardAccounting($user->id, $product->point, 'withdraw', null, false, RewardAccounting::DEDUCTION);

                $toastData = [
                    'title' => '',
                    'msg' => trans('update.success_pay_product_with_point_msg'),
                    'status' => 'success'
                ];
                return back()->with(['toast' => $toastData]);
            }

            abort(404);
        } else {
            return redirect('/login');
        }
    }
}
