<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use App\Models\FilterIndex;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Queue;
use Mtc\Filter\Contracts\FilterInstance;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\TransmissionType;
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 Tests\FilterSettingSeed;
use Tests\SortingSettingSeed;
use Tests\TenantTestCase;

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

    public function testFilterByMake()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        $make = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();
        Vehicle::factory(5)->create([
            'is_published' => true,
            'make_id' => $make->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'make_id' => $make2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'make_id' => 100,
            ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First Make
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second make
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both Makes
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make->slug,
                    ],
                    [
                        'type' => 'make',
                        'value' => $make2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

    public function testFilterByModel()
    {
        $this->seed(FilterSettingSeed::class);
        $model = VehicleModel::factory()->create();
        $model2 = VehicleModel::factory()->create();
        Vehicle::factory(5)->create([
            'is_published' => true,
            'model_id' => $model->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'model_id' => $model2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'model_id' => 100,
        ]);

        // No  specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => $model->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => $model2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => $model->slug,
                    ],
                    [
                        'type' => 'model',
                        'value' => $model2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

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

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

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

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

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'model' => 'vehicle',
                    'name' => 'vehicle_category',
                ],
                [
                    'slug' => 'vehicle_category',
                    'type' => 'text',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle1->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => 'foo',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle2->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => 'baz',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle3->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => 'baz',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_category',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_category',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_category',
                        'value' => 'foo',
                    ],
                    [
                        'type' => 'vehicle_category',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
    }

    public function testFilterByAge()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'manufacture_year' => 2021,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'manufacture_year' => 2015,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'manufacture_year' => 2009,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'age',
                        'value' => 2020,
                    ],
                    [
                        'type' => 'age',
                        'value' => 2021,
                    ],
                    [
                        'type' => 'age',
                        'value' => 2022,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'age',
                        'value' => 2015,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'age',
                        'value' => 2021
                    ],
                    [
                        'type' => 'age',
                        'value' => 2015
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(8, $response3->json('results.total'));
    }

    public function testFilterByBodyStyle()
    {
        $this->seed(FilterSettingSeed::class);
        $body_style = BodyStyleType::factory()->create();
        $body_style->filterIndex()->updateOrCreate(['slug' => $body_style->slug]);
        $body_style2 = BodyStyleType::factory()->create();
        $body_style2->filterIndex()->updateOrCreate(['slug' => $body_style2->slug]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'body_style_id' => $body_style->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'body_style_id' => $body_style2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'body_style_id' => 100,
        ]);

        // No specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => $body_style->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => $body_style2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => $body_style->slug,
                    ],
                    [
                        'type' => 'body_type',
                        'value' => $body_style2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

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

        // Adding filter index for matching, due to queue fake it is not created automatically
        FilterIndex::create([
            'slug' => 'red',
            'name' => 'red',
            'filter_type' => 'colour',
            'filter_id' => 'red',
        ]);
        FilterIndex::create([
            'slug' => 'black',
            'name' => 'black',
            'filter_type' => 'colour',
            'filter_id' => 'black',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'colour' => 'red',
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'colour' => 'black',
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'colour' => 'silver',
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'black',
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                    [
                        'type' => 'colour',
                        'value' => 'black',
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

    /*
     * commenting out this test, as the filter is not currently included in config
    public function testFilterByDoorCount()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'door_count' => 4,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'door_count' => 5,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'door_count' => 3,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'door_count',
                        'value' => 4,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'door_count',
                        'value' => 5,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'door_count',
                        'value' => 4,
                    ],
                    [
                        'type' => 'door_count',
                        'value' => 5,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }
    */

    /*
     * commenting out this test, as the filter is not currently included in config
    public function testFilterByEngineSize()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'engine_size_cc' => 1400,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'engine_size_cc' => 1999,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'engine_size_cc' => 2500,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size',
                        'value' =>  1500,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size',
                        'value' => 2000,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(8, $response3->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size',
                        'value' =>  2000,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(8, $response3->json('results.total'));
    }
    */

    public function testFilterByFuelType()
    {
        $this->seed(FilterSettingSeed::class);
        $fuel_type = FuelType::factory()->create();
        $fuel_type->filterIndex()->updateOrCreate(['slug' => $fuel_type->slug]);
        $fuel_type2 = FuelType::factory()->create();
        $fuel_type2->filterIndex()->updateOrCreate(['slug' => $fuel_type2->slug]);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'fuel_type_id' => $fuel_type->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'fuel_type_id' => $fuel_type2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'fuel_type_id' => 100,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First Make
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => $fuel_type->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => $fuel_type2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => $fuel_type->slug,
                    ],
                    [
                        'type' => 'fuel_type',
                        'value' => $fuel_type2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

    public function testFilterByLocation()
    {
        $this->seed(FilterSettingSeed::class);
        $location = Dealership::factory()->create();
        $location2 = Dealership::factory()->create();
        Vehicle::factory(5)->create([
            'is_published' => true,
            'dealership_id' => $location->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'dealership_id' => $location2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'dealership_id' => 100,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => $location->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => $location2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => $location->slug,
                    ],
                    [
                        'type' => 'location',
                        'value' => $location2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

    /*
     * commenting out this test, as the filter is not currently included in config
    public function testFilterByMileage()
    {
        $this->seed(FilterSettingSeed::class);
        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'Distance measurement',
            'config_key' => 'automotive-distance_measurement',
            'type' => 'string',
            'value' => 'mi',
        ]);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'odometer_mi' => 60000,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'odometer_mi' => 45000,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 48000,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'odometer_mi' => 25000,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(19, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage',
                        'value' =>  30000,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(10, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage',
                        'value' => 47500,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(13, $response3->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage',
                        'value' => 50000,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(14, $response3->json('results.total'));
    }
    */

    /*
     * commenting out this test, as the filter is not currently included in config
    public function testFilterByPrice()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'price' => 10200,
            'monthly_price' => 250,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'price' => 8500,
            'monthly_price' => 170,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'price' => 5000,
            'monthly_price' => 130,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price',
                        'value' => [
                            'payment_type' => 'full',
                            'min' => 10000,
                            'max' => 12500,
                        ],
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price',
                        'value' => [
                            'payment_type' => 'full',
                            'min' => 7500,
                            'max' => 10000,
                        ],
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

    }
    */

    /*
     * commenting out this test, as the filter is not currently included in config
    public function testFilterBySeatCount()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'seats' => 4,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'seats' => 2,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'seats' => 5,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats',
                        'value' => 4,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats',
                        'value' => 2,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats',
                        'value' => 4,
                    ],
                    [
                        'type' => 'seats',
                        'value' => 2,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }
    */

    public function testFilterByTransmission()
    {
        $this->seed(FilterSettingSeed::class);
        $transmission = TransmissionType::factory()->create(['slug' => 'foo']);
        $transmission->filterIndex()->updateOrCreate(['slug' => $transmission->slug]);
        $transmission2 = TransmissionType::factory()->create(['slug' => 'faz']);
        $transmission2->filterIndex()->updateOrCreate(['slug' => $transmission2->slug]);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'transmission_id' => $transmission->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'transmission_id' => $transmission2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'transmission_id' => 100,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission->slug,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(5, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission2->slug,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission->slug,
                    ],
                    [
                        'type' => 'transmission',
                        'value' => $transmission2->slug,
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

    public function testFilterBySearchTerm(): never
    {
        $this->markTestSkipped('Unable to test fulltext search in sqlite');
    }

    public function testFilterByMultipleFilters()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        $transmission = TransmissionType::factory()->create();
        $transmission->filterIndex()->updateOrCreate(['slug' => $transmission->slug]);
        $transmission2 = TransmissionType::factory()->create();
        $transmission2->filterIndex()->updateOrCreate(['slug' => $transmission2->slug]);
        Vehicle::factory(3)->create([
            'transmission_id' => $transmission->id,
            'colour' => 'blue',
            'is_published' => true,
        ]);
        Vehicle::factory(4)->create([
            'transmission_id' => $transmission->id,
            'colour' => 'red',
            'is_published' => true,
        ]);
        Vehicle::factory(5)->create([
            'transmission_id' => $transmission2->id,
            'colour' => 'blue',
            'is_published' => true,
        ]);
        Vehicle::factory(6)->create([
            'transmission_id' => $transmission2->id,
            'colour' => 'red',
            'is_published' => true,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'transmission_id' => 100,
        ]);
        // Adding filter index for matching, due to queue fake it is not created automatically
        FilterIndex::create([
            'slug' => 'red',
            'name' => 'red',
            'filter_type' => 'colour',
            'filter_id' => 'red',
        ]);
        FilterIndex::create([
            'slug' => 'blue',
            'name' => 'blue',
            'filter_type' => 'colour',
            'filter_id' => 'blue',
        ]);


        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(28, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission->slug,
                    ],
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(4, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission->slug,
                    ],
                    [
                        'type' => 'colour',
                        'value' => 'blue',
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(3, $response3->json('results.total'));

        // Both
        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => $transmission->slug,
                    ],
                    [
                        'type' => 'transmission',
                        'value' => $transmission2->slug,
                    ],
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                ]
            ]);
        $response4->assertStatus(200);
        $this->assertEquals(10, $response4->json('results.total'));
    }
    public function testFilterByConsumption()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'mpg' => 21,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'mpg' => 40,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'mpg' => 55,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(18, $response->json('results.total'));

        // First
        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'consumption',
                        'value' => 50,
                    ],
                ]
            ]);
        $response2->assertStatus(200);
        $this->assertEquals(10, $response2->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'consumption',
                        'value' => 25,
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(13, $response3->json('results.total'));

        // Second
        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'consumption',
                        'value' => 20
                    ],
                    [
                        'type' => 'consumption',
                        'value' => 40
                    ],
                ]
            ]);
        $response3->assertStatus(200);
        $this->assertEquals(18, $response3->json('results.total'));
    }

    public function testFiltersAreEnabledBySettings()
    {
        $this->seed(FilterSettingSeed::class);
        $filters = App::make(FilterInstance::class)->getFilters();
        $this->assertEquals(32, $filters->count());

        Settings::update('automotive-vehicle-filters-colour', false);
        Settings::update('automotive-vehicle-filters-fuel_type', false);
        $filters = App::make(FilterInstance::class)->getFilters();
        $this->assertEquals(30, $filters->count());
        $this->assertArrayNotHasKey('colour', $filters);
        $this->assertArrayNotHasKey('fuel_type', $filters);
    }

    public function testFilteWidget()
    {
        $this->seed(FilterSettingSeed::class);
        $make = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();
        Vehicle::factory(5)->create([
            'is_published' => true,
            'make_id' => $make->id,
        ]);
        Vehicle::factory(3)->create([
            'is_published' => true,
            'make_id' => $make2->id,
        ]);
        Vehicle::factory(10)->create([
            'is_published' => true,
            'make_id' => 100,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.widget'));

        $response->assertStatus(200);
        $this->assertTrue(count($response->json('filters')) > 1);

        $response = $this
            ->postJson(route('vehicles.widget'), [
                'only_filters' => [
                    'make'
                ]
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('make', $response->json('filters'));
    }

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


        // create some testing data

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

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

        VehicleAutoTraderData::factory()->create([
           'vehicle_id' => 123,
           'price_point' => 'Fair'
        ]);

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

        // try search with no filters. Should bring back all of our example vehicles.
        $response = $this
            ->postJson(route('vehicles.index'));

        // test that call worked and brought back results
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $selected_price_point_filters = 0;

        foreach ($response->json('filters.price_point.results') as $filter_option) {
            if ($filter_option['selected']) {
                $selected_price_point_filters++;
            }
        }

        $this->assertEquals(0, $selected_price_point_filters);

        // search with a filter for one of the vehicles.
        // should return filtered vehicles.
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_point',
                        'value' => 'Good'
                    ]
                ]
            ]);

        // assert that the price point filter results match what we expect
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        $selected_price_point_filters = 0;

        foreach ($response->json('filters.price_point.results') as $filter_option) {
            if ($filter_option['selected']) {
                $selected_price_point_filters++;
            }
        }

        $this->assertEquals(1, $selected_price_point_filters);

        // filter on a price point that does not belong to any vehicles.
        // should not return vehicles.
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_point',
                        'value' => 'Poor'
                    ]
                ]
            ]);

        // assert that the price point filter results match what we expect
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));

        // test multiple filter selections
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_point',
                        'value' => 'Good'
                    ],
                    [
                        'type' => 'price_point',
                        'value' => 'Fair'
                    ]
                ]
            ]);

        // assert that the price point filter results match what we expect
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $selected_price_point_filters = 0;

        foreach ($response->json('filters.price_point.results') as $filter_option) {
            if ($filter_option['selected']) {
                $selected_price_point_filters++;
            }
        }

        $this->assertEquals(2, $selected_price_point_filters);
    }

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

        // create our testing data
        Vehicle::factory()->create([
            'id' => 123,
            'is_published' => true,
        ]);

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

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

        VehicleAutoTraderData::factory()->create([
            'vehicle_id' => 123,
            'price_point' => 'Fair'
        ]);

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

        VehicleAutoTraderData::factory()->create([
            'vehicle_id' => 789,
            'price_point' => 'Great'
        ]);

        Settings::make([
            'tab' => 'automotive',
            'section' => 'AutoTrader',
            'group' => 'Enriched vehicle data',
            'name' => 'Display price indicator when value is equal or better than',
            'config_key' => 'autotrader-show-price-indicator-min-value',
            'type' => 'string',
            'value' => 'Good',
            'min_tier' => 'pro',
            'order' => 22,
        ]);

        // try search with no filters. Should bring back all of our example vehicles.
        $response = $this
            ->postJson(route('vehicles.index'));

        // test that call worked and brought back results
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // get the list of price point filters returned by the search
        $available_price_point_selections = [];

        foreach ($response->json('filters.price_point.results') as $filter_option) {
            $available_price_point_selections[$filter_option['name']] = $filter_option['name'];
        }

        // assert that unwanted values were not returned (case sensitive)
        $this->assertArrayHasKey('Good', $available_price_point_selections);
        $this->assertArrayHasKey('Great', $available_price_point_selections);
        $this->assertArrayNotHasKey('Fair', $available_price_point_selections);
    }

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

        // create our testing data
        Vehicle::factory()->create([
            'id' => 123,
            'is_published' => true,
        ]);

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

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

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

        VehicleAutoTraderData::factory()->create([
            'vehicle_id' => 123,
            'price_point' => 'Fair'
        ]);

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

        VehicleAutoTraderData::factory()->create([
            'vehicle_id' => 789,
            'price_point' => 'Great'
        ]);

        Settings::make([
            'tab' => 'automotive',
            'section' => 'AutoTrader',
            'group' => 'Enriched vehicle data',
            'name' => 'Display price indicator when value is equal or better than',
            'config_key' => 'autotrader-show-price-indicator-min-value',
            'type' => 'string',
            'value' => 'Fair',
            'min_tier' => 'pro',
            'order' => 22,
        ]);

        // try search with no filters. Should bring back all of our example vehicles.
        $response = $this
            ->postJson(route('vehicles.index'));

        // test that call worked and brought back results
        $response->assertStatus(200);
        $this->assertEquals(4, $response->json('results.total'));

        // get the list of price point filters returned by the search
        $available_price_point_selections = [];

        foreach ($response->json('filters.price_point.results') as $filter_option) {
            $available_price_point_selections[] = $filter_option['name'];
        }

        $this->assertEquals(3, count($available_price_point_selections));

        $this->assertEquals('Great', $available_price_point_selections[0]);
        $this->assertEquals('Good', $available_price_point_selections[1]);
        $this->assertEquals('Fair', $available_price_point_selections[2]);
    }

    public function testVehicleData()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'autotrader-advert-performance',
            'value' => true,
            'type' => 'bool',
        ]);
        $this->seed();
        $this->seed(FilterSettingSeed::class);


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

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $this->assertArrayHasKey('autoTraderData', $response->json('results.data.0'));
        $this->assertArrayHasKey('dealership', $response->json('results.data.0'));
        $this->assertArrayHasKey('derivative', $response->json('results.data.0'));
        $this->assertArrayHasKey('finance_example', $response->json('results.data.0'));
        $this->assertArrayHasKey('fuel_type', $response->json('results.data.0'));
        $this->assertArrayHasKey('is_vat_applicable', $response->json('results.data.0'));
        $this->assertArrayHasKey('make', $response->json('results.data.0'));
        $this->assertArrayHasKey('manufacture_year', $response->json('results.data.0'));
        $this->assertArrayHasKey('model', $response->json('results.data.0'));
        $this->assertArrayHasKey('odometer_mi', $response->json('results.data.0'));
        $this->assertArrayHasKey('odometer_km', $response->json('results.data.0'));
        $this->assertArrayHasKey('original_price', $response->json('results.data.0'));
        $this->assertArrayHasKey('previous_price', $response->json('results.data.0'));
        $this->assertArrayHasKey('price', $response->json('results.data.0'));
        $this->assertArrayHasKey('rrp_price', $response->json('results.data.0'));
        $this->assertArrayHasKey('title', $response->json('results.data.0'));
        $this->assertArrayHasKey('transmission', $response->json('results.data.0'));
        $this->assertArrayHasKey('type', $response->json('results.data.0'));
        $this->assertArrayHasKey('custom', $response->json('results.data.0'));
        $this->assertArrayHasKey('age_identifier', $response->json('results.data.0'));
        $this->assertArrayHasKey('coming_soon', $response->json('results.data.0'));
        $this->assertArrayHasKey('reservation_amount', $response->json('results.data.0'));

        $this->assertTrue($response->json('results.data.0.coming_soon'));
    }

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

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled-previous-price',
            'value' => true,
            'type' => 'bool',
        ]);

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

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

        $dealership = Dealership::factory()->create([
            'id' => 1,
            'location_stock' => 'VE',
            'name' => 'Carz Edinburgh'
        ]);

        Vehicle::factory()->create([
            'id' => 123,
            'is_published' => true,
            'type' => 'car',
            'price' => 8000,
            'original_price' => 8000,
            'previous_price' => 9000,
            'dealership_id' => $dealership->id,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertEquals(1000, $response->json('results.data.0.extra.saving_original_price'));
    }

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

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

        $dealership = Dealership::factory()->create([
            'id' => 1,
            'location_stock' => 'VE',
            'name' => 'Carz Edinburgh'
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'type' => 'car',
            'price' => null,
            'dealership_id' => $dealership->id,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
    }

    public function testVehicleFinanceExample()
    {
        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,
        ]);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);

        $this->assertEquals('HP', $response->json('results.data.0.finance_example.finance_type'));
        $this->assertEquals(123, $response->json('results.data.0.finance_example.monthly_price'));

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

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);

        $this->assertEmpty($response->json('results.data.0.finance_example'));
    }

    public function testVehicleResultFranchise()
    {
        $this->seed(SortingSettingSeed::class);

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

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

        $dealership2 = Dealership::factory()->create();

        Vehicle::factory()->create([
            'dealership_id' => $dealership2->id,
            'is_published' => true,
            'price' => 456,
        ]);

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEmpty($response->json('results.data.0.finance_example'));
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertEquals(123, $response->json('results.data.0.price'));
        $this->assertNotNull($response->json('results.data.0.dealership'));
        $this->assertNotNull($response->json('results.data.0.dealership.franchise'));
        $this->assertNotNull($response->json('results.data.0.dealership.franchise.name'));
        $this->assertEquals($franchise->name, $response->json('results.data.0.dealership.franchise.name'));
        $this->assertArrayNotHasKey('franchise', $response->json('results.data.1.dealership'));
    }

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
        ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(1, $response->json('results.data.0.labels'));

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

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(1, $response->json('results.data.0.labels'));
    }

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(1, $response->json('results.data.0.labels'));
    }

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(1, $response->json('results.data.0.labels'));
    }

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(0, $response->json('results.data.0.labels'));
    }

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

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(0, $response->json('results.data.0.labels'));
    }

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

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);

        $this->assertEquals(1, $response->json('results.total'));
        $this->assertCount(1, VehicleLabel::all());
        $this->assertNotNull($response->json('results.data.0.labels'));
        $this->assertCount(1, $response->json('results.data.0.labels'));
        $this->assertArrayHasKey('content', $response->json('results.data.0.labels.0'));
        $this->assertEquals('test', $response->json('results.data.0.labels.0.content'));
    }

    public function testPriceSelectFilters()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 12000
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 23000
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 45000
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('price', $response->json('filters'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_min',
                        'value' => 18000,
                    ],
                    [
                        'type' => 'price_max',
                        'value' => 31000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_max',
                        'value' => 5000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_max',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_min',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testMonthlyPriceSelectFilters()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 12000
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 23000
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 45000
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('monthly_price', $response->json('filters'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_min',
                        'value' => 18000,
                    ],
                    [
                        'type' => 'price_monthly_max',
                        'value' => 31000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_max',
                        'value' => 5000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_max',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_min',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testDoorRangeFilters()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'door_count' => 2
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'door_count' => 4
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'door_count' => 5
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'doors_min',
                        'value' => 2,
                    ],
                    [
                        'type' => 'doors_max',
                        'value' => 3,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'doors_max',
                        'value' => 1,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'doors_max',
                        'value' => 8,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'doors_min',
                        'value' => 99,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testSeatRangeFilters()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'seats' => 2
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'seats' => 4
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'seats' => 5
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats_min',
                        'value' => 2,
                    ],
                    [
                        'type' => 'seats_max',
                        'value' => 3,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats_max',
                        'value' => 1,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats_max',
                        'value' => 8,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'seats_min',
                        'value' => 99,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testEngineSizeFilter()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'engine_size_cc' => 1234,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'engine_size_cc' => 2345,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'engine_size_cc' => 3456,
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('engine_size', $response->json('filters'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size_min',
                        'value' => 2000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size_min',
                        'value' => 456789,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size_max',
                        'value' => 1,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'engine_size_min',
                        'value' => 1000,
                    ],
                    [
                        'type' => 'engine_size_max',
                        'value' => 2100,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }
    public function testMileageFilter()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'Distance measurement',
            'config_key' => 'automotive-distance_measurement',
            'type' => 'string',
            'value' => 'mi',
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 12000,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 45000,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 99000,
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('mileage', $response->json('filters'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage_min',
                        'value' => 15000,
                    ],
                    [
                        'type' => 'mileage_max',
                        'value' => 75000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage_min',
                        'value' => 15000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'mileage_max',
                        'value' => 75000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));
        $this->assertArrayHasKey('vehicle_type', $response->json('filters'));
        $this->assertCount(2, $response->json('filters.vehicle_type.results'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_type',
                        'value' => 'car',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_type',
                        'value' => 'lcv',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_type',
                        'value' => 'bike',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'vehicle_type',
                        'value' => 'car',
                    ],
                    [
                        'type' => 'vehicle_type',
                        'value' => 'lcv',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));
    }

    public function testManufactureYearFilter()
    {
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2010,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2015,
        ]);
        Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2020,
        ]);
        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('manufacture_year', $response->json('filters'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'manufacture_year_min',
                        'value' => 2012,
                    ],
                    [
                        'type' => 'manufacture_year_max',
                        'value' => 2018,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'manufacture_year_min',
                        'value' => 2012,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'manufacture_year_max',
                        'value' => 2018,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

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

        $dealership = Dealership::factory()->create();

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);

        $filters = [
            'make',
            'model',
            'gearbox',
            'fuel type',
            'body types',
            'colour',
            'location',
        ];
        collect($response->json('filters'))->each(function ($filter) use ($filters) {
            if (in_array((string) strtolower($filter['title']), $filters) && !empty($filters['results'])) {
                $this->assertArrayHasKey('slug', $filter['results'][0]);
                $this->assertNotEmpty($filter['results'][0]['slug']);
            }
        });
    }

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

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

        VehicleModel::factory(5)->create([
            'make_id' => $model->make->id
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $model->make->name
                    ]
                ]
            ]);

        $response->assertStatus(200);
        $this->assertArrayHasKey('model', $response->json('filters'));
        $this->assertGreaterThan(0, count($response->json('filters.model')));
    }

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

        $fuel_type_petrol = FuelType::factory()->create([
            'name' => 'petrol',
            'slug' => 'petrol'
        ]);

        $fuel_type_diesel = FuelType::factory()->create([
            'name' => 'diesel',
            'slug' => 'diesel'
        ]);

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

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

        Vehicle::factory(5)->create([
            'is_published' => true,
            'fuel_type_id' => $fuel_type_diesel->id
        ]);

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

        // test search with no filters
        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(9, $response->json('results.total'));

        // test fuel type filter
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => 'petrol',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // test fuel type filter
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => 'diesel',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        // test multiple selections
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'fuel_type',
                        'value' => 'diesel',
                    ],
                    [
                        'type' => 'fuel_type',
                        'value' => 'petrol',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));
    }

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

        $transmission_type_manual = TransmissionType::factory()->create([
            'name' => 'manual',
            'slug' => 'manual',
        ]);

        $transmission_type_automatic = TransmissionType::factory()->create([
            'name' => 'automatic',
            'slug' => 'automatic',
        ]);

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

        Vehicle::factory(5)->create([
            'is_published' => true,
            'transmission_id' => $transmission_type_automatic->id
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => 'manual',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => 'automatic',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => 'automatic',
                    ],
                    [
                        'type' => 'transmission',
                        'value' => 'manual',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'transmission',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        $make_audi = VehicleMake::factory()->create([
            'name' => 'audi'
        ]);

        $make_bmw = VehicleMake::factory()->create([
            'name' => 'bmw'
        ]);

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

        Vehicle::factory(5)->create([
            'is_published' => true,
            'make_id' => $make_bmw->id
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => 'audi',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => 'bmw',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => 'audi',
                    ],
                    [
                        'type' => 'make',
                        'value' => 'bmw',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        $model_one = VehicleModel::factory()->create([
            'name' => 'one'
        ]);

        $model_two = VehicleModel::factory()->create([
            'name' => 'two'
        ]);

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => 'one',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => 'two',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => 'one',
                    ],
                    [
                        'type' => 'model',
                        'value' => 'two',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'model',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        $body_coupe = BodyStyleType::factory()->create([
            'name' => 'coupe'
        ]);

        $body_saloon = BodyStyleType::factory()->create([
            'name' => 'saloon'
        ]);
        // Adding filter index for matching, due to queue fake it is not created automatically
        FilterIndex::create([
            'slug' => 'coupe',
            'name' => 'coupe',
            'filter_type' => 'body_type',
            'filter_id' => $body_coupe->id,
        ]);
        FilterIndex::create([
            'slug' => 'saloon',
            'name' => 'saloon',
            'filter_type' => 'body_type',
            'filter_id' => $body_saloon->id,
        ]);


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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => 'coupe',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => 'saloon',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => 'coupe',
                    ],
                    [
                        'type' => 'body_type',
                        'value' => 'saloon',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'body_type',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        $franchise_one = Franchise::factory()->create([
            'slug' => 'foo'
        ]);

        $franchise_two = Franchise::factory()->create([
            'slug' => 'baz'
        ]);

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

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

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response2 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'franchise',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response2->assertStatus(200);
        $this->assertEquals(3, $response2->json('results.total'));

        $response3 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'franchise',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response3->assertStatus(200);
        $this->assertEquals(5, $response3->json('results.total'));

        $response4 = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'franchise',
                        'value' => 'foo',
                    ],
                    [
                        'type' => 'franchise',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response4->assertStatus(200);
        $this->assertEquals(8, $response4->json('results.total'));
    }

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

        $dealer_one = Dealership::factory()->create([
            'name' => 'one'
        ]);

        $dealer_two = Dealership::factory()->create([
            'name' => 'two'
        ]);

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => 'one',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => 'two',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => 'one',
                    ],
                    [
                        'type' => 'location',
                        'value' => 'two',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'location',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        Vehicle::factory(3)->create([
            'is_published' => true,
            'colour' => 'red'
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'colour' => 'Midnight Blue'
        ]);

        // Adding filter index for matching, due to queue fake it is not created automatically
        FilterIndex::create([
            'slug' => 'red',
            'name' => 'red',
            'filter_type' => 'colour',
            'filter_id' => 'red',
        ]);
        FilterIndex::create([
            'slug' => 'midnight-blue',
            'name' => 'Midnight Blue',
            'filter_type' => 'colour',
            'filter_id' => 'midnight-blue',
        ]);


        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'midnight-blue',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'red',
                    ],
                    [
                        'type' => 'colour',
                        'value' => 'midnight-blue',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(8, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'colour',
                        'value' => 'yellow',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'Vehicle Brand',
            'config_key' => 'automotive-vehicle-brand-on-filter-card',
            'type' => 'boolean',
            'value' => 'true',
        ]);

        $make = VehicleMake::factory()->create();

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $this->assertEquals($make->name, $response->json('results.data.0.make.name'));
        $this->assertEquals($make->slug, $response->json('results.data.0.make.slug'));
    }

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

        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'Vehicle Brand',
            'config_key' => 'automotive-vehicle-model-on-filter-card',
            'type' => 'boolean',
            'value' => 'true',
        ]);

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

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $this->assertEquals($model->name, $response->json('results.data.0.model.name'));
        $this->assertEquals($model->slug, $response->json('results.data.0.model.slug'));
    }

    public function testRepresentativeFinanceExample()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'foo',
            'config_key' => 'vehicle-list-load-finance-example',
            'type' => 'boolean',
            'value' => 'true',
        ]);

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

        $finance = VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'monthly_price' => 123,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $this->assertArrayHasKey('finance_example', $response->json());
        $this->assertEquals($finance->monthly_price, $response->json('finance_example.monthly_price'));
    }

    public function testMissingFinanceExample()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'foo',
            'config_key' => 'vehicle-list-load-finance-example',
            'type' => 'boolean',
            'value' => 'true',
        ]);

        $this->seed();
        $this->seed(FilterSettingSeed::class);

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

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
        $this->assertArrayHasKey('finance_example', $response->json());
        $this->assertEmpty($response->json('finance_example'));
    }

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

        // try search with no filters. Should bring back all of our example vehicles.
        $response = $this
            ->postJson(route('vehicles.index'));

        // test that call worked and brought back results
        $response->assertStatus(200);

        $this->assertArrayHasKey('price', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.price.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.price.results'));

        $this->assertArrayHasKey('monthly_price', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.monthly_price.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.monthly_price.results'));

        $this->assertArrayHasKey('doors', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.doors.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.doors.results'));

        $this->assertArrayHasKey('engine_size', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.engine_size.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.engine_size.results'));

        $this->assertArrayHasKey('manufacture_year', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.manufacture_year.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.manufacture_year.results'));

        $this->assertArrayHasKey('mileage', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.mileage.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.mileage.results'));

        $this->assertArrayHasKey('seats', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.seats.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.seats.results'));
    }

    public function testMissingColourIndex()
    {
        $this->seed(FilterSettingSeed::class);
        Vehicle::factory(5)->create([
            'is_published' => true,
            'colour' => 'red',
        ]);

        // delete the filter indexes, to simulate us not having a filter index for a colour
        FilterIndex::query()->where('filter_type', '=', 'colour')->delete();

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));
    }

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

        Vehicle::factory(2)->create([
            'is_published' => true,
            'is_demo' => false,
            'is_new' => false
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_demo' => false,
            'is_new' => true
        ]);

        Vehicle::factory(1)->create([
            'is_published' => true,
            'is_demo' => true,
            'is_new' => false
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(6, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'is_new',
                        'value' => 'new',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'is_new',
                        'value' => 'used',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'is_new',
                        'value' => 'used',
                    ],
                    [
                        'type' => 'is_new',
                        'value' => 'new',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'is_new',
                        'value' => 'ex_demo',
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }

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

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

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

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

        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'stock_status',
                    'model' => 'vehicle'
                ],
                [
                    'slug' => 'stock_status',
                    'type' => 'text',
                    'validation' => [],
                    'data' => []
                ]
            );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle1->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => 'foo',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle2->id,
                'owner_type' => 'vehicle'
            ],
            [
                'value' => 'baz',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle3->id,
                'owner_type' => 'vehicle'
            ],
            [
                'value' => 'baz',
                'slug' => $vehicle_attribute->slug,
                'type' => 'text'
            ]
        );

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'stock_status',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'stock_status',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'stock_status',
                        'value' => 'foo',
                    ],
                    [
                        'type' => 'stock_status',
                        'value' => 'baz',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
    }

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

        Vehicle::factory(2)->create([
            'is_published' => true,
            'trim' => 'foo'
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'trim' => 'bar'
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'trim',
                        'value' => 'foo',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'trim',
                        'value' => 'bar',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'trim',
                        'value' => 'foo',
                    ],
                    [
                        'type' => 'trim',
                        'value' => 'bar',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));
    }

    public function testAttributeFilter()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Filtering',
            'name' => 'Trim',
            'config_key' => 'automotive-vehicle-filters-too-good-to-trade',
            'type' => 'boolean',
            'value' => true,
        ]);
        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true
        ]);
        Vehicle::factory()->create([
            'is_published' => true
        ]);

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

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

        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => $vehicle_attribute->slug,
                        'value' => 'yes',
                    ],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }

    public function testReservationAmount()
    {
        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::factory(10)->create([
            'is_published' => true,
            'type' => 'car',
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);

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

    public function testReservationAmountLcv()
    {
        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::factory(10)->create([
            'is_published' => true,
            'type' => 'lcv',
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);

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

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

        Vehicle::factory(4)->create([
            'is_published' => true,
            'is_sold' => false,
        ]);

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

        // No filter - returns all 7
        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(7, $response->json('results.total'));

        // Filter for sold only
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'is_sold', 'value' => 'sold'],
            ],
        ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // Filter for available only
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'is_sold', 'value' => 'available'],
            ],
        ]);
        $response->assertStatus(200);
        $this->assertEquals(4, $response->json('results.total'));

        // Both selections - returns all 7
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'is_sold', 'value' => 'sold'],
                ['type' => 'is_sold', 'value' => 'available'],
            ],
        ]);
        $response->assertStatus(200);
        $this->assertEquals(7, $response->json('results.total'));
    }

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

        Vehicle::factory(4)->create([
            'is_published' => true,
            'is_sold' => false,
        ]);

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

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        // Assert the is_sold filter key exists in the response
        $this->assertArrayHasKey('is_sold', $response->json('filters'));

        $filterResults = collect($response->json('filters.is_sold.results'));

        // Should have both "Sold" and "Available" options
        $this->assertCount(2, $filterResults);

        $sold = $filterResults->firstWhere('slug', 'sold');
        $available = $filterResults->firstWhere('slug', 'available');

        // Assert both options are present with correct structure and counts
        $this->assertNotNull($sold);
        $this->assertEquals('sold', $sold['id']);
        $this->assertEquals('Sold', $sold['name']);
        $this->assertEquals(3, $sold['count']);

        $this->assertNotNull($available);
        $this->assertEquals('available', $available['id']);
        $this->assertEquals('Available', $available['name']);
        $this->assertEquals(4, $available['count']);
    }

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

        // Only available vehicles, no sold
        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_sold' => false,
        ]);

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $this->assertArrayHasKey('is_sold', $response->json('filters'));

        $filterResults = collect($response->json('filters.is_sold.results'));

        // Both options are always present, even when one has a 0 count
        $this->assertCount(2, $filterResults);

        $available = $filterResults->firstWhere('slug', 'available');
        $this->assertNotNull($available);
        $this->assertEquals(5, $available['count']);

        // "Sold" option is present with a count of 0
        $sold = $filterResults->firstWhere('slug', 'sold');
        $this->assertNotNull($sold);
        $this->assertEquals(0, $sold['count']);
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            [
                'slug' => 'horsepower',
                'type' => 'integer',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 100, 'value_integer' => 100, 'slug' => 'horsepower', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 250, 'value_integer' => 250, 'slug' => 'horsepower', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 400, 'value_integer' => 400, 'slug' => 'horsepower', 'type' => 'integer']
        );

        // No filter — all 3 returned
        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // Min 250 — vehicles with hp >= 250 (vehicle2 + vehicle3)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 250],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        // Min 400 — only vehicle3
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 400],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            [
                'slug' => 'horsepower',
                'type' => 'integer',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 100, 'value_integer' => 100, 'slug' => 'horsepower', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 250, 'value_integer' => 250, 'slug' => 'horsepower', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 400, 'value_integer' => 400, 'slug' => 'horsepower', 'type' => 'integer']
        );

        // Max 250 — vehicles with hp <= 250 (vehicle1 + vehicle2)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_max', 'value' => 250],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        // Max 100 — only vehicle1
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_max', 'value' => 100],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            [
                'slug' => 'horsepower',
                'type' => 'integer',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
            ]
        );

        foreach ([100, 200, 300, 400, 500] as $hp) {
            $v = Vehicle::factory()->create(['is_published' => true]);
            VehicleAttributeValue::query()->updateOrCreate(
                ['attribute_id' => $attribute->id, 'owner_id' => $v->id, 'owner_type' => 'vehicle'],
                ['value' => $hp, 'value_integer' => $hp, 'slug' => 'horsepower', 'type' => 'integer']
            );
        }

        // Range 200–400 — 3 vehicles (200, 300, 400)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 200],
                ['type' => 'horsepower_max', 'value' => 400],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // Range 300–500 — 3 vehicles (300, 400, 500)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 300],
                ['type' => 'horsepower_max', 'value' => 500],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Battery Capacity'],
            [
                'slug' => 'battery_capacity',
                'type' => 'number',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 40.5, 'value_float' => 40.5, 'slug' => 'battery_capacity', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 75.0, 'value_float' => 75.0, 'slug' => 'battery_capacity', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 100.5, 'value_float' => 100.5, 'slug' => 'battery_capacity', 'type' => 'number']
        );

        // Min 75.0 — vehicle2 + vehicle3
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'battery_capacity_min', 'value' => 75.0],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        // Max 75.0 — vehicle1 + vehicle2
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'battery_capacity_max', 'value' => 75.0],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

    public function testVehicleAttributeRangeFilterDisabledWithoutSetting()
    {
        $this->seed(FilterSettingSeed::class);
        // Generic setting NOT created — all dynamic attribute range filters should be disabled

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Torque'],
            [
                'slug' => 'torque',
                'type' => 'integer',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
            ]
        );

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

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 100, 'value_integer' => 100, 'slug' => 'torque', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 500, 'value_integer' => 500, 'slug' => 'torque', 'type' => 'integer']
        );

        // Selection should be ignored — filter not enabled, both vehicles returned
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'torque_min', 'value' => 400],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

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

        // One setting enables range filters for ALL filterable attributes
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Filtering',
            'name' => 'Vehicle Attribute Range',
            'config_key' => 'automotive-vehicle-filters-vehicle_attribute_range',
            'type' => 'boolean',
            'value' => true,
        ]);

        $hpAttr = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            ['slug' => 'horsepower', 'type' => 'integer', 'validation' => [], 'data' => [], 'filterable' => 1]
        );
        $rangeAttr = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Range Miles'],
            ['slug' => 'range_miles', 'type' => 'integer', 'validation' => [], 'data' => [], 'filterable' => 1]
        );

        // Vehicle A: 300hp, 200mi
        $a = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $a->id, 'owner_type' => 'vehicle',
            'value' => 300, 'value_integer' => 300, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $rangeAttr->id, 'owner_id' => $a->id, 'owner_type' => 'vehicle',
            'value' => 200, 'value_integer' => 200, 'slug' => 'range_miles', 'type' => 'integer',
        ]);

        // Vehicle B: 150hp, 400mi
        $b = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $b->id, 'owner_type' => 'vehicle',
            'value' => 150, 'value_integer' => 150, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $rangeAttr->id, 'owner_id' => $b->id, 'owner_type' => 'vehicle',
            'value' => 400, 'value_integer' => 400, 'slug' => 'range_miles', 'type' => 'integer',
        ]);

        // Vehicle C: 300hp, 400mi
        $c = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $c->id, 'owner_type' => 'vehicle',
            'value' => 300, 'value_integer' => 300, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $rangeAttr->id, 'owner_id' => $c->id, 'owner_type' => 'vehicle',
            'value' => 400, 'value_integer' => 400, 'slug' => 'range_miles', 'type' => 'integer',
        ]);

        // hp >= 200 AND range >= 300 — only Vehicle C matches both
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 200],
                ['type' => 'range_miles_min', 'value' => 300],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        // hp <= 200 AND range <= 300 — no vehicle matches both
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_max', 'value' => 200],
                ['type' => 'range_miles_max', 'value' => 300],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

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

        // filterable = 0 — should NOT be picked up by getAdditionalFilters
        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Internal Score'],
            [
                'slug' => 'internal_score',
                'type' => 'integer',
                'validation' => [],
                'data' => [],
                'filterable' => 0,
            ]
        );

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

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 10, 'value_integer' => 10, 'slug' => 'internal_score', 'type' => 'integer']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 90, 'value_integer' => 90, 'slug' => 'internal_score', 'type' => 'integer']
        );

        // Selection ignored — attribute not filterable, both vehicles returned
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'internal_score_min', 'value' => 50],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

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

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

        $hpAttr = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            ['slug' => 'horsepower', 'type' => 'integer', 'validation' => [], 'data' => [], 'filterable' => 1]
        );
        $weightAttr = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Weight'],
            ['slug' => 'weight', 'type' => 'number', 'validation' => [], 'data' => [], 'filterable' => 1]
        );

        // Vehicle A: 150hp, 1200kg (low power, light)
        $a = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $a->id, 'owner_type' => 'vehicle',
            'value' => 150, 'value_integer' => 150, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $weightAttr->id, 'owner_id' => $a->id, 'owner_type' => 'vehicle',
            'value' => 1200, 'value_float' => 1200, 'slug' => 'weight', 'type' => 'number',
        ]);

        // Vehicle B: 300hp, 1500kg (mid power, mid weight)
        $b = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $b->id, 'owner_type' => 'vehicle',
            'value' => 300, 'value_integer' => 300, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $weightAttr->id, 'owner_id' => $b->id, 'owner_type' => 'vehicle',
            'value' => 1500, 'value_float' => 1500, 'slug' => 'weight', 'type' => 'number',
        ]);

        // Vehicle C: 500hp, 1800kg (high power, heavy)
        $c = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $c->id, 'owner_type' => 'vehicle',
            'value' => 500, 'value_integer' => 500, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $weightAttr->id, 'owner_id' => $c->id, 'owner_type' => 'vehicle',
            'value' => 1800, 'value_float' => 1800, 'slug' => 'weight', 'type' => 'number',
        ]);

        // Vehicle D: 500hp, 1200kg (high power, light)
        $d = Vehicle::factory()->create(['is_published' => true]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $hpAttr->id, 'owner_id' => $d->id, 'owner_type' => 'vehicle',
            'value' => 500, 'value_integer' => 500, 'slug' => 'horsepower', 'type' => 'integer',
        ]);
        VehicleAttributeValue::query()->create([
            'attribute_id' => $weightAttr->id, 'owner_id' => $d->id, 'owner_type' => 'vehicle',
            'value' => 1200, 'value_float' => 1200, 'slug' => 'weight', 'type' => 'number',
        ]);

        // No filter — all 4 returned
        $response = $this->postJson(route('vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(4, $response->json('results.total'));

        // horsepower_min 300 — B(300), C(500), D(500) match
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 300],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        // weight_min 1500 — B(1500), C(1800) match
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'weight_min', 'value' => 1500],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        // horsepower_min 300 AND weight_min 1500 — only B(300hp,1500kg) and C(500hp,1800kg)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 300],
                ['type' => 'weight_min', 'value' => 1500],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));

        // horsepower_min 500 AND weight_min 1500 — only C(500hp,1800kg)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 500],
                ['type' => 'weight_min', 'value' => 1500],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        // horsepower_min 500 AND weight_min 1800 — only C(500hp,1800kg)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 500],
                ['type' => 'weight_min', 'value' => 1800],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));

        // horsepower_min 500 AND weight_min 1900 — none match
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'horsepower_min', 'value' => 500],
                ['type' => 'weight_min', 'value' => 1900],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Horsepower'],
            ['slug' => 'horsepower', 'type' => 'integer', 'validation' => [], 'data' => [], 'filterable' => 1]
        );

        // Scattered values that should NOT each become an individual option
        foreach ([100, 120, 150, 180, 200, 210] as $hp) {
            $v = Vehicle::factory()->create(['is_published' => true]);
            VehicleAttributeValue::query()->create([
                'attribute_id' => $attribute->id, 'owner_id' => $v->id, 'owner_type' => 'vehicle',
                'value' => $hp, 'value_integer' => $hp, 'slug' => 'horsepower', 'type' => 'integer',
            ]);
        }

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $this->assertArrayHasKey('horsepower', $response->json('filters'));
        $this->assertArrayHasKey('filter_min', $response->json('filters.horsepower.results'));
        $this->assertArrayHasKey('filter_max', $response->json('filters.horsepower.results'));

        $minOptions = collect($response->json('filters.horsepower.results.filter_min'));
        $maxOptions = collect($response->json('filters.horsepower.results.filter_max'));

        $minIds = $minOptions->pluck('id')->values();
        $maxIds = $maxOptions->pluck('id')->values();

        // Should produce a manageable number of options, not one per distinct value
        $this->assertGreaterThanOrEqual(3, $minIds->count(), 'Should have at least 3 min options');
        $this->assertLessThanOrEqual(15, $minIds->count(), 'Should not have too many min options');

        // First min option should be at or below the data minimum (100)
        $this->assertLessThanOrEqual(100, $minIds->first(), 'Lowest "from" option should cover the data minimum');

        // Last max option should be at or above the data maximum (210)
        $this->assertGreaterThanOrEqual(210, $maxIds->last(), 'Highest "up to" option should cover the data maximum');

        // Steps should be evenly spaced
        $step = $minIds[1] - $minIds[0];
        $this->assertGreaterThan(0, $step, 'Step size should be positive');

        // Option names should be formatted correctly
        $this->assertStringStartsWith('From ', $minOptions->first()['name']);
        $this->assertStringStartsWith('Up To ', $maxOptions->first()['name']);
    }

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

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

        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Engine CC'],
            ['slug' => 'engine_cc', 'type' => 'integer', 'validation' => [], 'data' => [], 'filterable' => 1]
        );

        // Large range: 998 to 4999
        foreach ([998, 1200, 1600, 2000, 3000, 4999] as $cc) {
            $v = Vehicle::factory()->create(['is_published' => true]);
            VehicleAttributeValue::query()->create([
                'attribute_id' => $attribute->id, 'owner_id' => $v->id, 'owner_type' => 'vehicle',
                'value' => $cc, 'value_integer' => $cc, 'slug' => 'engine_cc', 'type' => 'integer',
            ]);
        }

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $minIds = collect($response->json('filters.engine_cc.results.filter_min'))->pluck('id')->values();

        $this->assertGreaterThanOrEqual(3, $minIds->count());
        $this->assertLessThanOrEqual(15, $minIds->count());

        // First option should cover the minimum (998)
        $this->assertLessThanOrEqual(998, $minIds->first());

        // Step size should scale with the range — expect multiples of 100 or 500
        $step = $minIds[1] - $minIds[0];
        $this->assertGreaterThanOrEqual(100, $step, "Step size {$step} should be at least 100 for a large range");
        $this->assertEquals(0, $step % 100, "Step size {$step} should be a multiple of 100");
    }

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

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

        // precision=0 forces integer steps even when the stored values are floats.
        // Range 1.3–4.6 → niceStep(0.33)=0.5 → but precision=0 snaps step to max(1, round(0.5))=1
        // → options [1, 2, 3, 4, 5] (all integers, no 1.5 present)
        // With precision=1 the same raw step of 0.5 would produce [1.0, 1.5, 2.0, 2.5, …] including non-integers.
        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Fuel Economy'],
            [
                'slug' => 'fuel_economy',
                'type' => 'number',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
                'precision' => 0,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 1.3, 'value_float' => 1.3, 'slug' => 'fuel_economy', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 2.7, 'value_float' => 2.7, 'slug' => 'fuel_economy', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 4.6, 'value_float' => 4.6, 'slug' => 'fuel_economy', 'type' => 'number']
        );

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $minIds = collect($response->json('filters.fuel_economy.results.filter_min'))->pluck('id')->values();
        $this->assertNotEmpty($minIds);

        // All option IDs must be integers — precision=0 must cast to int, never float
        foreach ($minIds->all() as $id) {
            $this->assertIsInt($id, "Expected integer option for precision 0, got: {$id}");
        }

        // The raw step of 0.5 would produce 1.5 with precision=1; precision=0 must suppress it
        $this->assertFalse(
            $minIds->contains(1.5),
            'Expected no decimal option 1.5 with precision 0 — step must be rounded to integer 1'
        );

        // Positive check: the integer options derived from range 1.3–4.6 with step 1 must be present
        $this->assertTrue($minIds->contains(1), 'Expected integer option 1 to be present with precision 0');
        $this->assertTrue($minIds->contains(2), 'Expected integer option 2 to be present with precision 0');
        $this->assertTrue($minIds->contains(3), 'Expected integer option 3 to be present with precision 0');

        // Filtering with an integer boundary: min 3 → only vehicle3 (4.6 >= 3)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'fuel_economy_min', 'value' => 3],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(1, $response->json('results.total'));
    }

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

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

        // precision=1 rounds options to exactly 1 decimal place.
        // Range 0.1–0.5 → niceStep(0.04)=0.05 → intermediate values include 0.15, 0.25, 0.35, 0.45
        // With precision=1: round(0.15, 1)=0.1, round(0.25, 1)=0.3, etc. — only 1dp values remain.
        // With precision=2: 0.15, 0.25, 0.35, 0.45 survive, which would fail the round-to-1dp assertions.
        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'CO2 Output'],
            [
                'slug' => 'co2_output',
                'type' => 'number',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
                'precision' => 1,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 0.1, 'value_float' => 0.1, 'slug' => 'co2_output', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 0.3, 'value_float' => 0.3, 'slug' => 'co2_output', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 0.5, 'value_float' => 0.5, 'slug' => 'co2_output', 'type' => 'number']
        );

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $minIds = collect($response->json('filters.co2_output.results.filter_min'))->pluck('id')->values();
        $this->assertNotEmpty($minIds);

        // All options must be rounded to exactly 1 decimal place — no 2dp values permitted
        foreach ($minIds->all() as $id) {
            $this->assertEquals(
                round((float) $id, 1),
                (float) $id,
                "Option {$id} is not rounded to 1 decimal place"
            );
        }

        // The 0.05 step generates 0.20 as a 1dp option — confirms decimal values are present
        $this->assertTrue(
            $minIds->contains(0.2),
            'Expected option 0.2 to be present with precision 1 and step 0.05'
        );

        // 0.15 is a 2dp intermediate that precision=1 must round away (to 0.1)
        // If it appears, precision=2 was used instead of precision=1
        $this->assertFalse(
            $minIds->contains(0.15),
            'Expected no 2dp option 0.15 with precision 1 — it must be rounded to 0.1'
        );

        // Filtering with a 1dp value: min 0.3 → vehicle2 (0.3) and vehicle3 (0.5)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'co2_output_min', 'value' => 0.3],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }

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

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

        // precision=2 rounds steps to 2 decimal places.
        // Range 0.10–0.40 → niceStep(0.03)=0.05 → options [0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40]
        $attribute = VehicleAttribute::query()->firstOrCreate(
            ['model' => 'vehicle', 'name' => 'Tyre Depth'],
            [
                'slug' => 'tyre_depth',
                'type' => 'number',
                'validation' => [],
                'data' => [],
                'filterable' => 1,
                'precision' => 2,
            ]
        );

        $vehicle1 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => true]);
        $vehicle3 = Vehicle::factory()->create(['is_published' => true]);

        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle1->id, 'owner_type' => 'vehicle'],
            ['value' => 0.10, 'value_float' => 0.10, 'slug' => 'tyre_depth', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle2->id, 'owner_type' => 'vehicle'],
            ['value' => 0.25, 'value_float' => 0.25, 'slug' => 'tyre_depth', 'type' => 'number']
        );
        VehicleAttributeValue::query()->updateOrCreate(
            ['attribute_id' => $attribute->id, 'owner_id' => $vehicle3->id, 'owner_type' => 'vehicle'],
            ['value' => 0.40, 'value_float' => 0.40, 'slug' => 'tyre_depth', 'type' => 'number']
        );

        $response = $this->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $minIds = collect($response->json('filters.tyre_depth.results.filter_min'))->pluck('id')->values();
        $this->assertNotEmpty($minIds);

        // All options must be rounded to at most 2 decimal places
        foreach ($minIds->all() as $id) {
            $this->assertEquals(
                round((float) $id, 2),
                (float) $id,
                "Option {$id} is not rounded to 2 decimal places"
            );
        }

        // The 0.05 step produces 2dp options — 0.15 must be present
        $this->assertTrue(
            $minIds->contains(0.15),
            'Expected option 0.15 to be present with precision 2 and step 0.05'
        );

        // Filtering with a 2dp value: min 0.25 → vehicle2 (0.25) and vehicle3 (0.40)
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'tyre_depth_min', 'value' => 0.25],
            ]
        ]);
        $response->assertStatus(200);
        $this->assertEquals(2, $response->json('results.total'));
    }
}
