<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Traits\HasPlaceholderImage;
use Carbon\Carbon;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\OfferView;
use Mtc\MercuryDataModels\Traits\HasVehicleCustomAttributes;
use Mtc\MercuryDataModels\VehicleOffer;

class OfferListResource extends JsonResource
{
    use HasPlaceholderImage;
    use HasVehicleCustomAttributes;

    public static $wrap = '';

    private Collection $placeholder;

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        $this->resource->load(['finance', 'primaryMediaUse.media', 'attributeValues']);
        $this->trackViews();
        if ($this->resource instanceof LengthAwarePaginator) {
            $this->resource->through(fn(VehicleOffer $offer) => $this->map($offer, $request));
        } else {
            $this->resource = $this->resource->map(fn(VehicleOffer $offer) => $this->map($offer, $request));
        }
        return parent::toArray($request);
    }

    protected function map(VehicleOffer $offer, Request $request): array
    {
        $data = [
            'slug' => $offer->slug,
            'name' => $offer->name,
            'derivative' => $offer->derivative,
            'make' => $offer->make?->name,
            'model' => $offer->model?->name,
            'image' => $this->getPreviewImage($offer, 'medium'),
            'image_sizes' => !empty($offer->primaryMediaUse)
                ? $this->allSizesForUse($offer, $offer->primaryMediaUse)
                : [],
            'images' => [
                [
                    'id' => $offer->primaryMediaUse?->id,
                    'title' => $offer->primaryMediaUse?->title,
                    'alt_text' => $offer->primaryMediaUse?->alt_text,
                    'description' => $offer->primaryMediaUse?->description,
                    'caption' => $offer->primaryMediaUse?->caption,
                    'interior' => $offer->primaryMediaUse?->interior,
                    'exterior' => $offer->primaryMediaUse?->exterior,
                    'hex1' => $offer->primaryMediaUse?->media?->hex1,
                    'hex2' => $offer->primaryMediaUse?->media?->hex2,
                    'type' => $offer->primaryMediaUse?->media->type,
                    'src' => $offer->primaryMediaUse?->media->getOriginalUrlAttribute(),
                    'sizes' => $offer->primaryMediaUse
                        ? $this->allSizesForUse($offer, $offer->primaryMediaUse)
                        : [],
                ]
            ],
            'price' => $offer->price,
            'excerpt' => $offer->excerpt,
            'label' => $offer->label,
            'deposit' => $offer->deposit,
            'offer_section_url' => $offer->make?->slug . '/' . $offer->model?->slug,
            'offer_type_slug' => $offer->offerType?->slug,
            'transmission_type' => $offer->transmission?->name,
            'mpg' => $offer->mpg,
            'apr' => $offer->cheapestFinance?->apr,
            'monthly_price' => $offer->cheapestFinance?->monthly_price,
            'monthly_price_type' => $offer->cheapestFinance?->finance_type,
            'finance_example' => $offer->cheapestFinance,
            'dealership' => $this->getDealership($offer),
            'type' => $offer->new_car_type,
            'body_type' => $offer->bodyStyle?->name,
            'cta_button1_label' => $offer->cta_button1_label,
            'cta_button1_url' => $offer->cta_button1_url,
            'cta_button2_label' => $offer->cta_button2_label,
            'cta_button2_url' => $offer->cta_button2_url,
            'footnote' => $offer->footnote,
            'finance' => $offer->finance,
            'colour' => $offer->colour,
            'trim' => $offer->trim,
            'extra' => $this->getExtraData($offer),
        ];
        if (Settings::get('offer-list-load-features')) {
            $data['features'] = $offer->features->pluck('name');
        }

        if (Settings::get('offers-multiple-fuel-types')) {
            $data['fuel_type'] = $offer->fuelTypes->pluck('name');
        } else {
            $data['fuel_type'] = $offer->fuelType?->name;
        }

        if (in_array('form', $request->input('with', []))) {
            $data['form'] = (new FormViewResource($offer->form))->setValues(['offer_id' => $offer->id]);
        }
        return $data;
    }


    private function placeholder(VehicleOffer $offer)
    {
        return $this->advancedPlaceholderImageThumbnail('offer', $offer);
    }

    private function trackViews(): void
    {
        /** @var Collection $ids */
        $ids = $this->resource->pluck('id');
        $existing = OfferView::query()
            ->whereIn('offer_id', $ids)
            ->where('date', Carbon::now()->format('Y-m-d'))
            ->pluck('offer_id');

        $missing = $ids->reject(fn($id) => $existing->search($id));

        if ($missing->isNotEmpty()) {
            $data = $missing->map(fn($id) => [
                'offer_id' => $id,
                'hits' => 0,
                'filter_views' => 1,
                'date' => Carbon::now()->format('Y-m-d'),
            ]);
            OfferView::query()->upsert($data->toArray(), ['offer_id', 'date']);
        }

        OfferView::query()
            ->whereIn('offer_id', $existing)
            ->increment('filter_views');
    }

    private function getDealership(VehicleOffer $offer)
    {
        if (empty($offer->dealership)) {
            return null;
        }

        $dealership = $offer->dealership->only([
            'contact_no',
            'email',
            'name',
            'slug',
        ]);

        return $dealership;
    }

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

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

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