<?php

namespace App\Http\Controllers\Admin;

/** Ajax Request */

use App\Enums\ProductCostStatusEnum;
use App\Models\Attribute;
use App\Models\Brand;
use App\Models\Category;
use App\Models\Rate;
use App\Models\CategoryDescription;
use App\Models\CategoryAttribute;
use App\Models\ProductAttribute;
use App\Models\ProductAttributeChoice;
use App\Models\ProductCost;
use App\Models\ProductPhoto;
use App\Services\Response\ResponseService;
use Exception;

use App\Models\Product;
use Illuminate\View\View;
use App\Models\ProductDescription;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Redirector;
use Illuminate\Http\RedirectResponse;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ProductRequest; // for Validation
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class ProductController extends Controller
{

    /** Redirect to this path after each operation success*/
    private $redirectSuccessPath = '/admin/products';
    /** View folder */
    private $viewDirectory = 'admin.products.';

    /**
     * Display a listing of the products.
     *
     * @param Request $request
     * @return View
     */
    public function index(Request $request) :View
    {
        $title= __('products.head');
        $request= $request->toArray();
        return view($this->viewDirectory.'index',compact('title'));
    }

    /**
     * return data of the products.
     *
     * @param Request $request
     * @return View
     */
    public function grid(Request $request) :View
    {
        $query = Product::latest()
            ->join('product_descriptions AS cd', 'products.id', 'cd.product_id')
            ->join('languages', 'languages.id', 'cd.language_id')
            ->where('local', LaravelLocalization::getCurrentLocale())
            ->select(['cd.name', 'products.*']);

        if ($request->date_from) {
            $query->whereDate('products.created_at', '>=', $request->date_from);
        }

        if ($request->date_to) {
            $query->whereDate('products.created_at', '<=', $request->date_to);
        }
        if($request->category)
        {
            $ids = CategoryDescription::where('name', 'LIKE', '%'.$request->category.'%')->pluck('category_id')->toArray();
            if(count($ids) == 0)
            {
                $ids =['0'];
            }
            $query->whereRaw("category_id IN (".implode(',', $ids).")");
        }
        if($request->model)
        {
            $ids = CategoryDescription::where('name', 'LIKE', '%'.$request->model.'%')->pluck('category_id')->toArray();
            if(count($ids) == 0)
            {
                $ids =['0'];
            }
            $query->whereRaw("model_id IN (".implode(',', $ids).")");
        }
        if ($request->name) {
            $query->where('cd.name', 'LIKE', '%'.$request->name.'%');
        }

        if ( !is_null($request->status) && $request->status == 0) {
            $query->onlyTrashed();
        }
        $products= $query->paginate(100);

        return view($this->viewDirectory.'grid',compact('products'));
    }

    /**
     * Show the form for creating a new Product.
     *
     * @return View
     */
    public function create() :View
    {
        $action= route('products.store');
        $head = metaFields('products', 'add_new', getCurrentLocale()) ?? __('products.new');

        $categories = Category::withDescription()->where('categories.category_id',null)->cursor();
        $brands = Brand::withDescription()->cursor();
        $cost_status = ProductCostStatusEnum::status();

        return view( $this->viewDirectory.'form', compact('action', 'head','categories','brands','cost_status') );
    }

    /**
     * Store a newly created Product in storage.
     * @param ProductRequest $request
     * @return RedirectResponse|Redirector
     */
    public function store(ProductRequest $request) 
    {
        $product = Product::create($request->all());

        // Insert Description
        $this->saveData( $request, $product->id );

        session()->flash('message', __('dashboard.saveDone'));
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> $this->redirectSuccessPath,
        ];
        return ResponseService::response($response);
    }

    /**
     * Show the form for editing the specified Product.
     *
     * @param  Product  $product
     * @return View
     */
    public function edit(Product $product) :View
    {
        $action= route('products.update', $product->id);
        $head = metaFields('products', 'edit', getCurrentLocale()) ?? __('products.edit');

        $query = ProductDescription::where('product_id', $product->id)
            ->join('languages', 'languages.id', 'product_descriptions.language_id')
            ->select(['product_descriptions.*', 'languages.local']);

        $productDescription= $query->get();

        $categories = Category::withDescription()->where('categories.category_id',null)->cursor();
        $brands = Brand::withDescription()->cursor();
        $models = Category::withDescription()->where('categories.category_id',$product->category_id)->cursor();
        $category = Category::withDescription()->withTrashed()->find($product->category_id);
        $ids = CategoryAttribute::where('category_id',$product->category_id)->pluck('attribute_id')->toArray();
        $ones = Attribute::withDescription()->find($ids);
        foreach ($productDescription as $row) {
            $product[$row->local]= $row;
        }
        $cost_status = ProductCostStatusEnum::status();
        $main = Attribute::find($category->main_id);
        $sub = Attribute::find($category->sub_id);
        $rates = Rate::where('product_id',$product->id)->where('user_id',null)->cursor();

        return view( $this->viewDirectory.'form', compact('product', 'main','sub','rates','action','category','ones', 'head','categories','brands','models','cost_status') );
    }

    /**
     * Update the specified Product in storage.
     * @param ProductRequest $request
     * @param Product $product
     * @return RedirectResponse|Redirector
     */
    public function update(ProductRequest $request, Product $product) 
    {
        // Update the "updated_at" column only
        $product->update($request->all());

        // Delete old description
        ProductDescription::where('product_id', $product->id)->delete();
        ProductPhoto::where('product_id', $product->id)->delete();
        ProductCost::where('product_id', $product->id)->delete();
        ProductAttribute::where('product_id', $product->id)->where('choice_id','!=',null)->delete();
        Rate::withTrashed()->where('product_id',$product->id)->where('user_id',null)->forceDelete();
        // Insert new description
        $this->saveData( $request, $product->id );

        session()->flash('message', __('dashboard.saveDone'));
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> $this->redirectSuccessPath,
        ];
        return ResponseService::response($response);
    }

    /**
     * Handle Save form data
     *
     * @param ProductRequest $request
     * @param int $product_id
     * @return void
     */

    private function saveData(ProductRequest $request, int $product_id ) :void
    {
        $requestData= $request->all();

        foreach (languages() as $lang) {
            $data=[
                'product_id'=> $product_id,
                'language_id'=> $lang->id,
                'name'=> $requestData['name_'.$lang->local],
                'description'=> $requestData['description_'.$lang->local],
            ];

            ProductDescription::create($data);
        }

        $cost_status = ProductCostStatusEnum::status();
        foreach ($cost_status as $status)
        {
            ProductCost::create([
                'status'=>$status,
                'product_id'=>$product_id,
                'cost'=>$requestData['costs'][$status]['cost'],
                'cost_discount'=>$requestData['costs'][$status]['cost_discount'],
            ]);
        }
        if(!is_null($request['one']))
        {
            foreach ($request['one'] as $key=>$row)
            {
                ProductAttribute::create([
                    'image' => $row['image'] ?? null,
                    'count' => $row['count'] ?? null,
                    'product_id' => $product_id,
                    'attribute_id' => $key,
                    'choice_id' => $row['choice_id'],
                ]);
            }
        }
        if(!is_null($request['multi']))
        {
            foreach ($request['multi'] as $key=>$row)
            {
                $main_attr = ProductAttribute::where('product_id',$product_id)
                    ->where('attribute_id',$key)
                    ->where('choice_id',null)->where('product_attribute_id',null)->first();
                if(!$main_attr)
                {
                    $main_attr = ProductAttribute::create([
                        'product_id' => $product_id,
                        'attribute_id' => $key,
                    ]);
                }
                foreach ($row as $choice_main=>$rows)
                {
                    $main_choice = ProductAttributeChoice::where('product_attribute_id',$main_attr->id)
                        ->where('choice_id',$choice_main)->first();
                    if(!$main_choice)
                    {
                        $main_choice = ProductAttributeChoice::create([
                            'product_attribute_id' => $main_attr->id,
                            'choice_id' => $choice_main,
                            'count' => $rows['count'] ?? null,
                            'image' => $rows['image'] ?? null,
                        ]);
                    }
                    else
                    {
                        $main_choice->update([
                            'product_attribute_id' => $main_attr->id,
                            'choice_id' => $choice_main,
                            'count' => $rows['count'] ?? null,
                            'image' => $rows['image'] ?? null,
                        ]);
                    }
                    if(isset($rows['sub']))
                    {
                        foreach ($rows['sub'] as $sub_attr_key=>$row)
                        {
                            $sub_attr = ProductAttribute::where('product_id',$product_id)
                                ->where('attribute_id',$sub_attr_key)
                                ->where('product_attribute_id',$main_attr->id)
                                ->where('product_attribute_choice_id',$main_choice->id)->first();
                            if(!$sub_attr)
                            {
                                $sub_attr = ProductAttribute::create([
                                    'product_id' => $product_id,
                                    'attribute_id' => $sub_attr_key,
                                    'product_attribute_id' => $main_attr->id,
                                    'product_attribute_choice_id' => $main_choice->id,
                                ]);
                            }
                            foreach ($row as $sub_choice_key=>$value)
                            {
    //                            $sub_choice_key = array_key_first($row[$chpice_main][$sub_attr_key]);
                                // if (!is_null($value['count']) )
                                // {
                                    $attr_choice = ProductAttributeChoice::where('product_attribute_id',$sub_attr->id)
                                        ->where('choice_id',$sub_choice_key)->first();
    
                                    if($attr_choice)
                                    {
                                        $attr_choice->update([
                                            'product_attribute_id' => $sub_attr->id,
                                            'choice_id' => $sub_choice_key,
                                            'count' => $value['count'],
                                            'image' => $value['image'],
                                        ]);
                                    }
                                    else
                                    {
                                        if(!is_null($value['count']))
                                        {
                                            ProductAttributeChoice::create([
                                                'product_attribute_id' => $sub_attr->id,
                                                'choice_id' => $sub_choice_key,
                                                'count' => $value['count'],
                                                'image' => $value['image'],
                                            ]);
                                        }
                                    }
    
                                // }
                            }
                        }
                    }
                }
                
            }
        }
        if(isset($request->rates))
        {
            foreach ($request->rates as $row)
            {
                Rate::create([
                    'rate' => $row['rate'],
                    'image' => $row['image'] ?? 'user.png',  
                    'name' => $row['name'],
                    'comment' => $row['comment'],
                    'status' => 'visitor',
                    'product_id' => $product_id,
                ]);
            }
        }
        if(isset($request->images))
        {
            foreach ($request->images as $row)
            {
                ProductPhoto::create([
                    'image' => $row,
                    'product_id' => $product_id,
                ]);
            }
        }

    }

    /**
     * Remove the specified Product from storage.
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function destroy(Request $request, int $id) :JsonResponse
    {
        $product= Product::withTrashed()->find($id);
        if ($product) {
            if ($product->deleted_at) {
                $product->forceDelete();
            } else {
                $product->delete();
            }
            return response()->json(['message'=> __('dashboard.deletedDone')]);
        } else{
            return response()->json(['message'=> __('dashboard.noResult')], 400);
        }
    }

    /**
     * Remove several products by IDs.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function destroyAll(Request $request) :JsonResponse
    {
        $ids= $request->ids;

        if ($request->force) {
            Product::onlyTrashed()->whereIn('id', $ids)->forceDelete();
        } else {
            Product::whereIn('id', $ids)->delete();
        }

        return response()->json(['message'=> __('dashboard.deletedDone')]);
    }

    /**
     * Restore the specified Product from storage.
     *
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     */
    public function restore(Request $request, int $id) :JsonResponse
    {
        $product= Product::withTrashed()->find($id);
        if ($product) {
            $product->restore();
            return response()->json(['message'=> __('dashboard.saveDone')]);
        }
        return response()->json(['message'=> __('dashboard.noResult')], 400);

    }

    /**
     * Restore several products by IDs.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function restoreAll(Request $request) :JsonResponse
    {
        $ids= $request->ids;
        Product::whereIn('id', $ids)->onlyTrashed()->restore();
        return response()->json(['message'=> __('dashboard.saveDone')]);
    }
}
