<?php

namespace App\Libs\Backoffice\Fields;

use App\Helpers\Backoffice\LanguageHelper;
use App\Libs\Backoffice\Contracts\ListableField;
use App\Libs\Backoffice\Contracts\SearchableField;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\Rule;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class TextBoxField extends BaseField implements ListableField, SearchableField
{
    private $maxLength = null;
    private $woMultilang = false;
    private $unique = false;

    public function __construct($config)
    {
        parent::__construct($config);

        if (!empty($config["maxLength"])) {
            $this->maxLength = $config["maxLength"];
        }

        if (!empty($config["woMultilang"])) {
            $this->woMultilang = $config["woMultilang"];
        }

        if (!empty($config["unique"])) {
            $this->unique = $config["unique"];
        }
    }

    public function getMaxLength()
    {
        return $this->maxLength;
    }

    public function setMaxLength($maxLength = null)
    {
        $this->maxLength = $maxLength;
    }

    public function buildSelect(Builder $query)
    {
        if ($this->isMultiLanguage()) {
            if ($this->woMultilang) {
                //Not very nice hardcode, but...
                $tablePrefix = 'website_objects_lang';
            } else {
                $tablePrefix = $query->getModel()->languages()->getRelated()->getTable();
            }
        } else {
            $tablePrefix = $query->getModel()->getTable();
        }

        $query->addSelect("{$tablePrefix}.{$this->name}");
        return $query;
    }

    public function buildWhere(Builder $query, $searchPhrase)
    {
        if (empty($searchPhrase) || !$this->isSearchable()) {
            return $query;
        }

        if ($this->isMultiLanguage()) {
            $tablePrefix = $query->getModel()->languages()->getRelated()->getTable();
        } else {
            $tablePrefix = $query->getModel()->getTable();
        }

        $query->orWhere("{$tablePrefix}.{$this->name}", 'like', "%{$searchPhrase}%");
        return $query;
    }

    public function buildOrder(Builder $query, $sortOrder = "asc")
    {
        if ($this->isMultiLanguage()) {
            $tablePrefix = $query->getModel()->languages()->getRelated()->getTable();
        } else {
            $tablePrefix = $query->getModel()->getTable();
        }

        $query->orderBy("{$tablePrefix}.{$this->getName()}", $sortOrder);
        return $query;
    }

    public function toArray()
    {
        $array = parent::toArray();
        $array["maxLength"] = $this->maxLength;
        return $array;
    }

    public function getListData()
    {
        return [
            'name' => $this->getName(),
            'type' => ucfirst($this->getType()),
            'label' => ucfirst($this->getLabel())
        ];
    }

    public function getData(Model | null $model, $enabled = true, $hidden = false)
    {
        $fieldName = $this->getName();

        if ($this->isMultiLanguage()) {
            $locales = LaravelLocalization::getSupportedLocales();

            $value = [];
            foreach ($locales as $locale => $localeData) {
                if ($model && $model->exists) {
                    $languageModel = $model->languages->findByLocale($locale);

                    if (!empty($languageModel)) {
                        $value[$locale] = $languageModel->$fieldName;
                    } else {
                        $value[$locale] = '';
                    }
                } else {
                    $value[$locale] = '';
                }
            }
        } else {
            $value = $model && $model->exists ? $model->$fieldName : '';
        }

        $validation = $this->getValidation();

        return [
            'name' => $this->getName(),
            'type' => ucfirst($this->getType()),
            'isMultilanguage' => $this->isMultiLanguage(),
            'label' => $this->getLabel(),
            'info' => $this->getInfo(),
            'value' => $value,
            'maxLength' => $this->getMaxLength(),
            'required' => $validation &&  str_contains($validation, 'required'),
            'hide' => $hidden,
            'enabled' => $enabled,
            'conditions' => $this->conditions,
        ];
    }

    public function getSearchStructure(Model $model, $view = false)
    {
        $searchData = array();
        $fieldName = $this->getName();
        if ($this->isMultiLanguage()) {
            foreach ($model->languages as $languageModel) {
                if (!empty($languageModel->$fieldName)) {
                    $value = $languageModel->$fieldName;
                    $searchData[$languageModel->language_id] = $languageModel->$fieldName;
                }
            }
        } else {
            if (!empty($model->$fieldName)) {
                $languages = LaravelLocalization::getSupportedLocales();
                foreach ($languages as $locale => $localeData) {
                    $searchData[$locale] = $model->$fieldName;
                }
            }
        }
        return $searchData;
    }

    public function getValidationDataRules($model = null, $prefix = '')
    {
        $fieldName = $prefix . $this->getName();
        $validation = array(
            "rules" => array(),
            "labels" => array()
        );

        $rules = $this->getValidation();

        if (!empty($rules)) {
            if ($this->isMultiLanguage()) {
                $locales = LaravelLocalization::getSupportedLanguagesKeys();

                $validation["rules"] = LanguageHelper::generateLangRules(
                    array($fieldName => $rules),
                    $locales);

                $validation["labels"] = LanguageHelper::generateLangLabels(
                    $fieldName, $this->getLabel(), $locales);
            } else {
                if ($this->unique && $model) {
                    $rules = explode('|', $rules);
                    $rules[] = Rule::unique($model->getTable(), $this->name)->ignore($model);
                } else if ($this->unique) {
                    $rules = $rules ? $rules . '|unique' : 'unique';
                }
                $validation["rules"][$fieldName] = $rules;
                $validation["labels"][$fieldName] = $this->getLabel();
            }
        }

        return $validation;
    }
}
