<?php

namespace Tests\Tenant;

use App\Facades\Feature;
use App\Facades\Settings;
use App\Facades\Site;
use App\Http\Resources\VehicleResource;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;
use Mtc\Crm\Models\EnquiryType;
use Mtc\Crm\Models\FormQuestion;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Jobs\TrackResourceView;
use Mtc\MercuryDataModels\Jobs\VehicleComparisonMailRequest;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\MediaUse;
use Mtc\MercuryDataModels\SeoDefault;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleAttributeValue;
use Mtc\MercuryDataModels\VehicleAutoTraderData;
use Mtc\MercuryDataModels\VehicleFinance;
use Mtc\MercuryDataModels\VehicleLabel;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleStandardEquipment;
use Mtc\MercuryDataModels\ResourceView;
use Tests\FilterSettingSeed;
use Tests\TenantTestCase;

class VehicleControllerTest extends TenantTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        Queue::fake();
    }

    public function testFilterLoads()
    {
        Vehicle::factory(10)->create([
            'is_published' => true,
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('sort_options', $response->json());
        $this->assertArrayHasKey('results', $response->json());
        $this->assertArrayHasKey('filters', $response->json());
        $this->assertEquals(10, $response->json('results.total'));
    }

    public function testViewSingleVehicle()
    {
        Http::fake([
            'https://cdn.imagin.studio/getPaints*' => Http::response(['paintData' => ['paintCombinations' => []]])
        ]);
        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'app-content-car-and-driving-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-location',
            'value' => true,
            'type' => 'boolean',
        ]);


        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);
        SeoDefault::query()->create([
            'section' => 'vehicle',
            'title' => '{{TITLE}} | {{MAKE}} Offers | {{SITE_NAME}} ',
            'description' => '{{CONTENT_EXCERPT}}',
        ]);
        $dealership = Dealership::factory()->create();
        $bodystyle = BodyStyleType::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
            'body_style_id' => $bodystyle->id,
            'is_new' => false,
        ]);
        $vehicle->original_price = 123123;
        $vehicle->rrp_price = 456456;
        $vehicle->save();

        VehicleStandardEquipment::factory()->create([
            'price' => 0,
            'vat_amount' => 0,
            'vehicle_id' => $vehicle->id,
            'vehicle_type' => 'vehicle'
        ]);

        VehicleStandardEquipment::factory()->create([
            'price' => 0,
            'vat_amount' => 0,
            'vehicle_id' => $vehicle->id,
            'vehicle_type' => 'vehicle'
        ]);

        VehicleStandardEquipment::factory()->create([
            'price' => 100,
            'vat_amount' => 83.34,
            'vehicle_id' => $vehicle->id,
            'vehicle_type' => 'vehicle'
        ]);

        VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'finance_type' => 'HP',
            'cash_price' => 20000,
            'total_deposit' => 3000,
            'payable_amount' => 25000,
            'total_credit_amount' => 17000,
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('age_identifier', $response->json('data'));
        $this->assertArrayHasKey('battery_capacity_kwh', $response->json('data'));
        $this->assertArrayHasKey('battery_charge_time', $response->json('data'));
        $this->assertArrayHasKey('battery_quick_charge_time', $response->json('data'));
        $this->assertArrayHasKey('battery_range', $response->json('data'));
        $this->assertArrayHasKey('battery_usable_capacity_kwh', $response->json('data'));
        $this->assertArrayHasKey('bhp', $response->json('data'));
        $this->assertArrayHasKey('bodyStyle', $response->json('data'));
        $this->assertArrayHasKey('co2', $response->json('data'));
        $this->assertArrayHasKey('colour', $response->json('data'));
        $this->assertArrayHasKey('content', $response->json('data'));
        $this->assertArrayHasKey('dealership', $response->json('data'));
        $this->assertArrayHasKey('derivative', $response->json('data'));
        $this->assertArrayHasKey('door_count', $response->json('data'));
        $this->assertArrayHasKey('drivetrain', $response->json('data'));
        $this->assertArrayHasKey('engine_size_cc', $response->json('data'));
        $this->assertArrayHasKey('equipment', $response->json('data'));
        $this->assertArrayHasKey('features', $response->json('data'));
        $this->assertArrayHasKey('financeExamples', $response->json('data'));
        $this->assertArrayHasKey('fuel_type', $response->json('data'));
        $this->assertArrayHasKey('gross_vehicle_weight_kg', $response->json('data'));
        $this->assertArrayHasKey('is_vat_applicable', $response->json('data'));
        $this->assertArrayHasKey('main_video_url', $response->json('data'));
        $this->assertArrayHasKey('make', $response->json('data'));
        $this->assertArrayHasKey('manufacture_year', $response->json('data'));
        $this->assertArrayHasKey('model', $response->json('data'));
        $this->assertArrayHasKey('mpg', $response->json('data'));
        $this->assertArrayHasKey('odometer_km', $response->json('data'));
        $this->assertArrayHasKey('odometer_mi', $response->json('data'));
        $this->assertArrayHasKey('original_price', $response->json('data'));
        $this->assertArrayHasKey('payload_kg', $response->json('data'));
        $this->assertArrayHasKey('price', $response->json('data'));
        $this->assertArrayHasKey('registration_number', $response->json('data'));
        $this->assertArrayHasKey('rrp_price', $response->json('data'));
        $this->assertArrayHasKey('seats', $response->json('data'));
        $this->assertArrayHasKey('specs', $response->json('data'));
        $this->assertArrayHasKey('title', $response->json('data'));
        $this->assertArrayHasKey('transmission', $response->json('data'));
        $this->assertArrayHasKey('type', $response->json('data'));
        $this->assertArrayHasKey('wheelbase_mm', $response->json('data'));
        $this->assertArrayHasKey('wheelbase_type', $response->json('data'));
        $this->assertArrayHasKey('is_new', $response->json('data'));

        $this->assertNotNull($response->json('data.age_identifier'));
        $this->assertNotNull($response->json('data.battery_capacity_kwh'));
        $this->assertNotNull($response->json('data.battery_quick_charge_time'));
        $this->assertNotNull($response->json('data.battery_range'));
        $this->assertNotNull($response->json('data.bodyStyle'));
        $this->assertNotNull($response->json('data.co2'));
        $this->assertNotNull($response->json('data.colour'));
        $this->assertNotNull($response->json('data.content'));
        $this->assertNotNull($response->json('data.dealership'));
        $this->assertNotNull($response->json('data.derivative'));
        $this->assertNotNull($response->json('data.door_count'));
        $this->assertNotNull($response->json('data.drivetrain'));
        $this->assertNotNull($response->json('data.engine_size_cc'));
        $this->assertNotNull($response->json('data.equipment'));
        $this->assertNotNull($response->json('data.features'));
        $this->assertNotNull($response->json('data.financeExamples'));
        $this->assertNotNull($response->json('data.fuel_type'));
        $this->assertNotNull($response->json('data.main_video_url'));
        $this->assertNotNull($response->json('data.make'));
        $this->assertNotNull($response->json('data.manufacture_year'));
        $this->assertNotNull($response->json('data.model'));
        $this->assertNotNull($response->json('data.mpg'));
        $this->assertNotNull($response->json('data.odometer_km'));
        $this->assertNotNull($response->json('data.odometer_mi'));
        $this->assertNotNull($response->json('data.original_price'));
        $this->assertNotNull($response->json('data.price'));
        $this->assertNotNull($response->json('data.registration_number'));
        $this->assertNotNull($response->json('data.rrp_price'));
        $this->assertNotNull($response->json('data.seats'));
        $this->assertNotNull($response->json('data.specs'));
        $this->assertNotNull($response->json('data.title'));
        $this->assertNotNull($response->json('data.transmission'));
        $this->assertNotNull($response->json('data.type'));
        $this->assertNotNull($response->json('data.is_new'));

        $this->assertArrayHasKey('extra', $response->json('data'));

        $this->assertArrayHasKey('saving_total', $response->json('data.extra'));

        $this->assertCount(3, $response->json('data.equipment'));

        $this->assertArrayHasKey('reviews', $response->json('data'));
        $this->assertArrayHasKey('car_and_driving', $response->json('data.reviews'));
        $this->assertArrayHasKey('review', $response->json('data.reviews.car_and_driving'));

        $this->assertEquals(17000, $response->json('data.financeExamples.HP.total_credit_amount'));
    }

    public function testPvEmptyPriceWithSavings()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-type',
            'value' => 'peter-vardy',
            'type' => 'string',
        ]);

        $dealership = Dealership::factory()->create([
            'location_stock' => 'foo',
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership->id,
            'slug' => 'foo-baz-bar',
            'price' => null,
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
    }

    public function testQuickViewVehicle()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        SeoDefault::query()->create([
            'section' => 'vehicle',
            'title' => '{{TITLE}} | {{MAKE}} Offers | {{SITE_NAME}} ',
            'description' => '{{CONTENT_EXCERPT}}',
        ]);
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'General',
            'name' => 'Load finance example for vehicle listing',
            'config_key' => 'vehicle-list-load-finance-example',
            'type' => 'boolean',
            'value' => true,
            'superadmin' => true,
            'min_tier' => 'standard',
            'description' => 'Enable loading finance example for lists of vehicles, such as search result page.<br/>',
            'order' => 0,
        ]);
        VehicleFinance::factory()->create(['vehicle_id' => $vehicle->id]);

        $response = $this
            ->getJson(route('vehicles.quick-view', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('title', $response->json('data'));
        $this->assertArrayHasKey('price', $response->json('data'));
        $this->assertArrayHasKey('actions', $response->json('data'));
        $this->assertArrayHasKey('odometer_mi', $response->json('data'));
        $this->assertArrayHasKey('odometer_km', $response->json('data'));
        $this->assertArrayHasKey('fuel_type', $response->json('data'));
        $this->assertArrayHasKey('transmission', $response->json('data'));

        $this->assertArrayHasKey('finance_example', $response->json('data'));
        $this->assertArrayHasKey('monthly_price', $response->json('data.finance_example'));
        $this->assertArrayHasKey('apr', $response->json('data.finance_example'));
        $this->assertArrayHasKey('term', $response->json('data.finance_example'));
        $this->assertArrayHasKey('annual_mileage', $response->json('data.finance_example'));
        $this->assertArrayHasKey('cash_price', $response->json('data.finance_example'));
        $this->assertArrayHasKey('dealer_deposit', $response->json('data.finance_example'));
        $this->assertArrayHasKey('customer_deposit', $response->json('data.finance_example'));
        $this->assertArrayHasKey('total_deposit', $response->json('data.finance_example'));
        $this->assertArrayHasKey('payable_amount', $response->json('data.finance_example'));
        $this->assertArrayHasKey('option_to_purchase_fee', $response->json('data.finance_example'));
        $this->assertArrayHasKey('documentation_fee', $response->json('data.finance_example'));

        Queue::assertPushed(TrackResourceView::class);
    }

    public function testFeaturedVehicleList()
    {
        $dealership = Dealership::factory()->create();
        Vehicle::factory(3)->create([
            'is_published' => true,
            'featured' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'featured' => false,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        $response = $this
            ->getJson(route('vehicles.featured'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());
        $this->assertCount(3, $response->json('items'));
    }

    public function testPromotedVehiclesListFeatured()
    {
        $dealership = Dealership::factory()->create();
        Vehicle::factory(3)->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
        ]);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
        ]);
        $response = $this
            ->getJson(route('vehicles.promoted', [
                'types' => [
                    'featured',
                ],
                'limit' => 10,
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());

        // assert that we only receive the featured vehicles
        $this->assertCount(3, $response->json('items'));
    }

    public function testPromotedVehiclesListFeaturedAndRecentlyViewed()
    {
        $dealership = Dealership::factory()->create();

        $vehicle_featured_1 = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
        ]);

        $vehicle_featured_2 = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
        ]);

        $vehicle_recent = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
        ]);

        $response = $this
            ->getJson(route('vehicles.promoted', [
                'types' => [
                    'featured',
                    'recently-viewed',
                ],
                'slugs' => [
                    $vehicle_featured_1->slug,
                    $vehicle_recent->slug,
                ]
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());

        // We have two featured vehicles and two recently viewed vehicles.
        // One of the recently viewed vehicles is a featured vehicle.
        // We don't want to retrieve the viewed featured vehicle twice.
        $slugs = collect($response->json('items'))->pluck('slug');
        $this->assertCount(3, $response->json('items'));
        $this->assertContains($vehicle_featured_1->slug, $slugs);
        $this->assertContains($vehicle_featured_2->slug, $slugs);
        $this->assertContains($vehicle_recent->slug, $slugs);
    }

    public function testPromotedVehiclesListFeaturedAndRecentlyAdded()
    {
        $dealership = Dealership::factory()->create();
        $vehicle_featured = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
        ]);
        $vehicle_featured->created_at = Carbon::now()->subMinutes(5);
        $vehicle_featured->save();

        $vehicle_latest = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
        ]);
        $vehicle_latest->created_at = Carbon::now()->addMinutes(5);
        $vehicle_latest->save();

        Vehicle::factory(5)->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
        ]);

        $response = $this
            ->getJson(route('vehicles.promoted', [
                'types' => [
                    'featured',
                    'recently-added',
                ],
                'limit' => 7,
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());
        $this->assertCount(7, $response->json('items'));

        $slugs = collect($response->json('items'))->pluck('slug');
        $this->assertContains($vehicle_featured->slug, $slugs);
        $this->assertContains($vehicle_latest->slug, $slugs);
    }

    public function testPromotedVehiclesListFeaturedAndSimilar()
    {
        $dealership = Dealership::factory()->create();
        $vehicle_featured = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
            'price' => 9999,
        ]);

        $vehicle_target = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
            'price' => 123,
        ]);

        Vehicle::factory(2)->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
            'price' => 123,
        ]);

        $response = $this
            ->getJson(route('vehicles.promoted', [
                $vehicle_target->slug,
                'types' => [
                    'featured',
                    'similar',
                ],
                'limit' => 3,
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());
        $this->assertCount(3, $response->json('items'));

        $slugs = collect($response->json('items'))->pluck('slug');
        $this->assertContains($vehicle_featured->slug, $slugs);
        $this->assertNotContains($vehicle_target->slug, $slugs);
    }

    public function testPromotedVehiclesAll()
    {
        $dealership = Dealership::factory()->create();
        Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
            'price' => 9999,
        ]);

        $vehicle_target = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
            'price' => 123,
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'featured' => false,
            'dealership_id' => $dealership->id,
            'price' => 123,
        ]);

        $response = $this
            ->getJson(route('vehicles.promoted', [
                $vehicle_target->slug,
                'types' => [
                    'featured',
                    'similar',
                    'recently-viewed',
                    'recently-added',
                ],
                'slugs' => [
                    $vehicle_target->slug,
                ],
                'limit' => 3,
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());
        $this->assertCount(3, $response->json('items'));
    }

    public function testPromotedVehiclesDuplicates()
    {
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'featured' => true,
            'dealership_id' => $dealership->id,
            'price' => 9999,
        ]);

        $response = $this
            ->getJson(route('vehicles.promoted', [
                'types' => [
                    'featured',
                    'recently-viewed',
                    'recently-added',
                ],
                'slugs' => [
                    $vehicle->slug,
                ],
                'limit' => 10,
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('items', $response->json());

        // There is only one vehicle which should fit into all categories.
        // Assert that we only include it once.
        $this->assertCount(1, $response->json('items'));
    }

    public function testViewVehicleWithAccessKey()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        $vehicle = Vehicle::factory()->create([
            'is_published' => false,
            'slug' => 'foo-baz-bar',
        ]);
        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));
        $response->assertStatus(403);
        $response = $this->getJson(
            route('vehicles.show', 'foo-baz-bar') . '?a=' . base64_encode($vehicle->id . '-' . $vehicle->slug)
        );
        $response->assertStatus(200);
    }

    public function testRecentlyViewed()
    {
        $vehicles = Vehicle::factory(3)->create(['is_published' => true]);
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);
        $response = $this
            ->getJson(route('vehicles.recentlyViewed', 'foo-baz-bar') . '?'
                . http_build_query(['slugs' => $vehicles->pluck('slug')->toArray()]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('items', $response->json('recently_viewed'));
        $this->assertCount(3, $response->json('recently_viewed.items'));
    }

    public function testCompare()
    {
        $vehicles = Vehicle::factory(3)->create(['is_published' => true]);

        $response = $this
            ->getJson(route('vehicles.compare') . '?'
                . http_build_query(['slugs' => $vehicles->pluck('slug')->toArray()]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('data', $response->json());
        $this->assertCount(3, $response->json('data'));
        $this->assertArrayHasKey('make', $response->json('data.0'));
        $this->assertArrayHasKey('bodystyle', $response->json('data.0'));
        $this->assertArrayHasKey('is_reserved', $response->json('data.0'));
        $this->assertArrayHasKey('co2', $response->json('data.0'));
        $this->assertArrayHasKey('mpg', $response->json('data.0'));
        $this->assertArrayHasKey('seats', $response->json('data.0'));
        $this->assertArrayHasKey('door_count', $response->json('data.0'));
    }

    public function testRecentlyAdded()
    {
        $vehicles = Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => false
        ]);

        $response = $this
            ->getJson(route('vehicles.recentlyAdded') . '?limit=3');

        $response->assertStatus(200);
        $this->assertArrayHasKey('items', $response->json('recently_added'));
        $this->assertCount(3, $response->json('recently_added.items'));
    }

    public function testRecentlyAddedWithBodyStyleFilter()
    {
        $bodyStyleSuv = BodyStyleType::factory()->create(['slug' => 'suv']);
        $bodyStyleSedan = BodyStyleType::factory()->create(['slug' => 'sedan']);
        $bodyStyleHatchback = BodyStyleType::factory()->create(['slug' => 'hatchback']);

        // Create vehicles with different body styles
        Vehicle::factory(2)->create([
            'is_published' => true,
            'body_style_id' => $bodyStyleSuv->id
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'body_style_id' => $bodyStyleSedan->id
        ]);

        Vehicle::factory(1)->create([
            'is_published' => true,
            'body_style_id' => $bodyStyleHatchback->id
        ]);

        // Test single body style filter
        $response = $this
            ->getJson(route('vehicles.recentlyAdded') . '?body_style=suv&limit=10');

        $response->assertStatus(200);
        $this->assertArrayHasKey('items', $response->json('recently_added'));
        $this->assertCount(2, $response->json('recently_added.items'));

        // Test array of body styles filter
        $response = $this
            ->getJson(route('vehicles.recentlyAdded') . '?' . http_build_query([
                'body_style' => ['suv', 'sedan'],
                'limit' => 10
            ]));

        $response->assertStatus(200);
        $this->assertArrayHasKey('items', $response->json('recently_added'));
        $this->assertCount(5, $response->json('recently_added.items'));
    }

    public function testViewWithDefaultFinanceWidget()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        VehicleFinance::factory()->create(['vehicle_id' => $vehicle->id]);
        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('finance', $response->json('data'));
        $this->assertEquals('FinanceCalculator', $response->json('data.finance.value'));
        $this->assertArrayHasKey('change_values', $response->json('data.finance.data'));
        $this->assertArrayHasKey('values', $response->json('data.finance.data'));
    }

    public function testViewWithIvendiFinanceWidget()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-ivendi-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-term',
            'value' => 60,
            'type' => 'string',
        ]);
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('finance', $response->json('data'));
        $this->assertIsArray($response->json('data.finance'));
        $this->assertEquals('component', $response->json('data.finance.type'));
        $this->assertEquals('IVendiCalculator', $response->json('data.finance.value'));
        $this->assertEquals('60', $response->json('data.finance.data.term'));
    }

    public function testViewWithCodeweaversFinanceWidget()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-codeweavers-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-term',
            'value' => 60,
            'type' => 'string',
        ]);
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('finance', $response->json('data'));
        $this->assertIsArray($response->json('data.finance'));
        $this->assertEquals('component', $response->json('data.finance.type'));
        $this->assertEquals('CodeweaversCalculator', $response->json('data.finance.value'));
        $this->assertEquals('60', $response->json('data.finance.data.term'));
    }

    public function testViewWithEvolutionFinanceWidget()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-evolution-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-term',
            'value' => 60,
            'type' => 'string',
        ]);
        $dealership = Dealership::factory()->create();
        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
            'dealership_id' => $dealership->id,
        ]);
        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertArrayHasKey('finance', $response->json('data'));
        $this->assertIsArray($response->json('data.finance'));
        $this->assertEquals('component', $response->json('data.finance.type'));
        $this->assertEquals('EvolutionCalculator', $response->json('data.finance.value'));
        $this->assertEquals('60', $response->json('data.finance.data.term'));
    }

    public function testVehicleResource()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'bool',
        ]);

        $vehicle_resource_array = (new VehicleResource(Vehicle::factory()->create()))->toArray(request());
        $extras = $vehicle_resource_array['extra'];
        $lez_compliant = collect($extras)->where('name', '=', 'lez_compliant');

        $this->assertEmpty($lez_compliant);
    }

    public function testVehicleAttributes()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'autotrader-advert-performance',
            'value' => true,
            'type' => 'boolean',
        ]);

        $make = VehicleMake::factory()->create([
            'name' => 'Vehicle Make'
        ]);

        $model = VehicleModel::factory()->create([
            'name' => 'Vehicle Model',
            'make_id' => $make->id
        ]);


        $vehicle = Vehicle::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);

        $this->assertNotEmpty($vehicle);

        // try setting attribute
        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'model' => 'vehicle',
                    'name' => 'lez_compliant',
                ],
                [
                    'slug' => 'lez_compliant',
                    'type' => 'boolean',
                    'validation' => [],
                    'data' => []
                ]
            );

        $vehicle_attribute_coming_soon = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'model' => 'vehicle',
                    'name' => 'coming_soon',
                ],
                [
                    'slug' => 'coming_soon',
                    'type' => 'boolean',
                    'validation' => [],
                    'data' => []
                ]
            );

        // assert that vehicle doesn't have any attributes
        $example_vehicle_lez_compliant = $vehicle->attributeValues()->where('attribute_id', '=', $vehicle_attribute->id)->first();

        $this->assertEmpty($example_vehicle_lez_compliant);

        VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'finance_type' => 'HP'
        ]);

        VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'finance_type' => 'PCP'
        ]);

        // add an attribute value for the vehicle
        $vehicle_attribute_value = VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => true,
                'value_integer' => 1,
                'slug' => $vehicle_attribute->slug,
                'type' => 'boolean'
            ]
        );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute_coming_soon->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => false,
                'value_integer' => 0,
                'slug' => $vehicle_attribute_coming_soon->slug,
                'type' => 'boolean'
            ]
        );

        $this->assertEquals(2, VehicleAttributeValue::count());
        $this->assertEquals($vehicle->id, $vehicle_attribute_value->owner_id);
        $this->assertEquals($vehicle_attribute->id, $vehicle_attribute_value->attribute_id);
        $this->assertGreaterThan(0, $vehicle->attributeValues->count());

        // check that looking up the vehicle attribute works as expected
        $example_vehicle_lez_compliant = $vehicle->attributeValues()
            ->whereHas('attribute', function ($query) {
                $query->where('name', '=', 'lez_compliant');
            })->first();

        $this->assertNotEmpty($example_vehicle_lez_compliant);
        $this->assertEquals('lez_compliant', $example_vehicle_lez_compliant->attribute->name);
        $this->assertEquals(1, $example_vehicle_lez_compliant->value);

        // ensure that asking for values for missing vehicle attributes is handled gracefully
        $test_missing_value = $vehicle->attributeValues()
            ->whereHas('attribute', function ($query) {
                $query->where('name', '=', 'missing_value');
            })->first();

        $this->assertNull($test_missing_value);

        VehicleAutoTraderData::factory()->create([
            'vehicle_id' => $vehicle->id,
            'price_point' => 'Good'
        ]);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());
        $extras = $vehicle_resource_array['extra'];
        $lez_compliant = collect($extras)->where('name', '=', 'lez_compliant');
        $missing_value = collect($extras)->where('name', '=', 'my_missing_value');

        $this->assertNotEmpty($lez_compliant);
        $this->assertEmpty($missing_value);

        $this->assertArrayHasKey('autoTraderData', $vehicle_resource_array);
        $this->assertNotEmpty($vehicle_resource_array['autoTraderData']);
        $this->assertEquals('Good', $vehicle_resource_array['autoTraderData']['price_point']);

        $this->assertArrayHasKey('custom', $vehicle_resource_array);
        $this->assertArrayHasKey('lez_compliant', $vehicle_resource_array['custom']);
        $this->assertNotNull($vehicle_resource_array['custom']['lez_compliant']);
        $this->assertTrue($vehicle_resource_array['custom']['lez_compliant']);

        $this->assertArrayHasKey('coming_soon', $vehicle_resource_array['custom']);
        $this->assertFalse($vehicle_resource_array['custom']['coming_soon']);

        $this->assertEquals('vehicle-make', $vehicle_resource_array['make']['slug']);
        $this->assertEquals('vehicle-model', $vehicle_resource_array['model']['slug']);

        $this->assertNotNull($vehicle_resource_array['financeExamples']);
        $this->assertCount(2, $vehicle_resource_array['financeExamples']);
    }

    public function testMediaUses()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $vehicle = Vehicle::factory()->create();
        $media_item = Media::factory()->create();
        MediaUse::factory()->create([
            'media_id' => $media_item->id,
            'owner_type' => 'vehicle',
            'owner_id' => $vehicle->id
        ]);

        $this->assertNotEmpty($vehicle);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertCount(1, $vehicle_resource_array['media_uses']);
        $this->assertArrayHasKey('src_large', $vehicle_resource_array['media_uses'][0]);
        $this->assertArrayHasKey('src_medium', $vehicle_resource_array['media_uses'][0]);
        $this->assertArrayHasKey('src_thumbnail', $vehicle_resource_array['media_uses'][0]);
    }

    public function testVehicleDealershipFranchise()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $franchise = Franchise::factory()->create([
            'name' => 'foo'
        ]);

        $dealership = Dealership::factory()->create([
            'franchise_id' => $franchise->id
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $this->assertEquals($franchise->name, $vehicle->dealership->franchise->name);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertArrayHasKey('franchise', $vehicle_resource_array['dealership']);
        $this->assertEquals($franchise->name, $vehicle_resource_array['dealership']['franchise']['name']);
    }

    public function testDealershipWhatsappDisabled()
    {
        $dealership = Dealership::factory()->create([
            'data' => [
                'whatsapp-phone-number' => 12345,
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertArrayHasKey('whatsapp_no', $vehicle_resource_array['dealership']);
        $this->assertNull($vehicle_resource_array['dealership']['whatsapp_no']);
    }

    public function testDealershipWhatsappEnabled()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Dealerships',
            'name' => 'Dealership WhatsApp Enabled',
            'config_key' => 'dealerships-whatsapp-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [
                'whatsapp-phone-number' => 12345,
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertArrayHasKey('whatsapp_no', $vehicle_resource_array['dealership']);
        $this->assertEquals(12345, $vehicle_resource_array['dealership']['whatsapp_no']);
    }

    public function testDealershipWhatsappEnabledAndEmpty()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Dealerships',
            'name' => 'Dealership WhatsApp Enabled',
            'config_key' => 'dealerships-whatsapp-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [
                'whatsapp-phone-number' => null,
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertArrayHasKey('whatsapp_no', $vehicle_resource_array['dealership']);
        $this->assertNull($vehicle_resource_array['dealership']['whatsapp_no']);
    }

    public function testDealershipWhatsappEnabledAndMissing()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Dealerships',
            'name' => 'Dealership WhatsApp Enabled',
            'config_key' => 'dealerships-whatsapp-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $vehicle_resource_array = (new VehicleResource($vehicle))->toArray(request());

        $this->assertArrayHasKey('whatsapp_no', $vehicle_resource_array['dealership']);
        $this->assertNull($vehicle_resource_array['dealership']['whatsapp_no']);
    }

    public function testVehicleApplicableLabel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-labels-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'fpa'
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(1, $response->json('data.labels'));

        $this->assertArrayHasKey('name', $response->json('data.labels.0'));
        $this->assertArrayHasKey('content', $response->json('data.labels.0'));
        $this->assertArrayNotHasKey('data', $response->json('data.labels.0'));
        $this->assertEquals($label->name, $response->json('data.labels.0.name'));
        $this->assertEquals($label->id, $response->json('data.labels.0.id'));
        $this->assertEquals($label->type, $response->json('data.labels.0.type'));
    }

    public function testVehicleApplicableEmptyLabel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-labels-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => ''
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(1, $response->json('data.labels'));
    }

    public function testVehicleApplicableAllLabel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-labels-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'all'
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(1, $response->json('data.labels'));
    }

    public function testVehicleInvalidLabel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'srp'
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(0, $response->json('data.labels'));
    }

    public function testLabelContent()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-labels-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'all',
            'content' => 'test',
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(1, $response->json('data.labels'));
        $this->assertArrayHasKey('content', $response->json('data.labels.0'));
        $this->assertEquals('test', $response->json('data.labels.0.content'));
    }

    public function testLabelIsDisabled()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'srp'
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'foo-baz-bar',
        ]);

        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(0, $response->json('data.labels'));
    }

    public function testMakeModelSlugs()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $model = VehicleModel::factory()->create();

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'make_id' => $model->make_id,
            'model_id' => $model->id,
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertArrayHasKey('make', $response->json('data'));
        $this->assertArrayHasKey('slug', $response->json('data.make'));
        $this->assertArrayHasKey('model', $response->json('data'));
        $this->assertArrayHasKey('slug', $response->json('data.model'));

        $this->assertEquals($model->make->slug, $response->json('data.make.slug'));
        $this->assertEquals($model->slug, $response->json('data.model.slug'));
    }

    public function testVehicleComingSoon()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'coming-soon',
            'available_date' => Carbon::now()->addDays(5)
        ]);

        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'slug' => 'not-coming-soon',
            'available_date' => Carbon::now()
        ]);

        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'available_date' => null
        ]);

        $this->assertTrue($vehicle1->getComingSoonStatus());
        $this->assertFalse($vehicle2->getComingSoonStatus());
        $this->assertFalse($vehicle3->getComingSoonStatus());

        $response = $this
            ->getJson(route('vehicles.show', 'coming-soon'));
        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('coming_soon', $response->json('data'));
        $this->assertTrue($response->json('data.coming_soon'));

        $response = $this
            ->getJson(route('vehicles.show', 'not-coming-soon'));
        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('coming_soon', $response->json('data'));
        $this->assertFalse($response->json('data.coming_soon'));
    }

    public function testRiskBasedEligibileVehicle()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-ivendi-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-finance-type',
            'value' => 'peter-vardy',
            'type' => 'text',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-risk-based-pricing-finance-options',
            'value' => '1,4',
            'type' => 'text',
        ]);

        $dealership_eligible = Dealership::factory()->create([
            'data' => [
                'finance-risk-based-pricing' => true
            ]
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership_eligible->id
        ]);

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'finance_option',
                ],
                [
                    'slug' => 'finance_option',
                    'type' => 'number',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value_float' => 1,
                'slug' => $vehicle_attribute->slug,
                'type' => 'number'
            ]
        );

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->arrayHasKey('actions', $response->json('data'));
        $this->arrayHasKey('eligible_for_risk_based_finance', $response->json('data.actions'));
        $this->assertTrue($response->json('data.actions.eligible_for_risk_based_finance'));
    }

    public function testRiskBasedIneligibileFuel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-ivendi-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-finance-type',
            'value' => 'peter-vardy',
            'type' => 'text',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-risk-based-pricing-finance-options',
            'value' => '1,4',
            'type' => 'text',
        ]);

        $dealership_eligible = Dealership::factory()->create([
            'data' => [
                'finance-risk-based-pricing' => true
            ]
        ]);

        $fuel_type = FuelType::factory()->create([
            'name' => 'electric'
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership_eligible->id,
            'fuel_type_id' => $fuel_type->id
        ]);

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'finance_option',
                ],
                [
                    'slug' => 'finance_option',
                    'type' => 'number',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value_float' => 1,
                'slug' => $vehicle_attribute->slug,
                'type' => 'number'
            ]
        );

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->arrayHasKey('actions', $response->json('data'));
        $this->arrayHasKey('eligible_for_risk_based_finance', $response->json('data.actions'));
        $this->assertFalse($response->json('data.actions.eligible_for_risk_based_finance'));
    }

    public function testRiskBasedIneligibileDealership()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-ivendi-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-finance-type',
            'value' => 'peter-vardy',
            'type' => 'text',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-risk-based-pricing-finance-options',
            'value' => '1,4',
            'type' => 'text',
        ]);

        $dealership_eligible = Dealership::factory()->create([
            'data' => [
                'finance-risk-based-pricing' => false
            ]
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership_eligible->id
        ]);

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'finance_option',
                ],
                [
                    'slug' => 'finance_option',
                    'type' => 'number',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value_float' => 1,
                'slug' => $vehicle_attribute->slug,
                'type' => 'number'
            ]
        );

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->arrayHasKey('actions', $response->json('data'));
        $this->arrayHasKey('eligible_for_risk_based_finance', $response->json('data.actions'));
        $this->assertFalse($response->json('data.actions.eligible_for_risk_based_finance'));
    }

    public function testRiskBasedIneligibleFinanceOption()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-ivendi-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-finance-type',
            'value' => 'peter-vardy',
            'type' => 'text',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'finance-risk-based-pricing-finance-options',
            'value' => '1,4',
            'type' => 'text',
        ]);

        $dealership_eligible = Dealership::factory()->create([
            'data' => [
                'finance-risk-based-pricing' => true
            ]
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership_eligible->id
        ]);

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'finance_option',
                ],
                [
                    'slug' => 'finance_option',
                    'type' => 'number',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value_float' => 99,
                'slug' => $vehicle_attribute->slug,
                'type' => 'number'
            ]
        );

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->arrayHasKey('actions', $response->json('data'));
        $this->arrayHasKey('eligible_for_risk_based_finance', $response->json('data.actions'));
        $this->assertFalse($response->json('data.actions.eligible_for_risk_based_finance'));
    }

    public function testVehicleHasTestDriveForm()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $test_drive_enquiry_type = EnquiryType::factory()->create([
            'name' => 'Test Drive',
        ]);

        $form = \Mtc\MercuryDataModels\Form::factory()->create([
            'name' => 'Book a Test Drive Offer Enquiry',
            'type_id' => $test_drive_enquiry_type->id,
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'form-enquiry-type-test-drive',
            'type' => 'string',
            'value' => 'Test Drive',
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertArrayHasKey('forms', $response->json('data'));
        $this->assertCount(1, $response->json('data.forms'));
        $this->assertArrayHasKey('test_drive', $response->json('data.forms'));
        $this->assertNotNull($response->json('data.forms.test_drive'));
    }

    public function testFinanceExampleContent()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
        ]);

        $finance = VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'terms_and_conditions' => 'foo',
            'finance_type' => 'HP',
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertArrayHasKey('financeExamples', $response->json('data'));
        $this->assertArrayHasKey('HP', $response->json('data.financeExamples'));
        $this->assertEquals($finance->terms_and_conditions, $response->json('data.financeExamples.HP.terms_and_conditions'));
    }

    public function testReservePriceCar()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'sales-reserve_price',
            'type' => 'number',
            'value' => 100,
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'sales-reserve_price_lcv',
            'type' => 'number',
            'value' => 500,
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'type' => 'car',
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);

        $this->assertEquals(100, $response->json('data.reservation_amount'));
    }

    public function testReservePriceLcv()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'sales-reserve_price',
            'type' => 'number',
            'value' => 100,
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'sales-reserve_price_lcv',
            'type' => 'number',
            'value' => 500,
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'type' => 'lcv',
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));

        $response->assertStatus(200);

        $this->assertEquals(500, $response->json('data.reservation_amount'));
    }

    public function testIsVatApplicableFilter()
    {
        $dealership = \Mtc\MercuryDataModels\Dealership::factory()->create();

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Filtering',
            'name' => 'Vat Applicable',
            'config_key' => 'automotive-vehicle-filters-is_vat_applicable',
            'type' => 'boolean',
            'value' => true,
        ]);

        $vat_vehicle = \Mtc\MercuryDataModels\Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership->id,
            'is_vat_applicable' => 1,
        ]);
        $non_vat_vehicle = \Mtc\MercuryDataModels\Vehicle::factory()->create([
            'is_published' => true,
            'dealership_id' => $dealership->id,
            'is_vat_applicable' => 0,
        ]);

        $is_vat_response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                [
                    "type" => "is_vat_applicable",
                    "value" => "true"
                ]
            ],
        ]);
        $is_vat_response->assertStatus(200);

        $ids = collect($is_vat_response->json('results.data'))->pluck('id');
        $this->assertTrue($ids->contains($vat_vehicle->id));
        $this->assertFalse($ids->contains($non_vat_vehicle->id));

        $is_not_vat_response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                [
                    "type" => "is_vat_applicable",
                    "value" => "false"
                ]
            ],
        ]);
        $is_not_vat_response->assertStatus(200);

        $ids = collect($is_not_vat_response->json('results.data'))->pluck('id');
        $this->assertFalse($ids->contains($vat_vehicle->id));
        $this->assertTrue($ids->contains($non_vat_vehicle->id));
    }

    public function testCompareEmailInvalidRequest()
    {
        $response = $this->postJson(route('vehicles.compare-mail'));

        $response->assertStatus(422);
        $this->assertArrayHasKey('errors', $response->json());
        $this->assertArrayHasKey('slugs', $response->json('errors'));
        $this->assertArrayHasKey('email', $response->json('errors'));
    }

    public function testCompareEmailRequest()
    {
        $response = $this->postJson(route('vehicles.compare-mail', [
            'slugs' => [
                'abc',
                'xyz',
            ],
            'email' => 'foo@bar.com',
        ]));

        $response->assertStatus(200);
        $this->assertTrue($response->json('success'));

        Queue::assertPushed(VehicleComparisonMailRequest::class);
        Queue::assertPushed(function (VehicleComparisonMailRequest $job) {
            $reflection = new \ReflectionClass($job);
            $property_comparison_url = $reflection->getProperty('comparison_url');
            $comparison_url_actual = $property_comparison_url->getValue($job);
            $comparison_url_expected = Site::vehicleComparisonUrl([
                'abc',
                'xyz',
            ]);

            return $comparison_url_expected === $comparison_url_actual
                && Str::contains($comparison_url_actual, '?slug=abc&slug=xyz');
        });
    }

    public function testCompareEmailRequestCustomUrl()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-compare-path',
            'value' => 'foo',
            'type' => 'string',
        ]);

        $response = $this->postJson(route('vehicles.compare-mail', [
            'slugs' => [
                'abc',
                'xyz',
            ],
            'email' => 'foo@bar.com',
        ]));

        $response->assertStatus(200);
        $this->assertTrue($response->json('success'));

        Queue::assertPushed(VehicleComparisonMailRequest::class);
        Queue::assertPushed(function (VehicleComparisonMailRequest $job) {
            $reflection = new \ReflectionClass($job);
            $property_comparison_url = $reflection->getProperty('comparison_url');
            $comparison_url_actual = $property_comparison_url->getValue($job);
            $comparison_url_expected = Site::vehicleComparisonUrl([
                'abc',
                'xyz',
            ]);

            return $comparison_url_expected === $comparison_url_actual
                && Str::contains($comparison_url_actual, 'foo?slug=abc&slug=xyz');
        });
    }
}
