<?php

namespace Eminiarts\Aura\Traits;

use Eminiarts\Aura\Pipeline\ApplyGroupedInputs;
use Illuminate\Pipeline\Pipeline;
use Illuminate\Support\Facades\Cache;

trait InputFieldsHelpers
{
    protected $fieldsCollectionCache = null;

    public function clearModelCache()
    {
        // set accessibleFieldKeysCache to null
        $this->accessibleFieldKeysCache = null;

        // Generate the cache keys based on the model class
        $fieldsCacheKey = $this->getFieldCacheKey();
        $mappedFieldsCacheKey = $this->getFieldCacheKey().'-mappedFields';

        // Check if the cache keys are bound and remove them
        if (app()->bound($fieldsCacheKey)) {
            app()->offsetUnset($fieldsCacheKey);
        }

        if (app()->bound($mappedFieldsCacheKey)) {
            app()->offsetUnset($mappedFieldsCacheKey);
        }
    }

    public function fieldBySlug($slug)
    {
        // return $this->fieldsCollection()->firstWhere('slug', $slug);

        // $backtrace = debug_backtrace();

        // $latestTrace = $backtrace[0];

        // ray($latestTrace['file'] . ':' . $latestTrace['line'] . ' - ' . $latestTrace['function']);


        $cacheKey = get_class($this) . ".fields." . $slug;

        if (!app()->bound($cacheKey)) {
            //ray()->count();

            app()->singleton($cacheKey, function () use ($slug) {
                return $this->fieldsCollection()->firstWhere('slug', $slug);
            });
        }

        return app($cacheKey);
    }

    public function fieldClassBySlug($slug)
    {

        if (optional($this->fieldBySlug($slug))['type']) {
            return app($this->fieldBySlug($slug)['type']);
        } else {
            return false;
        }

        $cacheKey = get_class($this) . ".fieldClass." . $slug;

        if (!app()->bound($cacheKey)) {
            if (optional($this->fieldBySlug($slug))['type']) {
                app()->singleton($cacheKey, function () use ($slug) {
                    return app($this->fieldBySlug($slug)['type']);
                });
            } else {
                return false;
            }
        }

        return app($cacheKey);
    }

    public function fieldsCollection()
    {

        if ($this->fieldsCollectionCache === null) {
            // ray()->count();

            $this->fieldsCollectionCache = collect($this->getFields());
        }

        return $this->fieldsCollectionCache;


        return collect($this->getFields());

        $cacheKey = get_class($this) . ".fields";

        //ray()->count();

        if (!app()->bound($cacheKey)) {
            app()->singleton($cacheKey, function () {
                return collect($this->getFields());
            });
        }

        return app($cacheKey);
    }

    public function findBySlug($array, $slug)
    {
        foreach ($array as $item) {
            if ($item['slug'] === $slug) {
                return $item;
            }
            if (isset($item['fields'])) {
                $result = $this->findBySlug($item['fields'], $slug);
                if ($result) {
                    return $result;
                }
            }
        }
    }

    public function getFieldCacheKey()
    {
        return 'fieldsCollectionCache.'.get_class($this);
    }

    public function getFieldSlugs()
    {
        return $this->fieldsCollection()->pluck('slug');
    }

    public function getFieldValue($key)
    {
        return $this->fieldClassBySlug($key)->get($this->fieldBySlug($key), $this->meta->$key);
    }

    public function groupedFieldBySlug($slug)
    {
        $fields = $this->getGroupedFields();

        return $this->findBySlug($fields, $slug);
    }

    public function inputFields()
    {
        // ray()->count();
        // ray()->trace();
        // dd('hier');
        // $newFields = $this->sendThroughPipeline($this->newFields, [ApplyGroupedInputs::class]);
        return $this->getFieldsBeforeTree()->filter(fn ($item) => in_array($item['field_type'], ['input', 'repeater', 'group']));
    }

    public function inputFieldsSlugs()
    {
        return $this->inputFields()->pluck('slug');


        return cache()->rememberForever(get_class($this) . '.inputFieldsSlugs', function () {
            return $this->inputFields()->pluck('slug');
        });
    }

    public function mappedFieldBySlug($slug)
    {
        // dd($this->mappedFields(), $this->newFields);
        return $this->mappedFields()->firstWhere('slug', $slug);
    }

    public function mappedFields()
    {

        // Generate the cache key based on the model class and method name
        $cacheKey = $this->getFieldCacheKey().'-mappedFields';

        // Bind the mapped fields collection as a singleton if it's not already bound
        app()->singletonIf($cacheKey, function () {
            return $this->fieldsCollection()->map(function ($item) {
                $item['field'] = app($item['type'])->field($item);
                $item['field_type'] = app($item['type'])->type;

                return $item;
            });
        });

        // Return the cached result
        return app($cacheKey);

    }

    public function sendThroughPipeline($fields, $pipes)
    {
        return app(Pipeline::class)
            ->send($fields)
            ->through($pipes)
            ->thenReturn();
    }
}
