<?php

namespace App\Http\Controllers\Api\V1\Vendor;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use App\Models\Item;
use App\Models\Translation;
use App\Models\Review;
use Illuminate\Support\Facades\Storage;
use App\CentralLogics\Helpers;
use App\Models\Tag;

class ItemController extends Controller
{

    public function store(Request $request)
    {
        if(!$request->vendor->stores[0]->item_section)
        {
            return response()->json([
                'errors'=>[
                    ['code'=>'unauthorized', 'message'=>translate('messages.permission_denied')]
                ]
            ],403);
        }

        $validator = Validator::make($request->all(), [
            'category_id' => 'required',
            'image' => 'required',
            'price' => 'required|numeric|min:0.01',
            'discount' => 'required|numeric|min:0',
            'translations'=>'required',
        ], [
            'category_id.required' => translate('messages.category_required'),
        ]);

        if ($request['discount_type'] == 'percent') {
            $dis = ($request['price'] / 100) * $request['discount'];
        } else {
            $dis = $request['discount'];
        }

        if ($request['price'] <= $dis) {
            $validator->getMessageBag()->add('unit_price', translate('messages.discount_can_not_be_more_than_or_equal'));
        }

        $data = json_decode($request->translations, true);

        if (count($data) < 1) {
            $validator->getMessageBag()->add('translations', translate('messages.Name and description in english is required'));
        }

        if ($request['price'] <= $dis || count($data) < 1 || $validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 402);
        }

        $tag_ids = [];
        if ($request->tags != null) {
            $tags = explode(",", $request->tags);
        }
        if(isset($tags)){
            foreach ($tags as $key => $value) {
                $tag = Tag::firstOrNew(
                    ['tag' => $value]
                );
                $tag->save();
                array_push($tag_ids,$tag->id);
            }
        }

        $item = new Item;
        $item->name = $data[0]['value'];

        $category = [];
        if ($request->category_id != null) {
            $category[] = [
                'id' => $request->category_id,
                'position' => 1,
            ];
        }
        if ($request->sub_category_id != null) {
            $category[] = [
                'id' => $request->sub_category_id,
                'position' => 2,
            ];
        }
        if ($request->sub_sub_category_id != null) {
            $category[] = [
                'id' => $request->sub_sub_category_id,
                'position' => 3,
            ];
        }
        $item->category_id = $request->sub_category_id?$request->sub_category_id:$request->category_id;
        $item->category_ids = json_encode($category);
        $item->description = $data[1]['value'];

        $choice_options = [];
        if ($request->has('choice')) {
            foreach (json_decode($request->choice_no) as $key => $no) {
                $str = 'choice_options_' . $no;
                if ($request[$str][0] == null) {
                    $validator->getMessageBag()->add('name', translate('messages.attribute_choice_option_value_can_not_be_null'));
                    return response()->json(['errors' => Helpers::error_processor($validator)]);
                }
                $i['name'] = 'choice_' . $no;
                $i['title'] = json_decode($request->choice)[$key];
                $i['options'] = explode(',', implode('|', preg_replace('/\s+/', ' ', json_decode($request[$str]))));
                array_push($choice_options, $i);
            }
        }
        $item->choice_options = json_encode($choice_options);
        $variations = [];
        $options = [];
        if ($request->has('choice_no')) {
            foreach (json_decode($request->choice_no) as $key => $no) {
                $name = 'choice_options_' . $no;
                $my_str = implode('|', json_decode($request[$name]));
                $options[] = explode(',', $my_str);
            }
        }
        //Generates the combinations of customer choice options
        $combinations = Helpers::combinations($options);
        if (count($combinations[0]) > 0) {
            foreach ($combinations as $key => $combination) {
                $str = '';
                foreach ($combination as $k => $i) {
                    if ($k > 0) {
                        $str .= '-' . str_replace(' ', '', $i);
                    } else {
                        $str .= str_replace(' ', '', $i);
                    }
                }
                $i = [];
                $i['type'] = $str;
                $i['price'] = abs($request['price_' . str_replace('.', '_', $str)]);
                $i['stock'] = abs($request['stock_' . str_replace('.', '_', $str)]);
                $variations[] = $i;
            }
        }

        $images = [];
        if (!empty($request->file('item_images'))) {
            foreach ($request->item_images as $img) {
                $image_name = Helpers::upload('product/', 'png', $img);
                $images[] = $image_name;
            }
        }

        //combinations end
        $item->variations = json_encode($variations);

        $food_variations = [];
        if(isset($request->options))
        {
            foreach(json_decode($request->options, true) as $option)
            {
                $temp_variation['name']= $option['name'];
                $temp_variation['type']= $option['type'];
                $temp_variation['min']= $option['min'] ?? 0;
                $temp_variation['max']= $option['max'] ?? 0;
                $temp_variation['required']= $option['required']??'off';
                $temp_value = [];
                foreach($option['values'] as $value)
                {
                    if(isset($value['label'])){
                        $temp_option['label'] = $value['label'];
                    }
                    $temp_option['optionPrice'] = $value['optionPrice'];
                    $temp_value[] = $temp_option;
                }
                $temp_variation['values']= $temp_value;
                $food_variations[] = $temp_variation;
            }
        }
        //combinations end
        $item->food_variations = json_encode($food_variations);
        $item->price = $request->price;
        $item->image = Helpers::upload('product/', 'png', $request->file('image'));
        $item->available_time_starts = $request->available_time_starts;
        $item->available_time_ends = $request->available_time_ends;
        $item->discount = $request->discount_type == 'amount' ? $request->discount : $request->discount;
        $item->discount_type = $request->discount_type;
        $item->attributes = $request->has('attribute_id') ? $request->attribute_id : json_encode([]);
        $item->add_ons = $request->has('addon_ids') ? json_encode(explode(',',$request->addon_ids)) : json_encode([]);
        $item->store_id = $request['vendor']->stores[0]->id;
        $item->veg = $request->veg;
        $item->module_id = $request['vendor']->stores[0]->module_id;
        $item->stock= $request->current_stock;
        $item->images = $images;
        $item->unit_id = $request->unit;
        $item->is_approved = 0;
        $item->data_to_update = null;
        $item->save();
        $item->tags()->sync($tag_ids);

        unset($data[1]);
        unset($data[0]);
        foreach ($data as $key=>$i) {
            $data[$key]['translationable_type'] = 'App\Models\Item';
            $data[$key]['translationable_id'] = $item->id;
        }
        Translation::insert($data);

        return response()->json(['message'=>translate('messages.product_added_successfully_waiting_for_admin_approve')], 200);
    }

    public function status(Request $request)
    {
        if(!$request->vendor->stores[0]->item_section)
        {
            return response()->json([
                'errors'=>[
                    ['code'=>'unauthorized', 'message'=>translate('messages.permission_denied')]
                ]
            ],403);
        }

        $validator = Validator::make($request->all(), [
            'id' => 'required',
            'status' => 'required|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $product = Item::find($request->id);
        $product->status = $request->status;
        $product->save();

        return response()->json(['message' => translate('messages.product_status_updated')], 200);
    }

    public function update(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'id' => 'required',
            'category_id' => $request->has('only_price') ? 'nullable' : 'required',
            'price' => 'required|numeric|min:0.01',
            'discount' => 'required|numeric|min:0',
        ], [
            'category_id.required' => translate('messages.category_required'),
        ]);

        $p = Item::findOrFail($request->id);
        $itemInfo = Item::where('id', $request->id)->first();

        if(isset($request->only_price) and $request->only_price == 'true'){

            if ($request['discount_type'] == 'percent') {
                $dis = ($request['price'] / 100) * $request['discount'];
            } else {
                $dis = $request['discount'];
            }
            if ($request['price'] <= $dis) {
                $validator->getMessageBag()->add('unit_price', translate('messages.discount_can_not_be_more_than_or_equal'));
            }

            $p->price = $request->price;
            $p->discount_type = $request->discount_type;
            $p->discount = $request->discount;
            $p->save();

            return response()->json(['message'=>translate('messages.price_updated_successfully')], 200);
        }else{
            if(!$request->vendor->stores[0]->item_section)
            {
                return response()->json([
                    'errors'=>[
                        ['code'=>'unauthorized', 'message'=>translate('messages.permission_denied')]
                    ]
                ],403);
            }
        }

        if ($request['discount_type'] == 'percent') {
            $dis = ($request['price'] / 100) * $request['discount'];
        } else {
            $dis = $request['discount'];
        }

        if ($request['price'] <= $dis) {
            $validator->getMessageBag()->add('unit_price', translate('messages.discount_can_not_be_more_than_or_equal'));
        }
        $data = json_decode($request->translations, true);

        if(!isset($data[0]['value']) or empty($data[0]['value'])){
            $data[0]['value'] = '';
        }
        if(!isset($data[1]['value']) or empty($data[1]['value'])){
            $data[1]['value'] = '';
        }

        if (count($data) < 1) {
            $validator->getMessageBag()->add('translations', translate('messages.Name and description in english is required'));
        }

        if ($request['price'] <= $dis || count($data) < 1 || $validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 402);
        }
        $tag_ids = [];
        if ($request->tags != null) {
            $tags = explode(",", $request->tags);
        }
        if(isset($tags)){
            foreach ($tags as $key => $value) {
                $tag = Tag::firstOrNew(
                    ['tag' => $value]
                );
                $tag->save();
                $tag_ids[] = $tag->id;
            }
        }



        $category = [];
        if ($request->category_id != null) {
            $category[] = [
                'id' => $request->category_id,
                'position' => 1,
            ];
        }
        if ($request->sub_category_id != null) {
            $category[] = [
                'id' => $request->sub_category_id,
                'position' => 2,
            ];
        }
        if ($request->sub_sub_category_id != null) {
            $category[] = [
                'id' => $request->sub_sub_category_id,
                'position' => 3,
            ];
        }

        $choice_options = [];
        if ($request->has('choice')) {
            foreach (json_decode($request->choice_no) as $key => $no) {
                $str = 'choice_options_' . $no;
                if (json_decode($request[$str])[0] == null) {
                    $validator->getMessageBag()->add('name', translate('messages.attribute_choice_option_value_can_not_be_null'));
                    return response()->json(['errors' => Helpers::error_processor($validator)]);
                }
                $item['name'] = 'choice_' . $no;
                $item['title'] = json_decode($request->choice)[$key];
                $item['options'] = explode(',', implode('|', preg_replace('/\s+/', ' ', json_decode($request[$str]))));
                $choice_options[] = $item;
            }
        }

        $variations = [];
        $options = [];
        if ($request->has('choice_no')) {
            foreach (json_decode($request->choice_no) as $key => $no) {
                $name = 'choice_options_' . $no;
                $my_str = implode('|', json_decode($request[$name]));
                array_push($options, explode(',', $my_str));
            }
        }
        //Generates the combinations of customer choice options
        $combinations = Helpers::combinations($options);
        if (count($combinations[0]) > 0) {
            foreach ($combinations as $key => $combination) {
                $str = '';
                foreach ($combination as $k => $i) {
                    if ($k > 0) {
                        $str .= '-' . str_replace(' ', '', $i);
                    } else {
                        $str .= str_replace(' ', '', $i);
                    }
                }
                $i = [];
                $i['type'] = $str;
                $i['price'] = abs($request['price_' . str_replace('.', '_', $str)]);
                $i['stock'] = abs($request['stock_' . str_replace('.', '_', $str)]);
                $variations[] = $i;
            }
        }
        //combinations end

        $images = $p['images'];

        foreach ($p['images'] as $img) {
            if (!in_array($img, json_decode($request->images, true))) {
                if(Storage::disk('public')->exists('product/' . $img))
                {
                    Storage::disk('public')->delete('product/' . $img);
                }
                $key = array_search($img, $images);
                unset($images[$key]);
            }
        }
        if ($request->has('item_images')){
            foreach ($request->item_images as $img) {
                $image = Helpers::upload('product/', 'png', $img);
                $images[] = $image;
            }
        }

        $food_variations = [];
        if(isset($request->options))
        {
            foreach(json_decode($request->options,true) as $key=>$option)
            {
                $temp_variation['name']= $option['name'];
                $temp_variation['type']= $option['type'];
                $temp_variation['min']= $option['min'] ?? 0;
                $temp_variation['max']= $option['max'] ?? 0;
                $temp_variation['required']= $option['required']??'off';
                $temp_value = [];
                foreach($option['values'] as $value)
                {
                    if(isset($value['label'])){
                        $temp_option['label'] = $value['label'];
                    }
                    $temp_option['optionPrice'] = $value['optionPrice'];
                    $temp_value[] = $temp_option;
                }
                $temp_variation['values']= $temp_value;
                $food_variations[] = $temp_variation;
            }
        }

        if(
            $itemInfo->name != $data[0]['value'] or
            $itemInfo->description != $data[1]['value'] or
            $itemInfo->category_id != ($request->sub_category_id ? $request->sub_category_id : $request->category_id) or
            $itemInfo->category_ids != json_encode($category) or
            //$itemInfo->choice_options != json_encode($choice_options) or
            $itemInfo->images != array_values($images) or
            $itemInfo->food_variations != json_encode($food_variations) or
            $itemInfo->variations != json_encode($variations) or
            $request->has('image')
        ){
            $p->is_approved = 0;
            $data_to_update = [
                'name' => $data[0]['value'],
                'description' => $data[1]['value'],
                'ar_name' => $data[2]['value'] ?? null,
                'ar_description' => $data[3]['value'] ?? null,
                'price' => $request->price,
                'discount' => $request->discount,
                'discount_type' => $request->discount_type,
                'category_id' => $request->sub_category_id ? $request->sub_category_id : $request->category_id,
                'category_ids' => json_encode($category),
                'choice_options' => json_encode($choice_options),
                'images' => array_values($images),
                'image' => $p->image,
                'variations' => json_encode($variations),
                'food_variations' => json_encode($food_variations),
                'available_time_starts' => $request->available_time_starts,
                'available_time_ends' => $request->available_time_ends,
                'attributes' => ($request->attribute_id ?? json_encode([])),
                'add_ons' => ($request->has('addon_ids') ? json_encode(explode(',',$request->addon_ids)) : json_encode([])),
                'stock' => ($request->current_stock ?? 0),
                'veg' => ($request->veg ?? 0),
                'unit_id' => $request->unit,
            ];
            $p->data_to_update = json_encode($data_to_update);
        }else{
            $p->name = $data[0]['value'];
            $p->description = $data[1]['value'];
            $p->category_id = $request->sub_category_id?$request->sub_category_id:$request->category_id;
            $p->category_ids = json_encode($category);
            $p->choice_options = json_encode($choice_options);
            $p->variations = json_encode($variations);
            $p->food_variations = json_encode($food_variations);
            $p->price = $request->price;
            $p->image = $request->has('image') ? Helpers::update('product/', $p->image, 'png', $request->file('image')) : $p->image;
            $p->available_time_starts = $request->available_time_starts;
            $p->available_time_ends = $request->available_time_ends;
            $p->discount = $request->discount;
            $p->discount_type = $request->discount_type;
            $p->attributes = $request->has('attribute_id') ? $request->attribute_id : json_encode([]);
            $p->add_ons = $request->has('addon_ids') ? json_encode(explode(',',$request->addon_ids)) : json_encode([]);
            $p->stock= $request->current_stock ?? 0;
            $p->veg = $request->veg ?? 0;
            $p->images = array_values($images);
            $p->unit_id = $request->unit;
            unset($data[1]);
            unset($data[0]);
            foreach ($data as $key=>$item) {
                Translation::updateOrInsert(
                    ['translationable_type' => 'App\Models\Item',
                        'translationable_id' => $p->id,
                        'locale' => $item['locale'],
                        'key' => $item['key']],
                    ['value' => $item['value']]
                );
            }
        }

        $p->save();
        $p->tags()->sync($tag_ids);

        return response()->json(['message'=>translate('messages.product_updated_successfully_waiting_for_admin_approve')], 200);
    }

    public function delete(Request $request)
    {
        if(!$request->vendor->stores[0]->item_section)
        {
            return response()->json([
                'errors'=>[
                    ['code'=>'unauthorized', 'message'=>translate('messages.permission_denied')]
                ]
            ],403);
        }
        $product = Item::findOrFail($request->id);

        if($product->image)
        {
            if (Storage::disk('public')->exists('product/' . $product['image'])) {
                Storage::disk('public')->delete('product/' . $product['image']);
            }
        }
        $product->translations()->delete();
        $product->delete();

        return response()->json(['message'=>translate('messages.product_deleted_successfully')], 200);
    }

    public function search(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        // حضّر الكلمات
        $search  = trim((string) $request->input('name', ''));
        $tokens  = array_values(array_filter(preg_split('/\s+/u', $search)));

        $products = Item:://active()
            with(['reviews'])
            ->where('store_id', $request['vendor']->stores[0]->id)
            ->when($request->category_id, function ($query) use ($request) {
                $query->whereHas('category', function ($q) use ($request) {
                    return $q->whereId($request->category_id)
                        ->orWhere('parent_id', $request->category_id);
                });
            })
            ->when($request->store_id, function ($query) use ($request) {
                return $query->where('store_id', $request->store_id);
            })
            ->when($tokens, function ($query) use ($tokens) {
                $query->where(function ($wrap) use ($tokens) {

                    // AND على كل كلمة: إمّا name أو ترجمة name (ar/en)
                    $wrap->where(function ($outer) use ($tokens) {
                        foreach ($tokens as $token) {
                            $outer->where(function ($q) use ($token) {
                                $q->where('name', 'like', "%{$token}%")
                                    ->orWhereHas('translations', function ($t) use ($token) {
                                        $t->where('key', 'name')
                                            ->where('translationable_type', 'App\Models\Item')
                                            ->whereIn('locale', ['ar', 'en'])
                                            ->where('value', 'like', "%{$token}%");
                                    });
                            });
                        }
                    });

                    //$wrap->orWhereHas('tags', function ($t) use ($tokens) {
                    //    $t->where(function ($qq) use ($tokens) {
                    //        foreach ($tokens as $token) {
                    //            $qq->where('tag', 'like', "%{$token}%");
                    //        }
                    //    });
                    //});

                });
            })
            ->limit(50)
            ->get();

        $data = Helpers::product_data_formatting($products, true, false, app()->getLocale());
        return response()->json($data, 200);
    }

    public function reviews(Request $request)
    {
        $id = $request['vendor']->stores[0]->id;;

        $reviews = Review::with(['customer', 'item'])
        ->whereHas('item', function($query)use($id){
            return $query->where('store_id', $id);
        })
        ->latest()->get();

        $storage = [];
        foreach ($reviews as $item) {
            $item['attachment'] = json_decode($item['attachment']);
            $item['item_name'] = null;
            $item['item_image'] = null;
            $item['customer_name'] = null;
            if($item->item)
            {
                $item['item_name'] = $item->item->name;
                $item['item_image'] = $item->item->image;
                if(count($item->item->translations)>0)
                {
                    $translate = array_column($item->item->translations->toArray(), 'value', 'key');
                    $item['item_name'] = $translate['name'];
                }
            }

            if($item->customer)
            {
                $item['customer_name'] = $item->customer->f_name.' '.$item->customer->l_name;
            }

            unset($item['item']);
            unset($item['customer']);
            array_push($storage, $item);
        }

        return response()->json($storage, 200);
    }

    public function recommended(Request $request)
    {
        if(!$request->vendor->stores[0]->item_section)
        {
            return response()->json([
                'errors'=>[
                    ['code'=>'unauthorized', 'message'=>translate('messages.permission_denied')]
                ]
            ],403);
        }

        $validator = Validator::make($request->all(), [
            'id' => 'required',
            'status' => 'required|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $product = Item::find($request->id);
        $product->recommended = $request->status;
        $product->save();

        return response()->json(['message' => translate('messages.product_recommended_status_updated')], 200);

    }

    public function get_product($id)
    {
        try {
            $item = Item::withCount('whislists')//->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();
            $item = Helpers::product_data_formatting($item, false, false, app()->getLocale());
            return response()->json($item, 200);
        } catch (\Exception $e) {
            return response()->json([
                'errors' => ['code' => 'product-001', 'message' => translate('messages.not_found')]
            ], 404);
        }
    }

    public function pending_items(Request $request)
    {
        $limit = $request->limit ? $request->limit : 25;
        $offset = $request->offset ? $request->offset : 1;

        $type = $request->query('type', 'all');

        $paginator = Item::withoutGlobalScope('translate')->with('tags', 'category')->type($type)->where('is_approved', 0)->where('store_id', $request['vendor']->stores[0]->id)->latest()->paginate($limit, ['*'], 'page', $offset);
        $data = [
            'total_size' => $paginator->total(),
            'limit' => (int)$limit,
            'offset' => $offset,
            'items' => Helpers::product_data_formatting($paginator->items(), true, true, app()->getLocale())
        ];

        return response()->json($data, 200);
    }
}
