<?php

namespace App\Http\Resources;

use App\Traits\RetrievesFieldData;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Mtc\ContentManager\Contracts\ContentElementField;
use Mtc\ContentManager\Contracts\FormField;
use Mtc\ContentManager\Contracts\MediaUse;
use Mtc\ContentManager\Http\Resources\MediaEntryResource;
use Mtc\ContentManager\Contracts\ContentElement;
use Mtc\ContentManager\Contracts\GlobalContent;

class ContentElementBlockResource extends JsonResource
{
    use RetrievesFieldData;

    private int $contentNestedLimit = 150;

    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    #[\Override]
    public function toArray($request)
    {
        if ($this->resource instanceof LengthAwarePaginator) {
            $this->resource
                ->through(fn($content) => $this->map($content));
        } else {
            $this->resource = $this->resource
                ->map(fn($content) => $this->map($content));
        }
        return parent::toArray($request);
    }

    /**
     * Map Menu entry
     *
     * @param GlobalContent|ContentElement $content
     * @return array
     */
    private function map($content)
    {
        if ($content instanceof FormField) {
            return $this->formField($content);
        }
        return $content instanceof GlobalContent
            ? $this->globalContent($content)
            : $this->contentElement($content);
    }

    private function globalContent(GlobalContent $content): array
    {
        $data = array_merge([
            'id' => null,
            'name' => $content->name,
            'slug' => $content->slug,
            'element_id' => null,
            'global_content_id' => $content->id,
            'content' => null,
            'fieldId' => 'group',
            'previewImage' => $content->preview_image
                ?  Storage::disk(Config::get('filesystems.default_media'))->url($content->preview_image)
                : null,
            'icon' => $content->element->icon ?? 'layer-group',
            'nestable' => $content->data['nestable'] ?? false,
            'componentName' => false,
            'component' => false ,
            'nestedLimit' => $content->data['nested_limit'] ?? false,
            'editable' => false,
            'globalContent' => true,
            'repeatable' => $content->data['repeatable'] ?? false,
            'optionsMenuVisible' => false,
            'type' =>  'element',
            'isGroup' => false,
            'error' => null,
            'children' => [],

        ], $content->data ?? []);

        $data['meta'] = $this->getMeta($content, $content['meta'] ?? []);
        return $data;
    }

    private function contentElement(ContentElement $content, $currentLevel = 0): array
    {
        if ($currentLevel >= $this->contentNestedLimit) {
            return [];
        }

        $data = array_merge([
            'id' => null,
            'name' => $content->title,
            'slug' => $content->slug,
            'element_id' => $content->id,
            'global_content_id' => null,
            'content' => $this->getContentValue($content),
            'fieldId' => 'group',
            'icon' => $content->icon ?? 'layer-group',
            'nestable' => $content->data['nestable'] ?? false,
            'componentName' => false,
            'previewImage' => $content->preview_image
                ?  Storage::disk(Config::get('filesystems.default_media'))->url($content->preview_image)
                : null,
            'component' => !empty($content->data['componentName'])
                ? 'EditableContent' . $content->data['componentName']
                : false ,
            'nestedLimit' => $content->data['nested_limit'] ?? false,
            'editable' => true,
            'globalContent' => false,
            'repeatable' => $content->data['repeatable'] ?? false,
            'optionsMenuVisible' => false,
            'type' => 'element',
            'isGroup' => ($content->data['fieldId'] ?? 'group') === 'group',
            'error' => null,
            'children' => $content->fields
                ? $content->fields->map(fn ($field) => $this->field($field, $currentLevel + 1))
                : [],

        ], $content->data ?? []);

        $data['meta'] = $this->getMeta($content, $content['meta'] ?? []);
        return $data;
    }

    private function field(ContentElementField $content, $currentLevel = 0): array
    {
        if ($currentLevel >= $this->contentNestedLimit) {
            return [];
        }

        $data = array_merge([
            'id' => null,
            'name' => $content->name,
            'slug' => $content->slug,
            'element_id' => $content->child_element_id,
            'global_content_id' => null,
            'content' => $this->getContentValue($content),
            'fieldId' => $content->field_type,
            'icon' => $this->getFieldIcon($content),
            'nestable' => $content->data['nestable'] ?? false,
            'component' => 'EditableContent' . $this->getField($content->field_type)?->getComponent(),
            'componentName' => $this->getField($content->field_type)?->getComponent(),
            'nestedLimit' => $content->data['nested_limit'] ?? false,
            'editable' => true,
            'globalContent' => false,
            'repeatable' => $content->data['repeatable'] ?? false,
            'optionsMenuVisible' => false,
            'type' => $content->field_type,
            'isGroup' => ($content->data['fieldId'] ?? $content->field_type) === 'group',
            'error' => null,
            'children' => $content->childElement
                ? $content->childElement->fields->map(fn ($field) => $this->field($field, $currentLevel + 1))
                : [],

        ], $content->data ?? []);

        $data['meta'] = $this->getMeta($content, $content['meta'] ?? []);
        return $data;
    }

    private function getContentValue($content)
    {
        if (($content->data['fieldId'] ?? '') === 'image') {
            return $content->mediaUses?->pluck('media_id') ?? [];
        }
        return $content->content;
    }

    private function getMeta($content, array $data)
    {
        if (($content->data['fieldId'] ?? '') === 'image') {
            $data['selected'] = $content->mediaUses?->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse));
        }
        return $data;
    }

    private function formField(FormField $content): array
    {
        return [
            'id' => null,
            'name' => $content::NAME,
            'slug' => null,
            'element_id' => null,
            'global_content_id' => null,
            'content' => [],
            'fieldId' => $content::TYPE,
            'icon' => $content->getIcon(),
            'nestable' => $content->data['nestable'] ?? false,
            'componentName' => false,
            'component' => $content->getComponent(),
            'nestedLimit' => $content->data['nested_limit'] ?? false,
            'editable' => true,
            'globalContent' => false,
            'repeatable' => $content->data['repeatable'] ?? false,
            'optionsMenuVisible' => true,
            'type' => $content::TYPE,
            'isGroup' => ($content::TYPE ?? 'group') === 'group',
            'error' => null,
            'children' => [],

        ];
    }
}
