<?php

namespace App\Http\Resources;

use App\Facades\Feature;
use App\Facades\Settings;
use App\Facades\Site;
use App\IntegrationRepository;
use App\Modules\Stock\AutoTraderStock;
use App\OfferRepository;
use App\Services\RemoveBg;
use App\TierHelper;
use App\Traits\MakeAndModelList;
use App\VehicleType;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\App;
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\NewCar;
use Mtc\MercuryDataModels\OfferType;
use Mtc\MercuryDataModels\Traits\HasVehicleCustomAttributes;
use Mtc\MercuryDataModels\TransmissionType;
use Mtc\MercuryDataModels\VehicleTrim;
use App\Http\Resources\Traits\TransformsImageAttributesForAdmin;

class VehicleOfferViewResource 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.globalContent.contentElement.fields',
            'content.contentElement.fields',
            'content.subContent.contentElement.fields',
            'content.subContent.subContent.contentElement.fields',
            'content.subContent.subContent.subContent.contentElement.fields',
            'mediaUses.media',
            'finance',
            'features',
            'equipment',
            'specs',
        ]);

        $this->resource->choose_new_car = Settings::get('offers-link-with-new-car');
        $this->resource->choose_trim = Settings::get('offers-link-with-trim');
        $offer = $this->resource->toArray();
        $offer['multiple_fuel_types'] = Settings::get('offers-multiple-fuel-types');
        if ($offer['multiple_fuel_types']) {
            $offer['fuel_type_id'] = $this->resource->fuelTypes()->pluck('fuel_type_id');
        }
        $offer['dealership_name'] = $this->resource->dealership?->name;
        $offer['franchise_name'] = $this->resource->franchise?->name;
        $offer = array_merge($offer, $this->getMediaEntries());
        $offer['seo'] = $this->getSeoData($this->resource);
        $offer['finance'] = $this->resource->finance;
        $offer['stats'] = $this->getStats();
        $offer['structure_in_sync'] = $this->offerRepository()->isContentOutOfSync($this->resource) !== true;
        $offer['content'] = $this->resource->content
            ->filter(fn ($content) => !empty($content->slug))
            ->map(fn ($content) => $this->mapContent($content))
            ->values();
        $offer['site_url'] = Site::offerUrl($this->resource, true);
        $offer['versions'] = $this->getVersioningData();
        $offer['extra'] = $this->transformImageAttributesForAdmin(
            $this->getExtraData($this->resource)->toArray()
        );

        return [
            'offer' => $offer,
            'makes' => $this->getMakeList($this->resource->vehicle_type),
            'models' => $this->getModelList($this->resource->make_id, $this->resource->vehicle_type),
            'trims' => $this->getTrimList(),
            'new_cars' => $this->getNewCarList(),
            'forms' => Form::query()->select('name', 'id')->where('is_active', 1)->get(),
            'offerTypes' => OfferType::query()->select('name', 'id', 'template_id', 'slug')->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'),
                'show_ai_button' => new IntegrationRepository()->getEnabledForType('ai-content')->isNotEmpty(),
                'show_remove_background_button' => RemoveBg::enabled(),
                'show_cap_id_field' => (Settings::get('app-details-country') ?? config('app.default_country')) === 'GB',
                'cap_integration_enabled' => (bool) Settings::get('vehicle-spec-providers-cap-enabled'),
                'show_auto_trader_id_field' => App::make(AutoTraderStock::class)->enabled(),
                'custom_finance_enabled' => Feature::isEnabled('offer-custom-finance'),
                'show_priority_weight_field' => (bool) Settings::get('automotive-srp-vehicle-offers-enabled'),
            ],
            'vehicle_types' => collect(VehicleType::cases())
                ->map(fn (VehicleType $value) => [
                    'id' => $value->value,
                    'name' => $value->name,
                ]),
        ];
    }

    private function getStats(): array
    {
        $views = $this->resource->views()
            ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
            ->orderBy('date')
            ->get();

        $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(),
            'views_today' => $views
                    ->where('date', Carbon::now()->format('Y-m-d'))
                    ->pluck('hits')
                    ->first() ?? 0,
            'views_week' => $views
                    ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
                    ->sum('hits') ?? 0,
            'views_month' => $views
                    ->where('date', '>=', Carbon::now()->subMonth()->format('Y-m-d'))
                    ->sum('hits') ?? 0,
            'graph' => [
                'labels' => $views->pluck('date')->unique()->map(fn ($date) => Carbon::parse($date)->format('dS M')),
                'datasets' => [
                    [
                        'label' => 'Full page ad views',
                        'backgroundColor' => '#600000',
                        'data' => $views->pluck('hits'),
                        'tension' => 0.5
                    ],
                    [
                        'label' => 'Views in search results',
                        'backgroundColor' => '#000060',
                        'data' => $views->pluck('filter_views'),
                        'tension' => 0.5
                    ],
                ]
            ],
            '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 offerRepository(): OfferRepository
    {
        return App::make(OfferRepository::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();
    }


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

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

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

    private function getNewCarList(): Collection
    {
        if (!$this->resource->choose_new_car) {
            return collect();
        }

        return NewCar::query()
            ->select('name', 'id')
            ->when($this->resource->make_id, fn ($query) => $query->where('make_id', $this->resource->make_id))
            ->when($this->resource->model_id, fn ($query) => $query->where('model_id', $this->resource->model_id))
            ->get();
    }

    private function getTrimList(): Collection
    {
        if (!$this->resource->choose_trim) {
            return collect();
        }

        return VehicleTrim::query()
            ->select('name', 'id')
            ->when($this->resource->make_id, fn ($query) => $query->where('make_id', $this->resource->make_id))
            ->when($this->resource->model_id, fn ($query) => $query->where('model_id', $this->resource->model_id))
            ->get();
    }
}
