<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\CatalogOffer;
use Mtc\MercuryDataModels\CatalogOfferRule;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleLabel;
use Mtc\MercuryDataModels\VehicleMake;
use Tests\FilterSettingSeed;
use Tests\TenantTestCase;

class CatalogOfferFilterTest extends TenantTestCase
{
    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        $this->withoutExceptionHandling();

        // Enable catalog offers injection
        Settings::make([
            'tab' => 'filter',
            'section' => 'filter',
            'group' => 'filter',
            'name' => 'Inject offers',
            'config_key' => 'filter-inject-offers-into-used-car-filter',
            'type' => 'boolean',
            'value' => true,
        ]);
    }

    public function testCatalogOfferWithNoRulesIsIncluded()
    {
        Queue::fake();
        Vehicle::factory(5)->create(['is_published' => true]);
        $offer = CatalogOffer::factory()->create(['active' => true]);

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

        $response->assertStatus(200);
        // Total should only count vehicles, not the injected catalog offer
        $this->assertEquals(5, $response->json('results.total'));
        // Data should contain 5 vehicles + 1 catalog offer
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
        $this->assertEquals($offer->id, $catalogOfferInResults['id']);
    }

    public function testCatalogOfferWithMatchingRulesIsIncluded()
    {
        Queue::fake();
        $make = VehicleMake::factory()->create();
        Vehicle::factory(5)->create([
            'is_published' => true,
            'make_id' => $make->id,
        ]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make->id,
        ]);

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

        $response->assertStatus(200);
        // Total should only count vehicles, not the injected catalog offer
        $this->assertEquals(5, $response->json('results.total'));
        // Data should contain 5 vehicles + 1 catalog offer
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithNonMatchingRulesIsExcluded()
    {
        Queue::fake();
        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();

        // All vehicles have make1
        Vehicle::factory(5)->create([
            'is_published' => true,
            'make_id' => $make1->id,
        ]);

        // Offer requires make2 which no vehicles have
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make2->id,
        ]);

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

        $response->assertStatus(200);
        // Only 5 vehicles, no catalog offer
        $this->assertEquals(5, $response->json('results.total'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithPriceRulesIsRespected()
    {
        Queue::fake();
        Vehicle::factory(3)->create([
            'is_published' => true,
            'price' => 15000,
        ]);
        Vehicle::factory(2)->create([
            'is_published' => true,
            'price' => 5000,
        ]);

        // Offer only for vehicles over 10000
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'price',
            'condition' => '>',
            'value' => '10000',
        ]);

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

        $response->assertStatus(200);
        // Total should only count vehicles, not the injected catalog offer
        $this->assertEquals(5, $response->json('results.total'));
        // Data should contain 5 vehicles + 1 catalog offer
        $this->assertCount(6, $response->json('results.data'));
    }

    public function testCatalogOfferWithMultipleRulesRequiresAllToMatch()
    {
        Queue::fake();
        $make = VehicleMake::factory()->create();

        // Vehicle matches both conditions
        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make->id,
            'price' => 15000,
        ]);

        // Vehicle matches only make condition
        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make->id,
            'price' => 5000,
        ]);

        // Offer requires make_id AND price > 10000
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make->id,
        ]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'price',
            'condition' => '>',
            'value' => '10000',
        ]);

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

        $response->assertStatus(200);
        // Total should only count vehicles, not the injected catalog offer
        $this->assertEquals(4, $response->json('results.total'));
        // Data should contain 4 vehicles + 1 catalog offer
        $this->assertCount(5, $response->json('results.data'));
    }

    public function testCatalogOfferExcludedWhenMultipleRulesNotAllMatch()
    {
        Queue::fake();
        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();

        // Vehicles have make1 with high price
        Vehicle::factory(3)->create([
            'is_published' => true,
            'make_id' => $make1->id,
            'price' => 15000,
        ]);

        // Offer requires make2 AND high price - make2 doesn't exist
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make2->id,
        ]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'price',
            'condition' => '>',
            'value' => '10000',
        ]);

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

        $response->assertStatus(200);
        // Only 3 vehicles, no catalog offer
        $this->assertEquals(3, $response->json('results.total'));
    }

    public function testCatalogOfferRespectsFilteredResults()
    {
        Queue::fake();
        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();

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

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

        // Offer matches make1
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make1->id,
        ]);

        // Filter for make2 - catalog offer should not appear since it targets make1
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make2->slug,
                    ],
                ]
            ]);

        $response->assertStatus(200);
        // Only 3 vehicles (make2), no catalog offer since it requires make1
        $this->assertEquals(3, $response->json('results.total'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferAppearsWhenFilterMatchesOfferRules()
    {
        Queue::fake();
        $make = VehicleMake::factory()->create();

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

        // Some other vehicles
        Vehicle::factory(3)->create([
            'is_published' => true,
        ]);

        // Offer matches the make
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make->id,
        ]);

        // Filter for the same make - catalog offer should appear
        $response = $this
            ->postJson(route('vehicles.index'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make->slug,
                    ],
                ]
            ]);

        $response->assertStatus(200);
        // Total should only count vehicles, not the injected catalog offer
        $this->assertEquals(5, $response->json('results.total'));
        // Data should contain 5 vehicles + 1 catalog offer
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testInactiveCatalogOfferIsNotIncluded()
    {
        Queue::fake();
        Vehicle::factory(5)->create(['is_published' => true]);
        CatalogOffer::factory()->create(['active' => false]);

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

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

    public function testCatalogOffersDisabledSetting()
    {
        Queue::fake();
        // Disable catalog offers
        Settings::update('filter-inject-offers-into-used-car-filter', false);

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

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

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

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithInConditionMatchesMultipleDealerships()
    {
        Queue::fake();
        $dealership1 = Dealership::factory()->create();
        $dealership2 = Dealership::factory()->create();
        $dealership3 = Dealership::factory()->create();

        // Vehicles at dealership1 and dealership2
        Vehicle::factory(3)->create([
            'is_published' => true,
            'dealership_id' => $dealership1->id,
        ]);
        Vehicle::factory(2)->create([
            'is_published' => true,
            'dealership_id' => $dealership2->id,
        ]);

        // Offer targets dealership1, dealership2 (stored as JSON array)
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'dealership_id',
            'condition' => 'in',
            'value' => json_encode([$dealership1->id, $dealership2->id]),
        ]);

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

        $response->assertStatus(200);
        // 5 vehicles + 1 catalog offer
        $this->assertEquals(5, $response->json('results.total'));
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithInConditionExcludesNonMatchingDealerships()
    {
        Queue::fake();
        $dealership1 = Dealership::factory()->create();
        $dealership2 = Dealership::factory()->create();
        $dealership3 = Dealership::factory()->create();

        // All vehicles at dealership3 (not in offer's target list)
        Vehicle::factory(5)->create([
            'is_published' => true,
            'dealership_id' => $dealership3->id,
        ]);

        // Offer targets dealership1, dealership2 only
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'dealership_id',
            'condition' => 'in',
            'value' => json_encode([$dealership1->id, $dealership2->id]),
        ]);

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

        $response->assertStatus(200);
        // Only 5 vehicles, no catalog offer since no vehicles match the rule
        $this->assertEquals(5, $response->json('results.total'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithNotInConditionExcludesDealerships()
    {
        Queue::fake();
        $dealership1 = Dealership::factory()->create();
        $dealership2 = Dealership::factory()->create();
        $dealership3 = Dealership::factory()->create();

        // Vehicles at dealership3 (not excluded)
        Vehicle::factory(3)->create([
            'is_published' => true,
            'dealership_id' => $dealership3->id,
        ]);

        // Vehicles at dealership1 (excluded)
        Vehicle::factory(2)->create([
            'is_published' => true,
            'dealership_id' => $dealership1->id,
        ]);

        // Offer excludes dealership1 and dealership2
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'dealership_id',
            'condition' => 'not_in',
            'value' => json_encode([$dealership1->id, $dealership2->id]),
        ]);

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

        $response->assertStatus(200);
        // 5 vehicles total, catalog offer appears because dealership3 vehicles exist
        $this->assertEquals(5, $response->json('results.total'));
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testWeightedOfferAppearsOnPageOneButNotAtPositionZero(): void
    {
        Queue::fake();
        $this->seedMaxWeightedSetting(2);

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

        $weightedOffer = CatalogOffer::factory()->create(['active' => true, 'weight' => 1]);
        CatalogOffer::factory()->create(['active' => true, 'weight' => 0]);

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

        $response->assertStatus(200);

        $data = $response->json('results.data');

        // Weighted offer appears on page 1
        $catalogOffer = collect($data)->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOffer);
        $this->assertEquals($weightedOffer->id, $catalogOffer['id']);

        // First item must be a vehicle, not an offer card
        $this->assertNotEquals('catalog-offer', $data[0]['type']);
    }

    public function testTwoWeightedOffersAppearOnPageOneNotAdjacent(): void
    {
        Queue::fake();
        $this->seedMaxWeightedSetting(2);

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

        $offerA = CatalogOffer::factory()->create(['active' => true, 'weight' => 2]);
        $offerB = CatalogOffer::factory()->create(['active' => true, 'weight' => 1]);

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

        $response->assertStatus(200);

        $data = $response->json('results.data');
        $offerPositions = collect($data)
            ->keys()
            ->filter(fn ($key) => $data[$key]['type'] === 'catalog-offer')
            ->values();

        // Both offers present
        $this->assertCount(2, $offerPositions);

        // Neither at position 0
        $this->assertNotContains(0, $offerPositions->toArray());

        // Not adjacent to each other
        $this->assertGreaterThan(1, abs($offerPositions[0] - $offerPositions[1]));
    }

    public function testPageTwoFallsBackToRandomOfferWhenWeightedConfigured(): void
    {
        Queue::fake();
        $this->seedMaxWeightedSetting(2);

        Vehicle::factory(20)->create(['is_published' => true]);
        CatalogOffer::factory()->create(['active' => true, 'weight' => 1]);

        $response = $this->postJson(route('vehicles.index'), ['page' => 2]);

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testWeightedOfferFeatureOffFallsBackToRandom(): void
    {
        Queue::fake();
        // catalog-offer-max-weighted not seeded (defaults to 0 = feature off)

        Vehicle::factory(5)->create(['is_published' => true]);
        CatalogOffer::factory()->create(['active' => true, 'weight' => 1]);

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

        $response->assertStatus(200);
        // Offer still appears (falls back to random), just not pinned to position 0
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testWeightedOfferWithNonMatchingRulesNotInjected(): void
    {
        Queue::fake();
        $this->seedMaxWeightedSetting(2);

        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();

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

        $weightedOffer = CatalogOffer::factory()->create(['active' => true, 'weight' => 1]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $weightedOffer->id,
            'field' => 'make_id',
            'condition' => '=',
            'value' => $make2->id,
        ]);

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

        $response->assertStatus(200);

        // Weighted offer rules don't match so it should not appear
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    private function seedMaxWeightedSetting(int $value): void
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'General',
            'name' => 'Max weighted offer cards on page 1',
            'config_key' => 'catalog-offer-max-weighted',
            'type' => 'integer',
            'value' => $value,
        ]);
    }

    public function testCatalogOfferWithInConditionAndMultipleMakes()
    {
        Queue::fake();
        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();
        $make3 = VehicleMake::factory()->create();

        // Vehicles with make1 and make2
        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make1->id,
        ]);
        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make2->id,
        ]);
        // Vehicle with make3 (not in offer target)
        Vehicle::factory(1)->create([
            'is_published' => true,
            'make_id' => $make3->id,
        ]);

        // Offer targets make1 and make2
        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'make_id',
            'condition' => 'in',
            'value' => json_encode([$make1->id, $make2->id]),
        ]);

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

        $response->assertStatus(200);
        // 5 vehicles + 1 catalog offer (because some vehicles match the rule)
        $this->assertEquals(5, $response->json('results.total'));
        $this->assertCount(6, $response->json('results.data'));

        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithLabelEqualsRuleIsIncludedWhenVehicleHasLabel()
    {
        Queue::fake();
        $label = Label::factory()->create(['active' => true]);

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

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

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'label',
            'condition' => '=',
            'value' => $label->id,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithLabelEqualsRuleIsExcludedWhenNoVehicleHasLabel()
    {
        Queue::fake();
        $label = Label::factory()->create(['active' => true]);
        Vehicle::factory(5)->create(['is_published' => true]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'label',
            'condition' => '=',
            'value' => $label->id,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithLabelNotEqualsRuleHidesOfferWhenAllVehiclesHaveLabel()
    {
        Queue::fake();
        $label = Label::factory()->create(['active' => true]);

        $vehicles = Vehicle::factory(3)->create(['is_published' => true]);
        foreach ($vehicles as $vehicle) {
            VehicleLabel::create([
                'vehicle_id' => $vehicle->id,
                'label_id' => $label->id,
            ]);
        }

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'label',
            'condition' => '!=',
            'value' => $label->id,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithLabelNotEqualsRuleShowsOfferWhenSomeVehiclesLackLabel()
    {
        Queue::fake();
        $label = Label::factory()->create(['active' => true]);

        $tagged = Vehicle::factory()->create(['is_published' => true]);
        VehicleLabel::create([
            'vehicle_id' => $tagged->id,
            'label_id' => $label->id,
        ]);

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

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'label',
            'condition' => '!=',
            'value' => $label->id,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithLabelInRuleMatchesAnyOfMultipleLabels()
    {
        Queue::fake();
        $label1 = Label::factory()->create(['active' => true]);
        $label2 = Label::factory()->create(['active' => true]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);
        VehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label2->id,
        ]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'label',
            'condition' => 'in',
            'value' => json_encode([$label1->id, $label2->id]),
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithConditionNewRuleIsIncludedWhenNewVehiclesExist()
    {
        Queue::fake();
        Vehicle::factory()->create(['is_published' => true, 'is_new' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'is_new' => false]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'condition',
            'condition' => '=',
            'value' => 1,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithConditionNewRuleIsExcludedWhenOnlyUsedVehiclesExist()
    {
        Queue::fake();
        Vehicle::factory(5)->create(['is_published' => true, 'is_new' => false]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'condition',
            'condition' => '=',
            'value' => 1,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithConditionUsedRuleIsIncludedWhenUsedVehiclesExist()
    {
        Queue::fake();
        Vehicle::factory(5)->create(['is_published' => true, 'is_new' => false]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'condition',
            'condition' => '=',
            'value' => 0,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNotNull($catalogOfferInResults);
    }

    public function testCatalogOfferWithConditionUsedRuleIsExcludedWhenOnlyNewVehiclesExist()
    {
        Queue::fake();
        Vehicle::factory(5)->create(['is_published' => true, 'is_new' => true]);

        $offer = CatalogOffer::factory()->create(['active' => true]);
        CatalogOfferRule::query()->create([
            'catalog_offer_id' => $offer->id,
            'field' => 'condition',
            'condition' => '=',
            'value' => 0,
        ]);

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

        $response->assertStatus(200);
        $catalogOfferInResults = collect($response->json('results.data'))
            ->firstWhere('type', 'catalog-offer');
        $this->assertNull($catalogOfferInResults);
    }
}
