<?php

namespace Tests\Tenant;

use App\Crm\Config\EnquiryMaxConfig;
use App\Facades\Settings;
use App\Services\EnquiryMaxApi;
use App\Services\LocatingService;
use Carbon\Carbon;
use Database\Seeders\Tenant\EnquiryMaxSettingSeeder;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Mockery;
use Mockery\MockInterface;
use Mtc\Crm\Facades\Enquiries;
use Mtc\Crm\Models\Enquiry;
use Mtc\Crm\Models\EnquiryAction;
use Mtc\Crm\Models\FormQuestion;
use Mtc\Crm\Models\FormSection;
use Mtc\MercuryDataModels\Contracts\LocatingServiceEngine;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\PostcodeGeo;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleAttributeValue;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleValuation;
use Mtc\VehicleReservations\Facades\Reservation;
use Tests\TenantTestCase;

class SendToEnquiryMaxTest extends TenantTestCase
{

    protected function setUp(): void
    {
        parent::setUp();

        // just to be EXTRA careful that no outbound http call would be made
        Http::preventStrayRequests();
    }

    public function testSendEnquiry()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create();
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

        $this->assertStringContainsString('1123', $enquiry_max->successDetails());
    }

    public function testSkipsProcessed()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create();
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => Carbon::now(),
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

    }

    public function testSkipsTooManyAttempts()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create();
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'attempts' => 3,
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

    }


    public function testGetFormFields()
    {
        $fields = Enquiries::makeAction('send-to-enquiry-max')->formAdditionalDataFields();

        $this->assertIsArray($fields);
        $this->assertArrayHasKey('fallback-dealership', $fields);
    }

    public function testGetDealershipFields()
    {
        $fields = Enquiries::makeAction('send-to-enquiry-max')->dealershipAdditionalDataFields();

        $this->assertIsArray($fields);
        $this->assertArrayHasKey('enquiry-max-dealership', $fields);
    }

    public function testGetFormQuestionDataFields()
    {
        $fields = Enquiries::makeAction('send-to-enquiry-max')->formQuestionDataFields();
        $this->assertArrayHasKey('enquiry-max-field', $fields);
        $this->assertArrayHasKey('type', $fields['enquiry-max-field']);
        $this->assertArrayHasKey('label', $fields['enquiry-max-field']);
        $this->assertArrayHasKey('choices', $fields['enquiry-max-field']);
    }

    public function testVehicleDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 0,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);
        $enquiry = Enquiry::factory()->create([
            'reason_id' => $vehicle->id,
            'reason_type' => 'vehicle'
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['vehicleOfInterest']['isUsed'] === 1
                && $request['vehicleOfInterest']['price'] === 23450
                && $request['vehicleOfInterest']['make'] === 'Ford'
                && $request['vehicleOfInterest']['model'] === 'Raptor'
                && $request['vehicleOfInterest']['derivative'] === '5.6l V6 Extreme'
                && $request['vehicleOfInterest']['vrm'] === 'AB60 DEV'
                && $request['vehicleOfInterest']['fuelType'] === 'Petrol'
                && $request['vehicleOfInterest']['vehicleIdentificationCode'] === '182371283'
                && $request['vehicleOfInterest']['stockNumber'] === $vehicle->id
                && $request['vehicleOfInterest']['odometer']['currentValue'] === 123000;
        });
    }

    public function testCustomerDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $q1 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "forename"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "surname"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "bestTimeToCall"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "preferedContactMethod"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "homeTelephoneNumber"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "emailAddress"]]);
        $q7 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.post"]]);
        $q8 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.phone"]]);
        $q9 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.sms"]]);
        $q10 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.email"]]);
        $q11 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "appointmentDateTime"]]);

        $enquiry = Enquiry::factory()->create([
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => 'PM'],
                $q4->id => ['answer' => 'email'],
                $q5->id => ['answer' => '1231231122'],
                $q6->id => ['answer' => 'jdoe@test.com'],
                $q7->id => ['answer' => 0],
                $q8->id => ['answer' => 0],
                $q9->id => ['answer' => 0],
                $q10->id => ['answer' => 1],
                $q11->id => ['answer' => '2022-04-22'],
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['customer']['forename'] === 'Peter'
                && $request['customer']['surname'] === 'Parker'
                && $request['customer']['bestTimeToCall'] === 'PM'
                && $request['customer']['preferedContactMethod'] === 'email'
                && $request['customer']['homeTelephoneNumber'] === '1231231122'
                && $request['customer']['emailAddress'] === 'jdoe@test.com'
                && $request['customer']['marketingPreferences']['post'] === 'false'
                && $request['customer']['marketingPreferences']['phone'] === 'false'
                && $request['customer']['marketingPreferences']['sms'] === 'false'
                && $request['customer']['marketingPreferences']['email'] === 'true'
                && $request['appointment']['appointmentDateTime'] === '2022-04-22';
        });
    }

    public function testMiscDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $q1 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_source"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_medium"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_campaign"]]);

        $enquiry = Enquiry::factory()->create([
            'details' => [
                $q1->id => ['answer' => 'answer source'],
                $q2->id => ['answer' => 'answer medium'],
                $q3->id => ['answer' => 'answer campaign'],
            ],
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['Misc']['UTM Source'] === 'answer source'
                && $request['Misc']['UTM Medium'] === 'answer medium'
                && $request['Misc']['UTM Campaign'] === 'answer campaign';
        });
    }

    public function testOfferDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $offer = VehicleOffer::factory()->create([
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Limited',
        ]);

        $enquiry = Enquiry::factory()->create([
            'reason_id' => $offer->id,
            'reason_type' => 'offer'
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['vehicleOfInterest']['isUsed'] === 0
                && $request['vehicleOfInterest']['price'] === 23450
                && $request['vehicleOfInterest']['make'] === 'Ford'
                && $request['vehicleOfInterest']['model'] === 'Raptor'
                && $request['vehicleOfInterest']['derivative'] === '5.6l V6 Limited';
        });
    }


    public function testValuationDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 0,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);

        $vehicle_valuation = VehicleValuation::factory()->create();

        $enquiry_model = config('crm.enquiry_model');
        $enquiry = $enquiry_model::create([
            'ingested_at' => random_int(0, 1) ? Carbon::now()->subMinutes(random_int(0, 2000)) : null,
            'form_id' => random_int(1, 50),
            'email' => 'example@example.com',
            'submitter_id' => null,
            'submitter_type' => null,
            'type_id' => 6,
            'status_id' => random_int(1, 10),
            'title' => 'Title Schmitle',
            'message' => "the medium, per Mcluhan",
            'details' => [],
            'data' => [],
            'assigned_user_id' => random_int(0, 10) ?: null,
            'customer_id' => random_int(0, 10) ?: null,
            'reason_id' => $vehicle->id,
            'reason_type' => 'valuation',
            'valuation_id' => $vehicle_valuation->id
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');

        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle_valuation) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['notes'] === 'Valuation: ' . $vehicle_valuation->retail_price;
        });
    }

    public function testAdjustedValuationDataMapping()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 0,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);

        $vehicle_valuation = VehicleValuation::factory()->create([
            'retail_price' => 64900,
            'adjusted_retail_price' => 69420
        ]);

        $enquiry_model = config('crm.enquiry_model');
        $enquiry = $enquiry_model::create([
            'ingested_at' => random_int(0, 1) ? Carbon::now()->subMinutes(random_int(0, 2000)) : null,
            'form_id' => random_int(1, 50),
            'email' => 'example@example.com',
            'submitter_id' => null,
            'submitter_type' => null,
            'type_id' => 6,
            'status_id' => random_int(1, 10),
            'title' => 'Title Schmitle',
            'message' => "the medium, per Mcluhan",
            'details' => [],
            'data' => [],
            'assigned_user_id' => random_int(0, 10) ?: null,
            'customer_id' => random_int(0, 10) ?: null,
            'reason_id' => $vehicle->id,
            'reason_type' => 'valuation',
            'valuation_id' => $vehicle_valuation->id
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');

        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle_valuation) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead'
                && $request['notes'] !== 'Valuation: ' . $vehicle_valuation->retail_price
                && $request['notes'] === 'Valuation: ' . $vehicle_valuation->adjusted_retail_price;
        });
    }

    public function testFullDetailEnquirySend()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'test');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 0,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEL',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182481',
            'odometer_mi' => 123000,
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "forename"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "surname"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "bestTimeToCall"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "preferedContactMethod"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "homeTelephoneNumber"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "emailAddress"]]);
        $q7 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.post"]]);
        $q8 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.phone"]]);
        $q9 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.sms"]]);
        $q10 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "marketing.email"]]);
        $q11 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "appointmentDateTime"]]);
        $q12 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_source"]]);
        $q13 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_medium"]]);
        $q14 = FormQuestion::factory()->create(['data' => ["enquiry-max-field" => "utm_campaign"]]);

        $enquiry = Enquiry::factory()->create([
            'reason_id' => $vehicle->id,
            'reason_type' => 'vehicle',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => 'PM'],
                $q4->id => ['answer' => 'email'],
                $q5->id => ['answer' => '1231231122'],
                $q6->id => ['answer' => 'jdoe@test.com'],
                $q7->id => ['answer' => 0],
                $q8->id => ['answer' => 0],
                $q9->id => ['answer' => 0],
                $q10->id => ['answer' => 1],
                $q11->id => ['answer' => '2022-04-22'],
                $q12->id => ['answer' => 'test-utm-source'],
                $q13->id => ['answer' => 'test-utm-medium'],
                $q14->id => ['answer' => 'test-utm-campaign'],
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://stagingapi.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://stagingapi.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle) {
            return $request->url() === 'https://stagingapi.enquirymax.net/services/v1/2/lead'
                && $request['vehicleOfInterest']['isUsed'] === 1
                && $request['vehicleOfInterest']['price'] === 23450
                && $request['vehicleOfInterest']['make'] === 'Ford'
                && $request['vehicleOfInterest']['model'] === 'Raptor'
                && $request['vehicleOfInterest']['derivative'] === '5.6l V6 Extreme'
                && $request['vehicleOfInterest']['vrm'] === 'AB60 DEL'
                && $request['vehicleOfInterest']['fuelType'] === 'Petrol'
                && $request['vehicleOfInterest']['vehicleIdentificationCode'] === '182481'
                && $request['vehicleOfInterest']['stockNumber'] === $vehicle->id
                && $request['vehicleOfInterest']['odometer']['currentValue'] === 123000
                && $request['customer']['forename'] === 'Peter'
                && $request['customer']['surname'] === 'Parker'
                && $request['customer']['bestTimeToCall'] === 'PM'
                && $request['customer']['preferedContactMethod'] === 'email'
                && $request['customer']['homeTelephoneNumber'] === '1231231122'
                && $request['customer']['emailAddress'] === 'jdoe@test.com'
                && $request['customer']['marketingPreferences']['post'] === 'false'
                && $request['customer']['marketingPreferences']['phone'] === 'false'
                && $request['customer']['marketingPreferences']['sms'] === 'false'
                && $request['customer']['marketingPreferences']['email'] === 'true'
                && $request['appointment']['appointmentDateTime'] === '2022-04-22'
                && $request['Misc']['UTM Source'] === 'test-utm-source'
                && $request['Misc']['UTM Medium'] === 'test-utm-medium'
                && $request['Misc']['UTM Campaign'] === 'test-utm-campaign';
        });
    }

    public function testSendEnquiryToClosestDealership()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        $target_latitude = 56.46;
        $target_longitude = -2.96;
        $this->setMockResponseFromLocatingService($target_latitude, $target_longitude);

        Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => $target_latitude . ',' . $target_longitude,
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ]
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create([
            'details' => [
                2 => 'DD13JA'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'baz'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });
    }

    public function testLocationEnquiryWithDealerIdWhenVehicleAndOfferNotSet()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        $dealer_example = Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => '56.46,-2.96',
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ]
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create([
            'details' => [
                2 => 'DD13JA'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'dealer-id' => $dealer_example->id
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'foo'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });
    }

    public function testLocationEnquiryWithDealerId()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        $dealer_example = Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => '56.46,-2.96',
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ]
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ]
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

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

        $enquiry = Enquiry::factory()->create([
            'reason_type' => 'vehicle',
            'reason_id' => $vehicle->id,
            'details' => [
                2 => 'DD13JA'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'dealer-id' => $dealer_example->id
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'foo'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });
    }

    public function testLocationEnquiryWithFranchiseId()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        $target_latitude = 56.46;
        $target_longitude = -2.96;
        $this->setMockResponseFromLocatingService($target_latitude, $target_longitude);

        Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ],
            'franchise_id' => 1,
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => $target_latitude . ',' . $target_longitude,
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ],
            'franchise_id' => 2,
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ],
            'franchise_id' => 3,
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create([
            'details' => [
                2 => 'DD13JA'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'franchise-id' => 3
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'bar'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });
    }

    public function testLocationEnquiryWithId()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        $target_latitude = 56.46;
        $target_longitude = -2.96;
        $this->setMockResponseFromLocatingService($target_latitude, $target_longitude);

        Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ],
            'franchise_id' => 1,
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => $target_latitude . ',' . $target_longitude,
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ],
            'franchise_id' => 2,
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ],
            'franchise_id' => 3,
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create([
            'details' => [
                2 => 'DD13JA'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'franchise-id' => 3
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'bar'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });
    }

    public function testLocationEnquiryWithFallbackDealership()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'crm-enquiry-max-closest-dealer',
            'value' => true,
            'type' => 'boolean',
        ]);

        Dealership::factory()->create([
            'postcode' => 'AB123LQ',
            'coordinates' => '57.12,-2.09',
            'data' => [
                'enquiry-max-dealership' => 'foo'
            ],
            'franchise_id' => 1,
        ]);

        Dealership::factory()->create([
            'postcode' => 'DD13JA',
            'coordinates' => '56.46,-2.96',
            'data' => [
                'enquiry-max-dealership' => 'baz'
            ],
            'franchise_id' => 2,
        ]);

        Dealership::factory()->create([
            'postcode' => 'G12FF',
            'coordinates' => '55.86,-4.25',
            'data' => [
                'enquiry-max-dealership' => 'bar'
            ],
            'franchise_id' => 3,
        ]);

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

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $enquiry = Enquiry::factory()->create([
            'details' => [
                2 => 'NOT_A_VALID_POSTCODE'
            ],
            'data' => [
                'questions' => [
                    2 => [
                        'enquiry-max-field' => 'address.postcode'
                    ]
                ]
            ]
        ]);

        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'foo'
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        // we expect to have used the dealer ID corresponding to 'foo'
        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/1/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/2/lead';
        });

        Http::assertNotSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/v1/3/lead';
        });
    }

    public function testEnquiryMaxVehicleLink()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'vehicles-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}',
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Foo', 'slug' => 'foo']);
        $model = VehicleModel::factory()->create(['name' => 'Faz', 'slug' => 'faz']);
        $vehicle = Vehicle::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);
        $enquiry = Enquiry::factory()->create([
            'reason_type' => 'vehicle',
            'reason_id' => $vehicle->id,
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        Http::assertSent(function (Request $request) use ($vehicle) {

            if (array_key_exists('link', $request->data())) {
                return $this->assertStringContainsString('/foo/faz/' . $vehicle->slug, $request->data()['link']);
            }

            return true;
        });

        $this->assertStringContainsString('1123', $enquiry_max->successDetails());
    }

    public function testEnquiryMaxOfferLink()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}O',
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $offer = VehicleOffer::factory()->create();
        $enquiry = Enquiry::factory()->create([
            'reason_type' => 'offer',
            'reason_id' => $offer->id,
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) {
            return $request->url() === 'https://api.enquirymax.net/services/token'
                && $request['granttype'] === 'client_credentials'
                && $request['clientId'] === 'foo-baz'
                && $request['clientSecret'] === 'baz-bar';
        });

        Http::assertSent(function (Request $request) use ($offer) {

            if (array_key_exists('link', $request->data())) {
                return $this->assertStringContainsString('/make/model/' . $offer->slug, $request->data()['link']);
            }

            return true;
        });

        $this->assertStringContainsString('1123', $enquiry_max->successDetails());
    }

    public function testEnquiryMaxOfferTypeEnabled()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}O',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'crm-enquiry-max-append-offer-type-to-enquiry-title',
            'type' => 'boolean',
            'value' => true,
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $form = Form::factory()->create();
        $section = FormSection::factory()->create(['form_id' => $form->id]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test1',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'Offer',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test2',
        ]);

        $offer = VehicleOffer::factory()->create([
            'form_id' => $form->id,
            'type' => 'offer_type',
        ]);
        $enquiry = Enquiry::factory()->create([
            'form_id' => $form->id,
            'reason_type' => 'offer',
            'reason_id' => $offer->id,
            'details' => [
                [
                    'id' => 124,
                    'question' => 'test1',
                    'answer' => 'answer1',
                ],
                [
                    'id' => 123,
                    'question' => 'Offer',
                    'answer' => $offer->id,
                ],
                [
                    'id' => 125,
                    'question' => 'test2',
                    'answer' => 'answer2',
                ],
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        $lead_type_tested = false;

        Http::assertSent(function (Request $request) use (&$lead_type_tested) {
            $request_data = json_decode($request->body(), true);

            if (array_key_exists('leadType', $request_data)) {
                $lead_type_tested = true;
                return $request_data['leadType'] == 'New Car Enquiry - offer_type';
            }

            return false;
        });

        $this->assertTrue($lead_type_tested);
    }

    public function testEnquiryMaxOfferTypeOfferNotFound()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}O',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'crm-enquiry-max-append-offer-type-to-enquiry-title',
            'type' => 'boolean',
            'value' => true,
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $form = Form::factory()->create();
        $section = FormSection::factory()->create(['form_id' => $form->id]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test1',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'Offer',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test2',
        ]);

        $offer = VehicleOffer::factory()->create([
            'form_id' => $form->id,
            'type' => 'offer_type',
        ]);
        $enquiry = Enquiry::factory()->create([
            'form_id' => $form->id,
            'reason_type' => 'offer',
            'reason_id' => $offer->id + 1,
            'details' => [
                [
                    'id' => 124,
                    'question' => 'test1',
                    'answer' => 'answer1',
                ],
                [
                    'id' => 123,
                    'question' => 'Offer',
                    'answer' => $offer->id + 1,
                ],
                [
                    'id' => 125,
                    'question' => 'test2',
                    'answer' => 'answer2',
                ],
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        $lead_type_tested = false;

        Http::assertSent(function (Request $request) use (&$lead_type_tested) {
            $request_data = json_decode($request->body(), true);

            if (array_key_exists('leadType', $request_data)) {
                $lead_type_tested = true;
                return $request_data['leadType'] == 'New Car Enquiry';
            }

            return false;
        });

        $this->assertTrue($lead_type_tested);
    }

    public function testEnquiryMaxOfferTypeThrowsAnExceptionAndLogsBothWarningAndError()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}O',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'crm-enquiry-max-append-offer-type-to-enquiry-title',
            'type' => 'boolean',
            'value' => true,
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $form = Form::factory()->create();
        $section = FormSection::factory()->create(['form_id' => $form->id]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test2',
        ]);

        $offer = VehicleOffer::factory()->create([
            'form_id' => $form->id,
            'type' => 'offer_type',
        ]);
        $enquiry = Enquiry::factory()->create([
            'form_id' => $form->id,
            'reason_type' => 'offer',
            'reason_id' => $offer->id + 1,
            'details' => [
                [
                    'id' => 124,
                    '_wrong_question_key_' => 'test1', // this line will throw an exception which is what we want
                    'answer' => 'answer1',
                ]
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        Log::shouldReceive('warning')
            ->once();

        Log::shouldReceive('error')
            ->once()
            ->withArgs(function ($message) {
                return str_starts_with($message, 'Exception');
            });

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);
    }

    public function testEnquiryMaxOfferTypeDisabled()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/vehicle-details/{{MAKE}}/{{MODEL}}/{{SLUG}}O',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'test',
            'config_key' => 'crm-enquiry-max-append-offer-type-to-enquiry-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $form = Form::factory()->create();
        $section = FormSection::factory()->create(['form_id' => $form->id]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test1',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'Offer',
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'name' => 'test2',
        ]);

        $offer = VehicleOffer::factory()->create([
            'form_id' => $form->id,
            'type' => 'offer_type',
        ]);
        $enquiry = Enquiry::factory()->create([
            'form_id' => $form->id,
            'reason_type' => 'offer',
            'reason_id' => $offer->id,
            'details' => [
                [
                    'id' => 124,
                    'question' => 'test1',
                    'answer' => 'answer1',
                ],
                [
                    'id' => 123,
                    'question' => 'Offer',
                    'answer' => $offer->id,
                ],
                [
                    'id' => 125,
                    'question' => 'test2',
                    'answer' => 'answer2',
                ],
            ],
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        $lead_type_tested = false;

        Http::assertSent(function (Request $request) use (&$lead_type_tested) {
            $request_data = json_decode($request->body(), true);

            if (array_key_exists('leadType', $request_data)) {
                $lead_type_tested = true;
                return $request_data['leadType'] == 'New Car Enquiry';
            }

            return false;
        });

        $this->assertTrue($lead_type_tested);
    }

    public function testLeadTypeUsedCar()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 0,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);
        $enquiry = Enquiry::factory()->create([
            'reason_id' => $vehicle->id,
            'reason_type' => 'vehicle'
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('leadType', $request->data())) {
                return $request['leadType'] == 'Used Car Enquiry';
            }
        });
    }

    public function testLeadTypeNewCar()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 1,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);
        $enquiry = Enquiry::factory()->create([
            'reason_id' => $vehicle->id,
            'reason_type' => 'vehicle'
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('leadType', $request->data())) {
                return $request['leadType'] == 'New Car Enquiry';
            }
        });
    }

    public function testLeadTypeNewCarWithStockStatus()
    {
        $this->seed(EnquiryMaxSettingSeeder::class);

        Config::set('services.enquiry-max.mode', 'live');
        Settings::update('crm-enquiry-max-client-id', 'foo-baz');
        Settings::update('crm-enquiry-max-client-secret', 'baz-bar');

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Raptor']);
        $fuel_type = FuelType::factory()->create(['name' => 'Petrol']);
        $vehicle = Vehicle::factory()->create([
            'is_new' => 1,
            'price' => 23450,
            'make_id' => $make->id,
            'model_id' => $model->id,
            'derivative' => '5.6l V6 Extreme',
            'registration_number' => 'AB60 DEV',
            'fuel_type_id' => $fuel_type->id,
            'cap_id' => '182371283',
            'odometer_mi' => 123000,
        ]);


        // TODO: add vehicle attribute value
        // add vehicle attribute for stock_status
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'stock status',
            'model' => 'vehicle',
            'slug' => 'stock_status',
            'type' => 'string',
            'count' => 1
        ]);

        // set attribute value
        VehicleAttributeValue::factory()->create([
            'attribute_id' => $attribute->id,
            'owner_id' => $vehicle->id,
            'slug' => 'stock_status',
            'type' => 'string',
            'value' => 'foo'
        ]);

        $enquiry = Enquiry::factory()->create([
            'reason_id' => $vehicle->id,
            'reason_type' => 'vehicle'
        ]);
        $action = EnquiryAction::factory()->create([
            'action_name' => 'send-to-enquiry-max',
            'data' => [
                'fallback-dealership' => 'baz',
            ],
            'processed_at' => null,
            'failed_at' => null
        ]);

        Storage::fake('file-storage');
        Http::fake([
            'https://api.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            'https://api.enquirymax.net/services/v1/*/lead' => Http::response($this->leadResponse()),
            "*" => Http::response([], 400),
        ]);

        $enquiry_max = Enquiries::makeAction('send-to-enquiry-max');
        $enquiry_max->handle($action, $enquiry);

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('leadType', $request->data())) {
                return $request['leadType'] == 'New Car Enquiry - foo';
            }
        });
    }

    public function testCanSendReservationToEnquiryMzax()
    {
        Http::preventStrayRequests();

        Http::fake([
            '*.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            '*.enquirymax.net/services/v1/*/lead' => Http::response(['status' => 'success'], 200),
        ]);

        $dealership = Dealership::factory()->create([
            'data' => ['enquiry-max-dealership' => 'Test Dealership'],
        ]);
        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
            'is_new' => true,
            'price' => 30000,
            'registration_number' => 'ABC123'
        ]);

        $reservation = Reservation::create([
            'vehicle_id' => $vehicle->id,
            'reference' => fake()->swiftBicNumber(),
            'status' => 'pending',
            'name' => 'John Doe',
            'email' => 'johndoe@example.com',
            'contact_number' => '1234567890',
        ], $vehicle);

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-id')
            ->once()
            ->andReturn('129202');
        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-secret')
            ->once()
            ->andReturn('secret-key');

        Storage::fake();
        $service = new EnquiryMaxApi(new EnquiryMaxConfig);

        $result = $service->sendReservation($reservation);

        $this->assertTrue($result);
    }


    public function testAuthenticateExitsWhenTokenIsActive()
    {
        Http::preventStrayRequests();

        Http::fake([
            '*.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            '*.enquirymax.net/services/v1/*/lead' => Http::response(['status' => 'success'], 200),
        ]);

        Storage::fake('file-storage');
        Storage::disk('file-storage')->put('enquiry-max/' . tenant('id') . '/auth-token', json_encode([
            'accessToken' => 'active-token',
            'dealers' => [['dealerId' => '123', 'dealerName' => 'Test Dealer']],
            'expires_at' => Carbon::now()->addMinutes(15)->toISOString(),
        ]));

        $service = new EnquiryMaxApi(new EnquiryMaxConfig);

        $reflection = new \ReflectionClass($service);
        $method = $reflection->getMethod('authenticate');
        $method->setAccessible(true);
        $method->invoke($service);

        Http::assertNothingSent();
    }

    public function testCanReauthenticateWhenTokenIsExpired()
    {
        Http::preventStrayRequests();

        Http::fake([
            '*.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            '*.enquirymax.net/services/v1/*/lead' => Http::response(['status' => 'success'], 200),
        ]);

        Storage::fake('file-storage');
        Storage::disk('file-storage')->put('enquiry-max/' . tenant('id') . '/auth-token', json_encode([
            'accessToken' => 'active-token',
            'dealers' => [['dealerId' => '123', 'dealerName' => 'Test Dealer']],
            'expires_at' => Carbon::now()->subMinutes(45)->toISOString(), // expired
        ]));

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-id')
            ->once()
            ->andReturn('129202');

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-secret')
            ->once()
            ->andReturn('secret-key');

        $service = new EnquiryMaxApi(new EnquiryMaxConfig);

        $reflection = new \ReflectionClass($service);
        $method = $reflection->getMethod('authenticate');
        $method->setAccessible(true);
        $method->invoke($service);

        Http::assertSent(function ($request) {
            return str_contains($request->url(), 'services/token') &&
                $request->method() === 'POST';
        });
    }

    public function testAuthenticateFailsAndLogsError()
    {
        Http::fake([
            '*.enquirymax.net/services/token' => Http::response([
                'error' => 'invalid_client',
                'error_description' => 'Client authentication failed'
            ], 401), // simulate failure
        ]);

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-id')
            ->twice()
            ->andReturn('129202');
        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-secret')
            ->once()
            ->andReturn('secret-key');

        Storage::fake('file-storage');

        // Log mock must be set up BEFORE instantiation since authenticate() is called in constructor
        Log::shouldReceive('error')
            ->once()
            ->with('Failed to authenticate EnquiryMax', \Mockery::on(function ($context) {
                return isset($context['tenant'], $context['client_id'], $context['status code'], $context['response data']);
            }));

        // Expect the exception - authenticate() is called in constructor and will throw
        $this->expectException(AuthenticationException::class);
        $this->expectExceptionMessage('Failed to authenticate EnquiryMax');

        new EnquiryMaxApi(new EnquiryMaxConfig);
    }

    public function testMapReservationDataReturnsExpectedArray()
    {
        Http::fake([
            '*.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            '*.enquirymax.net/services/v1/*/lead' => Http::response(['status' => 'success'], 200),
        ]);

        $dealership = Dealership::factory()->create([
            'data' => ['enquiry-max-dealership' => 'Test Dealership'],
        ]);
        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id
        ]);

        $reservation = Reservation::create([
            'vehicle_id' => $vehicle->id,
            'reference' => fake()->swiftBicNumber(),
            'status' => 'pending',
            'name' => 'John Doe',
            'email' => 'johndoe@example.com',
            'contact_number' => '1234567890',
        ], $vehicle);

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-id')
            ->andReturn('129202');
        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-secret')
            ->andReturn('secret-key');

        Storage::fake();
        $service = new EnquiryMaxApi(new EnquiryMaxConfig());

        $reflection = new \ReflectionClass($service);
        $method = $reflection->getMethod('mapReservationData');
        $method->setAccessible(true);

        $mapped = $method->invoke($service, $reservation);

        $this->assertIsArray($mapped);
        $this->assertSame([
            'leadType' => 'Reservation',
            'customer' => [
                'forename' => 'John',
                'surname' => 'Doe',
            ],
        ], [
            'leadType' => $mapped['leadType'],
            'customer' => [
                'forename' => $mapped['customer']['forename'],
                'surname' => $mapped['customer']['surname'],
            ],
        ]);
    }

    public function testGetClosestDealershipToPostcodeReturnsNullWhenPostcodeNotFound()
    {
        Http::fake([
            '*.enquirymax.net/services/token' => Http::response($this->authTokenResponse()),
            '*.enquirymax.net/services/v1/*/lead' => Http::response(['status' => 'success'], 200),
        ]);

        $locatingServiceMock = Mockery::mock(LocatingService::class);
        $locatingServiceMock->shouldReceive('locate')
            ->with('XX00 0XX')
            ->andReturnSelf();
        $locatingServiceMock->shouldReceive('lat')->andReturn(0);
        $locatingServiceMock->shouldReceive('lng')->andReturn(0);

        $this->app->instance(LocatingService::class, $locatingServiceMock);

        $dealerships = [];

        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-id')
            ->andReturn('129202');
        Settings::shouldReceive('get')
            ->with('crm-enquiry-max-client-secret')
            ->andReturn('secret-key');

        Storage::fake();
        $service = new EnquiryMaxApi(new EnquiryMaxConfig);

        $reflection = new \ReflectionClass($service);
        $method = $reflection->getMethod('getClosestDealershipToPostcode');
        $method->setAccessible(true);

        $result = $method->invoke($service, 'XX00 0XX', $dealerships);

        $this->assertNull($result);
    }

    private function setMockResponseFromLocatingService($latitude, $longitude)
    {
        $postcode_geo_model = new PostcodeGeo();
        $postcode_geo_model->latitude = $latitude;
        $postcode_geo_model->longitude = $longitude;

        $this->partialMock(LocatingServiceEngine::class, function (MockInterface $mock) use ($postcode_geo_model) {
            $mock->shouldReceive('find')->andReturn($postcode_geo_model);
        });

        $this->partialMock(LocatingService::class, function (MockInterface $mock) use ($postcode_geo_model) {
            $mock->shouldReceive('locate')
                ->andReturnSelf();
            $mock->shouldReceive('lat')
                ->andReturn($postcode_geo_model->latitude);
            $mock->shouldReceive('lng')
                ->andReturn($postcode_geo_model->longitude);
            $mock->shouldReceive('asString')
                ->andReturn($postcode_geo_model->latitude . ',' . $postcode_geo_model->longitude);
        });
    }

    private function authTokenResponse()
    {
        return [
            'accessToken' => 'lorem-ipsum',
            'expiresIn' => 1000,
            'dealers' => [
                [
                    'dealerId' => 1,
                    'dealerName' => 'foo',
                ],
                [
                    'dealerId' => 2,
                    'dealerName' => 'baz',
                ],
                [
                    'dealerId' => 3,
                    'dealerName' => 'bar',
                ],
            ]

        ];
    }

    private function leadResponse()
    {
        return [
            'leadId' => 1123,
        ];
    }
}
