<?php

namespace App\Services\Backoffice;

use App\Facades\Backoffice\ContentTypes;
use App\Jobs\Backoffice\ProcessSearch;
use App\Libs\Backoffice\ContentType;
use App\Libs\Backoffice\Contracts\ExternalField;
use App\Libs\Backoffice\Contracts\NonSavableField;
use App\Libs\Backoffice\Contracts\PostSavableField;
use App\Libs\Backoffice\Contracts\SavableField;
use App\Models\Backoffice\Auth\BackendUser;
use App\Models\Backoffice\MenuItem;
use App\Models\Backoffice\MenuItemLanguage;
use App\Models\Backoffice\Page;
use App\Models\Backoffice\Support\ContentTypeModel;
use App\Models\Backoffice\Support\TranslationModel;
use App\Models\Backoffice\WebsiteObject;
use App\Models\Backoffice\WebsiteObjectLanguage;
use Illuminate\Support\Facades\DB;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use stdClass;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
use Illuminate\Support\Str;

class BackofficeService
{

    /**
     * Saves content type model
     *
     * @param  ContentType  $contentType
     * @param  ContentTypeModel  $model
     * @param  array  $formData
     * @param  BackendUser  $author
     * @param  array|boolean  $parentData
     * @param  int|boolean  $parentId
     * @param  boolean  $hasPivot
     * @return ContentTypeModel
     *
     * @throws Throwable
     */
    public function saveContentType(
        ContentType $contentType,
        ContentTypeModel $model,
        $formData,
        BackendUser $author,
        $parentData = false,
        $parentId = false,
        $hasPivot = false
    ) {

        if (!empty($parentData) && !$model->exists && !$hasPivot) {
            $parentField = $parentData["field"];
            $model->$parentField = $parentId;
        }

        $modelFields = $contentType->getFields()->getSingleLanguageFields();

        foreach ($modelFields as $field) {
            if ($field->isRelationField() || $field instanceof ExternalField || $field instanceof NonSavableField) {
                continue;
            }
            $fieldName = $field->getName();
            if ($field instanceof SavableField) {
                $field->save($model, $formData[$fieldName]);
            } else {
                $model->$fieldName = $formData[$fieldName];
            }

        }

        DB::beginTransaction();
        $isNew = false;
        try {
            if (!$model->exists) {
                $model->backend_user_id = $author->id;
                $isNew = true;
            }
            if ($model->exists || !$hasPivot) {
                $model->save();
            } else {
                $parentModel = $this->_getParentModelFromContentType($parentId, $parentData["contentType"]);
                $prop = $parentData["field"];
                $parentModel->$prop()->save($model);
            }

            $languageFields = $contentType->getFields()->getMultiLanguageFields();
            $languageModels = $model->languages;

            foreach ($languageFields as $field) {
                if ($field->isRelationField() || $field instanceof ExternalField || $field instanceof NonSavableField) {
                    continue;
                }

                $fieldName = $field->getName();
                $values = $formData[$fieldName];
                $languageModelType = $model->languages()->getRelated();

                foreach ($values as $languageId => $value) {
                    $languageModel = $languageModels->findByLocale($languageId);
                    if (empty($languageModel)) {
                        $languageModel = new $languageModelType;
                        $languageModel->language_id = $languageId;
                        $languageModels->add($languageModel);
                    }

                    if ($field instanceof SavableField) {
                        $field->save($languageModel, $value);
                    } else {
                        $languageModel->$fieldName = $value;
                    }
                }
            }

            $model->languages()->saveMany($languageModels->all());
            $websiteObjects = $model->websites;

            $websiteObject = $websiteObjects->first();

            if (empty($websiteObject)) {
                $websiteObject = new WebsiteObject();
                $websiteObject->content_type = $contentType->getType();

                if ($contentType->isOrderable()) {
                    $position = WebsiteObject::maxPosition(
                        get_class($model));
                    if (empty($position)) {
                        $position = 0;
                    }
                    $websiteObject->position = $position + 1;
                }

                $websiteObjects->add($websiteObject);
                foreach ($languageModels as $lang) {
                    $woLang = new WebsiteObjectLanguage();
                    $woLang->wo_language_id = $lang->language_id;

                    $websiteObject->languages->add($woLang);
                }
            }

            $defaultLang = LaravelLocalization::getDefaultLocale();
            if ($contentType->isPage()) {
                foreach ($languageModels as $lang) {
                    $woLang = $websiteObject->languages->findByLocale($lang->language_id);

                    if (isset($formData["slug"][$lang->language_id])) {
                        $woLang->slug = $formData["slug"][$lang->language_id];
                    } else {
                        $woLang->slug = $formData["slug"][$defaultLang];
                    }

                    if (isset($formData["status"][$lang->language_id])) {
                        $woLang->status = $formData["status"][$lang->language_id];
                    } else {
                        $woLang->status = $formData["status"][$defaultLang];
                    }

                    if ($defaultLang == $lang->language_id) {
                        $woLang->slug = $formData["slug"][$lang->language_id];
                    }

                    $metaUpdateEnabled = config('backoffice.meta_info.update.enabled');
                    $excludeUris = config('backoffice.meta_info.update.exclude_uris');
                    if ($metaUpdateEnabled && !in_array($websiteObject->uri, $excludeUris)) {
                        $languageModel = $model->languages->findByLocale($lang->language_id);
                        $this->_insertMetaInfo($languageModel, $model);
                    }
                }

                $websiteObject->template = $formData["template"];

                $this->_updateUri($websiteObject, $contentType, !$isNew);
            }

            $model->websites()->saveMany($websiteObjects->all());

            foreach ($websiteObjects as $websiteObject) {
                $websiteObject->languages()->saveMany($websiteObject->languages->all());
            }

            $relationFields = $contentType->getFields()->getRelationFields();

            foreach ($relationFields as $field) {
                $fieldName = $field->getName();
                if (isset($formData[$fieldName])) {
                    $field->save($model, $formData[$fieldName]);
                }
            }

            foreach ($modelFields as $field) {
                if ($field instanceof ExternalField || $field instanceof NonSavableField) {
                    continue;
                }
                $fieldName = $field->getName();
                if ($field instanceof PostSavableField) {
                    $field->postSave($model, $contentType, $formData[$fieldName]);
                }
            }

            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            throw($e);
        }

        if (!empty($contentType->getSearch())) {
            ProcessSearch::dispatch($contentType, $model);
        }

        return $model;
    }

    /**
     * @param int $parentId
     * @param string $contentType
     * @return ContentTypeModel|null
     */
    protected function _getParentModelFromContentType(int $parentId, string $contentType): ?ContentTypeModel
    {
        $parentContentType = ContentTypes::find($contentType);
        $parentModelType = $parentContentType->getModelType();
        return $parentModelType::find($parentId);
    }

    /**
     * Inserts meta info if not set, in models that have those properties
     * If the model has a parent, sets with the parent's info
     * If not, sets with the info of the page defined in config
     *
     * @param TranslationModel $languageModel
     * @param ContentTypeModel $model
     */
    protected function _insertMetaInfo(TranslationModel $languageModel, ContentTypeModel $model)
    {
        $config = config('backoffice.meta_info.update');
        $mustSave = false;
        if (property_exists($languageModel, 'meta_title') && empty($languageModel->meta_title)) {
            $metaTitleSourceField = config('backoffice.contentTypes.'.$model->content_type.'.meta_title_update_field');
            $metaTitle = $metaTitleSourceField ? $languageModel->$metaTitleSourceField : $languageModel->title;
            $languageModel->meta_title = $metaTitle . ' - ' . $config['title_extra'];
            $mustSave = true;
        }

        if (property_exists($languageModel, 'meta_description') &&
            property_exists($languageModel, 'meta_keywords') &&
            (empty($languageModel->meta_description) || empty($languageModel->meta_keywords))) {
            if (!is_null($model->parent_id)) {
                $parentModel = $this->_getParentModelFromContentType($model->parent_id, $model->content_type);
                $parentLanguageModel = $parentModel->languages->findByLocale($languageModel->language_id);
                $description = $parentLanguageModel->meta_description;
                $keywords = $parentLanguageModel->meta_keywords;
            } else {
                $baseUri = $config['no_parent_source'];
                $wsObject = WebsiteObject::where('uri', $baseUri)->first();
                $description = "";
                $keywords = "";
                if ($wsObject) {
                    $sourceLanguageModel = $wsObject->objectable;
                    $description = $sourceLanguageModel->meta_description;
                    $keywords = $sourceLanguageModel->meta_keywords;
                }
                if (empty($description)) {
                    $description = $config['title_extra'];
                }
                if (empty($keywords)) {
                    $keywords = $config['title_extra'];
                }
            }

            if (empty($languageModel->meta_description)) {
                $languageModel->meta_description = $description;
            }
            if (empty($languageModel->meta_keywords)) {
                $languageModel->meta_keywords = $keywords;
            }
            $mustSave = true;
        }

        if ($mustSave) {
            $languageModel->save();
        }
    }

    /**
     * Get the Uri of a object by lang
     *
     * @param  WebsiteObject  $websiteObject
     * @param  ContentType  $contentType
     */
    public function getUriLang(string $slug, string $langCode, ContentType $contentType, WebsiteObject $websiteObject = null)
    {
        $uri = $contentType->getBaseUri();

        $uri = empty($uri) ? '' : $uri[$langCode];

        if ($websiteObject && $websiteObject->parent) {
            $parent = $websiteObject->parent;

            $parentWoLang = $parent->languages->findByLocale($langCode);
            $uri = $uri . $parentWoLang->uri . '/' . $slug;
        } else {
            if ($slug == 'home') {
                $uri = '/';
            } else {
                $uri = $uri . '/' . $slug;
            }
        }

        return $uri;
    }

    /**
     * Updated the Uri on websiteobject and it's languages
     *
     * @param  WebsiteObject  $websiteObject
     * @param  ContentType  $contentType
     * @param  bool  $save
     */
    protected function _updateUri(WebsiteObject $websiteObject, ContentType $contentType, $save = true)
    {
        $uri = $contentType->getBaseUri();
        $languages = LaravelLocalization::getSupportedLocales();

        if ($websiteObject->parent) {
            $parent = $websiteObject->parent;

            foreach ($languages as $langCode => $lang) {
                $parentWoLang = $parent->languages->findByLocale($langCode);
                $woLang = $websiteObject->languages->findByLocale($langCode);
                $woLang->uri = $parentWoLang->uri.'/'.$woLang->slug;

                if ($save) {
                    $woLang->save();
                }
            }
        } else {
            if ($websiteObject->slug == 'home') {
                foreach ($languages as $langCode => $lang) {
                    $woLang = $websiteObject->languages->findByLocale($langCode);
                    $woLang->lang_uri = '/';
                    if ($save) {
                        $woLang->save();
                    }
                }
            } else {
                foreach ($languages as $langCode => $lang) {
                    $woLang = $websiteObject->languages->findByLocale($langCode);

                    if (is_array($uri)) {
                        $uriLang = $uri[$langCode];
                    } else {
                        $uriLang = $uri;
                    }
                    $woLang->uri = $uriLang.'/'.$woLang->slug;

                    if ($save) {
                        $woLang->save();
                    }
                }
            }
        }

        if ($save) {
            $websiteObject->save();
        }

        if ($websiteObject->website_object_id) {
            $children = $websiteObject->children;
            foreach ($children as $child) {
                $this->_updateUri($child, $contentType, $save);
            }
        }
    }

    /**
     * Update the uris of all content types or of a specific one
     *
     * @param string|null $contentType
     * @return void
     */
    public function updateUris(string $contentType = null)
    {
        $contentTypes = ContentTypes::all();
        foreach ($contentTypes as $ct) {
            if (!is_null($contentType) && $ct->getType() != $contentType) {
                continue;
            }
            if ($ct->isPage()) {
                $modelType = $ct->getModelType();
                $models = $modelType::full()->get();
                foreach ($models as $model) {
                    $websiteObjects = $model->websites;
                    foreach ($websiteObjects as $websiteObject) {
                        $this->_updateUri($websiteObject, $ct);
                    }
                }
            }
        }
    }

    /**
     * Generates a slug or returns false in case is not possible
     *
     * @param  string  $originSlug
     * @param  string  $langId
     * @return bool|string
     */
    public function generateSlug($originSlug, $langId, $contentType, $websiteObjectLang = null)
    {
        $originSlug = Str::slug($originSlug);
        $slug = $originSlug;

        $slugCounter = 1;
        $uri = $this->getUriLang($slug, $langId, $contentType, $websiteObjectLang ? $websiteObjectLang->websiteObject : null);

        while (

            WebsiteObjectLanguage::where('uri', $uri)->where('wo_language_id', $langId)->count() > 0 && $slugCounter <= 100) {
            $slug = $originSlug."-".$slugCounter;
            $uri = $this->getUriLang($slug, $langId, $contentType, $websiteObjectLang ? $websiteObjectLang->websiteObject : null);
            $slugCounter++;
        }

        if ($slugCounter == 100) {
            return false;
        } else {
            return $slug;
        }
    }

    /**
     * Deletes a content type entry
     *
     * @param  ContentType  $contentType
     * @param  int  $id
     *
     * @return ContentTypeModel
     *
     * @throws NotFoundHttpException
     * @throws Throwable
     */
    public function deleteContentType(ContentType $contentType, $id)
    {
        $modelType = $contentType->getModelType();

        $model = $modelType::find($id);

        if (is_null($model)) {
            throw new NotFoundHttpException();
        }

        DB::beginTransaction();

        try {
            $model->delete();
            WebsiteObject::where("object_id", $id)
                ->where("object_type", $modelType)
                ->delete();
            $this->_cleanWebsiteObjects();
            $this->_cleanWebsiteObjectSearches();
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            throw $e;
        }

        return $model;
    }

    /**
     * Cleans website objects that are not in the main tables
     */
    protected function _cleanWebsiteObjects()
    {
        $contentTypes = ContentTypes::all();

        foreach ($contentTypes as $contentType) {
            $modelType = $contentType->getModelType();
            $model = new $modelType();
            $table = $model->getTable();

            WebsiteObject::where('content_type', $contentType->getType())
                ->whereNotExists(function ($query) use ($table) {
                    $query->select(DB::raw(1))
                        ->from($table)
                        ->whereRaw("website_objects.object_id = {$table}.id");
                })->delete();
        }
    }

    /**
     * Cleans website object searches that are not in the main tables
     */
    protected function _cleanWebsiteObjectSearches()
    {
        DB::table("website_objects_search")
            ->whereNotExists(function ($query) {
                $query->select(DB::raw(1))
                    ->from("website_objects")
                    ->whereRaw("website_objects_search.website_object_id = website_objects.website_object_id");
            })->delete();
    }

    /**
     * Commit the new order in the website objects
     *
     * @param  ContentType  $contentType
     * @param  array  $orderTree
     *
     * @throws BadRequestHttpException
     * @throws Throwable
     */
    public function reorderContentType(ContentType $contentType, $orderTree)
    {
        DB::beginTransaction();
        try {
            $counter = 0;
            $this->_saveContentTypeOrder($orderTree, $contentType->getModelType(), $counter);
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            throw $e;
        }
    }

    /**
     * Saves the new order in the website objects
     *
     * @param  array  $orderTree
     * @param  string  $objectType
     * @param  int  $i
     * @param  Model|null  $parent
     *
     * @throws BadRequestHttpException
     */
    protected function _saveContentTypeOrder($orderTree, $objectType, &$i, $parent = null)
    {
        foreach ($orderTree as $orderItem) {
            $i++;
            if (!is_numeric($orderItem->id)) {
                throw new BadRequestHttpException();
            }
            $websiteObject = WebsiteObject::find($orderItem->id);
            if (empty($websiteObject) || $websiteObject->object_type !== $objectType) {
                throw new BadRequestHttpException();
            }
            $websiteObject->position = $i;
            if ($parent) {
                $websiteObject->parent_id = $parent->id;
                if ($websiteObject->object_type == 'Entry') {
                    $websiteObject->uri = $websiteObject->parent->uri.'/'.$websiteObject->slug;
                }
            } else {
                if ($websiteObject->object_type == 'Entry') {
                    $websiteObject->uri = '/'.($websiteObject->slug == 'home' ? '' : $websiteObject->slug);
                }
                $websiteObject->parent_id = null;
            }
            $websiteObject->save();

            if (isset($orderItem->children)) {
                $this->_saveContentTypeOrder($orderItem->children, $objectType, $i, $orderItem);
            }
        }
    }

    /**
     * Creates a content type template data
     *
     * @param  ContentType  $contentType
     * @param  int  $parentId
     * @param  BackendUser  $author
     *
     * @return ContentTypeModel
     *
     * @throws NotFoundHttpException
     * @throws Throwable
     */
    public function createContentTypeTemplate(ContentType $contentType, $parentId, BackendUser $author)
    {
        $modelType = $contentType->getModelType();
        $model = new $modelType;

        $parentData = $contentType->getParent();
        $parentContentType = ContentTypes::find($parentData["contentType"]);
        $parentModelType = $parentContentType->getModelType();
        $parentModel = $parentModelType::find($parentId);
        $fkName = $parentModel->getForeignKey();

        if (empty($parentModel)) {
            throw new NotFoundHttpException();
        }

        DB::beginTransaction();

        try {
            $model->$fkName = $parentId;
            $model->backend_user_id = $author->id;
            $model->save();

            $languageModels = $model->languages;
            $languageModelType = $model->languages()->getRelated();

            foreach ($parentModel->languages as $parentLangModel) {
                $languageModel = new $languageModelType;
                $languageModel->language_id = $parentLangModel->language_id;
                $languageModel->title = $parentLangModel->title;
                $languageModels->add($languageModel);
            }

            $model->languages()->saveMany($languageModels->all());

            $websiteObjects = $model->websites;
            $parentWebsiteObject = $parentModel->websites->first();

            $websiteObject = new WebsiteObject();
            $websiteObject->content_type = $contentType->getType();

            $slug = $parentWebsiteObject->slug."-conf-".$parentWebsiteObject->id;
            $websiteObject->slug = $slug;

            $websiteObjects->add($websiteObject);

            $model->websites()->saveMany($websiteObjects->all());

            foreach ($parentModel->languages as $langModel) {
                $woLang = new WebsiteObjectLanguage();
                $woLang->website_object_id = $websiteObject->id;
                $woLang->wo_language_id = $langModel->language_id;
                $woLang->status = $parentWebsiteObject->languages->findByLocale($langModel->language_id)->status;
                $woLang->lang_slug = $slug;
                $woLang->lang_uri = null;

                $woLang->save();
            }

            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            throw $e;
        }

        return $model;
    }

    /**
     * Returns a dummy MenuItem as stdClass
     *
     * @param  array  $data
     * @return stdClass
     */
    public function createTempMenuItem($data)
    {
        $languages = LaravelLocalization::getSupportedLanguagesKeys();
        $defaultLanguage = config('app.locale');
        $tempMenuItem = new stdClass();
        if ($data['type'] === 'page') {

            $page = Page::find($data['page_id']);

            //$tempMenuItem->url = $page->uri;
            $tempMenuItem->target = null;
            $tempMenuItem->active = $page->status == 'published';
            $tempMenuItem->id = 'new_'.rand(0, 3000000);
            $tempMenuItem->Page = $page;
            $tempMenuItem->languages = array();
            foreach ($languages as $language) {
                $itemLang = new stdClass();
                $itemLang->language_id = $language;
                $pageLanguage = $page->languages->findByLocale($language);
                $pageWO = $page->getActiveWebsiteEntry();
                if ($pageLanguage) {
                    $itemLang->title = $pageLanguage->title;
                } else {
                    $itemLang->title = '';
                }
                if ($pageWO) {
                    $pageWOLang = $pageWO->languages->findBylocale($language);
                    $itemLang->url = $pageWOLang->lang_uri;
                }
                $tempMenuItem->languages[] = $itemLang;

                if ($language == $defaultLanguage) {
                    $tempMenuItem->title = $pageLanguage->title;
                }
            }
        } else {
            //$tempMenuItem->url = $data['url'];
            $tempMenuItem->target = $data['new_window'] ? '_blank' : null;
            $tempMenuItem->active = true;
            $tempMenuItem->id = 'new_'.rand(0, 3000000);
            $tempMenuItem->Page = null;
            $tempMenuItem->languages = [];
            foreach ($data['title'] as $lang => $value) {
                $itemLang = new stdClass();
                $itemLang->language_id = $lang;
                $itemLang->title = $value;
                $itemLang->url = $data['url'][$lang];
                $tempMenuItem->languages[] = $itemLang;

                if ($lang == $defaultLanguage) {
                    $tempMenuItem->title = $value;
                }
            }
        }

        return $tempMenuItem;
    }

    /**
     * Build menu structure for FB insertion
     *
     * @param  array  $menuStructure
     * @param  int  $i
     * @param  array  $data
     * @param  null|int  $parentId
     */
    public function buildStructure(&$menuStructure, &$i, &$data, $parentId = null)
    {

        foreach ($menuStructure as $menuItem) {
            $i++;
            $menuItem->title = $data['titles'][$menuItem->id]['en'];
            $menuItem->position = $i;
            $menuItem->parent_id = $parentId;

            $pageWO = null;
            if ($data['types'][$menuItem->id] == 'page') {
                $page = Page::find($data['entry_id'][$menuItem->id]);

                if (is_null($page)) {
                    //Todo: some error action?
                }
                $menuItem->entry = $page;
                $pageWO = $menuItem->entry->getActiveWebsiteEntry();
                //$menuItem->url = $page->uri;
            } else {
                //$menuItem->url = $data['urls'][$menuItem->id];
                $menuItem->entry = null;
            }
            $menuItem->target = isset($data['new_windows'][$menuItem->id]) ? '_blank' : null;
            $menuItem->active = isset($data['states'][$menuItem->id]) ? true : false;
            $languages = LaravelLocalization::getSupportedLanguagesKeys();
            $menuItem->languages = array();
            foreach ($languages as $language) {
                $itemLang = new stdClass();
                $itemLang->language_id = $language;
                $itemLang->title = $data['titles'][$menuItem->id][$language];

                $itemLang->url = $data['urls'][$menuItem->id][$language];
                if ($pageWO) {
                    $pageWOLang = $pageWO->languages->findByLocale($language);
                    $itemLang->url = $pageWOLang->lang_uri;
                } else {
                    $itemLang->url = $data['urls'][$menuItem->id][$language];
                }

                $menuItem->languages[] = $itemLang;

                if ($language == config('app.locale')) {
                    $menuItem->title = $data['titles'][$menuItem->id][$language];
                }
            }

            //$i++;
            if (isset($menuItem->children)) {
                $this->buildStructure($menuItem->children, $i, $data, $menuItem->id);
            }
        }
    }


    /**
     * Save the menu structure to the DB
     *
     * @param  Menu  $menu
     * @param  array  $menuStructure
     * @param  array  $toDelete
     * @return array
     */
    public function saveMenu($menu, $menuStructure, $toDelete)
    {
        DB::transaction(function () use ($menu, $menuStructure, $toDelete) {
            $existingItems = $menu->menuItems()->with('languages')->get()->keyBy('id');
            $existingItemsIds = $existingItems ? $existingItems->pluck('id')->toArray() : [];
            $savedItemsIds = [];
            $this->_saveMenuStructure($menu->id, $menuStructure, $existingItems, $savedItemsIds);

            // Delete items that were not in the new structure
            $deletedItemsIds = array_diff($existingItemsIds, $savedItemsIds);
            MenuItem::whereIn('id', $deletedItemsIds)->delete();

        /*
            if (!empty($toDelete)) {
                foreach ($toDelete as $id) {
                    if (is_numeric($id)) {
                        $menu->menuItems()->find($id)->delete();
                    }
                }
            }
                */
        });

        return $menuStructure;
    }

    /**
     * Saves a level of the menu structure
     *
     * @param  int  $menuId
     * @param  array  $menuStructure
     * @param  null|int  $parentId
     * @param  Collection  $existingItems
     */
    private function _saveMenuStructure($menuId, $menuStructure, $existingItems, &$savedItemsIds, $parentId = null, &$position = 1)
    {
        foreach ($menuStructure as $item) {
            $isNewItem = strpos($item['id'], 'new_') !== false;

            if ($isNewItem) {
                $menuItem = new MenuItem();
            } else {
                $menuItem = MenuItem::find($item['id']);
                if (!$menuItem) {
                    $menuItem = new MenuItem();
                }
                MenuItemLanguage::where('menu_item_id', $item['id'])->delete();
            }

            $menuItem->parent_id = $parentId;
            $menuItem->menu_id = $menuId;
            $menuItem->position = $position;

            $position++;
            $menuItem->active = $item['active'] ?? true;
            $menuItem->target = $item['openInNewTab'] ? '_blank' : null;
            $menuItem->use_object_title = $item['useObjectTitle'] ?? true;

            $refWebsiteObject = null;
            $refContent = null;
            if (isset($item['type']) && $item['type'] === 'object') {
                $menuItem->website_object_id = $item['websiteObjectId'];
                $refWebsiteObject = WebsiteObject::find($item['websiteObjectId']);
                $refContent = $refWebsiteObject->objectable;
            } else {
                $menuItem->website_object_id = null;
            }

            $menuItem->save();
            $savedItemsIds[] = $menuItem->id;

            $languages = LaravelLocalization::getSupportedLanguagesKeys();
            foreach ($languages as $lang) {
                $menuItemLang = new MenuItemLanguage([
                    'menu_item_id' => $menuItem->id,
                    'language_id' => $lang
                ]);

                if ($menuItem->use_object_title && $refContent) {
                    $menuItemLang->title = $refContent->languages()->where('language_id', $lang)->first()->title;
                } else {
                    $menuItemLang->title = $item['translations'][$lang]['title'] ?? '';
                }

                if ($refWebsiteObject) {
                    $menuItemLang->url = $refWebsiteObject->uri;
                } else {
                    $menuItemLang->url = $item['translations'][$lang]['url'] ?? '';
                }

                $menuItem->languages()->save($menuItemLang);
            }

            if (isset($item['menuItems']) && !empty($item['menuItems'])) {
                $this->_saveMenuStructure($menuId, $item['menuItems'], $existingItems, $savedItemsIds, $menuItem->id, $position);
            }
        }
    }
}
