<?php

namespace App\Http\Resources;

use App\Facades\Feature;
use App\Http\Resources\Traits\TransformsImageAttributesForDisplay;
use App\Traits\HasPlaceholderImage;
use App\Traits\MediaHasSizes;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\CarConfiguratorModel;
use Mtc\MercuryDataModels\CatalogOffer;
use Mtc\MercuryDataModels\NewCar;
use Mtc\MercuryDataModels\Traits\HasVehicleCustomAttributes;
use Mtc\MercuryDataModels\VehicleOffer;

class NewCarListResource extends JsonResource
{
    use HasPlaceholderImage;
    use MediaHasSizes;
    use HasVehicleCustomAttributes;
    use TransformsImageAttributesForDisplay;

    public static $wrap = '';

    private Collection $placeholder;

    public function __construct(
        public $resource,
        private readonly array $catalogOffers = []
    ) {
        parent::__construct($resource);
    }
    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    #[\Override]
    public function toArray($request)
    {
        $this->resource->load(['attributeValues']);

        if ($this->resource instanceof LengthAwarePaginator) {
            $this->resource->through(fn (NewCar $car) => $this->map($car));
        } else {
            $this->resource = $this->resource->map(fn (NewCar $car) => $this->map($car));
        }

        $resource = parent::toArray($request);

        foreach ($this->catalogOffers as $catalogOffer) {
            $resource = $this->addCatalogOffer($resource, $catalogOffer);
        }

        return $resource;
    }

    protected function map(NewCar $car): array
    {
        $fuelTypes = null;
        if ($car->fuelTypes->count() == 1) {
            $fuelTypes = $car->fuelTypes->first()->name;
        } elseif ($car->fuelTypes->count() > 1) {
            $fuelTypes = $car->fuelTypes->pluck('name');
        }

        $previewImage = $car->mediaUses
            ->filter(fn ($mediaUse) => $mediaUse->flags['listing'] ?? null)
            ->first();
        $heroImage = $car->mediaUses
            ->filter(fn ($mediaUse) => $mediaUse->flags['hero'] ?? null)
            ->first();

        $mobileHeroImage = $car->mediaUses
            ->filter(fn ($mediaUse) => $mediaUse->flags['mobile_hero'] ?? null)
            ->first();

        $imageSizes = !empty($previewImage)
            ? $this->allSizesForUse($car, $previewImage)
                ->put('original', $previewImage->media->getOriginalUrlAttribute())
            : [];

        $heroImageSizes = !empty($heroImage)
            ? $this->allSizesForUse($car, $heroImage)
                ->put('original', $heroImage->media->getOriginalUrlAttribute())
            : [];

        $mobileHeroImageSizes = !empty($mobileHeroImage)
            ? $this->allSizesForUse($car, $mobileHeroImage)
                ->put('original', $mobileHeroImage->media->getOriginalUrlAttribute())
            : [];

        if (Feature::isEnabled('car-configurator')) {
            $configurator_models = CarConfiguratorModel::query()
                ->where('active', 1)
                ->where('make_id', $car->make_id)
                ->where('model_id', $car->model_id)
                ->get();

            if ($configurator_models->whereNotNull('fuel_type_id')->count()) {
                $car->configurator = $configurator_models
                    ->filter(fn (CarConfiguratorModel $model) => $car->fuelTypes
                        ->filter(fn ($fuelType) => $fuelType->id == $model->fuel_type_id)->isNotEmpty())
                    ->map(fn ($item) => $item->only(['name', 'slug']))
                    ->values();
            } else {
                $car->configurator = $configurator_models->map(fn ($item) => $item->only(['name', 'slug']));
            }
        }
        return [
            'slug' => $car->slug,
            'name' => $car->name,
            'excerpt' => $car->excerpt,
            'derivative' => $car->derivative,
            'make' => $car->make?->name,
            'model' => $car->model?->name,
            'vehicle_type' => $car->vehicle_type,
            'image' => $this->getPreviewImage($car, 'tile', 'listing'),
            'image_sizes' => $imageSizes,
            'configurator' => $car->configurator ?? null,
            'images' => [
                'listing' => [
                    'id' => $previewImage?->id,
                    'title' => $previewImage?->title,
                    'alt_text' => $previewImage?->alt_text,
                    'description' => $previewImage?->description,
                    'caption' => $previewImage?->caption,
                    'interior' => $previewImage?->interior,
                    'exterior' => $previewImage?->exterior,
                    'hex1' => $previewImage?->media?->hex1,
                    'hex2' => $previewImage?->media?->hex2,
                    'type' => $previewImage?->media->type,
                    'src' => $previewImage?->media->getOriginalUrlAttribute(),
                    'sizes' => $imageSizes,
                ],
                'hero' => [
                    'id' => $heroImage?->id,
                    'title' => $heroImage?->title,
                    'alt_text' => $heroImage?->alt_text,
                    'description' => $heroImage?->description,
                    'caption' => $heroImage?->caption,
                    'interior' => $heroImage?->interior,
                    'exterior' => $heroImage?->exterior,
                    'hex1' => $heroImage?->media?->hex1,
                    'hex2' => $heroImage?->media?->hex2,
                    'type' => $heroImage?->media->type,
                    'src' => $heroImage?->media->getOriginalUrlAttribute(),
                    'sizes' => $heroImageSizes,
                ],
                'mobile_hero' => [
                    'id' => $mobileHeroImage?->id,
                    'title' => $mobileHeroImage?->title,
                    'alt_text' => $mobileHeroImage?->alt_text,
                    'description' => $mobileHeroImage?->description,
                    'caption' => $mobileHeroImage?->caption,
                    'interior' => $mobileHeroImage?->interior,
                    'exterior' => $mobileHeroImage?->exterior,
                    'hex1' => $mobileHeroImage?->media?->hex1,
                    'hex2' => $mobileHeroImage?->media?->hex2,
                    'type' => $mobileHeroImage?->media->type,
                    'src' => $mobileHeroImage?->media->getOriginalUrlAttribute(),
                    'sizes' => $mobileHeroImageSizes,
                ],
            ],
            'hero_image' => $this->getPreviewImage($car, 'tile', 'hero'),
            'price' => $car->price,
            'monthly_price' => $car->monthly_price,
            'section_url' => $car->make?->slug . '/' . $car->model?->slug,
            'fuel_type' => $fuelTypes,
            'colour' => $car->colour,
            'fuel_types' => $car->getAvailableFuelTypes(),
            'from_price' => $this->getFromPriceFromOffers($car),
            'extra' => $this->transformImageAttributesForDisplay($this->getExtraData($car)),
            'custom' => $car->getAllCustom(),
        ];
    }

    public function getPreviewImage(Model $model, string $dimensions, string $type): ?string
    {
        $listingImage = $model->mediaUses
            ->filter(fn ($mediaUse) => $mediaUse->flags[$type] ?? null)
            ->first();

        return $listingImage?->getUrl($dimensions) ?? $this->getPlaceholder($model, $dimensions);
    }

    protected function largeImageDimensions(): string
    {
        return 'tile';
    }

    protected function mediumImageDimensions(): string
    {
        return $this->largeImageDimensions();
    }

    protected function thumbnailImageDimensions(): string
    {
        return $this->largeImageDimensions();
    }

    protected function addCatalogOffer(array $resource, CatalogOffer $catalogOffer): array
    {
        $image = null;
        if ($catalogOffer->primaryMediaUse?->media) {
            $image = $catalogOffer->primaryMediaUse->media->type === 'image'
                ? $catalogOffer->getPreviewImage('325x250')
                : $catalogOffer->primaryMediaUse->media->getOriginalUrlAttribute();
        }

        $allMedia = $catalogOffer->mediaUses->map(fn ($mediaUse) => [
            'id' => $mediaUse->id,
            'title' => $mediaUse->title,
            'alt_text' => $mediaUse->alt_text,
            'description' => $mediaUse->description,
            'caption' => $mediaUse->caption,
            'original' => $mediaUse->media->getOriginalUrlAttribute(),
            'sizes' => $this->allSizesForUse($catalogOffer, $mediaUse)
                ->put('original', $mediaUse->media->getOriginalUrlAttribute())
                ->toArray() ?: null,
            'type' => $mediaUse->media->type,
        ]);

        $images = $allMedia->filter(fn ($item) => $item['type'] !== 'video')->values();
        $videos = $allMedia->filter(fn ($item) => $item['type'] === 'video')->values();

        $isPageOne = $this->resource instanceof LengthAwarePaginator
            && $this->resource->currentPage() === 1;

        $position = ($catalogOffer->weight > 0 && $isPageOne)
            ? 0
            : random_int(0, count($resource['data']));

        array_splice(
            $resource['data'],
            $position,
            0,
            [
                [
                    'id' => $catalogOffer->id,
                    'title' => $catalogOffer->name,
                    'subtitle' => $catalogOffer->subtitle,
                    'image' => $image,
                    'images' => $images->isNotEmpty() ? $images->toArray() : null,
                    'videos' => $videos->isNotEmpty() ? $videos->toArray() : null,
                    'link' => $catalogOffer->link,
                    'button_text' => $catalogOffer->button_text,
                    'type' => 'catalog-offer',
                ]
            ]
        );

        return $resource;
    }

    protected function getFromPriceFromOffers(NewCar $car): ?float
    {
        return VehicleOffer::query()
            ->where('make_id', '=', $car->make_id)
            ->where('model_id', '=', $car->model_id)
            ->where('price', '>', 0)
            ->orderBy('price')
            ->pluck('price')
            ->first();
    }
}
