<?php

namespace App\Http\Resources;

use App\Traits\IconForType;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Mtc\ContentManager\Contracts\MediaUse;
use Mtc\ContentManager\Http\Resources\MediaEntryResource;
use Mtc\ContentManager\Models\ContentElementField;
use Mtc\MercuryDataModels\ContentElement;

class SeoDataResource extends JsonResource
{
    use IconForType;

    public static $wrap = '';

    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        $this->resource->load([
            'contentElement.fields.childElement.fields.childElement.fields',
            'mediaUses.media',
        ]);
        $this->resource->content = [
            [
                'id' => $this->resource->contentElement?->id,
                'name' => $this->resource->contentElement?->title,
                'repeatable' => $this->resource->contentElement?->data['repeatable'] ?? false,
                'nestable' => $this->resource->contentElement?->data['nestable'] ?? false,
                'nestedLimit' => $this->resource->contentElement?->data['nested_limit'] ?? null,
                'optionsMenuVisible' => false,
                'icon' => $this->resource->contentElement?->icon,
                'component' => $this->getComponent('group'),
                'componentName' => $this->getComponent('group'),
                'children' => $this->childElementContentMap(
                    $this->resource->contentElement,
                    $this->resource->content[0]['children'] ?? []
                ),
            ]
        ];
        return parent::toArray($request);
    }

    protected function mapField($field, $content)
    {
        $icon = $this->getIcon($field->field_type);
        if ($field->child_element_id && $field->childElement->icon) {
            $icon = $field->childElement->icon;
        }
        $field->id = random_int(1, 999999);
        $field->editable = true;
        $field->optionsMenuVisible = false;
        $field->nestedLimit = $field->data['nestedLimit'] ?? false;
        $field->nestable = $field->data['nestable'] ?? false;
        $field->repeatable = $field->data['repeatable'] ?? false;
        $field->content = $this->getAttributeFormContent($field, $content);
        $field->meta = $this->getMetaFromContent($field);
        $field->icon = $icon;
        $field->component = 'EditableContent' . $this->getComponent($field->field_type);
        $field->componentName = $this->getComponent($field->field_type);
        $field->children = $field->child_element_id
            ? $this->childElementContentMap(
                $field->childElement,
                $this->getAttributeFormContent($field, $content, 'children')
            )
            : [];

        return $field;
    }

    private function getMetaFromContent($field)
    {
        $meta = $field->meta ?? [];
        if ($field->field_type === 'image') {
            $meta['selected'] = $this->resource->mediaUses
                ->filter(fn(MediaUse $mediaUse) => in_array($mediaUse->media_id, $field->content ?? []))
                ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse))
                ->values();
        }

        return $meta;
    }

    protected function getComponent(string $type): string
    {
        return match ($type) {
            'text' => 'TextField',
            'image' => 'ImageUpload',
            'boolean', 'confirm' => 'Boolean',
            'editor' => 'Editor',
            'checkbox', 'checkbox-list' => 'CheckboxList',
            'coords', 'location' => 'LocationPicker',
            'number' => 'NumberField',
            'select' => 'SelectField',
            'date', 'datetime' => 'DateTimeField',
            default => 'Group',
        };
    }

    private function getElementList()
    {
        return ContentElement::query()
            ->select(['id', 'title as name'])
            ->orderBy('name')
            ->active()
            ->get();
    }

    protected function getAttributeFormContent($field, $fromContent, string $attribute = 'content')
    {
        if (isset($fromContent['slug'])) {
            $value = $fromContent;
        } else {
            $value = collect($fromContent)
                ->filter(fn($value) => ($value['slug'] ?? '') === $field->slug)
                ->first();
        }

        return $value[$attribute] ?? null;
    }

    private function isContentRepeated($resource, $content): bool
    {
        $unique_elements = collect($content)
                ->map(fn($entry) => $entry['child_element_id'] ?? null)
                ->unique()
                ->count();
        return $resource?->fields->count() == 1
            && $unique_elements === 1;
    }

    private function repeaterContentMap(ContentElementField $field, ?array $repeated_content): Collection
    {
        return collect($repeated_content)
            ->map(fn($content) => $this->mapField(new ContentElementField($field->toArray()), $content))
            ->values();
    }

    private function childElementContentMap($resource, $content): ?Collection
    {
        if ($this->isContentRepeated($resource, $content)) {
            return $this->repeaterContentMap($resource->fields->first(), $content);
        }

        return $resource?->fields
            ->map(fn($field) => $this->mapField($field, $content));
    }
}
