<?php

namespace App\Http\Controllers;

use App\Facades\OfferFilter;
use App\Facades\Settings;
use App\Filter;
use App\Http\Requests\OfferSearchRequest;
use App\Http\Requests\ViewOfferRequest;
use App\Http\Resources\MakeListResource;
use App\Http\Resources\OfferListResource;
use App\Http\Resources\OfferResource;
use App\Http\Resources\PageResource;
use App\Traits\ModelsForMakeInSearch;
use Mtc\MercuryDataModels\Jobs\TrackResourceView;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\OfferType;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;

class OfferController extends Controller
{
    use ModelsForMakeInSearch;

    public function index(OfferSearchRequest $request): array
    {
        $page = Page::query()->where('slug', $request->input('page_slug', 'offers'))->first();
        $featured = VehicleOffer::query()->active()
            ->withListingRelationships()
            ->where('featured', 1)
            ->get();

        $makes = VehicleMake::query()
            ->whereHas('offers', fn ($query) => $query->active())
            ->get();

        $models = VehicleModel::query()
            ->whereHas('cheapestActiveOffer')
            ->with([
                'cheapestActiveOffer.primaryMediaUse.media',
                'cheapestActiveOffer.make',
                'cheapestActiveOffer.offerType',
                'cheapestActiveOffer.bodyStyle',
                'cheapestActiveOffer.model',
                'make',
                'cheapestActiveOffer.make',
                'cheapestActiveOffer.franchise',
                'cheapestActiveOffer.model',
                'cheapestActiveOffer.fuelType',
                'cheapestActiveOffer.transmission',
                'cheapestActiveOffer.drivetrain',
                'cheapestActiveOffer.bodyStyle',
            ])
            ->when(
                Settings::get('offer-list-load-features'),
                fn($query) => $query->with('cheapestActiveOffer.features')
            )
            ->when(
                in_array('form', $request->input('with', [])),
                fn($query) => $query->with('cheapestActiveOffer.form')
            )
            ->when($request->filled('offer_type'), fn($query) => $query
                ->whereHas(
                    'cheapestActiveOffer.offerType',
                    fn($typeQuery) => $typeQuery->where('slug', $request->input('offer_type'))
                ))
            ->get()
            ->groupBy(fn ($model) => $model->make?->slug)
            ->map(fn ($group) => new OfferListResource($group->map(fn ($model) => $model->cheapestActiveOffer)));

        return [
            'page' => new PageResource($page),
            'featured' => new OfferListResource($featured),
            'makes' => new MakeListResource($makes),
            'models' => $models,
            'types' => OfferType::query()->orderBy('name')->get(),
        ];
    }

    public function search(OfferSearchRequest $request, string $make): array
    {
        $makeModel = $make !== 'all'
            ? VehicleMake::query()->where('slug', $make)->firstOrFail()
            : null;
        $vehicleModel = null;
        if ($request->filled('model_id')) {
            $vehicleModel = $request->input('loose_model_match')
                ? VehicleModel::query()->where('slug', 'like', $request->input('model_id') . '%')->firstOrFail()
                : VehicleModel::query()->where('slug', $request->input('model_id'))->firstOrFail();
        }
        $makeId = $makeModel?->id;

        $offers = VehicleOffer::query()
            ->with([
                'primaryMediaUse.media',
                'make',
                'model',
                'offerType',
                'franchise',
                'fuelType',
                'bodyStyle',
                'transmission',
                'cheapestFinance',
                'dealership',
            ])
            ->when(
                in_array('form', $request->input('with', [])),
                fn($query) => $query->with('form')
            )
            ->when(
                $request->filled('vehicle_type'),
                fn($query) => $query->where('vehicle_type', $request->input('vehicle_type'))
            )
            ->when($request->filled('offer_type'), fn($query) => $query
                ->whereHas('offerType', fn($typeQuery) => $typeQuery->where('slug', $request->input('offer_type'))
                    ->orWhereHas('parent', fn($childQuery) => $childQuery
                        ->where('slug', $request->input('offer_type')))))
            ->when($make != 'all', fn($query) => $query->where('make_id', $makeId))
            ->when(
                $request->filled('model_id'),
                fn($query) => $query->when(
                    $request->input('loose_model_match'),
                    fn($query) => $query->whereHas(
                        'model',
                        fn ($modelQuery) => $modelQuery->where('slug', 'like', $request->input('model_id') . '%')
                    ),
                    fn($query) => $query->whereHas(
                        'model',
                        fn ($modelQuery) => $modelQuery->where('slug', $request->input('model_id'))
                    ),
                )
            )
            ->when(
                $request->filled('body_type'),
                fn($query) => $query->whereHas(
                    'bodyStyle',
                    fn($query) => $query->whereIn('slug', (array) $request->input('body_type'))
                )
            )
            ->setSortBy($request->input('sort_by'))
            ->active()
            ->paginate($request->input('per_page', 15));

        return [
            'make' => $makeModel?->name ?? '',
            'model' => $vehicleModel?->name,
            'models' => $this->getModelsForMake(
                $makeId,
                'offers',
                $request->input('offer_type'),
                $request->input('vehicle_type'),
            ),
            'offers' => new OfferListResource($offers),
        ];
    }

    public function searchWithFilters()
    {
        return OfferFilter::handle();
    }

    public function show(ViewOfferRequest $request): OfferResource
    {
        $vehicleOffer = $request->getOffer();
        if (!$vehicleOffer) {
            abort(404);
        }

        $vehicleOffer->load([
            'fuelType',
            'offerType',
            'transmission',
            'drivetrain',
            'bodyStyle',
            'dealership',
        ]);

        TrackResourceView::trackHit($vehicleOffer);

        return new OfferResource($vehicleOffer);
    }
}
