<?php

namespace App\Traits;

use App\Http\Resources\FormViewResource;
use App\LocalisationService;
use App\ShortcodeHelper;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Mtc\ContentManager\Models\MediaSize;
use Mtc\MercuryDataModels\Contracts\ContentModel;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\MediaUse;

trait RetrievesContent
{
    use MediaHasSizes;
    use CacheObject;
    use RetrievesSeoData;

    protected Collection $mediaSizes;

    private function getContent(Collection $contentList): Collection
    {
        return $contentList
            ->reject(fn ($content) => !empty($content->hidden))
            ->values()
            ->map(fn (ContentModel $content) => $this->isGlobalContent($content)
                ? $this->mapGlobalContent($content)
                : $this->mapContentElement($content));
    }

    private function isGlobalContent(ContentModel $content): bool
    {
        return !empty($content->global_content_id);
    }

    private function mapGlobalContent(ContentModel $content): array
    {
        return [
            'ui_component' => $content->globalContent?->ui_component ?? $this->componentFromField($content),
            'name' => $content->name,
            'slug' => $content->slug,
            'value' => collect($content->content ?? [])
                ->map(fn ($row) => $this->mapGlobalContentItem($row, $content)),
            'config' => [],
            'data' => [],

        ];
    }

    private function mapGlobalContentItem($entry, ContentModel $content): array
    {
        if (isset($entry['field_type']) && in_array($entry['field_type'], ['form', 'form-field'])) {
            $entry['content'] = (new FormViewResource(Form::query()->find($entry['content'])));
        }

        if (isset($entry['field_type']) && in_array($entry['field_type'], ['text', 'editor'])) {
            $entry['content'] = ShortcodeHelper::replaceShortcodes($entry['content']);
        }

        if (isset($entry['field_type']) && $entry['field_type'] === 'image') {
            $entry['content'] = $content->mediaUses
                ->filter(fn (MediaUse $mediaUse) => in_array($mediaUse->media_id, $entry['content'] ?? []))
                ->map(fn (MediaUse $mediaUse) => [
                    'src' => $mediaUse->getUrl('square-tile'),
                    'sizes' => $this->allSizesForGlobalContent($mediaUse),
                    'alt' => $mediaUse->alt_text,
                    'caption' => $mediaUse->caption,
                    'title' => $mediaUse->title,
                ]);
        }
        if (!empty($entry['children'])) {
            $entry['children'] = collect($entry['children'])
                ->map(fn ($child) => $this->mapGlobalContentItem($child, $content));
        }
        return collect($entry)
            ->except([
                'optionsMenuVisible',
                'editable',
                'nestedLimit',
                'nestable',
                'repeatable',
                'icon',
                'component',
                'componentName',
                'error',
                'data',
                'id',
                'meta',
            ])->toArray();
    }

    private function allSizesForGlobalContent(MediaUse $mediaUse): Collection
    {
        if (!isset($this->mediaSizes)) {
            $this->mediaSizes = MediaSize::query()
                ->where('model', 'global-content')
                ->get();
        }
        return $this->mediaSizes
            ->keyBy('label')
            ->map(fn (MediaSize $size) => $mediaUse->getUrl($size->label))
            ->put('original', $mediaUse->media->getOriginalUrlAttribute());
    }

    private function mapContentElement(ContentModel $content): array
    {
        return [
            'ui_component' => $content->contentElement?->ui_component ?? $this->componentFromField($content),
            'name' => $content->name,
            'slug' => $content->slug,
            'value' => $this->mapValue($content),
            'config' => [],
            'data' => $content->subContent && $this->componentHasUiResource($content) === false
                ? $this->getContent($content->subContent)
                : [],
        ];
    }

    private function mapValue(ContentModel $content)
    {
        if ($this->componentHasUiResource($content)) {
            $contentResource = $this->getUiResource($content);
            return new $contentResource($content);
        }

        return match ($content->data['fieldId'] ?? '') {
            'image', 'images' => collect($content->mediaUses)
                ->map(fn ($mediaUse) => [
                    'id' => $mediaUse->id,
                    'src' => $mediaUse->getUrl('square-tile'),
                    'sizes' => $this->allSizesForUse($content, $mediaUse)
                        ->prepend($mediaUse->media->getOriginalUrlAttribute(), 'original'),
                    'alt' => $mediaUse->alt_text,
                    'caption' => $mediaUse->caption,
                    'title' => $mediaUse->title,
                    'interior' => $mediaUse->interior,
                    'exterior' => $mediaUse->exterior,
                    'hex1' => $mediaUse->media?->hex1,
                    'hex2' => $mediaUse->media?->hex2,
                ]),
            'form-field' => new FormViewResource(Form::query()
                ->with('sections.questions')
                ->where('id', $content->content)
                ->first()),
            default => $content->content
        };
    }

    private function componentHasUiResource(ContentModel $content): bool
    {
        if (!empty($content->global_content_id)) {
            return !empty($content->globalContent->ui_component)
                && class_exists(self::UI_RESOURCE_PREFIX . $content->globalContent->ui_component);
        }

        return !empty($content->contentElement->ui_component)
            && class_exists(self::UI_RESOURCE_PREFIX . $content->contentElement->ui_component);
    }

    private function getUiResource(ContentModel $content): string
    {
        return
            !empty($content->global_content_id)
                ? self::UI_RESOURCE_PREFIX . $content->globalContent->ui_component
                : self::UI_RESOURCE_PREFIX . $content->contentElement->ui_component;
    }

    private function componentFromField(ContentModel $content)
    {
        return $content->data['uiComponent'] ?? $this->primitiveField($content);
    }

    private function primitiveField(ContentModel $content)
    {
        return match ($content->data['fieldId'] ?? null) {
            'text-content' => 'UiArticleText',
            'text_area' => 'UiArticleText',
            'images' => 'UiArticleBanner',
            'image' => 'UiArticleBanner',
            default => null,
        };
    }

    protected function getConditionValue()
    {
        if ($this->resource->is_new) {
            return __('labels.vehicle.new');
        }

        return $this->resource->ex_demo ? __('labels.vehicle.ex-demo') : __('labels.vehicle.used');
    }

    private function replaceSeoTags(array $replacements, string $string): string
    {
        $result = str_replace(array_keys($replacements), $replacements, $string);
        return preg_replace('/\s+/', ' ', trim($result));
    }


    private function getContactNumber(): ?array
    {
        if ($this->resource->dealership_id === null) {
            return null;
        }

        if ($this->resource->dealership->contact_no === null) {
            return null;
        }

        $countryCode = $this->resource->dealership->country;
        $prefix = App::make(LocalisationService::class)->phonePrefix($countryCode);
        return [
            'number' => $prefix . $this->resource->dealership->contact_no,
            'display' => $prefix . ' ' . $this->displayNumber($this->resource->dealership->contact_no),
        ];
    }
}
