<?php

namespace App\Http\Controllers;

use App\Facades\Settings;
use App\Facades\Site;
use App\Http\Requests\VehicleComparisonMailRequest;
use Illuminate\Support\Facades\Log;
use Mtc\Filter\Facades\Filter;
use App\Http\Requests\ViewVehicleRequest;
use App\Http\Resources\VehicleQuickViewResource;
use App\Http\Resources\VehicleResource;
use App\Traits\CacheObject;
use App\VehicleRepository;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\Jobs\TrackResourceView;
use Mtc\MercuryDataModels\Jobs\VehicleComparisonMailRequest as VehicleComparisonMailJob;
use App\Repositories\RecentlyViewed;
use Illuminate\Http\Request;

class VehicleController extends Controller
{
    use CacheObject;

    /**
     * Show vehicle FPA details
     *
     * @param Vehicle $vehicle
     * @return array
     */
    public function show(
        ViewVehicleRequest $request,
        Vehicle $vehicle,
        RecentlyViewed $recentlyViewed,
        VehicleRepository $repository
    ) {
        TrackResourceView::trackHit($vehicle);
        $recentlyViewed->add('vehicles', $vehicle->id);
        return $this->cache('vehicle-show-' . $vehicle->id, 2, function () use ($vehicle) {
            $crossSell = [];
            if (
                Settings::get('vehicles-cross-sell-enabled')
                && in_array(Settings::get('vehicles-cross-sell-location', ''), ['all', 'fpa'])
            ) {
                $crossSell = [
                    'name' => __('automotive.cross-sell.similar'),
                    'items' => new VehicleRepository()->similar(
                        $vehicle,
                        4,
                        Settings::get('vehicles-cross-sell-type')
                    ),
                ];
            }
            return [
                'data' => new VehicleResource($vehicle),
                'cross_sell' => $crossSell,
            ];
        });
    }

    public function quickView(
        ViewVehicleRequest $request,
        Vehicle $vehicle,
        VehicleRepository $repository
    ) {
        TrackResourceView::trackQuickView($vehicle);
        return [
            'data' => new VehicleQuickViewResource($vehicle),
        ];
    }

    /**
     * Get list of vehicles for compare
     *
     * @param Request $request
     * @param VehicleRepository $repository
     * @return array
     */
    public function compare(Request $request, VehicleRepository $repository): array
    {
        $vehicleSlugs = $request->input('slugs') ?? [];

        return [
            'data' => $repository->compare($vehicleSlugs),
        ];
    }

    /**
     * Get list of recently viewed vehicles
     *
     * @param string $vehicle
     * @param Request $request
     * @return array
     */
    public function recentlyViewed(string $vehicle, Request $request): array
    {
        $vehicleModel = Vehicle::query()->where('slug', $vehicle)->first();
        $vehicleSlugs = $request->input('slugs') ?? [];
        $limit = $request->input('limit', 4);

        return [
            'recently_viewed' => [
                'name' => __('automotive.recently_viewed'),
                'items' => new VehicleRepository()->recentlyViewed($vehicleModel, $vehicleSlugs, $limit),
            ]
        ];
    }

    /**
     * Get list of recently added vehicles
     *
     * @param Request $request
     * @return array
     */
    public function recentlyAdded(Request $request): array
    {
        $limit = $request->input('limit') ?? 4;
        $is_new = $request->input('is_new');

        $results = new VehicleRepository()->recentlyAdded(
            $limit,
            array_merge($request->input(), [
                'is_new' => $is_new
            ])
        );

        return [
            'recently_added' => [
                'name' => __('automotive.recently_added'),
                'items' => $results,
            ],
            'finance_example' => Filter::getRepresentativeFinance($results)
        ];
    }

    /**
     * Get list of featured vehicles
     *
     * @param Request $request
     * @param Vehicle $vehicle
     * @param VehicleRepository $repository
     * @return array
     */
    public function featured(Request $request, Vehicle $vehicle, VehicleRepository $repository): array
    {
        return [
            'name' => __('automotive.cross-sell.featured'),
            'items' => $repository
                ->featured(
                    !empty($vehicle->id) ? $vehicle : null,
                    $request->input('limit') ?? 4,
                    $request->input()
                )
                ->toArray($request),
        ];
    }

    /**
     * Get list of similar vehicles
     *
     * @param Request $request
     * @param Vehicle $vehicle
     * @param VehicleRepository $repository
     * @return array
     */
    public function similar(Request $request, Vehicle $vehicle, VehicleRepository $repository): array
    {
        return [
            'name' => __('automotive.cross-sell.similar'),
            'items' => $repository
                ->similar(
                    $vehicle,
                    $request->input('limit') ?? 4,
                    Settings::get('vehicles-cross-sell-type')
                )
                ->toArray($request),
        ];
    }

    /**
     * Get shuffled list of vehicles based on request input.
     *
     * @param Request $request
     * @param Vehicle $vehicle
     * @param VehicleRepository $repository
     * @return array
     */
    public function promoted(Request $request, Vehicle $vehicle, VehicleRepository $repository): array
    {
        try {
            $results = [
                'name' => __('automotive.cross-sell.promoted'),
                'items' => [],
            ];

            if ($request->has('types') && is_array($request->input('types'))) {
                $results['items'] = collect($request->input('types'))
                    ->mapWithKeys(function ($type) use ($request, $vehicle, $repository) {
                        $items = (match ($type) {
                            'featured' => $this->featured($request, $vehicle, $repository)['items'] ?? [],
                            'recently-viewed' =>
                                $this->recentlyViewed($vehicle, $request)['recently_viewed']['items'] ?? [],
                            'recently-added' => $this->recentlyAdded($request)['recently_added']['items'] ?? [],
                            'similar' => $this->similar($request, $vehicle, $repository)['items'] ?? [],
                            default => [],
                        });

                        return collect($items)->mapWithKeys(fn($item) => [$item['slug'] => $item]);
                    })->toArray();
            }

            // Shuffle the results.
            // Results will be limited, and we don't want to e.g. return all recently viewed but no featured vehicles.
            shuffle($results['items']);

            $results['items'] = array_slice(
                collect($results['items'])->unique('slug')->toArray(),
                0,
                $request->input('limit') ?? 4,
            );

            return $results;
        } catch (\Exception $exception) {
            Log::error('Failed to get promoted vehicles', [
                'error message' => $exception->getMessage(),
                'promotion types' => $request->input('types') ?? null,
            ]);
        }

        return [
            'name' => __('automotive.cross-sell.promoted'),
            'items' => [],
        ];
    }

    public function topTaxonomies(Request $request, VehicleRepository $repository): array
    {
        $limit = $request->input('limit');
        $split_new_used = (bool)$request->input('split_new_used', false);
        return collect($request->input('taxonomies', []))
            ->keyBy(fn($taxonomy) => $taxonomy)
            ->map(fn($taxonomy) => $this->cache("top-$taxonomy", 5, fn() => match ($taxonomy) {
                'makes' => $repository->topMakes($limit, $split_new_used),
                'body_types' => $repository->topBodyTypes($limit, $split_new_used),
                'fuel_types' => $repository->topFuelTypes($limit, $split_new_used),
                default => []
            }))
            ->filter()
            ->toArray();
    }

    public function compareMail(VehicleComparisonMailRequest $request)
    {
        $this->dispatch(new VehicleComparisonMailJob(
            $request->input('email'),
            $request->input('slugs'),
            Site::vehicleComparisonUrl($request->input('slugs')),
        ));

        return response([
            'success' => true,
        ]);
    }
}
