<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Facades\Site;
use App\NewCarRepository;
use App\TierHelper;
use App\VehicleTrimRepository;
use App\Traits\MakeAndModelList;
use App\VehicleType;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\App;
use Mtc\ContentManager\Contracts\MediaUse;
use Mtc\ContentManager\Http\Resources\MediaEntryResource;
use Mtc\ContentManager\Models\Template;
use Mtc\ContentManager\Traits\MapContentTrait;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\DrivetrainType;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Traits\HasVehicleCustomAttributes;
use Mtc\MercuryDataModels\TransmissionType;
use App\Http\Resources\Traits\TransformsImageAttributesForAdmin;

class NewCarViewResource extends JsonResource
{
    use MapContentTrait;
    use ResourceMediaEntries;
    use SeoDataForModel;
    use MakeAndModelList;
    use HasVehicleCustomAttributes;
    use TransformsImageAttributesForAdmin;

    public static $wrap = '';

    /**
     * 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([
            'content.mediaUses.media',
            'content.subContent.mediaUses.media',
            'content.subContent.subContent.mediaUses.media',
            'content.subContent.subContent.subContent.mediaUses.media',
            'content.subContent.subContent.subContent.subContent.mediaUses.media',
            'content.globalContent.contentElement.fields',
            'content.contentElement.fields',
            'content.subContent.contentElement.fields',
            'content.subContent.subContent.contentElement.fields',
            'content.subContent.subContent.subContent.contentElement.fields',
            'content.subContent.subContent.subContent.subContent.contentElement.fields',
            'mediaUses.media',
            'fuelTypes',
            'finance',
            'trims.mediaUses.media',
        ]);

        $car = $this->resource->toArray();

        $car['dealership_name'] = $this->resource->dealership?->name;
        $car['franchise_name'] = $this->resource->franchise?->name;
        $car = array_merge($car, $this->getMediaEntries());
        $car['seo'] = $this->getSeoData($this->resource);
        $car['stats'] = $this->getStats();
        $car['structure_in_sync'] = $this->repository()->isContentOutOfSync($this->resource) !== true;
        $car['content'] = $this->resource->content
            ->filter(fn($content) => !empty($content->slug))
            ->map(fn($content) => $this->mapContent($content))
            ->values();
        $car['site_url'] = Site::newCarUrl($this->resource, true);
        $car['versions'] = $this->getVersioningData();
        $car['fuel_types'] = !empty($this->resource->fuelTypes)
            ? $this->resource->fuelTypes->pluck('id')->toArray()
            : [];
        $car['listing_image'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['listing'] ?? null)
            ->values()
            ->pluck('media_id');

        $car['listing_image_uses'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['listing'] ?? null)
            ->values()
            ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse));

        $car['hero_image'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['hero'] ?? null)
            ->values()
            ->pluck('media_id');

        $car['hero_image_uses'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['hero'] ?? null)
            ->values()
            ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse));

        $car['mobile_hero_image'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['mobile_hero'] ?? null)
            ->values()
            ->pluck('media_id');
        $car['mobile_hero_image_uses'] = $this->resource->mediaUses
            ->filter(fn($mediaUse) => $mediaUse->flags['mobile_hero'] ?? null)
            ->values()
            ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse));

        $car['trims'] = $this->resource->getTrims()->map(function ($trim) {
            $trim->loadMissing([
                'content.mediaUses.media',
                'content.subContent.mediaUses.media',
                'content.subContent.subContent.mediaUses.media',
                'content.subContent.subContent.subContent.mediaUses.media',
                'content.globalContent.contentElement.fields',
                'content.contentElement.fields',
                'content.subContent.contentElement.fields',
                'content.subContent.subContent.contentElement.fields',
                'content.subContent.subContent.subContent.contentElement.fields',
            ]);

            return array_merge(
                $trim->toArray(),
                [
                    'data' => array_merge([
                        'payload_kg' => '',
                        'load_space' => '',
                        'towing_capacity' => '',
                    ], $trim->data ?? []),
                    'make_id' => $this->resource->make_id,
                    'model_id' => $this->resource->model_id,
                    'content' => $trim->content
                        ->filter(fn($content) => !empty($content->slug))
                        ->map(fn($content) => $this->mapContent($content))
                        ->values(),
                    'structure_in_sync' => $trim->template_id
                        ? $this->trimRepository()->isContentOutOfSync($trim) !== true
                        : true,
                    'extra' => $this->transformImageAttributesForAdmin($this->getExtraData($trim)->toArray()),
                    'image' => $trim->mediaUses->where('primary', 1)->pluck('media_id'),
                    'image_uses' => $trim->mediaUses->where('primary', 1)
                        ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse))->values(),
                    'image_primary_media' => true,
                    'listing_image' => $trim->mediaUses->where('primary', 0)->pluck('media_id'),
                    'listing_image_uses' => $trim->mediaUses->where('primary', 0)
                        ->map(fn(MediaUse $mediaUse) => new MediaEntryResource($mediaUse))->values(),
                    'listing_image_primary_media' => false,
                ]
            );
        });
        $car['extra'] = $this->transformImageAttributesForAdmin(
            $this->getExtraData($this->resource)->toArray()
        );

        return [
            'newVehicle' => $car,
            'vehicle_types' => collect(VehicleType::cases())
                ->map(fn(VehicleType $value) => [
                    'id' => $value->value,
                    'name' => $value->name,
                ]),
            'makes' => $this->getMakeList($this->resource->vehicle_type),
            'models' => $this->getModelList($this->resource->make_id, $this->resource->vehicle_type),
            'forms' => Form::query()->select('name', 'id')->where('is_active', 1)->get(),
            'templates' => Template::query()->active()->select('name', 'id')->get(),
            'fuel_types' => FuelType::all(),
            'drivetrains' => DrivetrainType::all(),
            'body_styles' => BodyStyleType::all(),
            'transmissions' => TransmissionType::all(),
            'settings' => [
                'distance_measurement' => Settings::get('automotive-distance_measurement'),
            ],
        ];
    }

    private function getStats(): array
    {

        $conversions = $this->resource->conversions()
            ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
            ->orderBy('date')
            ->get()
            ->groupBy('type');

        return [
            'days_in_stock' => Carbon::now()->diffInDays($this->resource->created_at, true),
            'days_since_update' => Carbon::now()->diffInDays($this->resource->updated_at, true),
            'enquiries' => $this->resource->allEnquiries()->count(),
            'conversions' => $conversions
                ->map(fn($data, $type) => [
                    'name' => __('vehicles.conversions.' . $type),
                    'today' => $data
                            ->where('date', Carbon::now()->format('Y-m-d'))
                            ->pluck('hits')
                            ->first() ?? 0,
                    'week' => $data
                        ->where('date', Carbon::now()->format('Y-m-d'))
                        ->sum('hits'),
                ])
                ->values()
        ];
    }

    private function repository(): NewCarRepository
    {
        return App::make(NewCarRepository::class);
    }

    private function trimRepository(): VehicleTrimRepository
    {
        return App::make(VehicleTrimRepository::class);
    }

    private function getFranchises(): ?Collection
    {
        return TierHelper::isAllowed(tenant()->tier, 'pro')
            ? Franchise::query()->select('name', 'id')->orderBy('name')->get()
            : null;
    }

    private function getDealerships(): ?Collection
    {
        return Dealership::query()->select('name', 'id')->get();
    }


    protected function mapVersion($carVersion)
    {
        return [
            'title' => $carVersion->id . ($carVersion->is_active ? ' (Active)' : ''),
            'description' => __('pages.version_description', [
                'author' => $carVersion->author?->name,
                'date' => Carbon::parse($carVersion->created_at)->format('d/m/Y H:i'),
            ]),
            'id' => $carVersion->id,
            'uuid' => $carVersion->uuid,
            'status' => $carVersion->status,
            'comments' => $carVersion->comment_count,
            'is_active' => $carVersion->is_active,
            'created_at' => Carbon::parse($carVersion->created_at)->format('d/m/Y H:i'),
            'url' => $carVersion->url(),
            'author' => $carVersion->author_id
                ? ['alt' => $carVersion->author?->name, 'src' => $carVersion->author?->profile_photo_url]
                : [],
        ];
    }

    private function getVersioningData()
    {
        if ($this->repository()->hasVersioning() !== true) {
            return false;
        }

        return $this->resource->versions()
            ->withCommentCount()
            ->with([
                'author',
                'car',
            ])
            ->latest()
            ->get()
            ->map(fn($version) => $this->mapVersion($version));
    }
}
