<?php

namespace App\DataTables\Warehouses;

use App\Models\LocalizationManagement\City;
use App\Models\StockManagement\Warehouse;
use App\Models\StockManagement\WareHouseType;
use App\Models\UserManagement\Admin;
use App\Models\UserManagement\User;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Validation\Rule;
use Throwable;
use Yajra\DataTables\DataTablesEditor;

class WarehouseDataTableEditor extends DataTablesEditor{
    protected $model = Warehouse::class;

    /**Get create action validation rules.
     * @return array
     */
    public function createRules(){
        return  [
            "name" => ["required",'min:4',],
            "code" => ["nullable",'min:2',],
        ];
    }

    /**Get edit action validation rules.
     * @param Model $model
     * @return array
     */
    public function editRules(Model $model){
        $city_table = (new City)->getTable();
        $user_table = (new Admin)->getTable();

        $datas = Arr::first(request()->all()['data']);

       // dd(WareHouseType::all()->pluck("code")->toArray());

        $rules = [
            "name" => ["required",'min:4',],
            "city_id" => ['sometimes',"int","exists:$city_table,id"],
            "warehouse_type_code" => ['required',Rule::in(WareHouseType::all()->pluck("id")->toArray())],
        ];

        if ($datas['warehouse_type_code'] == WareHouseType::POINT_OF_SALE){
            $rules['managers'] = ['nullable',"array"];
            $rules['managers.*'] = ['nullable',"int","exists:$user_table,id"];

            $rules['cities'] = ['nullable',"array"];
            $rules['cities.*'] = ['nullable',"int","exists:$city_table,id"];
        }else{
            $rules['is_bad_goods'] = ['required',"boolean"];
        }
        return  $rules;
    }

    /**
     * Get remove action validation rules.
     *
     * @param Model $model
     * @return array
     */
    public function removeRules(Model $model){
       // $role_table_name = $this->resolveModel()->getTable();
        return [
//            "ids" => ['required',"array","min:1"],
//            "ids.*" => ['required',"int","exists:$role_table_name,id,deleted_at,NULL"],
        ];
    }

    public function attributes(){
        return [
            "warehouse_type_code" => __("Type"),
            "name" => __("Name"),
            "cities" => __("Villes"),
            "cities.*" => __("Ville"),
            "states" => __("States"),
            "states.*" => __("State"),
            "state" => __("State"),
            "store" => __("Magasin Principal"),
            "city" => __("Ville"),
            "managers" => __("Gérants"),
            "managers.*" => __("Gérant"),
            "is_bad_goods" => __("Déffectueux"),
        ];
    }

    public function created(Warehouse $warehouse, $data){
        $cities= $data['cities'] ?? [];
        $managers = $data['managers'] ?? [];

        if (isset($data['cities'])){
            if ($cities){
                //met a jour les les villes d'approvisionnement
                City::whereIn("id",$cities)->update(["warehouse_id" => $warehouse->id]);
            }else{
                $warehouse->cities()->update(['warehouse_id' => null]);
            }
        }
        if (isset($data['managers'])){
            $warehouse->managers()->sync($managers);
        }
        return $warehouse;
    }

    public function updated(Warehouse $warehouse, $data){
        $cities= $data['cities'] ?? [];
        $managers = $data['managers'] ?? [];

        if (isset($data['cities'])){
            if ($cities){
                //met a jour les les villes d'approvisionnement
                City::whereIn("id",$cities)->update(["warehouse_id" => $warehouse->id]);
            }else{
                $warehouse->cities()->update(['warehouse_id' => null]);
            }
        }
        if (isset($data['managers'])){
            $warehouse->managers()->sync($managers);
        }
        return $warehouse;
    }

//    public function updating(Warehouse $warehouse, array $data){
//        return $this->editing($warehouse,$data,"ing");
//    }
//
//    public function creating(Warehouse $warehouse, array $data){
//        return $this->editing($warehouse,$data,"ing");
//    }

    protected function editing(Warehouse $warehouse,$datas,$event = "ed"){
        $cities = $datas['cities'] ?? [];
        $managers = $datas['managers'] ?? [];

        if ($cities){
            //met a jour les les villes d'approvisionnement
            City::whereIn("id",$cities)->update(["warehouse_id" => $warehouse->id]);
        }

        if ($managers){
            $warehouse->managers()->sync($managers);
        }
        unset($datas['cities']);
        unset($datas['managers']);

        return ($event === "ing") ? $datas : $warehouse;
    }


    /**
     * Process edit action request.
     *
     * @param  Request  $request
     * @return JsonResponse
     */
    public function edit(Request $request)
    {
        $connection = $this->getBuilder()->getConnection();
        $affected   = [];
        $errors     = [];

        $connection->beginTransaction();
        foreach ($request->get('data') as $key => $data) {
            $this->currentData = $data;

            $model     = $this->getBuilder()->findOrFail($key);
            $validator = $this->getValidationFactory()
                            ->make(
                                $data,
                                $this->editRules($model), $this->messages() + $this->editMessages(),
                                $this->attributes()
                            );
            if ($validator->fails()) {
                foreach ($this->formatErrors($validator) as $error) {
                    $errors[] = $error;
                }
                continue;
            }

            if (method_exists($this, 'updating')) {
                $data = $this->updating($model, $data);
            }

            if (method_exists($this, 'saving')) {
                $data = $this->saving($model, $data);
            }

            $this->restoring ? $model->restore() : $model->fill($data)->save();

            if (method_exists($this, 'updated')) {
                $model = $this->updated($model, $data);
            }

            if (method_exists($this, 'saved')) {
                $model = $this->saved($model, $data);
            }

           // $model->setAttribute('DT_RowId', $model->getKey());
            $affected[] = $model;
        }

        if (! $errors) {
            $connection->commit();
        } else {
            $connection->rollBack();
        }

        return $this->toJson($affected, $errors);
    }

    /**
     * Process create action request.
     *
     * @param Request $request
     * @return JsonResponse
     *
     * @throws Exception
     * @throws Throwable
     */
    public function create(Request $request){
        $model      = $this->resolveModel();
        $connection = $model->getConnection();
        $affected   = [];
        $errors     = [];

        $connection->beginTransaction();
        foreach ($request->get('data') as $data) {
            $this->currentData = $data;

            $instance  = $model->newInstance();
            $validator = $this->getValidationFactory()
                ->make(
                    $data,
                    $this->createRules(), $this->messages() + $this->createMessages(),
                    $this->attributes()
                );
            if ($validator->fails()) {
                foreach ($this->formatErrors($validator) as $error) {
                    $errors[] = $error;
                }

                continue;
            }

            if (method_exists($this, 'creating')) {
                $data = $this->creating($instance, $data);
            }

            if (method_exists($this, 'saving')) {
                $data = $this->saving($instance, $data);
            }

            $instance->fill($data)->save();

            if (method_exists($this, 'created')) {
                $instance = $this->created($instance, $data);
            }

            if (method_exists($this, 'saved')) {
                $instance = $this->saved($instance, $data);
            }
            $affected[] = $instance;
        }

        if (! $errors) {
            $connection->commit();
        } else {
            $connection->rollBack();
        }

        return $this->toJson($affected, $errors);
    }
}
