<?php

namespace App\CentralLogics;

use App\Models\Item;
use App\Models\Review;
use Illuminate\Support\Facades\DB;
use Twig\Node\Expression\Test\NullTest;

class ProductLogic
{
    public static function get_product($id)
    {
        return Item::active()
        ->when(config('module.current_module_data'), function($query){
            $query->module(config('module.current_module_data')['id']);
        })
        ->when(is_numeric($id),function ($qurey) use($id){
            $qurey-> where('id', $id);
        })
        ->when(!is_numeric($id),function ($qurey) use($id){
            $qurey-> where('slug', $id);
        })
        ->first();
    }

    public static function get_latest_products($zone_id, $limit, $offset, $store_id, $category_id, $type, $min=false, $max=false,$product_id=null)
    {
        $paginator = Item::active()->type($type)
        ->when($category_id != 0, function($q)use($category_id){
            $q->whereHas('category',function($q)use($category_id){
                return $q->whereId($category_id)->orWhere('parent_id', $category_id);
            });
        })
        ->when(isset($product_id), function($q)use($product_id){
            $q->where('id', '!=', $product_id);
        })
        ->whereHas('module.zones', function($query)use($zone_id){
            $query->whereIn('zones.id', json_decode($zone_id, true));
        })
        ->whereHas('store', function($query)use($zone_id){
            $query->when(config('module.current_module_data'), function($query){
                $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                    $query->where('modules.id', config('module.current_module_data')['id']);
                });
            })->whereIn('zone_id', json_decode($zone_id, true));
        })
        ->when($min && $max, function($query)use($min,$max){
            $query->whereBetween('price',[$min,$max]);
        })
        ->where('store_id', $store_id)->orderByRaw('(stock > 0) DESC')->orderBy('id', 'ASC')->paginate($limit, ['*'], 'page', $offset);

        return [
            'total_size' => $paginator->total(),
            'limit' => $limit,
            'offset' => $offset,
            'products' => $paginator->items()
        ];
    }

    public static function get_ads_products($zone_id, $limit, $offset, $store_id)
    {
        $paginator = Item::whereHas('module.zones', function($query)use($zone_id){
                $query->whereIn('zones.id', json_decode($zone_id, true));
            })
            ->where('store_id', $store_id)->active()->orderBy('id', 'ASC')->paginate($limit, ['*'], 'page', $offset);

        return [
            'total_size' => $paginator->total(),
            'limit' => $limit,
            'offset' => $offset,
            'products' => $paginator->items()
        ];
    }

    public static function get_related_products($zone_id,$product_id)
    {
        $product = Item::find($product_id);
        return Item::active()
        ->whereHas('module.zones', function($query)use($zone_id){
            $query->whereIn('zones.id', json_decode($zone_id, true));
        })
        ->whereHas('store', function($query)use($zone_id){
            $query->when(config('module.current_module_data'), function($query){
                $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                    $query->where('modules.id', config('module.current_module_data')['id']);
                });
            })->whereIn('zone_id', json_decode($zone_id, true));
        })
        ->where('category_ids', $product->category_ids)
        ->where('id', '!=', $product->id)
        ->limit(10)
        ->get();
    }

    public static function recommended_items($zone_id,$store_id,$limit = null, $offset = null, $type='all')
    {
        $data =[];
        if($limit != null && $offset != null)
        {
            $paginator = Item::where('store_id', $store_id)->whereHas('store', function($query)use($zone_id){
                $query->when(config('module.current_module_data'), function($query){
                    $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                        $query->where('modules.id', config('module.current_module_data')['id']);
                    });
                })->whereIn('zone_id', json_decode($zone_id, true))->Weekday();
            })->active()->type($type)->Recommended()->paginate($limit, ['*'], 'page', $offset);
                $data = $paginator->items();
        }
        else{
            $paginator = Item::where('store_id', $store_id)->active()->type($type)->whereHas('store', function($query)use($zone_id){
                $query->when(config('module.current_module_data'), function($query){
                    $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                        $query->where('modules.id', config('module.current_module_data')['id']);
                    });
                })->whereIn('zone_id', json_decode($zone_id, true))->Weekday();
            })->Recommended()->limit(50)->get();
            $data =$paginator;
        }

        return [
            'total_size' => $paginator->count(),
            'limit' => $limit,
            'offset' => $offset,
            'items' => $data
        ];
    }


    public static function popular_products($zone_id, $limit = null, $offset = null, $type = 'all')
    {
        if($limit != null && $offset != null)
        {
            $paginator = Item::
            whereHas('module.zones', function($query)use($zone_id){
                $query->whereIn('zones.id', json_decode($zone_id, true));
            })
            ->whereHas('store', function($query)use($zone_id){
                $query->when(config('module.current_module_data'), function($query){
                    $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                        $query->where('modules.id', config('module.current_module_data')['id']);
                    });
                })->whereIn('zone_id', json_decode($zone_id, true));
            })
            ->active()->type($type)->popular()->paginate($limit, ['*'], 'page', $offset);

            return [
                'total_size' => $paginator->total(),
                'limit' => $limit,
                'offset' => $offset,
                'products' => $paginator->items()
            ];
        }
        $paginator = Item::active()
        ->whereHas('module.zones', function($query)use($zone_id){
            $query->whereIn('zones.id', json_decode($zone_id, true));
        })
        ->whereHas('store', function($query)use($zone_id){
            $query->when(config('module.current_module_data'), function($query){
                $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                    $query->where('modules.id', config('module.current_module_data')['id']);
                });
            })->whereIn('zone_id', json_decode($zone_id, true));
        })
        ->type($type)->hasDiscount()->limit(50)->get();

        return [
            'total_size' => $paginator->count(),
            'limit' => $limit,
            'offset' => $offset,
            'products' => $paginator
        ];

    }


    public static function offers_products($zone_id, $limit = null, $offset = null, $type = 'all')
    {
        if($limit != null && $offset != null)
        {
            $zoneIds = json_decode($zone_id, true);

            $discountOuter = "
  CASE
    WHEN items.discount_type = 'percent' THEN (items.discount / 100.0) * items.price
    WHEN items.discount_type = 'amount'  THEN items.discount
    ELSE 0
  END
";

            $discountInner = "
  CASE
    WHEN i2.discount_type = 'percent' THEN (i2.discount / 100.0) * i2.price
    WHEN i2.discount_type = 'amount'  THEN i2.discount
    ELSE 0
  END
";

            $paginator = Item::query()
                ->select('items.*')
                ->selectRaw("$discountOuter AS effective_discount")
                ->whereHas('store.module.zones', fn($q)=> $q->whereIn('zones.id', $zoneIds))
                ->whereHas('store', fn($q)=> $q->where('module_id','1')
                    ->whereIn('zone_id', $zoneIds)
                    ->where('status',1))
                ->active()
                ->type($type)
                ->hasDiscount()
                ->whereRaw("
      (
        SELECT COUNT(*)
        FROM items i2
        WHERE i2.store_id = items.store_id
          AND (
                ($discountInner) > ($discountOuter)
             OR (($discountInner) = ($discountOuter) AND i2.id > items.id)
          )
      ) < 3
    ")
                ->orderByDesc('effective_discount')
                ->orderByDesc('items.id')
                ->paginate($limit, ['*'], 'page', $offset);

            return [
                'total_size' => $paginator->total(),
                'limit' => $limit,
                'offset' => $offset,
                'products' => $paginator->items()
            ];
        }
        $paginator = Item::active()
            ->whereHas('module.zones', function($query)use($zone_id){
                $query->whereIn('zones.id', json_decode($zone_id, true));
            })
            ->whereHas('store', function($query)use($zone_id){
                $query->where('module_id', '1')->whereHas('zone.modules',function($query){
                    $query->where('modules.id', '1');
                })->whereIn('zone_id', json_decode($zone_id, true));
            })
            ->type($type)->hasDiscount()->limit(3)->get();

        return [
            'total_size' => $paginator->count(),
            'limit' => $limit,
            'offset' => $offset,
            'products' => $paginator
        ];

    }

    public static function most_reviewed_products($zone_id, $limit = null, $offset = null, $type = 'all')
    {
        if($limit != null && $offset != null)
        {
            $paginator = Item::
            whereHas('module.zones', function($query)use($zone_id){
                $query->whereIn('zones.id', json_decode($zone_id, true));
            })
            ->whereHas('store', function($query)use($zone_id){
                $query->when(config('module.current_module_data'), function($query){
                    $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                        $query->where('modules.id', config('module.current_module_data')['id']);
                    });
                })->whereIn('zone_id', json_decode($zone_id, true));
            })
            ->withCount('reviews')->active()->type($type)
            ->orderBy('reviews_count','desc')
            ->paginate($limit, ['*'], 'page', $offset);

            return [
                'total_size' => $paginator->total(),
                'limit' => $limit,
                'offset' => $offset,
                'products' => $paginator->items()
            ];
        }
        $paginator = Item::active()->type($type)
        ->whereHas('module.zones', function($query)use($zone_id){
            $query->whereIn('zones.id', json_decode($zone_id, true));
        })
        ->whereHas('store', function($query)use($zone_id){
            $query->when(config('module.current_module_data'), function($query){
                $query->where('module_id', config('module.current_module_data')['id'])->whereHas('zone.modules',function($query){
                    $query->where('modules.id', config('module.current_module_data')['id']);
                });
            })->whereIn('zone_id', json_decode($zone_id, true));
        })
        ->withCount('reviews')
        ->orderBy('reviews_count','desc')
        ->limit(50)->get();

        return [
            'total_size' => $paginator->count(),
            'limit' => $limit,
            'offset' => $offset,
            'products' => $paginator
        ];

    }

    public static function get_product_review($id)
    {
        $reviews = Review::where('product_id', $id)->get();
        return $reviews;
    }

    public static function get_rating($reviews)
    {
        $rating5 = 0;
        $rating4 = 0;
        $rating3 = 0;
        $rating2 = 0;
        $rating1 = 0;
        foreach ($reviews as $key => $review) {
            if ($review->rating == 5) {
                $rating5 += 1;
            }
            if ($review->rating == 4) {
                $rating4 += 1;
            }
            if ($review->rating == 3) {
                $rating3 += 1;
            }
            if ($review->rating == 2) {
                $rating2 += 1;
            }
            if ($review->rating == 1) {
                $rating1 += 1;
            }
        }
        return [$rating5, $rating4, $rating3, $rating2, $rating1];
    }

    public static function get_avg_rating($rating)
    {
        $total_rating = 0;
        $total_rating += $rating[1];
        $total_rating += $rating[2]*2;
        $total_rating += $rating[3]*3;
        $total_rating += $rating[4]*4;
        $total_rating += $rating[5]*5;

        return $total_rating/array_sum($rating);
    }

    public static function get_overall_rating($reviews)
    {
        $totalRating = count($reviews);
        $rating = 0;
        foreach ($reviews as $key => $review) {
            $rating += $review->rating;
        }
        if ($totalRating == 0) {
            $overallRating = 0;
        } else {
            $overallRating = number_format($rating / $totalRating, 2);
        }

        return [$overallRating, $totalRating];
    }

    public static function format_export_items($foods)
    {
        $storage = [];
        foreach($foods as $item)
        {
            $category_id = '';
            $sub_category_id = '';
            $enCategory = '';
            $enSubCategory = '';
            $catID = '';
            $subCatID = '';
            foreach(json_decode($item->category_ids, true) as $category)
            {
                if($category['position']==1)
                {
                    $enCategory = DB::table('categories')->where('id', $category['id'])->first()->name ?? '';
                    $category_id = DB::table('translations')
                        ->where('translationable_type', 'App\Models\Category')
                        ->where('translationable_id', $category['id'])
                        ->where('locale', 'ar')
                        ->where('key', 'name')->first();
                    $catID = $category['id'];
                    if($category_id) $category_id = $category_id->value;
                    if(!$category_id) {
                        $category_id = $enCategory;
                    }
                }
                else if($category['position']==2)
                {
                    $enSubCategory = DB::table('categories')->where('id', $category['id'])->first()->name ?? '';
                    $sub_category_id = DB::table('translations')
                        ->where('translationable_type', 'App\Models\Category')
                        ->where('translationable_id', $category['id'])
                        ->where('locale', 'ar')
                        ->where('key', 'name')->first();
                    $subCatID = $category['id'];
                    if($sub_category_id) $sub_category_id = $sub_category_id->value;
                    if(!$sub_category_id) {
                        $sub_category_id = $enSubCategory;
                    }
                }
            }

            $name = DB::table('translations')
                ->where('translationable_type', 'App\Models\Item')
                ->where('translationable_id', $item->id)
                ->where('locale', 'ar')
                ->where('key', 'name')->first()->value ?? $item->name;
            $description = DB::table('translations')
                ->where('translationable_type', 'App\Models\Item')
                ->where('translationable_id', $item->id)
                ->where('locale', 'ar')
                ->where('key', 'description')->first()->value ?? $item->description;

            $storage[] = [
                'ID'=>$item->id,
                'Name'=>$name,
                'Description'=>$description,
                //'image'=>$item->image,
                //'veg'=>$item->veg,
                'Category ID'=>$catID,
                'Category (AR)'=>$category_id,
                'Category (EN)'=>$enCategory,
                'Sub-Category ID'=>$subCatID,
                'Sub-category (AR)'=>$sub_category_id,
                'Sub-category (EN)'=>$enSubCategory,
                //'unit_id'=>$item->unit_id,
                //'stock'=>$item->stock,
                'Price'=>$item->price,
                'Discount'=>$item->discount,
                'Discount type'=>$item->discount_type,
                'Available time starts'=>$item->available_time_starts,
                'Available time ends'=>$item->available_time_ends,
                //'variations'=>str_replace(['{','}','[',']'],['(',')','',''],$item->variations),
                //'add_ons'=>str_replace(['"','[',']'],'',$item->add_ons),
                //'attributes'=>str_replace(['"','[',']'],'',$item->attributes),
                //'choice_options'=>str_replace(['{','}'],['(',')'],substr($item->choice_options, 1, -1)),
                'Store'=>DB::table('stores')->where('id', $item->store_id)->first()->name ?? '',
                'module_id'=>$item->module_id,
            ];
        }

        return $storage;
    }

    public static function update_food_ratings()
    {
        try{
            $foods = Item::withOutGlobalScopes()->whereHas('reviews')->with('reviews')->get();
            foreach($foods as $key=>$food)
            {
                $foods[$key]->avg_rating = $food->reviews->avg('rating');
                $foods[$key]->rating_count = $food->reviews->count();
                foreach($food->reviews as $review)
                {
                    $foods[$key]->rating = self::update_rating($foods[$key]->rating, $review->rating);
                }
                $foods[$key]->save();
            }
        }catch(\Exception $e){
            info($e);
            return false;
        }
        return true;
    }

    public static function update_rating($ratings, $product_rating)
    {

        $store_ratings = [1=>0 , 2=>0, 3=>0, 4=>0, 5=>0];
        if(isset($ratings))
        {
            $store_ratings = json_decode($ratings, true);
            $store_ratings[$product_rating] = $store_ratings[$product_rating] + 1;
        }
        else
        {
            $store_ratings[$product_rating] = 1;
        }
        return json_encode($store_ratings);
    }

    public static function update_stock($item, $quantity, $variant=null)
    {
        if(isset($variant))
        {
            $variations = is_array($item['variations'])?$item['variations']: json_decode($item['variations'], true);

            foreach ($variations as $key => $value) {
                if ($value['type'] == $variant) {
                    $variations[$key]['stock'] -= $quantity;
                }
            }
            $item['variations']= json_encode($variations);
        }
        $item->stock -= $quantity;
        return $item;
    }
}
