<?php

namespace App\Traits;

use App\Facades\Feature;
use App\Facades\Settings;
use Illuminate\Database\Eloquent\Model;
use App\Modules\PlaceholderImages\ImaginStudio;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\MediaUse;
use Mtc\MercuryDataModels\Setting;

trait HasPlaceholderImage
{
    use MediaHasSizes;
    use CacheObject;

    abstract protected function largeImageDimensions(): string;
    abstract protected function mediumImageDimensions(): string;
    abstract protected function thumbnailImageDimensions(): string;

    protected function getGallery(Model $model, ?int $limit = 0): ?Collection
    {
        if (is_null($model->mediaUses) || $model->mediaUses->isEmpty()) {
            return $this->getPlaceholderForGallery($model)
                ?->take($limit ?: 100);
        }

        return $model->mediaUses
            ->take($limit ?: 100)
            ->map(fn(MediaUse $mediaUse) => [
                'id' => $mediaUse->id,
                'title' => $mediaUse->title,
                'alt_text' => $mediaUse->alt_text,
                'description' => $mediaUse->description,
                'caption' => $mediaUse->caption,
                'src_large' => $mediaUse->getUrl($this->largeImageDimensions()),
                'src_medium' => $mediaUse->getUrl($this->mediumImageDimensions()),
                'src_thumbnail' => $mediaUse->getUrl($this->thumbnailImageDimensions()),
                'sizes' => $this->allSizesForUse($model, $mediaUse)
                    ->put('original', $mediaUse->media->getOriginalUrlAttribute())
                    ->toArray() ?: null,
                'type' => $mediaUse->media->type,
                'provider' => $mediaUse->media->image_provider,
                'interior' => $mediaUse->interior,
                'exterior' => $mediaUse->exterior,
                'hex1' => $mediaUse->media?->hex1,
                'hex2' => $mediaUse->media?->hex2,
            ]);
    }

    protected function getPreviewImage(Model $model): ?string
    {
        return $model->getPreviewImage($this->mediumImageDimensions())
            ?? $this->getPlaceholder($model, $this->mediumImageDimensions());
    }

    protected function getPlaceholderForGallery(Model $model): ?Collection
    {
        if ($this->canUseAdvancedPlaceholder($model)) {
            return $this->advancedPlaceholderGallery($model->getMorphClass(), $model)
                ->map(fn($image) => [
                    'id' => null,
                    'alt_text' => '',
                    'original' => null,
                    'src_large' => $image,
                    'src_medium' => $image,
                ]);
        }

        $image = Feature::isEnabled('makes-placeholders') ? $this->makePlaceholderImage($model) : '';

        if (!empty($image)) {
            return collect([
                [
                    'id' => null,
                    'alt_text' => '',
                    'original' => null,
                    'src_large' => $image,
                    'src_medium' => $image,
                ]
            ]);
        }

        $basic_placeholder = $this->basicPlaceholderImageObject($model->getMorphClass(), $model);
        return $basic_placeholder ? collect([$basic_placeholder]) : null;
    }

    protected function getPlaceholder(Model $model, string $dimensions): ?string
    {

        if ($this->canUseAdvancedPlaceholder($model)) {
            return $this->advancedPlaceholderImage($model->getMorphClass(), $model);
        }

        $image = Feature::isEnabled('makes-placeholders') ? $this->makePlaceholderImage($model, $dimensions) : '';

        if (empty($image)) {
            $image = $this->basicPlaceholderImage($model->getMorphClass(), $dimensions);
        }

        return $image;
    }

    protected function advancedPlaceholderForGallery(string $type)
    {
        return collect(match ($type) {
            'vehicle' => [
                [
                    'src_large' => (new ImaginStudio())
                        ->getForVehicle($this->resource, Settings::get('imagin-studio-angle', 1)),
                    'src_medium' => (new ImaginStudio())
                        ->getForVehicle($this->resource, Settings::get('imagin-studio-angle', 1)),
                ]
            ],
            'offer' => [
                [
                    'src_large' => (new ImaginStudio())
                        ->getForOffer($this->resource, Settings::get('imagin-studio-angle', 1)),
                    'src_medium' => (new ImaginStudio())
                        ->getForOffer($this->resource, Settings::get('imagin-studio-angle', 1)),
                ]
            ],
            'lease-vehicle' => [
                'src_large' => (new ImaginStudio())
                    ->getForLeaseVehicle($this->resource, Settings::get('imagin-studio-angle', 1)),
                'src_medium' => (new ImaginStudio())
                    ->getForLeaseVehicle($this->resource, Settings::get('imagin-studio-angle', 1)),
            ],
            default => [],
        });
    }

    protected function advancedPlaceholderImage(string $type, Model $model): string
    {
        return match ($type) {
            'vehicle' => (new ImaginStudio())->getForVehicle($model, Settings::get('imagin-studio-angle', 1)),
            'new-car' => (new ImaginStudio())->getForNewCar($model, Settings::get('imagin-studio-angle', 1)),
            'offer' => (new ImaginStudio())->getForOffer($model, Settings::get('imagin-studio-angle', 1)),
            'lease-vehicle' => (new ImaginStudio())
                ->getForLeaseVehicle($model, Settings::get('imagin-studio-angle', 1)),
            default => '',
        };
    }

    protected function advancedPlaceholderGallery(string $type, Model $model): Collection
    {
        return match ($type) {
            'vehicle' => $this->angles()->map(fn($i) => (new ImaginStudio())->getForVehicle($model, $i)),
            'new-car' => $this->angles()->map(fn($i) => (new ImaginStudio())->getForNewCar($model, $i)),
            'vehicle-trim' => $this->angles()->map(fn($i) => (new ImaginStudio())->getForNewCarTrim($model, $i)),
            'offer' => $this->angles()->map(fn($i) => (new ImaginStudio())->getForOffer($model, $i)),
            'lease-vehicle' => $this->angles()->map(fn($i) => (new ImaginStudio())->getForLeaseVehicle($model, $i)),
            default => collect(),
        };
    }

    protected function makePlaceholderImage($model, ?string $dimensions = null): ?string
    {
        if ($model->getMorphClass() != 'vehicle') {
            return null;
        }

        if (empty($dimensions)) {
            $dimensions = config(config("automotive.placeholder_media_sizes.placeholder-image-vehicle"))['large'];
        }
        $mediaUses = Setting::query()->where(
            'config_key',
            'placeholder-image-vehicle-make-' . $model->make_id
        )
            ->first()
            ?->mediaUses;

        if ($mediaUses && $mediaUses->count()) {
            $mediaUse = $mediaUses->first();
            $mediaUse->setOverrideOwnerType($mediaUse->owner_type);
            return $mediaUse->getUrl($dimensions);
        }

        return null;
    }

    protected function basicPlaceholderImage(string $type, ?string $dimensions = null): ?string
    {
        $cache_name = "basic-placeholder-image-$type-" . ($dimensions ?? 'default');
        return $this->cache($cache_name, 10, function () use ($type, $dimensions) {
            if (empty($dimensions)) {
                $dimensions = config(config("automotive.placeholder_media_sizes.placeholder-image-$type"))['large'];
            }
            $mediaUses = Setting::query()->where('config_key', 'placeholder-image-' . $type)
                ->first()
                ?->mediaUses;

            if ($mediaUses && $mediaUses->count()) {
                $mediaUse = $mediaUses->first();
                $mediaUse->setOverrideOwnerType($mediaUse->owner_type);
                return $mediaUse->getUrl($dimensions);
            }
            return '';
        });
    }


    protected function basicPlaceholderImageObject(string $type, Model $model): ?array
    {
        $cache_name = "basic-placeholder-image-object-$type";
        return $this->cache($cache_name, 10, function () use ($type, $model) {
            $mediaUses = Setting::query()->where('config_key', 'placeholder-image-' . $type)
                ->first()
                ?->mediaUses;

            if ($mediaUses && $mediaUses->count()) {
                $mediaUse = $mediaUses->first();
                $mediaUse->setOverrideOwnerType($mediaUse->owner_type);
                $dimensions = config(config("automotive.placeholder_media_sizes.placeholder-image-$type"));
                return [
                    'id' => $mediaUse->id,
                    'title' => $mediaUse->title,
                    'alt_text' => $mediaUse->alt_text,
                    'description' => $mediaUse->description,
                    'caption' => $mediaUse->caption,
                    'src' => $mediaUse->media->getOriginalUrlAttribute(),
                    'src_large' => $mediaUse->getUrl($dimensions['large'] ?? null),
                    'src_medium' => $mediaUse->getUrl($dimensions['medium'] ?? null),
                    'sizes' => $this->allSizesForUse($model, $mediaUse)
                        ->put('original', $mediaUse->media->getOriginalUrlAttribute())
                        ->toArray() ?: null,
                    'interior' => $mediaUse->interior,
                    'exterior' => $mediaUse->exterior,
                    'hex1' => $mediaUse->media?->hex1,
                    'hex2' => $mediaUse->media?->hex2,
                ];
            }
            return null;
        });
    }

    protected function canUseAdvancedPlaceholder(Model $model): bool
    {
        return match ($model->getMorphClass()) {
            'vehicle', 'offer', 'new-car', 'lease-vehicle' =>
                Feature::isEnabled('imagin-studio-placeholders')
                && Settings::get('imagin-placeholders-' . $model->getMorphClass() . '-enabled'),
            'vehicle-trim'=>
                Feature::isEnabled('imagin-studio-placeholders')
                && Settings::get('imagin-placeholders-new-car-enabled'),
            default => false,
        };
    }

    protected function angles(): Collection
    {
        // https://docs.imagin.studio/guides/getting-our-images/selecting-angles
        return collect([
            Settings::get('imagin-studio-angle', 1),
            5,
            9,
            13,
            17,
            21,
            22,
            23,
        ]);
    }
}
