<?php

namespace kernel;

use Illuminate\Database\Eloquent\Model;
use kernel\helpers\Debug;
use kernel\models\Option;
use kernel\modules\option\service\OptionService;
use kernel\services\ModuleService;

class EntityRelation
{
    protected ModuleService $moduleService;

    public function __construct()
    {
        $this->moduleService = new ModuleService();
    }


    public static function getEntityList(): array
    {
        $list = [];
        $moduleService = new ModuleService();
        $activeModules = $moduleService->getActiveModules();
        foreach ($activeModules as $module) {
            if (isset($module['type']) and $module['type'] === "entity") {
                $list[$module['slug']] = $module['name'];
            }
        }

        return $list;
    }

    public function getAdditionalPropertyList(): array
    {
        $list = [];
        $activeModules = $this->moduleService->getActiveModules();
        foreach ($activeModules as $module) {
            if (isset($module['type']) and $module['type'] === "additional_property") {
                $list[] = $module['slug'];
            }
        }

        return $list;
    }

    public function getEntitiesRelations(): array|bool
    {
        $entity_relations = OptionService::getItem("entity_relations");
        if ($entity_relations) {
            return json_decode($entity_relations, true);
        }

        return false;
    }

    public static function removePropertyFromEntityRelations(string $entity, string $property): bool
    {
        $entity_relations_info = Option::where("key", "entity_relations")->first();
        if ($entity_relations_info) {
            $entity_relations = json_decode($entity_relations_info->value, true);
            if ($entity_relations[$entity]) {
                if ($entity_relations[$entity][$property]) {
                    unset($entity_relations[$entity][$property]);
                    $entity_relations_info->value = json_encode($entity_relations, JSON_UNESCAPED_UNICODE);
                    $entity_relations_info->save();
                    return true;
                }
            }
        }

        return false;
    }

    public static function removePropertyRelation(string $property): bool
    {
        $entity_relations_info = Option::where("key", "entity_relations")->first();
        if ($entity_relations_info) {
            $entity_relations = json_decode($entity_relations_info->value, true);
            foreach ($entity_relations as $entity => $entity_relation){
                if (in_array($property, $entity_relation)) {
                    $index = array_search($property, $entity_relation);
                    unset($entity_relations[$entity][$index]);
                }
            }
            $entity_relations_info->value = json_encode($entity_relations, JSON_UNESCAPED_UNICODE);
            $entity_relations_info->save();

            return true;
        }

        return false;
    }

    public static function removeEntityRelation(string $entity): bool
    {
        $entity_relations_info = Option::where("key", "entity_relations")->first();
        if ($entity_relations_info) {
            $entity_relations = json_decode($entity_relations_info->value, true);
            if (isset($entity_relations[$entity])) {
                unset($entity_relations[$entity]);
                $entity_relations_info->value = json_encode($entity_relations, JSON_UNESCAPED_UNICODE);
                $entity_relations_info->save();
                return true;
            }
        }

        return false;
    }

    public function getEntityRelationsBySlug(string $slug)
    {
        $entityRelations = $this->getEntitiesRelations();
        if ($entityRelations) {
            if (isset($entityRelations[$slug])){
                return $entityRelations[$slug];
            }
        }

        return false;
    }

    public function addEntityRelation(string $entity, string $property): bool
    {
        $entity_relations_info = Option::where("key", "entity_relations")->first();
        if ($entity_relations_info) {
            $entity_relations = json_decode($entity_relations_info->value, true);
            if (isset($entity_relations[$entity])) {
                $entity_relations[$entity][] = $property;
            } else {
                $entity_relations[$entity] = $property;
            }
            $entity_relations_info->value = json_encode($entity_relations, JSON_UNESCAPED_UNICODE);
            $entity_relations_info->save();

            return true;
        }

        return false;
    }

    public function getAdditionalPropertyClassBySlug(string $slug)
    {
        $module = $this->moduleService->getModuleInfoBySlug($slug);
        if (isset($module['module_class'])) {
            return new $module['module_class']();
        }

        return false;
    }

    public function renderFormInputsBySlug(string $entity, string $slug, Model $model): void
    {
        $moduleClass = $this->getAdditionalPropertyClassBySlug($slug);
        if ($moduleClass and method_exists($moduleClass, "formInputs")) {
            $moduleClass->formInputs($entity, $model);
        }
    }

    public function renderEntityAdditionalPropertyFormBySlug(string $entity, Model $model = null): void
    {
        $relations = $this->getEntityRelationsBySlug($entity);
        if ($relations){
            foreach ($relations as $relation){
                $this->renderFormInputsBySlug($entity, $relation, $model);
            }
        }
    }

    public function saveEntityRelationBySlug(string $slug, string $entity, Model $model, Request $request): void
    {
        $moduleClass = $this->getAdditionalPropertyClassBySlug($slug);
        if ($moduleClass and method_exists($moduleClass, "saveInputs")) {
            $moduleClass->saveInputs($entity, $model, $request);
        }
    }

    public function saveEntityRelation(string $entity, Model $model, Request $request): void
    {
        $relations = $this->getEntityRelationsBySlug($entity);
        if ($relations){
            foreach ($relations as $relation){
                $this->saveEntityRelationBySlug($relation, $entity, $model, $request);
            }
        }
    }

    public function getEntityAdditionalProperty(string $entity, Model $model): array
    {
        $relations = $this->getEntityRelationsBySlug($entity);
        if ($relations){
            foreach ($relations as $relation){
                $moduleClass = $this->getAdditionalPropertyClassBySlug($relation);
                if ($moduleClass and method_exists($moduleClass, "getItems")) {
                    return $moduleClass->getItems($entity, $model);
                }
            }
        }

        return [];
    }
}