<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Libs\Backoffice\Generic\ContentType;
use App\Libs\Backoffice\Generic\Fields\MultiplePickerField;
use App\Libs\Contracts\Backoffice\SearchableField;
use App\Libs\Facades\ContentTypes;
use Illuminate\Support\Collection;
use WebsiteObjectSearch;
use ContentTypeModel;
use Website;

class ProcessSearch
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $contentTypeName;
    protected $model;
    protected $websiteId;
    protected $updateParents;
    protected $disabledLanguages;
    protected $modelWo;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(ContentType $contentType, ContentTypeModel $model, bool $updateParents, int $websiteId, Array $disabledLanguages = [])
    {
        $this->contentType = $contentType;
        $this->model = $model;
        $this->updateParents = $updateParents;
        $this->websiteId = $websiteId;
        $this->disabledLanguages = $disabledLanguages;
        $this->modelWo = $model->websites->findByWebsite($websiteId);
    }

    public function handle()
    {
        if ($this->model->no_index || !$this->contentType->isWebsiteSearchable($this->websiteId)) {
            $this->modelWo->searches()->detach();
            return;
        }
        $filter = $this->contentType->getSearchFilter($this->websiteId);
        if ($filter) {
            foreach ($filter as $filterField => $filterValue) {
                if ($this->model->$filterField != $filterValue) {
                    $this->modelWo->searches()->detach();
                    return;
                }
            }
        }

        $parentRelationships = $this->contentType->getSearchParentRelationships($this->websiteId);

        if ($parentRelationships && $this->updateParents) {
            $this->processParents($this->model, $this->contentType, $parentRelationships);
            return;
        }

        $this->generateSearch();
    }

    function getSearchContent($model, $type, $langId)
    {
        $value = '';
        $modelContentType = ContentTypes::findByModel(get_class($model));
        $fields = $modelContentType->getSearchFields($this->websiteId)[$type];
        $childRelations = $modelContentType->getSearchRelations($this->websiteId);

        $searchFields = $modelContentType->getFields()->getFieldsByNames($fields);
        foreach ($searchFields as $field) {
            if (!($field instanceof SearchableField)) {
                continue;
            }
            $fieldSearch = $field->getSearchStructure($model);

            if (empty($fieldSearch)) {
                continue;
            }

            $value .= '<||>' . strip_tags($fieldSearch[$langId]);
        }

        if (!$childRelations) {
            return $value;
        }

        foreach ($childRelations as $relation) {
            $relationfield = $modelContentType->getFields()->find($relation);

            if ($relationfield instanceof MultiplePickerField && $relationfield->isMultiLanguage()) {

                $relationValue = $model->$relation()->wherePivot('language_id', $langId)->get();
            } else {
                $relationValue = $model->$relation;
            }
            if (!$relationValue) {
                continue;
            }
            if ($relationValue instanceof Collection) {
                foreach ($relationValue as $relationItem) {
                    $value .= $this->getSearchContent($relationItem, $type, $langId);
                }
            } else {
                $value .= $this->getSearchContent($relationValue, $type, $langId);
            }
        }

        return $value;
    }

    function generateSearch()
    {
        $website = Website::find($this->websiteId);
        $activeLanguages = $website->languages()->where('is_active', true)->get();
        $searchDisplay = $this->contentType->getSearchDisplay($this->websiteId);
        $this->modelWo->searches()->detach();

        if ($searchDisplay == null || $this->modelWo->status !== 'published') {
            return;
        }

        foreach ($activeLanguages as $language) {
            if (in_array($language->id, $this->disabledLanguages)) {
                continue;
            }
            $modelLanguage = $this->model->languages->findByLocale($language->id);
            $languageWo = $this->modelWo->languages->findByLocale($language->id);

            if ($languageWo->lang_status !== 'published') {
                continue;
            }

            if (!empty($searchDisplay['title'])) {
                $titleField = $searchDisplay['title'];
                $title = $modelLanguage->$titleField;
            } else {
                $title = $modelLanguage->title;
            }

            $content = '';
            if (!empty($searchDisplay['content'])) {
                $splitFields = explode('|', $searchDisplay['content']);
                $content = '';
                foreach ($splitFields as $contentField) {
                    $content = strip_tags($modelLanguage->$contentField);
                    if (!empty($content)) {
                        break;
                    }
                }
                $content = cut_string($content, 500, '...');
            }

            $imageId = null;
            if (!empty($searchDisplay['image_id'])) {
                $imageField = $searchDisplay['image_id'];
                $imageId = $this->model->$imageField ? $this->model->$imageField->id : null;
            }

            $primary = $this->getSearchContent($this->model, 'primary', $language->id);
            $secondary = $this->getSearchContent($this->model, 'secondary', $language->id);

            $websiteObjectSearch = new WebsiteObjectSearch;
            $websiteObjectSearch->language_id = $language->id;
            $websiteObjectSearch->website_object_id = $this->modelWo->website_object_id;
            $websiteObjectSearch->title = $title;
            $websiteObjectSearch->primary_search = $primary;
            $websiteObjectSearch->secondary_search = $secondary;
            $websiteObjectSearch->website_id = $this->websiteId;
            $websiteObjectSearch->content_type = $this->contentType->getType();
            $websiteObjectSearch->uri = $languageWo->lang_uri;
            $websiteObjectSearch->group_label = trans("backend.{$this->contentType->getType()}_plural", [], $modelLanguage->language_id);
            $websiteObjectSearch->content = $content;
            $websiteObjectSearch->image_id = $imageId;
            $websiteObjectSearch->save();
        }
    }

    function processParents($model, $contentType, $parentRelationships)
    {
        if (!$parentRelationships) {
            ProcessSearch::dispatch($contentType, $model, true, $this->websiteId);
            return;
        }

        foreach ($parentRelationships as $parentRelationship) {
            $repetitionControl = [];
            $relationValues = $model->$parentRelationship;

            if (!is_a($relationValues, 'Illuminate\Database\Eloquent\Collection')) {
                $relationValues = [$relationValues];
            }

            foreach ($relationValues as $relationValue) {
                $modelClass = get_class($relationValue);
                if (!empty($repetitionControl[$modelClass]) && $relationValue->id === $repetitionControl[$modelClass]) {
                    continue;
                }

                $repetitionControl[$modelClass] = $relationValue->id;
                $relationContentType = ContentTypes::findByModel($modelClass);
                $relationParentRelationships = $relationContentType->getSearchParentRelationships();

                $this->processParents($relationValue, $relationContentType, $relationParentRelationships);
            }
        }
    }
}
