<?php

namespace App\Http\Controllers\Api\V1;

use App\CentralLogics\Helpers;
use App\CentralLogics\ProductLogic;
use App\CentralLogics\StoreLogic;
use App\Http\Controllers\Controller;
use App\Models\Item;
use App\Models\Order;
use App\Models\Review;
use App\Models\Store;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class ItemController extends Controller
{
    public function get_latest_products(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'store_id' => 'required',
            'category_id' => 'required',
            'limit' => 'required',
            'offset' => 'required',
        ]);

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

        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            $errors[] = ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')];
            return response()->json([
                'errors' => $errors
            ], 403);
        }
        $zone_id = $request->header('zoneId');
        $type = $request->query('type', 'all');
        $product_id = $request->query('product_id')??null;
        $min = $request->query('min_price');
        $max = $request->query('max_price');

        $items = ProductLogic::get_latest_products($zone_id, $request['limit'], $request['offset'], $request['store_id'], $request['category_id'], $type,$min,$max,$product_id);
        $items['products'] = Helpers::product_data_formatting($items['products'], true, false, app()->getLocale());
        return response()->json($items, 200);
    }

    public function get_searched_products(Request $request)
    {
        if (!$request->hasHeader('zoneId')) {
            return response()->json([
                'errors' => [['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]]
            ], 403);
        }

        $zone_id = $request->header('zoneId');
        $decoded_zone_id = json_decode($zone_id, true);

        if (!is_array($decoded_zone_id) || empty($decoded_zone_id)) {
            return response()->json([
                'errors' => [['code' => 'zoneId', 'message' => translate('messages.zone_id_invalid_or_empty')]]
            ], 403);
        }
        $validator = Validator::make($request->all(), [
            'name' => 'required'
        ]);

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

        $key = array_filter(explode(' ', $request['name']));

        if (empty($key)) {
            return response()->json([
                'errors' => [['code' => 'name', 'message' => translate('messages.search_keyword_invalid')]]
            ], 403);
        }

        $limit = $request['limit']??10;
        $offset = $request['offset']??1;

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

        $items = Item::active()->type($type)

        ->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);
        })
            ->whereHas('module.zones', function($query) use($decoded_zone_id){
                $query->whereIn('zones.id', $decoded_zone_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));
        //})
        ->where(function ($q) use ($key) {
            foreach ($key as $value) {
                $q->orWhere('name', 'like', "%{$value}%");
            }
            $q->orWhereHas('translations',function($query)use($key){
                $query->where(function($q)use($key){
                    foreach ($key as $value) {
                        $q->where('value', 'like', "%{$value}%");
                    };
                });
            });
            $q->orWhereHas('tags',function($query)use($key){
                $query->where(function($q)use($key){
                    foreach ($key as $value) {
                        $q->where('tag', 'like', "%{$value}%");
                    };
                });
            });
        })

        ->paginate($limit, ['*'], 'page', $offset);

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

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

    public function get_popular_products(Request $request)
    {
        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            array_push($errors, ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]);
            return response()->json([
                'errors' => $errors
            ], 403);
        }

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

        $zone_id= $request->header('zoneId');
        $items = ProductLogic::popular_products($zone_id, $request['limit'], $request['offset'], $type);
        $items['products'] = Helpers::product_data_formatting($items['products'], true, false, app()->getLocale());
        return response()->json($items, 200);
    }

    public function get_offers(Request $request): \Illuminate\Http\JsonResponse
    {
        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            array_push($errors, ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]);
            return response()->json([
                'errors' => $errors
            ], 403);
        }

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

        $zone_id= $request->header('zoneId');
        $items = ProductLogic::offers_products($zone_id, $request['limit'], $request['offset'], $type);
        $items['products'] = Helpers::product_data_formatting($items['products'], true, false, app()->getLocale());
        $items['ar_title'] = 'تخفيضات بوسطجي';
        $items['en_title'] = 'Postajji discounts';
        return response()->json($items, 200);
    }

    public function get_most_reviewed_products(Request $request)
    {
        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            array_push($errors, ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]);
            return response()->json([
                'errors' => $errors
            ], 403);
        }

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

        $zone_id= $request->header('zoneId');
        $items = ProductLogic::most_reviewed_products($zone_id, $request['limit'], $request['offset'], $type);
        $items['products'] = Helpers::product_data_formatting($items['products'], true, false, app()->getLocale());
        return response()->json($items, 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 get_related_products(Request $request,$id)
    {
        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            array_push($errors, ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]);
            return response()->json([
                'errors' => $errors
            ], 403);
        }
        $zone_id= $request->header('zoneId');
        if (Item::find($id)) {
            $items = ProductLogic::get_related_products($zone_id,$id);
            $items = Helpers::product_data_formatting($items, true, false, app()->getLocale());
            return response()->json($items, 200);
        }
        return response()->json([
            'errors' => ['code' => 'product-001', 'message' => translate('messages.not_found')]
        ], 404);
    }

    public function get_recommended(Request $request)
    {
        if (!$request->hasHeader('zoneId')) {
            $errors = [];
            array_push($errors, ['code' => 'zoneId', 'message' => translate('messages.zone_id_required')]);
            return response()->json([
                'errors' => $errors
            ], 403);
        }
        $validator = Validator::make($request->all(), [
            'store_id' => 'required'
        ]);

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

        $zone_id= $request->header('zoneId');
        $items = ProductLogic::recommended_items($zone_id, $request->store_id,$request['limit'], $request['offset'], $type);
        $items['items'] = Helpers::product_data_formatting($items['items'], true, false, app()->getLocale());
        return response()->json($items, 200);
    }

    public function get_set_menus()
    {
        try {
            $items = Helpers::product_data_formatting(Item::active()->with(['rating'])->where(['set_menu' => 1, 'status' => 1])->get(), true, false, app()->getLocale());
            return response()->json($items, 200);
        } catch (\Exception $e) {
            return response()->json([
                'errors' => ['code' => 'product-001', 'message' => 'Set menu not found!']
            ], 404);
        }
    }

    public function get_product_reviews($item_id)
    {
        $reviews = Review::with(['customer', 'item'])->where(['item_id' => $item_id])->active()->get();

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

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

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

    public function get_product_rating($id)
    {
        try {
            $item = Item::find($id);
            $overallRating = ProductLogic::get_overall_rating($item->reviews);
            return response()->json(floatval($overallRating[0]), 200);
        } catch (\Exception $e) {
            return response()->json(['errors' => $e], 403);
        }
    }

    public function submit_product_review(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'item_id' => 'required',
            'order_id' => 'required',
            'comment' => 'required',
            'rating' => 'required|numeric|max:5',
        ]);

        $order = Order::find($request->order_id);
        if (isset($order) == false) {
            $validator->errors()->add('order_id', translate('messages.order_data_not_found'));
        }

        $item = Item::find($request->item_id);
        if (isset($order) == false) {
            $validator->errors()->add('item_id', translate('messages.item_not_found'));
        }

        $multi_review = Review::where(['item_id' => $request->item_id, 'user_id' => $request->user()->id, 'order_id'=>$request->order_id])->first();
        if (isset($multi_review)) {
            return response()->json([
                'errors' => [
                    ['code'=>'review','message'=> translate('messages.already_submitted')]
                ]
            ], 403);
        } else {
            $review = new Review;
        }

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

        $image_array = [];
        if (!empty($request->file('attachment'))) {
            foreach ($request->file('attachment') as $image) {
                if ($image != null) {
                    if (!Storage::disk('public')->exists('review')) {
                        Storage::disk('public')->makeDirectory('review');
                    }
                    array_push($image_array, Storage::disk('public')->put('review', $image));
                }
            }
        }

        $review->user_id = $request->user()->id;
        $review->item_id = $request->item_id;
        $review->order_id = $request->order_id;
        $review->module_id = $order->module_id;
        $review->comment = $request->comment;
        $review->rating = $request->rating;
        $review->attachment = json_encode($image_array);
        $review->save();

        if($item->store)
        {
            $store_rating = StoreLogic::update_store_rating($item->store->rating, (int)$request->rating);
            $item->store->rating = $store_rating;
            $item->store->save();
        }

        $item->rating = ProductLogic::update_rating($item->rating, (int)$request->rating);
        $item->avg_rating = ProductLogic::get_avg_rating(json_decode($item->rating, true));
        $item->save();
        $item->increment('rating_count');

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

    public function importItems(Request $request): \Illuminate\Http\JsonResponse
    {
        $validator = Validator::make($request->all(), [
            //'token' => 'required|exists:stores,token',
            'items' => 'required|array|min:1',
            'items.*.vendor_product_id' => 'required',
            'items.*.name_en' => 'required|string',
            'items.*.name_ar' => 'nullable|string',
            'items.*.description_en' => 'nullable|string',
            'items.*.description_ar' => 'nullable|string',
            'items.*.price' => 'required|numeric|min:0',
            'items.*.stock' => 'required|min:0',
        ]);

        $token = $request->header('token');

        if (!$token || !Store::where('token', $token)->exists()) {
            return response()->json([
                'status' => false,
                'message' => 'Invalid or missing token.',
            ], 401);
        }

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

        $store = Store::where('token', $token)->firstOrFail();
        $storeId = $store->id;

        $existingItems = Item::where('store_id', $storeId)
            ->whereIn('vendor_product_id', collect($request->items)->pluck('vendor_product_id'))
            ->get()
            ->keyBy('vendor_product_id');

        $imported = [];

        DB::beginTransaction();
        try {
            foreach ($request->items as $data) {
                $vendorId = $data['vendor_product_id'];
                $item = $existingItems->get($vendorId);

                $commonData = [
                    'name' => $data['name_en'],
                    'description' => $data['description_en'] ?? null,
                    'price' => $data['price'],
                    'stock' => $data['stock'],
                    'status' => $data['stock'] == 0 ? 0 : 1,
                ];

                if ($item) {
                    $item->update($commonData);
                    $imported[] = ['vendor_product_id' => $vendorId, 'status' => 'updated'];
                } else {
                    $newItem = Item::create(array_merge($commonData, [
                        'store_id' => $storeId,
                        'vendor_product_id' => $vendorId,
                        'tax' => 0,
                        'tax_type' => 'percent',
                        'discount' => 0,
                        'discount_type' => 'percent',
                        'available_time_starts' => '00:00:00',
                        'available_time_ends' => '23:59:59',
                        'veg' => 0,
                        'order_count' => 0,
                        'avg_rating' => 0,
                        'rating_count' => 0,
                        'module_id' => $store->module_id,
                        'slug' => Str::slug($data['name_en'] . '-' . Str::random(6)),
                        'recommended' => 0,
                        'is_approved' => 1,
                        'variations' => '[]',
                        'add_ons' => '[]',
                        'attributes' => '[]',
                        'choice_options' => '[]',
                    ]));
                    $item = $newItem;
                    $imported[] = ['vendor_product_id' => $vendorId, 'status' => 'created'];
                }

                if (!empty($data['name_ar'])) {
                    DB::table('translations')->updateOrInsert(
                        [
                            'translationable_type' => 'App\Models\Item',
                            'translationable_id' => $item->id,
                            'locale' => 'ar',
                            'key' => 'name',
                        ],
                        [
                            'value' => $data['name_ar'],
                            'updated_at' => now(),
                        ]
                    );
                }

                if (!empty($data['description_ar'])) {
                    DB::table('translations')->updateOrInsert(
                        [
                            'translationable_type' => 'App\Models\Item',
                            'translationable_id' => $item->id,
                            'locale' => 'ar',
                            'key' => 'description',
                        ],
                        [
                            'value' => $data['description_ar'],
                            'updated_at' => now(),
                        ]
                    );
                }
            }

            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Items imported successfully.',
                'result' => $imported
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => false,
                'message' => 'Import failed.',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}
