<?php

namespace App\Http\Controllers\Api\Objects;

use App\Http\Controllers\Controller;
use App\Models\Objects\Field;
use App\Models\Objects\NirObject;
use App\Models\Objects\ObjectType;
use App\Transformers\Objects\ObjectTransformer;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ObjectsController extends Controller {
    protected NirObject $model;

    public function __construct(NirObject $model) {
        $this->model = $model;
    }

    public function index(Request $request): JsonResponse {
        $query = $this->model->query();
        if (($val = $request->get('type')) && ($type = ObjectType::query()->where(['name' => $val])->first())) {
            $query->whereHas('type', function ($query) use ($val) {
                $query->where('name', $val)->orWhereHas('parent', function ($query) use ($val) {
                    $query->where('name', $val);
                });
            });
            if (in_array('product', [$type->name, $type->parent->name ?? null]) && ($field = Field::byUuidOrName('specification-holder')->first())) {
                $field->applyFilter($query, $request->user()->companies->pluck('uuid')->all());
            }
        }
        $filters = collect($request->has('filters') ? json_decode($request->get('filters'), true) : []);
        $filters->each(function($value, $prop) use($query) {
            if ($prop === 'search') $this->model->applySearchFilter($query, $value);
            elseif ($field = Field::byUuidOrName($prop)->first()) $field->applyFilter($query, $value);
        });
        $query->orderBy('created_at', 'desc');
        $paginator = $query->paginate(config('app.pagination_limit'));
        return fractal($paginator, new ObjectTransformer())->respond();
    }

    public function show($id): JsonResponse {
        $model = $this->model->byUuid($id)->firstOrFail();
        return fractal($model, new ObjectTransformer())->respond();
    }

    public function store(Request $request): JsonResponse {
        $this->validate($request, [
            'type' => 'required',
            'properties' => 'required|array'
        ]);
        $objectType = ObjectType::byUuidOrName($request->get('type'))->firstOrFail();
        $model = $objectType->objects()->create($request->only('name') + ['owner_id' => $request->user()->id]);
        $model->setValues($request->get('properties'));
        if ($objectType->name === 'product') $model->setValue('specification-holder', $request->user()->selectedMember->company->uuid ?? null);
        return fractal($model, new ObjectTransformer())->respond(201);
    }

    public function move(Request $request, $id): JsonResponse {
        $model = $this->model->byUuid($id)->firstOrFail();
        if (($type = $request->get('model_type')) && ($className = Relation::$morphMap[$type] ?? null) && ($id = $request->get('model_id'))) {
            if ($related = $className::byUuid($id)->first()) $related->moveObject($model, $request->get('ord'), $request->get('group'));
        }
        return fractal($model, new ObjectTransformer())->respond();
    }

    public function update(Request $request, $uuid): JsonResponse	{
        $model = $this->model->byUuid($uuid)->firstOrFail();
        $this->validate($request, [
            'properties' => 'required|array'
        ]);
        $model->setValues($request->get('properties'));
        $model->update($request->only('name'));
        return fractal($model->fresh(), new ObjectTransformer())->respond();
    }

    public function destroy(Request $request, $uuid): JsonResponse {
        $model = $this->model->byUuid($uuid)->firstOrFail();
        $model->delete();
        return response()->json(null, 204);
    }
}
