<?php

namespace App\Traits;

use App\Facades\Settings;
use App\Http\Resources\FormViewResource;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Mtc\ContentManager\Models\MediaSize;
use Mtc\MercuryDataModels\Contracts\ContentModel;
use Mtc\MercuryDataModels\Country;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\MediaUse;
use Mtc\MercuryDataModels\SeoData;
use Mtc\MercuryDataModels\SeoDefault;

trait RetrievesContent
{
    use MediaHasSizes;
    use CacheObject;

    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']) && $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),
                    '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,
        };
    }

    private function fillSeo(string $section, ?string $urlPath = null): array
    {
        if (!empty($urlPath)) {
            $data = $this->getSeoForPath($urlPath);
            if ($data) {
                return $data->only([
                    'title',
                    'description',
                    'heading',
                    'content',
                ]);
            }
        }

        $seoData = $this->resource['seo'] ?? [];
        if (!empty($seoData['title']) && !empty($seoData['description'])) {
            return $seoData;
        }


        $default = $this->cache(
            'seo-default-' . $section,
            15,
            fn() => SeoDefault::query()->where('section', $section)->first()
        );
        if (!$default) {
            return $seoData;
        }

        if (empty($seoData['title'])) {
            $seoData['title'] = $this->replaceSeoTags([
                '{{TITLE}}' =>  $this->resource->title ?? $this->resource->name,
                '{{MAKE}}' => $this->resource->make->name ?? '',
                '{{MODEL}}' => $this->resource->model->name ?? '',
                '{{FUEL_TYPE}}' => $this->resource->fuelType->name ?? '',
                '{{BODY_STYLE}}' => $this->resource->bodyStyle->name ?? '',
                '{{TRANSMISSION}}' => $this->resource->transmission->name ?? '',
                '{{MANUFACTURE_YEAR}}' => $this->resource->manufacture_year ?? '',
                '{{COLOUR}}' => $this->resource->colour ?? '',
                '{{VEHICLE_TYPE}}' => $this->resource->vehicle_type ?? '',
                '{{CONDITION}}' => $this->getConditionValue(),
                '{{SITE_NAME}}' => Settings::get('app-name'),
                '{{NEW_USED}}' => ($this->resource->is_new ? __('labels.vehicle.new') : __('labels.vehicle.used')),

            ], $default->title ?? $this->resource->title);
        }

        if (empty($seoData['description'])) {
            $seoData['description'] = $this->replaceSeoTags([
                '{{TITLE}}' =>  $this->resource->title ?? $this->resource->name,
                '{{SITE_NAME}}' => Settings::get('app-name'),
                '{{MAKE}}' => $this->resource->make->name ?? '',
                '{{MODEL}}' => $this->resource->model->name ?? '',
                '{{FUEL_TYPE}}' => $this->resource->fuelType->name ?? '',
                '{{BODY_STYLE}}' => $this->resource->bodyStyle->name ?? '',
                '{{TRANSMISSION}}' => $this->resource->transmission->name ?? '',
                '{{MANUFACTURE_YEAR}}' => $this->resource->manufacture_year ?? '',
                '{{COLOUR}}' => $this->resource->colour ?? '',
                '{{VEHICLE_TYPE}}' => $this->resource->vehicle_type ?? '',
                '{{CONDITION}}' => $this->getConditionValue(),
                '{{CONTENT_EXCERPT}}' => Str::limit($this->resource->description, 150),
                '{{NEW_USED}}' => ($this->resource->is_new ? __('labels.vehicle.new') : __('labels.vehicle.used')),

            ], $default->description ?? '');
        }
        return $seoData;
    }

    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
    {
        return str_replace(array_keys($replacements), $replacements, $string);
    }


    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 = Cache::rememberForever(
//            'country-dial-code-' . $countryCode,
//            fn () => Country::query()->where('code', $countryCode)->first()?->dial_code
//        );

        $prefix = '+' . Country::query()->where('code', $countryCode)->first()?->dial_code;
        return [
            'number' => $prefix . $this->resource->dealership->contact_no,
            'display' => $prefix . ' ' . $this->displayNumber($this->resource->dealership->contact_no),
        ];
    }

    private function getSeoForPath(string $path): ?Model
    {
        return SeoData::query()->where('path', $path)->first();
    }
}
