<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Traits\HasPlaceholderImage;
use App\Traits\RetrievesContent;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Mtc\MercuryDataModels\DealershipHoliday;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\SeoData;
use Mtc\MercuryDataModels\SeoDefault;

class DealershipView extends JsonResource
{
    use FranchiseData;
    use HasPlaceholderImage;
    use RetrievesContent;

    public static $wrap = '';

    private const string UI_RESOURCE_PREFIX = 'App\\Http\\Resources\\';

    private Request $request;

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    #[\Override]
    public function toArray($request)
    {
        $this->request = $request;
        $this->resource->load([
            'mediaUses.media',
            'content.mediaUses.media',
            'content.subContent.mediaUses.media',
            'content.subContent.subContent.mediaUses.media',
            'content.subContent.subContent.subContent.mediaUses.media',
            'content.contentElement',
            'content.globalContent.contentElement',
            'content.subContent.contentElement',
            'content.subContent.globalContent.contentElement',
            'content.subContent.subContent.contentElement',
            'content.subContent.subContent.globalContent.contentElement',
            'content.subContent.subContent.subContent.contentElement',
            'content.subContent.subContent.subContent.globalContent.contentElement',
        ]);

        $form = Form::query()->find($this->resource->contact_form_id);
        $data = [
            'id' => $this->resource->id,
            'name' => $this->resource->name,
            'slug' => $this->resource->slug,
            'contact_no' => $this->resource->contact_no,
            'email' => $this->resource->email,
            'coordinates' => $this->resource->coordinates,
            'open_times' => $this->resource->open_times,
            'is_open' => $this->resource->is_open,
            'opens_at' => $this->resource->opens_at,
            'closes_at' => $this->resource->closes_at,
            'alt_open_times' => Settings::get('dealership-second-open-times')
                ? $this->getOpenTime($this->resource->alt_open_times)
                : [],
            'alt_open_time_name' => Settings::get('dealership-secondary-open-close-time-name'),
            'second_alt_open_times' => Settings::get('dealership-third-open-times')
                ? $this->getOpenTime($this->resource->second_alt_open_times)
                : [],
            'second_alt_open_time_name' => Settings::get('dealership-tertiary-open-close-time-name'),
            'holidays' => $this->getHolidays(),
            'notes' => $this->resource->notes,
            'seo' => $this->fillSeo(),
            'form' => $form
                ? (new FormViewResource($form))->setValues(['dealership_id' => $this->resource->id])
                : null,
            'address' => collect([
                $this->resource->address1,
                $this->resource->address2,
                $this->resource->city,
                $this->resource->county,
                $this->resource->postcode,
            ])->filter()->implode(', '),
            'city' => $this->resource->city,
            'images' => $this->getGallery($this->resource),
            'external_showroom_url' => $this->resource->external_showroom_url,
            'content' => $this->getContent($this->resource->content),
            'departments' => $this->resource->departments,
        ];
        $data['custom'] = $this->resource->getAllCustom();
        if (Settings::get('dealerships-multiple-franchises')) {
            $this->resource->load([
                'franchises.primaryMediaUse.media',
                'franchises.make',
            ]);
            $data['franchises'] = $this->resource->franchises->map(fn($franchise) => $this->franchiseData($franchise));
        } else {
            $this->resource->loadMissing('franchise.make');
            $data['franchise'] = $this->franchiseData($this->resource->franchise);
        }

        return $data;
    }

    private function getOpenTime($openTimes)
    {
        if (!empty($openTimes)) {
            foreach ($openTimes as $openTime) {
                if (!empty($openTime['open']) && !empty($openTime['close'])) {
                    return $openTimes;
                }
            }
        }

        return [];
    }

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

        $seo_entry = SeoData::query()
            ->where('path', $this->request->header('x-path'))
            ->orWhere('path', $this->resource->urlPath())
            ->first();

        if ($seo_entry) {
            return $seo_entry->only(['title', 'description', 'heading', 'canonical', 'json_schema']);
        }

        $default = SeoDefault::query()->where('section', 'dealership')->first();
        if (!$default) {
            return $seoData;
        }

        if (empty($seoData['title'])) {
            $seoData['title'] = $this->replaceSeoTags([
                '{{TITLE}}' => $this->resource->name,
                '{{SITE_NAME}}' => Settings::get('app-name'),

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

        if (empty($seoData['description'])) {
            $seoData['description'] = $this->replaceSeoTags([
                '{{TITLE}}' => $this->resource->name,
                '{{SITE_NAME}}' => Settings::get('app-name'),

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

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

    protected function largeImageDimensions(): string
    {
        return 'full-width-banner';
    }

    protected function mediumImageDimensions(): string
    {
        return '300x300';
    }

    protected function thumbnailImageDimensions(): string
    {
        return '300x300';
    }

    private function franchiseData($franchise): array
    {
        if (empty($franchise)) {
            return [];
        }

        $data = $franchise->only([
            'id',
            'logo',
            'name',
            'slug',
            'make_id',
            'primary_colour',
            'secondary_colour',
        ]);
        $data['make_slug'] = $franchise->make?->slug;
        if (!empty($franchise->primaryMediaUse)) {
            $data['logo'] = $this->sizesForFranchise($franchise, $franchise->primaryMediaUse);
        }
        return $data;
    }

    private function getHolidays()
    {
        return $this->resource->upcomingHolidays()
            ->get()
            ->map(fn (DealershipHoliday $holiday) => $holiday->date);
    }
}
