<?php

namespace App\Http\Controllers;

use App\Http\Requests\CopyNewCarRequest;
use App\Http\Requests\SelectionSearchSearchRequest;
use App\Http\Requests\StoreNewCarRequest;
use App\Http\Requests\UpdateNewCarRequest;
use App\Http\Resources\NewCarListResource;
use App\Http\Resources\NewCarViewResource;
use App\NewCarRepository;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Mtc\MercuryDataModels\NewCar;
use Mtc\MercuryDataModels\NewCarContentHistory;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\VehicleLookup\VehicleLookupService;

class NewCarController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(SelectionSearchSearchRequest $request): NewCarListResource
    {
        $perPage = min((int)$request->input('per_page', 15), 200);

        $cars = NewCar::query()
            ->with([
                'make',
                'model',
                'mediaUses.media',
            ])
            ->withImageCount()
            ->withEnquiryCount()
            ->setSortBy($request->input('sort_by', 'id_desc'))
            ->setFilters($request->input('filters') ?? '')
            ->when($request->filled('selections'), fn ($query) => $query->setSelections($request->getSelections()))
            ->when(
                $request->filled('search_term'),
                fn ($query) => $query->where(
                    fn ($q) => $q->whereFullText('search_content', $request->input('search_term'))
                        ->orWhere('slug', 'like', $request->input('search_term') . '%')
                )
            );

        if ($request->withArchived()) {
            $cars = $cars->withTrashed();
        }

        return new NewCarListResource($cars->paginate($perPage));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(
        StoreNewCarRequest $request,
        VehicleLookupService $lookupService,
        NewCarRepository $repository
    ) {
        $car = NewCar::query()
            ->create($request->validated());
        if (empty($car->vehicle_type)) {
            $modelType = VehicleModel::query()->find($request->input('model_id'))?->type;
            $car->update([
                'vehicle_type' => $modelType ? explode('-', $modelType)[0] : null
            ]);
        }

        if ($request->filled('variant')) {
            $column = match ($request->input('variant_type')) {
                'cap' => 'cap_id',
                'auto-trader' => 'auto_trader_id',
                'motor-check' => 'motor_check_id',
                default => null,
            };
            if (!empty($column)) {
                $variant = $request->input('variant');
                if ($lookupService->hasActiveDriver()) {
                    $carData = $repository->mapTechnicalData($lookupService->getTechnicalData($variant));
                    $carData[$column] = $variant;
                    $carData['make_id'] = $request->input('make_id');
                    $carData['model_id'] = $request->input('model_id');

                    $car->fill($carData);
                    $car->save();
                    $repository->storeUnmappedTaxonomy($car);

                    if (!empty($carData['fuel_type'])) {
                        $car->fuelTypes()->sync($carData['fuel_type']);
                    }
                }
            }
        }

        return new NewCarViewResource($car->refresh());
    }

    /**
     * Display the specified resource.
     */
    public function show(int $id): NewCarViewResource
    {
        $newCar = NewCar::query()->withTrashed()->findOrFail($id);
        return new NewCarViewResource($newCar);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(
        UpdateNewCarRequest $request,
        NewCar $newCar,
        NewCarRepository $repository
    ): NewCarViewResource {
        if ($request->has('trims')) {
            $repository->saveTrims($newCar, $request->input('trims'));
        }
        $repository->save($newCar, $request, Auth::id());
        return new NewCarViewResource($newCar);
    }

    /**
     * Copy the specified resource in storage.
     */
    public function copy(
        CopyNewCarRequest $request,
        NewCar $newCar,
        NewCarRepository $repository
    ): NewCarViewResource {
        $copy = $repository->copy($newCar, $request);
        return new NewCarViewResource($copy);
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(NewCar $newCar)
    {
        return $newCar->delete();
    }

    /**
     * Sync offer content with template
     *
     * @param int $carId
     * @param NewCarRepository $repository
     * @return NewCarViewResource|array
     */
    public function syncWithTemplate(int $carId, NewCarRepository $repository): NewCarViewResource|array
    {
        try {
            $repository->syncContentWithTemplate($carId);
            $car = NewCar::query()->find($carId);
        } catch (\Exception $exception) {
            Log::error('Failed to sync offer structure ', [
                'page_id' => $carId,
                'error' => $exception->getMessage(),
                'tenant' => tenant('id'),
            ]);
            return [
                'success' => false,
                'error' => $exception->getMessage(),
            ];
        }

        return new NewCarViewResource($car);
    }

    public function restore(int $new_car_id, NewCarRepository $repository): Response
    {
        $repository->restore($new_car_id);
        return \response('ok');
    }

    public function restoreVersion(
        NewCar $newCar,
        NewCarContentHistory $version,
        NewCarRepository $repository
    ): NewCarViewResource {
        $repository->restoreVersion($newCar, $version);
        $newCar->refresh();
        return new NewCarViewResource($newCar);
    }

    public function saveOrder(Request $request, NewCarRepository $repository)
    {
        $repository->updateOrder(collect($request->input())->pluck('id')->all());
        return response('ok');
    }
}
