<?php

namespace App\Http\Controllers\Frontend;

use App\Traits\FiresFacebookEventsTrait;
use Carbon\Carbon;
use App\Models\Product;
use App\Models\Variant;
use App\Models\Category;
use App\Models\Attribute;
use App\Models\SubCategory;
use App\Models\ProductVisit;
use Illuminate\Http\Request;
use App\Models\ProductReview;
use App\Models\GeneralSetting;
use App\Models\ProductVariant;
use App\Models\SiteConfiguration;
use App\Services\FrontendService;
use App\Models\BookAttachmentsImg;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Models\City;
use Illuminate\Support\Facades\Auth;
use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Support\Str;
use App\Models\Country;
use App\Traits\TypeWiseProducts;
use App\Models\Brand;

class ProductController extends Controller
{
    use FiresFacebookEventsTrait;
    use TypeWiseProducts;
    protected $site_configuration;

    public function __construct()
    {
        $this->site_configuration = SiteConfiguration::select('template_id', 'position_wise_product', 'active_server_side', 'fb_pixel_id')->first();
    }
    public function index()
    {
        return view('frontend.pages.product.index');
    }

    public function singleProduct(Request $request, $slug)
    {
        $product = Product::with([
            'category:id,name,slug,status',
            'subCategory:id,name,slug',
            'subSubCategory:id,name,slug',
            'productImage:id,product_id,image',
            'productVariant' => function ($q) {
                $q->where('status', 1)
                    ->select('id', 'product_id', 'variant_id', 'attribute_id', 'price', 'stock', 'image', 'status');
            },
            'productVariant:id,product_id,variant_id,attribute_id,price,stock,status,image',
            'productVariant.variant:id,name,status',
            'author:id,name',
            'publisher:id,name',
            'brand:id,slug,image'
        ])
            ->select('id', 'category_id', 'sub_category_id', 'sub_sub_category_id', 'name', 'avg_review', 'product_code', 'thumbnail_img', 'video_url', 'slug', 'stock', 'sale_price', 'discount', 'price', 'stock', 'status', 'details', 'meta_title', 'meta_description', 'meta_key', 'review_ratings', 'avg_review', 'author_id', 'publisher_id', 'information', 'created_at', 'brand_id', 'size_chart')
            ->where('slug', $slug)
            ->where('status', 1)
            ->firstOrFail();

        // return $product;

        $template = 'template' . $this->site_configuration->template_id;
        $category_id = $product->category->id ?? null;
        $sub_category_id = $product->subCategory->id ?? null;
        $sub_sub_category_id = $product->subSubCategory->id ?? null;

        $related_products = FrontendService::relatedProducts($product->id, $category_id, $sub_category_id, $sub_sub_category_id, $this->site_configuration->position_wise_product);
        //===================review section start===========================
        $product_review = ProductReview::where('product_id', $product->id)->where('status', 1)->get();

        $five_star = $product_review->where('rating_stars', 5)->count();
        $four_star = $product_review->where('rating_stars', 4)->count();
        $three_star = $product_review->where('rating_stars', 3)->count();
        $two_star = $product_review->where('rating_stars', 2)->count();
        $one_star = $product_review->where('rating_stars', 1)->count();

        $rating_stars = [
            'five_star' => $five_star,
            'four_star' => $four_star,
            'three_star' => $three_star,
            'two_star' => $two_star,
            'one_star' => $one_star,
        ];

        $product->{'rating_stars'} = $rating_stars;

        $product_reviews = ProductReview::where('product_id', $product->id)->where('status', 1)->orderBy('id', 'desc')->paginate(6);
        $total_review = DB::table('product_reviews')->where('status', 1)->where('product_id', $product->id)->count();

        $total_ratings = ($five_star * 5) + ($four_star * 4) + ($three_star * 3) + ($two_star * 2) + ($one_star * 1);
        $average_ratings = $total_ratings / 5;
        //===================review section end===========================
        $delivery_charges = DB::table('delivery_charges')->take(2)->get();
        $attributes = Attribute::orderBy('id', 'asc')->where('status', 1)->pluck('name', 'id');
        $book_img = BookAttachmentsImg::where('product_id', $product->id)->get();


        /* ============ product visitor ============== */
        $this->storeProductVisit($request, $product);
        /* ============ product visitor ============== */

        $data = [
            'product' => $product,
            'related_products' => $related_products,
            'product_reviews' => $product_reviews,
            'total_review' => $total_review,
            'average_ratings' => $average_ratings,
            'delivery_charges' => $delivery_charges,
            'attributes' => $attributes,
            'book_img' => $book_img,
        ];

        return view("frontend.pages.product.single_product.$template", $data);
    }

    public function storeProductVisit($request, $product)
    {
        $timeThreshold = Carbon::now()->subMinutes(30);
        $sessionId = session()->getId();
        $ipAddress = request()->ip();

        // Check for a visit by session or IP, regardless of the time threshold
        $visit = ProductVisit::where('product_id', $product->id)
            ->where(function ($query) use ($sessionId, $ipAddress) {
                $query->orWhere('session_id', $sessionId)
                    ->orWhere('ip', $ipAddress);
            })
            ->first();
        if (!empty($visit)) {
            $visit->update(['visit_time' => Carbon::now()]);
            //  if the visit is older than the 30-minute
            if ($visit->visit_time <= $timeThreshold) {
                $visit->increment('qty');
            }
        } else {
            ProductVisit::create([
                'ip' => $ipAddress,
                'product_id' => $product->id,
                'qty' => 1,
                'session_id' => $sessionId,
                'visit_time' => Carbon::now(),
            ]);
        }
    }

    //category wise product
    public function getCategoryProduct($slug, $sub_slug = null, $sub_sub_slug = null)
    {
        $category_slug = $slug;
        $sub_category_slug = $sub_slug;
        $sub_sub_category_slug = $sub_sub_slug;
        $category = null;
        $sub_category = null;
        $sub_sub_category = null;

        if ($category_slug && $sub_category_slug && $sub_sub_category_slug) {
            $category = DB::table('categories')->where('slug', $category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();
            $sub_sub_category = DB::table('sub_sub_categories')->where('slug', $sub_sub_category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();
            $sub_category = DB::table('sub_categories')->where('slug', $sub_category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();

            if (!$category || !$sub_category || !$sub_sub_category) {
                abort(404);
            }

            $products_ids = FrontendService::productIds('sub_sub_category_id', $sub_sub_category->id);
            $products = FrontendService::productFetcher($products_ids);
        } elseif ($category_slug && $sub_category_slug) {
            $category = DB::table('categories')->where('slug', $category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();
            $sub_category = SubCategory::with(['subSubCategory:id,name,slug,category_id,subcategory_id'])->where('slug', $sub_category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();

            if (!$category || !$sub_category) {
                abort(404);
            }

            $products_id = FrontendService::productIds('sub_category_id', $sub_category->id);
            $products = FrontendService::productFetcher($products_id);
        } elseif ($category_slug && $sub_category_slug == null && $sub_sub_category_slug == null) {
            $category = Category::with(['subCategory:id,name,slug,category_id'])->where('slug', $category_slug)->select('id', 'name', 'slug', 'meta_title', 'meta_description', 'meta_key', 'meta_content')->first();

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

            $products_id = FrontendService::productIds('category_id', $category->id);
            $products = FrontendService::productFetcher($products_id);
        } else {
            abort(404);
        }

        $data = [
            'products' => $products,
            'category' => $category,
            'sub_category' => $sub_category,
            'sub_sub_category' => $sub_sub_category,
            'selected_sub_sub_category_id' => $sub_sub_category ? $sub_sub_category->id : null,
        ];

        if ($this->site_configuration->template_id == 9) {
            return view('frontend.pages.product.cosmetic', $data);
            // return view('frontend.pages.product.index', $data);

        } else {
            return view('frontend.pages.product.index', $data);
        }
    }

    //brand wise product
    public function getBrandProduct($slug)
    {
        $brand_slug = $slug;
        $brand = null;

        if ($brand_slug) {
            $brand = DB::table('brands')->where('slug', $brand_slug)->select('id', 'name', 'slug', 'image')->first();

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

            $products_id = FrontendService::productIdForBrand('brand_id', $brand->id);
            $products = FrontendService::brandProductFetcher($products_id);
        } else {
            abort(404);
        }

        $data = [
            'products' => $products,
            'brand' => $brand,
        ];

        return view('frontend.pages.product.brand_product', $data);
    }


    //-------------Product search-----------------
    public function searchProduct(Request $request)
    {
        $search_key = $request->key;
        $search_numeric_key = is_numeric($search_key);
        if (!$search_numeric_key) {
            $products = Product::select('id', 'category_id', 'name', 'status', 'thumbnail_img', 'slug', 'sale_price', 'discount', 'stock', 'price')
                ->Where('product_code', 'LIKE', "%$search_key%")
                ->orWhere('details', 'like', '%' . $search_key . '%')
                ->orWhere('name', 'like', '%' . $search_key . '%')
                ->where('status', 1)
                ->inRandomOrder()
                ->latest()
                ->get();
        } else {
            $products = Product::select('id', 'category_id', 'name', 'status', 'thumbnail_img', 'slug', 'sale_price', 'discount', 'stock', 'price')
                ->where('product_code', $search_key)
                ->where('status', 1)
                ->inRandomOrder()
                ->latest()
                ->get();
        }

        $html = view('frontend.components.search_product', compact('products'))->render();
        // return $this->fireFacebookSearchEvent($search_key, $request);
        return response()->json([
            'status' => true,
            'message' => 'Search Successful',
            'data' => $html,
        ]);
    }

    public function loadSearchProducts(Request $request)
    {

        $searchTerm = $request->input('searchInput');
        $search_numeric_key = is_numeric($searchTerm);
        if (!$search_numeric_key) {
            $products = Product::select('id', 'category_id', 'sub_category_id', 'sub_sub_category_id', 'name', 'product_code', 'thumbnail_img', 'slug', 'stock', 'sale_price', 'discount', 'price', 'stock', 'status', 'details', 'is_free_delivery', 'review_ratings', 'author_id', 'publisher_id', 'avg_review', 'created_at')
                ->Where('product_code', 'LIKE', "%$searchTerm%")
                ->orWhere('details', 'like', '%' . $searchTerm . '%')
                ->orWhere('name', 'like', '%' . $searchTerm . '%')
                ->where('status', 1)
                ->inRandomOrder()
                ->latest()
                ->get();
        } else {
            $products = Product::select('id', 'category_id', 'sub_category_id', 'sub_sub_category_id', 'name', 'product_code', 'thumbnail_img', 'slug', 'stock', 'sale_price', 'discount', 'price', 'stock', 'status', 'details', 'is_free_delivery', 'review_ratings', 'author_id', 'publisher_id', 'avg_review', 'created_at')
                ->where('product_code', $searchTerm)
                ->where('status', 1)
                ->inRandomOrder()
                ->latest()
                ->get();
        }
        return view('frontend.components.load_search_product', compact('products', 'searchTerm'));
    }
    //--------------get product content----------------------
    public function getProductContent(Request $request)
    {
        $cart_total = Cart::total();
        $brand = GeneralSetting::select('title')->first();
        $product = Product::with(['category:id,name,status', 'subCategory:id,name', 'subSubCategory:id,name'])
            ->select('id', 'category_id', 'sub_category_id', 'stock', 'sub_sub_category_id', 'name', 'product_code', 'sale_price', 'discount', 'price', 'is_free_delivery')
            ->where('id', $request->product_id)
            ->firstOrFail();
        $coupon = DB::table('coupons')->select('id', 'code')->where('status', 1)->first();
        try {
            $items = [];
            $data = [];
            $data['product_id'] = $product->product_code;
            $data['item_id'] = $product->product_code;
            $data['item_name'] = $product->name;
            $data['affiliation'] = "Google Merchandise Store";
            $data['coupon'] = $coupon ? $coupon->code : "N/A";
            $data['discount'] = floatval($product->discount);
            $data['index'] = 0;
            $data['item_brand'] = $brand->title;
            $data['item_category'] = $product->category->name ?? "N/A";
            $data['item_category2'] = $product->subCategory->name ?? "N/A";
            $data['item_category3'] = $product->subSubCategory->name ?? "N/A";
            $data['item_category4'] = "N/A";
            $data['item_category5'] = "N/A";
            $data['item_list_id'] = $product->product_code;
            $data['item_list_name'] = "Related Products";
            $data['item_variant'] = "N/A";
            $data['location_id'] = "ChIJIQBpAG2ahYAR_6128GcTUEo";
            $data['price'] = floatval($product->sale_price);
            $data['quantity'] = $request->quantity ? $request->quantity : 1;
            array_push($items, $data);

            $event_id = Str::uuid()->toString();
            if ($this->site_configuration->active_server_side == 1 && $request->event == 'view_item') {
                $this->fireFacebookViewContentEvent($product, $request, $event_id, $request->page_url);
            }
            $user_data = $this->getUserData($request);

            return response()->json([
                'status' => true,
                'cart_total' => $cart_total != 0 ? floatval($cart_total) : floatval($product->sale_price),
                'event_id' => $event_id ?? "",
                'items' => $items ?? [],
                'user_data' => $user_data ?? [],
                'pixel_id' => $this->site_configuration->fb_pixel_id ?? "",
                'product' => $product ?? [],
            ]);
        } catch (\Throwable $th) {
            return response()->json([
                'status' => false,
                'message' => $th->getMessage(),
            ]);
        }
    }

    //--------------get cart items for ga4-------------------
    public function getCartItems(Request $request)
    {
        // return $request;
        try {
            $brand = GeneralSetting::select('title')->first();
            $cart_total = Cart::total();
            $cart_contents = Cart::content();
            $coupon = DB::table('coupons')->select('id', 'code')->where('status', 1)->first();
            $cus = Auth::guard('customer')->user();
            if (isset($cus->city_id)) {
                $city = City::where('id', $cus->city_id)->select('id', 'name')->first();
            }
            $customer = [];
            if ($cus) {
                $customer = [
                    'id' => $cus->id ?? "",
                    'name' => $cus->name ?? "N/A",
                    'phone' => $cus->phone ?? "N/A",
                    'address' => $cus->address ?? "N/A",
                    'city' => $city->name ?? "",
                ];
            }
            $items = [];
            foreach ($cart_contents as $cart) {
                $data = [];
                $data['product_id'] = $cart->options->product_code;
                $data['item_id'] = $cart->options->product_code;
                $data['item_name'] = $cart->name;
                $data['affiliation'] = "Google Merchandise Store";
                $data['coupon'] = $coupon->code ?? "N/A";
                $data['discount'] = floatval($cart->options->discount);
                $data['index'] = 0;
                $data['item_brand'] = $brand->title ?? "N/A";
                $data['item_category'] = $cart->options->category_name ?? "N/A";
                $data['item_category2'] = $cart->options->subcategory_name ?? "N/A";
                $data['item_category3'] = $cart->options->sub_subcategory_name ?? "N/A";
                $data['item_category4'] = "N/A";
                $data['item_category5'] = "N/A";
                $data['item_list_id'] = $cart->options->product_code;
                $data['item_list_name'] = "Related Products";
                $data['item_variant'] = $cart->options->variant_name ?? "N/A";
                $data['location_id'] = "ChIJIQBpAG2ahYAR_6128GcTUEo";
                $data['price'] = floatval($cart->price) ?? 0;
                $data['quantity'] = floatval($cart->qty) ?? 0;

                array_push($items, $data);
            }
            $event_id = Str::uuid()->toString();
            if ($this->site_configuration->active_server_side == 1) {
                if ($request->event == 'purchase') {
                    $this->fireFacebookPurchaseEvent($cart_contents, floatval($cart_total), $request, $customer, $event_id, $request->page_url);
                } else {
                    $this->fireFacebookInitiateCheckoutEvent($cart_contents, floatval($cart_total), $request, $event_id, $request->page_url);
                }
            }
            $user_data = $this->getUserData($request);

            return response()->json([
                'status' => true,
                'items' => $items ?? [],
                'cart_items' => $cart_contents
                    ->pluck('options.product_code')
                    ->unique()
                    ->values()
                    ->toArray() ?? [],
                'contents' => $cart_contents->map(fn($item) => [
                    'id' => $item->options->product_code,
                    'quantity' => intval($item->qty),
                    'item_price' => intval($item->price),
                ])->values()->toArray(),
                'cart_total' => floatval($cart_total) ?? "N/A",
                'coupon' => $coupon->code ?? "N/A",
                'event_id' => $event_id ?? "N/A",
                'customer' => $customer,
                'user_data' => $user_data ?? [],
                'pixel_id' => $this->site_configuration->fb_pixel_id ?? "",
                'external_id' => isset($customer['id']) ? hash('sha256', (string) $customer['id']) : null

            ]);
        } catch (\Throwable $th) {
            return response()->json([
                'status' => true,
                'message' => $th->getMessage(),
            ]);
        }
    }
    public function pageVIewEvent(Request $request)
    {
        // $event_id = 'event.id.' . rand(10000, 99999);
        $event_id = Str::uuid()->toString();
        if ($this->site_configuration->active_server_side == 1) {
            $this->fireFacebookPageViewEvent($request, $event_id, $request->url);
        }
        return response()->json([
            'event_id' => $event_id,
            'status' => true,
        ]);
    }

    public function storeFbc(Request $request)
    {
        $fbc = $request->input('fbc');
        $fbp = $request->input('fbp');

        if ($fbc && !str_ends_with($fbc, '.null')) {
            session(['_fbc' => $fbc]);
        }
        if ($fbp && !str_ends_with($fbp, '.null')) {
            session(['_fbp' => $fbp]);
        }
        return response()->json([
            'status' => true,
            'fbc' => session('_fbc'),
            'fbp' => session('_fbp'),
        ]);
    }
    //-------------load more data-----------------
    public function loadMoreData(Request $request)
    {
        // return $request;
        $page = $request->page;
        $limit = $request->limit;
        $start = ($page - 1) * $limit;
        $category_slug = $request->category_slug;
        $subcategory_slug = $request->subcategory_slug;
        $sub_subcategory_slug = $request->sub_subcategory_slug;

        $query = Product::skip($start)->select('id', 'category_id', 'name', 'status', 'thumbnail_img', 'slug', 'stock', 'sale_price', 'discount', 'price', 'is_free_delivery', 'product_position', 'review_ratings', 'avg_review')
            ->where('status', 1)
            ->take($limit);
        if ($this->site_configuration->position_wise_product == 1) {
            $query->orderBy('product_position', 'asc');
        } else {
            $query->orderBy('id', 'desc');
        }
        if ($category_slug && $subcategory_slug && $sub_subcategory_slug) {
            $sub_sub_category = DB::table('sub_sub_categories')->where('slug', $sub_subcategory_slug)->select('id', 'name', 'slug')->first();
            $products = $query->where('sub_sub_category_id', $sub_sub_category->id)->get();
        } elseif ($category_slug && $subcategory_slug) {
            $sub_category = DB::table('sub_categories')->where('slug', $subcategory_slug)->select('id', 'name', 'slug')->first();
            $products = $query->where('sub_category_id', $sub_category->id)->get();
        } elseif ($category_slug && $subcategory_slug == null && $sub_subcategory_slug == null) {
            $category = DB::table('categories')->where('slug', $category_slug)->select('id', 'name', 'slug')->first();
            $products = $query->where('category_id', $category->id)->get();
        }

        $template = 'template' . $this->site_configuration->template_id;

        $brands = $this->shopByProducts('brands');

        $countries = $this->shopByProducts('countries');


        $data = " ";
        foreach ($products as $product) {
            $data .= view("frontend.components.load_more_product_content.$template", compact('product'))->render();
        }

        return response()->json([
            'status' => true,
            'data' => $data,
            'brands' => $brands,
            'countries' => $countries,
            'product_length' => $products->count(),
            'message' => 'load Data',
        ]);
    }


    //-------------load more data-----------------
    public function loadMoreBrandData(Request $request)
    {
        // return $request;
        $page = $request->page;
        $limit = $request->limit;
        $start = ($page - 1) * $limit;
        $brand_slug = $request->brand_slug;


        $query = Product::skip($start)->select('id', 'brand_id', 'name', 'status', 'thumbnail_img', 'slug', 'stock', 'sale_price', 'discount', 'price', 'is_free_delivery', 'product_position', 'review_ratings', 'avg_review')
            ->where('status', 1)
            ->take($limit);
        if ($this->site_configuration->position_wise_product == 1) {
            $query->orderBy('product_position', 'asc');
        } else {
            $query->orderBy('id', 'desc');
        }
        if ($brand_slug) {
            $brand = DB::table('brands')->where('slug', $brand_slug)->select('id', 'name', 'slug')->first();
            $products = $query->where('brand_id', $brand->id)->get();
        }

        $template = 'template' . $this->site_configuration->template_id;

        $data = " ";
        foreach ($products as $product) {
            $data .= view("frontend.components.load_more_product_content.$template", compact('product'))->render();
        }

        return response()->json([
            'status' => true,
            'data' => $data,
            'product_length' => $products->count(),
            'message' => 'load Data',
        ]);
    }




    public function comboProducts()
    {
        return $this->renderProductView('is_combo');
    }

    public function dailyProducts()
    {
        return $this->renderProductView('is_daily_offer');
    }

    public function buyOneGetOneProducts()
    {
        return $this->renderProductView('is_buy_one_get_one');
    }

    public function concernProducts($slug)
    {

        $query = Product::select(
            'products.id',
            'products.name',
            'products.status',
            'products.thumbnail_img',
            'products.slug',
            'products.stock',
            'products.review_ratings',
            'products.avg_review',
            'products.sale_price',
            'products.discount',
            'products.price',
            'products.created_at'
        )
            ->where('products.status', 1)
            ->latest();

        $skins = DB::table('skins')->where('slug', $slug)->first();
        $query->join('product_skins', 'products.id', '=', 'product_skins.product_id')
            ->where('product_skins.skin_id', $skins->id);
        $products = $query->get();
        // $products = $this->conrcenWiseProduct('skin_id', $skin->id);
        $is_country = 0;
        return view('frontend.components.skin_concern_product', compact('products', 'is_country'));
    }
    public function countryProducts($id)
    {

        $country = Country::findOrFail($id);

        $products = $this->conrcenWiseProduct('country_id', $country->id);
        $is_country = 1;

        return view('frontend.components.skin_concern_product', compact('products', 'is_country'));
    }


    public function brandsProducts($slug)
    {

        $brand = Brand::where('slug', $slug)->select('name', 'id')->first();
        $brand_name = $brand->name;
        $products = $this->conrcenWiseProduct('brand_id', $brand->id);

        return view('frontend.components.brand_products', compact('products', 'brand_name'));
    }
}
