<?php

namespace Tests\Tenant;

use App\Facades\Feature;
use App\Facades\Settings;
use App\Models\FilterIndex;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use Mtc\Crm\Models\EnquiryType;
use Mtc\Crm\Models\Form;
use Mtc\Crm\Models\FormQuestion;
use Mtc\Crm\Models\FormSection;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\OfferType;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\SeoDefault;
use Mtc\MercuryDataModels\TransmissionType;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleOfferFinance;
use Tests\OfferFilterSettingSeed;
use Tests\TenantTestCase;

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

    public function testListOffers()
    {
        Page::factory()->create(['slug' => 'offers']);
        $make = VehicleMake::factory()->create();
        $index = FilterIndex::factory()->create([
            'filter_id' => $make->id,
            'filter_type' => 'make',
        ]);
        $model = VehicleModel::factory()->create(['make_id' => $make->id]);
        FilterIndex::factory()->create([
            'filter_id' => $model->id,
            'filter_type' => 'model',
        ]);

        $make2 = VehicleMake::factory()->create();
        FilterIndex::factory()->create([
            'filter_id' => $make2->id,
            'filter_type' => 'make',
        ]);
        $model2 = VehicleModel::factory()->create(['make_id' => $make2->id]);
        FilterIndex::factory()->create([
            'filter_id' => $model2->id,
            'filter_type' => 'model',
        ]);

        $type = OfferType::factory()->create();
        VehicleOffer::factory(5)
            ->create([
                'make_id' => $make->id,
                'model_id' => $model->id,
                'published_at' => Carbon::now()->subDays(3),
                'type_id' => $type->id,
            ]);
        VehicleOffer::factory(3)->create([
            'make_id' => $make2->id,
            'model_id' => $model2->id,
            'type_id' => $type->id,

        ]);
        $response = $this
            ->postJson(route('offers.index', $index->slug));

        $response->assertStatus(200);
        $this->assertArrayHasKey('page', $response->json());
        $this->assertArrayHasKey('featured', $response->json());
        $this->assertArrayHasKey('makes', $response->json());
        $this->assertArrayHasKey('models', $response->json());
        $this->assertArrayHasKey('models', $response->json());
    }

    public function testSearchOffers()
    {
        Page::factory()->create(['slug' => 'offers']);
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create();

        $type = OfferType::factory()->create();
        VehicleOffer::factory(5)
            ->create([
                'make_id' => $make->id,
                'model_id' => $model->id,
                'published_at' => Carbon::now()->subDays(3),
                'type_id' => $type->id,
            ]);
        VehicleOffer::factory(3);
        $response = $this
            ->postJson(route('offers.search', $make->slug));

        $response->assertStatus(200);
        $this->assertArrayHasKey('make', $response->json());
        $this->assertEquals($make->name, $response->json('make'));
        $this->assertArrayHasKey('models', $response->json());
        $this->assertArrayHasKey('offers', $response->json());
        foreach ($response->json('offers.data') as $offer) {
            $this->assertArrayHasKey('cta_button1_label', $offer);
            $this->assertArrayHasKey('cta_button1_url', $offer);
            $this->assertArrayHasKey('cta_button2_label', $offer);
            $this->assertArrayHasKey('cta_button2_url', $offer);
            $this->assertArrayHasKey('footnote', $offer);
        }
    }
    public function testSearchOffersLooseMatch()
    {
        Page::factory()->create(['slug' => 'offers']);
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create(['name' => 'foobar']);
        $type = OfferType::factory()->create();
        VehicleOffer::factory(5)
            ->create([
                'make_id' => $make->id,
                'model_id' => $model->id,
                'published_at' => Carbon::now()->subDays(3),
                'type_id' => $type->id,
            ]);
        VehicleOffer::factory(3);
        $response = $this
            ->postJson(route('offers.search', $make->slug), [
                'model_id' => 'foobar',
            ]);
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('offers.total'));

        $response = $this
            ->postJson(route('offers.search', $make->slug), [
                'model_id' => 'foo',
            ]);
        $response->assertStatus(404);

        $response = $this
            ->postJson(route('offers.search', $make->slug), [
                'model_id' => 'foo',
                'loose_model_match' => true
            ]);
        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('offers.total'));
    }

    public function testShowOffer()
    {
        Http::fake([
            'https://cdn.imagin.studio/getPaints*' => Http::response(['paintData' => ['paintCombinations' => []]])
        ]);
        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);
        $offer = VehicleOffer::factory()->create();
        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);

        $this->assertArrayHasKey('cta_button1_label', $response->json());
        $this->assertArrayHasKey('cta_button1_url', $response->json());
        $this->assertArrayHasKey('cta_button2_label', $response->json());
        $this->assertArrayHasKey('cta_button2_url', $response->json());
        $this->assertArrayHasKey('footnote', $response->json());
    }

    public function testShowOfferWithSeoData()
    {
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create();
        $offer = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'published' => 1,
            'seo' => ['title' => 'foo', 'description' => 'baz bar']
        ]);
        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);
        $this->assertEquals('foo', $response->json('seo.title'));
        $this->assertEquals('baz bar', $response->json('seo.description'));

        SeoDefault::query()->create([
            'section' => 'offer',
            'title' => '{{TITLE}} | {{MAKE}} Offers | {{SITE_NAME}} ',
            'description' => '{{CONTENT_EXCERPT}}',
        ]);

        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create();
        $offer = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);
        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);
        $this->assertStringContainsString($offer->name, $response->json('seo.title'));
        $this->assertStringContainsString($make->name, $response->json('seo.title'));
    }

    public function testOfferHasForm()
    {
        $form = Form::factory()->create();
        $section = FormSection::factory()->create(['form_id' => $form->id]);
        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'type' => 'text',
            'name' => 'First Name',
            'validation' => 'required',
        ]);

        $offer = VehicleOffer::factory()->create();

        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);

        $offer->update([
            'form_id' => $form->id,
        ]);
        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('forms.enquire'));
        $this->assertEquals($form->id, $response->json('forms.enquire.id'));
    }

    public function testOfferShowsDealershipNumber()
    {
        $this->withoutExceptionHandling();
        $dealership1 = Dealership::factory()->create([
            'contact_no' => '123123',
        ]);
        $dealership2 = Dealership::factory()->create([
            'contact_no' => null
        ]);
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create();

        $offer = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'published' => 1,
        ]);
        $offer1 = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'dealership_id' => $dealership1,
            'published' => 1,
        ]);
        $offer2 = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'dealership_id' => $dealership2,
            'published' => 1,
        ]);

        $response = $this
            ->getJson(route('offers.show', $offer));
        $response->assertStatus(200);
        $this->assertNull($response->json('contact_number'));

        $response = $this
            ->getJson(route('offers.show', $offer1));
        $response->assertStatus(200);
        $this->assertIsArray($response->json('contact_number'));
        $this->assertArrayHasKey('number', $response->json('contact_number'));
        $this->assertArrayHasKey('display', $response->json('contact_number'));
        $this->assertStringContainsString('123123', $response->json('contact_number.number'));

        $response = $this
            ->getJson(route('offers.show', $offer2));
        $response->assertStatus(200);
        $this->assertNull($response->json('contact_number'));
    }

    public function testOfferMakeFilter()
    {
        $this->seed(OfferFilterSettingSeed::class);

        $make_1 = VehicleMake::factory()->create();
        $make_2 = VehicleMake::factory()->create();

        VehicleOffer::factory(2)->create([
            'make_id' => $make_1->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'make_id' => $make_2->id,
            'published' => 1,
        ]);

        $response = $this
            ->postJson(route('offers.search-with-filters'));

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

        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make_1->slug,
                    ],
                ],
            ]);

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

        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make_2->slug,
                    ],
                ],
            ]);

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

        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'make',
                        'value' => $make_1->slug,
                    ],
                    [
                        'type' => 'make',
                        'value' => $make_2->slug,
                    ],
                ],
            ]);

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

    public function testFilterByModel()
    {
        $this->seed(OfferFilterSettingSeed::class);

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

        FilterIndex::factory()->create([
            'filter_id' => $model->id,
            'filter_type' => 'model',
            'slug' => $model->slug,
        ]);

        FilterIndex::factory()->create([
            'filter_id' => $model2->id,
            'filter_type' => 'model',
            'slug' => $model2->slug,
        ]);

        VehicleOffer::factory(5)->create([
            'model_id' => $model->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'model_id' => $model2->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(10)->create([
            'model_id' => 100,
            'published' => 1,
        ]);

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

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

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

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

    public function testPriceSelectFilters()
    {
        $this->seed();
        $this->seed(OfferFilterSettingSeed::class);
        VehicleOffer::factory()->create([
            'price' => 12000,
            'published' => 1,
        ]);
        VehicleOffer::factory()->create([
            'price' => 23000,
            'published' => 1,
        ]);
        VehicleOffer::factory()->create([
            'price' => 45000,
            'published' => 1,
        ]);
        $response = $this
            ->postJson(route('offers.search-with-filters'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));

        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                '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('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_max',
                        'value' => 5000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_max',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_min',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testMonthlyPriceSelectFilters()
    {
        $this->seed();
        $this->seed(OfferFilterSettingSeed::class);
        $offer_1 = VehicleOffer::factory()->create();
        $offer_2 = VehicleOffer::factory()->create();
        $offer_3 = VehicleOffer::factory()->create();

        VehicleOfferFinance::query()->create([
            'offer_id' => $offer_1->id,
            'published' => 1,
            'monthly_price' => 12000
        ]);

        VehicleOfferFinance::query()->create([
            'offer_id' => $offer_2->id,
            'published' => 1,
            'monthly_price' => 23000
        ]);

        VehicleOfferFinance::query()->create([
            'offer_id' => $offer_3->id,
            'published' => 1,
            'monthly_price' => 45000
        ]);

        $response = $this
            ->postJson(route('offers.search-with-filters'));
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $this->assertArrayHasKey('monthly_price', $response->json('filters'));
        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                '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('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_max',
                        'value' => 5000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_max',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(3, $response->json('results.total'));
        $response = $this
            ->postJson(route('offers.search-with-filters'), [
                'selections' => [
                    [
                        'type' => 'price_monthly_min',
                        'value' => 99000,
                    ],
                ]
            ]);
        $response->assertStatus(200);
        $this->assertEquals(0, $response->json('results.total'));
    }

    public function testFilterByLocation()
    {
        $this->seed(OfferFilterSettingSeed::class);
        $location = Dealership::factory()->create();
        $location2 = Dealership::factory()->create();
        VehicleOffer::factory(5)->create([
            'dealership_id' => $location->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'dealership_id' => $location2->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(10)->create([
            'dealership_id' => 100,
            'published' => 1,
        ]);

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

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

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

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

    public function testFilterByColour()
    {
        $this->seed(OfferFilterSettingSeed::class);
        VehicleOffer::factory(5)->create([
            'colour' => 'red',
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'colour' => 'black',
            'published' => 1,
        ]);
        VehicleOffer::factory(10)->create([
            'colour' => 'silver',
            'published' => 1,
        ]);

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

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

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

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

    public function testFilterByBodyStyle()
    {
        $this->seed(OfferFilterSettingSeed::class);
        $body_style = BodyStyleType::factory()->create();
        $body_style2 = BodyStyleType::factory()->create();
        FilterIndex::factory()->create([
            'filter_id' => $body_style->id,
            'filter_type' => 'body_type',
            'slug' => $body_style->slug,
        ]);
        FilterIndex::factory()->create([
            'filter_id' => $body_style2->id,
            'filter_type' => 'body_type',
            'slug' => $body_style2->slug,
        ]);

        VehicleOffer::factory(5)->create([
            'body_style_id' => $body_style->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'body_style_id' => $body_style2->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(10)->create([
            'body_style_id' => 100,
            'published' => 1,
        ]);

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

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

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

        // Both
        $response4 = $this
            ->postJson(route('offers.search-with-filters'), [
                '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 testFilterByFuelType()
    {
        $this->seed(OfferFilterSettingSeed::class);
        $fuel_type = FuelType::factory()->create(['slug' => 'foo']);
        $fuel_type2 = FuelType::factory()->create(['slug' => 'faz']);

        VehicleOffer::factory(5)->create([
            'fuel_type_id' => $fuel_type->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(3)->create([
            'fuel_type_id' => $fuel_type2->id,
            'published' => 1,
        ]);
        VehicleOffer::factory(10)->create([
            'fuel_type_id' => 100,
            'published' => 1,
        ]);

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

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

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

        // Both
        $response4 = $this
            ->postJson(route('offers.search-with-filters'), [
                '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 testFilterByTransmission()
    {
        $this->seed(OfferFilterSettingSeed::class);
        $transmission = TransmissionType::factory()->create();
        $transmission2 = TransmissionType::factory()->create();

        FilterIndex::factory()->create([
            'filter_id' => $transmission->id,
            'filter_type' => 'transmission',
            'slug' => $transmission->slug,
        ]);

        FilterIndex::factory()->create([
            'filter_id' => $transmission2->id,
            'filter_type' => 'transmission',
            'slug' => $transmission2->slug,
        ]);

        VehicleOffer::factory(5)->create([
            'transmission_id' => $transmission->id,
        ]);
        VehicleOffer::factory(3)->create([
            'transmission_id' => $transmission2->id,
        ]);
        VehicleOffer::factory(10)->create([
            'transmission_id' => 100,
        ]);

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

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

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

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

    public function testFilterResults()
    {
        $this->seed(OfferFilterSettingSeed::class);

        $make_1 = VehicleMake::factory()->create();
        $make_2 = VehicleMake::factory()->create();

        $model_1 = VehicleModel::factory()->create([
            'make_id' => $make_1->id,
        ]);
        $model_2 = VehicleModel::factory()->create([
            'make_id' => $make_2->id,
        ]);

        $fuel_type_1 = FuelType::factory()->create();
        $fuel_type_2 = FuelType::factory()->create();

        $transmission_1 = TransmissionType::factory()->create();
        $transmission_2 = TransmissionType::factory()->create();

        $body_style_1 = BodyStyleType::factory()->create();
        $body_style_2 = BodyStyleType::factory()->create();

        $dealership_1 = Dealership::factory()->create();
        $dealership_2 = Dealership::factory()->create();

        FilterIndex::factory()->create([
            'name' => 'red',
            'filter_type' => 'colour',
        ]);

        FilterIndex::factory()->create([
            'name' => 'blue',
            'filter_type' => 'colour',
        ]);

        $vehicle_offer_1 = VehicleOffer::factory()->create([
            'make_id' => $make_1->id,
            'model_id' => $model_1,
            'fuel_type_id' => $fuel_type_1,
            'transmission_id' => $transmission_1,
            'body_style_id' => $body_style_1,
            'colour' => 'red',
            'dealership_id' => $dealership_1->id,
            'price' => 22000,
        ]);

        $vehicle_offer_2 = VehicleOffer::factory()->create([
            'make_id' => $make_2->id,
            'model_id' => $model_2,
            'fuel_type_id' => $fuel_type_2,
            'transmission_id' => $transmission_2,
            'body_style_id' => $body_style_2,
            'colour' => 'blue',
            'dealership_id' => $dealership_2->id,
            'price' => 33000,
        ]);

        $finance_1 = VehicleOfferFinance::query()->create([
            'offer_id' => $vehicle_offer_1->id,
            'monthly_price' => 123,
        ]);

        $finance_2 = VehicleOfferFinance::query()->create([
            'offer_id' => $vehicle_offer_2->id,
            'monthly_price' => 789,
        ]);

        $this->assertCount(2, VehicleOffer::all());
        $this->assertCount(2, VehicleOfferFinance::all());

        $this->assertEquals($vehicle_offer_1->id, $finance_1->offer_id);
        $this->assertEquals($vehicle_offer_2->id, $finance_2->offer_id);

        $response = $this
            ->postJson(route('offers.search-with-filters'));

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

        $this->assertArrayHasKey('make', $response->json('filters'));
        $this->assertArrayHasKey('model', $response->json('filters'));
        $this->assertArrayHasKey('price', $response->json('filters'));
        $this->assertArrayHasKey('monthly_price', $response->json('filters'));
        $this->assertArrayHasKey('location', $response->json('filters'));
        $this->assertArrayHasKey('colour', $response->json('filters'));
        $this->assertArrayHasKey('body_type', $response->json('filters'));
        $this->assertArrayHasKey('fuel_type', $response->json('filters'));
        $this->assertArrayHasKey('transmission', $response->json('filters'));

        $this->assertNotEmpty($response->json('filters.make.results'));
        $this->assertNotEmpty($response->json('filters.model.results'));
        $this->assertNotEmpty($response->json('filters.fuel_type.results'));
        $this->assertNotEmpty($response->json('filters.transmission.results'));
        $this->assertNotEmpty($response->json('filters.body_type.results'));
        $this->assertNotEmpty($response->json('filters.colour.results'));
        $this->assertNotEmpty($response->json('filters.location.results'));
        $this->assertNotEmpty($response->json('filters.price.results.filter_min'));
        $this->assertNotEmpty($response->json('filters.price.results.filter_max'));
        $this->assertNotEmpty($response->json('filters.monthly_price.results.filter_min'));
        $this->assertNotEmpty($response->json('filters.monthly_price.results.filter_max'));
    }

    public function testOfferContent()
    {
        $this->seed(OfferFilterSettingSeed::class);

        $make_1 = VehicleMake::factory()->create();
        $model_1 = VehicleModel::factory()->create([
            'make_id' => $make_1->id,
        ]);
        $fuel_type_1 = FuelType::factory()->create();
        $transmission_1 = TransmissionType::factory()->create();
        $body_style_1 = BodyStyleType::factory()->create();
        $dealership_1 = Dealership::factory()->create();


        $vehicle_offer_1 = VehicleOffer::factory()->create([
            'make_id' => $make_1->id,
            'model_id' => $model_1,
            'fuel_type_id' => $fuel_type_1,
            'transmission_id' => $transmission_1,
            'body_style_id' => $body_style_1,
            'colour' => 'red',
            'dealership_id' => $dealership_1->id,
            'mpg' => 123,
            'new_car_type' => 'coming soon',
            'trim' => 'foo',
        ]);

        VehicleOfferFinance::query()->create([
            'offer_id' => $vehicle_offer_1->id,
            'monthly_price' => 123,
            'apr' => 55,
            'finance_type' => 'PCP',
        ]);

        $response = $this
            ->postJson(route('offers.search-with-filters'));

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

        $this->assertArrayHasKey('make', $response->json('results.data.0'));
        $this->assertArrayHasKey('model', $response->json('results.data.0'));
        $this->assertArrayHasKey('derivative', $response->json('results.data.0'));
        $this->assertArrayHasKey('fuel_type', $response->json('results.data.0'));
        $this->assertArrayHasKey('transmission_type', $response->json('results.data.0'));
        $this->assertArrayHasKey('mpg', $response->json('results.data.0'));
        $this->assertArrayHasKey('apr', $response->json('results.data.0'));
        $this->assertArrayHasKey('price', $response->json('results.data.0'));
        $this->assertArrayHasKey('monthly_price', $response->json('results.data.0'));
        $this->assertArrayHasKey('monthly_price_type', $response->json('results.data.0'));
        $this->assertArrayHasKey('dealership', $response->json('results.data.0'));
        $this->assertArrayHasKey('type', $response->json('results.data.0'));
        $this->assertArrayHasKey('finance_example', $response->json('results.data.0'));
        $this->assertArrayHasKey('colour', $response->json('results.data.0'));
        $this->assertArrayHasKey('trim', $response->json('results.data.0'));

        $this->assertNotNull($response->json('results.data.0.make'));
        $this->assertNotNull($response->json('results.data.0.model'));
        $this->assertNotNull($response->json('results.data.0.derivative'));
        $this->assertNotNull($response->json('results.data.0.fuel_type'));
        $this->assertNotNull($response->json('results.data.0.transmission_type'));
        $this->assertNotNull($response->json('results.data.0.mpg'));
        $this->assertNotNull($response->json('results.data.0.apr'));
        $this->assertNotNull($response->json('results.data.0.price'));
        $this->assertNotNull($response->json('results.data.0.monthly_price'));
        $this->assertNotNull($response->json('results.data.0.monthly_price_type'));
        $this->assertNotNull($response->json('results.data.0.dealership'));
        $this->assertNotNull($response->json('results.data.0.type'));
        $this->assertNotNull($response->json('results.data.0.finance_example'));
        $this->assertNotNull($response->json('results.data.0.colour'));
        $this->assertNotNull($response->json('results.data.0.trim'));

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

    public function testShowOfferData()
    {
        $this->withoutExceptionHandling();
        $this->seed(OfferFilterSettingSeed::class);

        $make_1 = VehicleMake::factory()->create();
        $model_1 = VehicleModel::factory()->create([
            'make_id' => $make_1->id,
        ]);
        $fuel_type_1 = FuelType::factory()->create();
        $transmission_1 = TransmissionType::factory()->create();
        $body_style_1 = BodyStyleType::factory()->create();
        $dealership_1 = Dealership::factory()->create();

        FilterIndex::factory()->create([
            'name' => 'red',
            'filter_type' => 'colour',
        ]);

        $vehicle_offer_1 = VehicleOffer::factory()->create([
            'make_id' => $make_1->id,
            'model_id' => $model_1,
            'fuel_type_id' => $fuel_type_1,
            'transmission_id' => $transmission_1,
            'body_style_id' => $body_style_1,
            'colour' => 'red',
            'dealership_id' => $dealership_1->id,
            'mpg' => 123,
            'new_car_type' => 'coming soon',
            'trim' => 'foo',
        ]);

        VehicleOfferFinance::query()->create([
            'offer_id' => $vehicle_offer_1->id,
            'monthly_price' => 123,
            'apr' => 55,
        ]);

        $response = $this
            ->getJson(route('offers.show', $vehicle_offer_1));

        $response->assertStatus(200);

        $this->assertArrayHasKey('make_name', $response->json());
        $this->assertArrayHasKey('model_name', $response->json());
        $this->assertArrayHasKey('derivative', $response->json());
        $this->assertArrayHasKey('fuel_type', $response->json());
        $this->assertArrayHasKey('transmission_type', $response->json());
        $this->assertArrayHasKey('mpg', $response->json());
        $this->assertArrayHasKey('apr', $response->json());
        $this->assertArrayHasKey('price', $response->json());
        $this->assertArrayHasKey('monthly_price', $response->json());
        $this->assertArrayHasKey('dealership', $response->json());
        $this->assertArrayHasKey('type', $response->json());
        $this->assertArrayHasKey('colour', $response->json());
        $this->assertArrayHasKey('trim', $response->json());

        $this->assertNotNull($response->json('make_name'));
        $this->assertNotNull($response->json('model_name'));
        $this->assertNotNull($response->json('derivative'));
        $this->assertNotNull($response->json('fuel_type'));
        $this->assertNotNull($response->json('transmission_type'));
        $this->assertNotNull($response->json('mpg'));
        $this->assertNotNull($response->json('apr'));
        $this->assertNotNull($response->json('price'));
        $this->assertNotNull($response->json('monthly_price'));
        $this->assertNotNull($response->json('dealership'));
        $this->assertNotNull($response->json('type'));
        $this->assertNotNull($response->json('colour'));
        $this->assertNotNull($response->json('trim'));

        $this->assertEquals('foo', $response->json('trim'));
    }

    public function testOfferHasTestDriveForm()
    {
        $offer = VehicleOffer::factory()->create();
        $response = $this
            ->getJson(route('offers.show', $offer));
        $response->assertStatus(200);
        $this->assertArrayHasKey('forms', $response->json());
        $this->assertCount(2, $response->json('forms'));
        $this->assertArrayHasKey('enquire', $response->json('forms'));
        $this->assertArrayHasKey('test_drive', $response->json('forms'));
        $this->assertNull($response->json('forms.test_drive'));

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

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

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

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

        $response = $this
            ->getJson(route('offers.show', $offer));

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

    public function testOfferShowData()
    {
        $this->withoutExceptionHandling();
        $dealership = Dealership::factory()->create();
        $body_style = BodyStyleType::factory()->create();
        $fuel = FuelType::factory()->create();
        $transmission = TransmissionType::factory()->create();

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

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

        $offer = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'dealership_id' => $dealership,
            'fuel_type_id' => $fuel->id,
            'transmission_id' => $transmission->id,
            'body_style_id' => $body_style->id,
            'mpg' => 123,
            'battery_range' => 456,
            'battery_capacity_kwh' => 789,
            'battery_usable_capacity_kwh' => 321,
            'battery_charge_time' => 654,
            'battery_quick_charge_time' => 987,
            'engine_size_cc' => 1995,
            'co2' => 555,
            'key_features' => [
                'a',
                'b',
                'c'
            ],
            'technical_spec' => [
                'd',
                'e',
            ],
            'standard_spec' => [
                'x',
            ],
            'description' => 'Aliquam at mi vitae justo sodales hendrerit quis id libero.',
            'youtube_video' => 'https://www.youtube.com/watch?v=LXb3EKWsInQ',
            't_and_cs' => 'Aliquam at mi vitae justo sodales hendrerit quis id libero.'
        ]);

        $finance = new VehicleOfferFinance();
        $finance->offer_id = $offer->id;
        $finance->monthly_price = 300;
        $finance->finance_type = 'PCP';
        $finance->save();

        $response = $this
            ->getJson(route('offers.show', $offer));
        $response->assertStatus(200);

        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('dealership', $response->json());
        $this->assertArrayHasKey('fuel_type', $response->json());
        $this->assertArrayHasKey('transmission_type', $response->json());
        $this->assertArrayHasKey('colour', $response->json());
        $this->assertArrayHasKey('mpg', $response->json());
        $this->assertArrayHasKey('battery_range', $response->json());
        $this->assertArrayHasKey('battery_capacity_kwh', $response->json());
        $this->assertArrayHasKey('battery_usable_capacity_kwh', $response->json());
        $this->assertArrayHasKey('battery_charge_time', $response->json());
        $this->assertArrayHasKey('battery_quick_charge_time', $response->json());
        $this->assertArrayHasKey('engine_size_cc', $response->json());
        $this->assertArrayHasKey('body_style', $response->json());
        $this->assertArrayHasKey('co2', $response->json());
        $this->assertArrayHasKey('key_features', $response->json());
        $this->assertArrayHasKey('technical_spec', $response->json());
        $this->assertArrayHasKey('standard_spec', $response->json());
        $this->assertArrayHasKey('description', $response->json());
        $this->assertArrayHasKey('youtube_video', $response->json());
        $this->assertArrayHasKey('t_and_cs', $response->json());
        $this->assertArrayHasKey('finance', $response->json());
        $this->assertArrayHasKey('monthly_price', $response->json());
        $this->assertArrayHasKey('monthly_price_type', $response->json());
        $this->assertArrayHasKey('make_name', $response->json());
        $this->assertArrayHasKey('model_name', $response->json());
        $this->assertArrayHasKey('make_slug', $response->json());
        $this->assertArrayHasKey('model_slug', $response->json());

        $this->assertEquals($fuel->name, $response->json('fuel_type'));
        $this->assertEquals($transmission->name, $response->json('transmission_type'));
        $this->assertEquals($offer->mpg, $response->json('mpg'));
        $this->assertEquals($offer->battery_range, $response->json('battery_range'));
        $this->assertEquals($offer->battery_capacity_kwh, $response->json('battery_capacity_kwh'));
        $this->assertEquals($offer->battery_usable_capacity_kwh, $response->json('battery_usable_capacity_kwh'));
        $this->assertEquals($offer->battery_charge_time, $response->json('battery_charge_time'));
        $this->assertEquals($offer->battery_quick_charge_time, $response->json('battery_quick_charge_time'));
        $this->assertEquals($offer->engine_size_cc, $response->json('engine_size_cc'));
        $this->assertEquals($body_style->name, $response->json('body_style'));
        $this->assertEquals($offer->co2, $response->json('co2'));
        $this->assertEquals($offer->description, $response->json('description'));
        $this->assertEquals($offer->youtube_video, $response->json('youtube_video'));
        $this->assertEquals($offer->t_and_cs, $response->json('t_and_cs'));
        $this->assertEquals($make->name, $response->json('make_name'));
        $this->assertEquals($model->name, $response->json('model_name'));
        $this->assertEquals($make->slug, $response->json('make_slug'));
        $this->assertEquals($model->slug, $response->json('model_slug'));

        $this->assertNotNull($response->json('dealership'));
        $this->assertNotNull($response->json('finance'));

        $this->assertIsArray($response->json('key_features'));
        $this->assertIsArray($response->json('technical_spec'));
        $this->assertIsArray($response->json('standard_spec'));
        $this->assertIsArray($response->json('finance'));
        $this->assertCount(3, $response->json('key_features'));
        $this->assertCount(2, $response->json('technical_spec'));
        $this->assertCount(1, $response->json('standard_spec'));
        $this->assertCount(1, $response->json('finance'));
        $this->assertEquals(300, $response->json('finance.PCP.monthly_price'));
        $this->assertEquals(300, $response->json('monthly_price'));
        $this->assertEquals('PCP', $response->json('monthly_price_type'));
    }

    public function testOfferShowContainsImaginStudioUrl()
    {
        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);

        $offer = VehicleOffer::factory()->create();

        $response = $this
            ->getJson(route('offers.show', $offer));

        $response->assertStatus(200);

        $this->assertArrayHasKey('imagin_studio_base_url', $response->json());
        $this->assertNotEmpty($response->json('imagin_studio_base_url'));
    }

    public function testSearchContainsImaginStudioUrl()
    {
        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);

        VehicleOffer::factory(3)->create();

        $response = $this
            ->postJson(route('offers.search-with-filters'));

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

        $this->assertArrayHasKey('imagin_studio_base_url', $response->json());
        $this->assertNotEmpty($response->json('imagin_studio_base_url'));
    }
}
