<?php

    namespace App\Http\Controllers\Admin;

    use App\Facades\ContentTypes;
    use App\Facades\RequestContext;
    use App\Facades\Services\BackendUserService;
    use App\Facades\Services\BackofficeService;
    use App\Http\Controllers\Controller;
    use App\Http\Requests\AdminContentAutoComplete;
    use App\Models\GenericBackoffice\WebsiteObjectLanguage;
    use Illuminate\Support\Facades\Validator;
    use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
    use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
    use App\Events\ContentTypeSaved;

    class ContentController extends Controller
    {
        public function getIndex($type)
        {
            $contentType = ContentTypes::find($type);

            return view('admin.generic.pages.list', ["contentType" => $contentType]);
        }

        public function postList($type)
        {
            $contentType = ContentTypes::find($type);

            //TODO implement form request
            $page = request()->input("current");
            $sort = request()->input("sort");
            $search = request()->input("searchPhrase");
            $rowCount = request()->input("rowCount");

            if (empty($sort) && $contentType->isOrderable() && !$contentType->isHierarchic()) {
                $sort = ["position" => "asc"];
            }
            $list = $contentType->toList($page, $rowCount, $sort, $search);

            return response()->json($list);
        }

        public function getForm($type, $id = false, $parentId = false, $parentContentType = false, $parentFieldName = false, $isPreview = false)
        {
            session()->forget("_old_input");

            $contentType = ContentTypes::find($type);

            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            $parentData = $contentType->getParent();

            if ($parentContentType && $parentFieldName) {
                $parentType = ContentTypes::find($parentContentType);
                $parentField = $parentType->getFields()->find($parentFieldName);
                if (!$parentField || $parentField->getObjectType() != $type) {
                    abort(404, trans("response.not_found"));
                }

                $parentData = [
                    'field'       => $parentFieldName,
                    'contentType' => $parentContentType
                ];
            }

            $modelType = $contentType->getModelType();

            if (!empty($id)) {
                $model = $modelType::find($id);

                if (is_null($model)) {
                    abort(404, trans("response.not_found"));
                }
            } else {
                if (!$contentType->userHasPermission()) {
                    abort(403, trans("response.forbidden"));
                }

                $modelType = $contentType->getModelType();
                $model = new $modelType;
            }
            if (!$model->exists && (!empty($parentId) && empty($parentData)) ||
                (empty($parentId) && !empty($parentData))) {
                abort(400, trans("response.bad_syntax"));
            }

            RequestContext::set('generic_form_timestamp', time());

            if (request()->ajax()) {
                return view(
                    'admin.generic.components.form',
                    [
                        "model"       => $model,
                        "contentType" => $contentType,
                        "parentId"    => $parentId,
                        "isPreview"   => $isPreview,
                    ]
                );
            } else {
                return view(
                    'admin.generic.pages.form',
                    [
                        "model"       => $model,
                        "contentType" => $contentType,
                        "parentId"    => $parentId,
                        "isPreview"   => $isPreview,
                    ]
                );
            }
        }
        public function getPreview($type, $id = false, $parentId = false, $parentContentType = false, $parentFieldName = false, $isPreview = true)
        {
            return $this->getForm($type, $id, $parentId, $parentContentType, $parentFieldName, $isPreview);
        }

        public function postCheckSlug()
        {
            $originSlug = request()->input("slug");
            $langId = request()->input("lang");

            if (empty($originSlug) || empty($langId)) {
                return response()->json([
                    "error"       => "bad_syntax",
                    "description" => "The request is missing the slug"
                ], 400);
            }
            $slug = BackofficeService::generateSlug($originSlug, $langId);

            if ($slug === false) {
                return response()->json([
                    "error"       => "invalid",
                    "description" => "Impossible to generate this slug"
                ], 400);
            } else {
                return response()->json(["slug" => $slug]);
            }
        }

        public function postForm(
            $type,
            $id = false,
            $parentId = false,
            $parentContentType = false,
            $parentFieldName = false
        ) {
            $contentType = ContentTypes::find($type);
            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            $loggedUser = BackendUserService::getLoggedUser();
            if (!empty($id)) {
                $modelType = $contentType->getModelType();
                $model = $modelType::find($id);

                if (is_null($model)) {
                    abort(404, trans("response.not_found"));
                }
            } else {
                $modelType = $contentType->getModelType();
                $model = new $modelType;
                $filters = $contentType->getFilters();
                foreach ($filters as $filter) {
                    $model->$filter["field"] = $filter["value"];
                }
            }

            $parentData = $contentType->getParent();
            $hasPivot = false;

            if ($parentContentType && $parentFieldName) {
                $parentType = ContentTypes::find($parentContentType);
                $parentField = $parentType->getFields()->find($parentFieldName);
                if (!$parentField || $parentField->getObjectType() != $type) {
                    abort(404, trans("response.not_found"));
                }

                $parentData = [
                    'field'       => $parentFieldName,
                    'contentType' => $parentContentType
                ];
                $hasPivot = true;
            }

            if (!$model->exists && (!empty($parentId) && empty($parentData)) ||
                (empty($parentId) && !empty($parentData))) {
                abort(400, trans("response.bad_syntax"));
            }

            //TODO use Form Request?
            $validation = $contentType->getValidation(!$model->exists);

            $validator = Validator::make(
                $validation["values"],
                $validation["rules"]
            );

            $validator->setAttributeNames($validation["labels"]);

            $languages = getAvailableLanguages();
            foreach ($languages as $langCode => $lang) {
                $originSlug = $validation["values"]["lang_slug"][ $langCode ];
                if ($model->exists && $model->website_object_id) {
                    $woLang = WebsiteObjectLanguage::where('website_object_id', $model->website_object_id)
                        ->where('wo_language_id', $langCode)
                        ->first();
                    if ($woLang && $woLang->lang_slug == $originSlug) {
                        continue;
                    }
                }
                $slug = BackofficeService::generateSlug($originSlug, $langCode);
                $validation["values"]["lang_slug"][ $langCode ] = ($slug ? $slug : '');
            }
            if ($validator->fails()) {
                RequestContext::set("errors", $validator->getMessageBag());
                view()->share("errors", $validator->getMessageBag());
                request()->flash();
                if (request()->ajax()) {
                    return view(
                        'admin/generic/components/form',
                        [
                            "model"       => $model,
                            "contentType" => $contentType,
                            "parentId"    => $parentId,
                            "isPreview"   => false
                        ]
                    );
                } else {
                    return view(
                        'admin/generic/pages/form',
                        [
                            "model"       => $model,
                            "contentType" => $contentType,
                            "parentId"    => $parentId,
                            "isPreview"   => false
                        ]
                    );
                }
            }

            BackofficeService::saveContentType(
                $contentType,
                $model,
                $validation["values"],
                $loggedUser,
                $parentData,
                $parentId,
                $hasPivot
            );
            
            // Event Listener to save Route waypoints time and distance through their coordenates
            event(new ContentTypeSaved($model, $contentType));

            $redirectUrl = request()->path();
            if ($id === false) {
                $redirectUrl .= "/" . $model->id;
            }
            session()->forget("_old_input");
            if (request()->ajax()) {
                return response()->json([
                    "id"                => $model->id,
                    "title"             => $model->title,
                    "website_object_id" => $model->website_object_id
                ]);
            } else {
                //If has template and has template configuration, jumps to it

                if ($contentType->hasTemplate()) {
                    $model->load('websites');
                    $websiteObject = $model->websites->first();
                    $objectTemplate = $contentType->getTemplates()[ $websiteObject->template ];
                    if (isset($objectTemplate['contentType'])) {
                        $contentType = ContentTypes::find($objectTemplate['contentType']);
                        $parentData = $contentType->getParent();
                        if (empty($parentData)) {
                            abort(404, trans("response.not_found"));
                        }
                        $modelType = $contentType->getModelType();
                        $configModel = $modelType::where($parentData["field"], $model->id)->first();

                        if (!$configModel) {
                            $redirectUrl = 'admin/content/form-template/' . $objectTemplate['contentType'] . '/' . $model->id;

                            return redirect()->to($redirectUrl);
                        }
                    }
                }

                return redirect()->to($redirectUrl)->withMessage(trans("backend.save_success"));
            }
        }

        public function postAutoComplete(AdminContentAutoComplete $request, $type)
        {
            $contentType = ContentTypes::find($type);
            $data = $request->validated();

            $results = $contentType->autoComplete($data['searchTerm']);

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

        public function deleteContentType($type, $id)
        {
            $contentType = ContentTypes::find($type);

            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            try {
                BackofficeService::deleteContentType($contentType, $id);
            } catch (NotFoundHttpException $e) {
                return response()->json(["success" => true]);
            }

            return response()->json(["success" => true]);
        }

        public function getOrder($type)
        {
            $contentType = ContentTypes::find($type);

            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            if ($contentType->isHierarchic()) {
                $entries = $contentType->toStructuredList();
            } else {
                $entries = $contentType->toList(null, null, ['position' => 'asc'])->all();
            }

            return view('admin.generic.pages.order', [
                "contentType" => $contentType,
                "entries"     => $entries
            ]);
        }

        public function postOrder($type)
        {
            $contentType = ContentTypes::find($type);

            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            $newOrder = request()->input('content_order');
            $newOrder = json_decode($newOrder);

            if (!$newOrder || !is_array($newOrder)) {
                abort(400, trans("response.bad_syntax"));
            }

            try {
                BackofficeService::reorderContentType($contentType, $newOrder);
            } catch (BadRequestHttpException $e) {
                abort(400, trans("response.bad_syntax"));
            }

            if (request()->ajax()) {
                return response()->json(["message" => "OK"]);
            } else {
                $redirectUrl = 'admin/content/index/' . $type;

                return response()->redirectTo($redirectUrl)->withMessage(trans("backend.save_success"));
            }
        }

        public function getFormTemplate($type, $parentId)
        {
            $contentType = ContentTypes::find($type);

            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            $parentData = $contentType->getParent();

            if (empty($parentData)) {
                abort(404, trans("response.not_found"));
            }
            $modelType = $contentType->getModelType();
            $model = $modelType::where($parentData["field"], $parentId)->first();

            if (empty($model)) {
                $loggedUser = BackendUserService::getLoggedUser();
                $model = BackofficeService::createContentTypeTemplate($contentType, $parentId, $loggedUser);
            }
            $url = "/admin/content/form/{$type}/{$model->id}/{$parentId}";


            return response()->redirectTo($url);
        }
    }
