<?php

namespace Tests\Tenant;

use App\Crm\Config\SalesforceCrmConfig;
use App\Facades\Settings;
use App\Facades\Site;
use App\Services\SalesforceCrmApi;
use Carbon\Carbon;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Mtc\Crm\Facades\Enquiries;
use Mtc\Crm\Models\Enquiry;
use Mtc\Crm\Models\EnquiryAction;
use Mtc\Crm\Models\EnquiryObject;
use Mtc\Crm\Models\EnquiryType;
use Mtc\Crm\Models\FormQuestion;
use Mtc\MercuryDataModels\ApiNotification;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleValuation;
use Mtc\VehicleReservations\Reservation;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class SalesforceCrmTest extends TenantTestCase
{
    use UserForTenant;

    public function testConfig()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-enabled',
            'type' => 'boolean',
            'value' => false,
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Username',
            'config_key' => 'salesforce-crm-username',
            'type' => 'string',
            'value' => 'foo_username',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Password',
            'config_key' => 'salesforce-crm-password',
            'type' => 'secret',
            'value' => 'foo_password',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Client ID',
            'config_key' => 'salesforce-crm-client-id',
            'type' => 'string',
            'value' => 'foo_client_id',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Client Secret',
            'config_key' => 'salesforce-crm-client-secret',
            'type' => 'secret',
            'value' => 'foo_client_secret',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        $config = App::make(SalesforceCrmConfig::class);
        $this->assertFalse($config->enabled());
        $this->assertEquals('foo_username', $config->username());
        $this->assertEquals('foo_password', $config->password());
        $this->assertEquals('foo_client_id', $config->clientId());
        $this->assertEquals('foo_client_secret', $config->clientSecret());
    }

    public function testToken()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-enabled',
            'type' => 'boolean',
            'value' => false,
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Username',
            'config_key' => 'salesforce-crm-username',
            'type' => 'string',
            'value' => 'foo_username',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Password',
            'config_key' => 'salesforce-crm-password',
            'type' => 'secret',
            'value' => 'foo_password',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Client ID',
            'config_key' => 'salesforce-crm-client-id',
            'type' => 'string',
            'value' => 'foo_client_id',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Client Secret',
            'config_key' => 'salesforce-crm-client-secret',
            'type' => 'secret',
            'value' => 'foo_client_secret',
            'validation_rules' => [
                "required_if:values.salesforce-crm-enabled,true"
            ],
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        (new SalesforceCrmApi(App::make(SalesforceCrmConfig::class)))->sendLead(new Enquiry(), new EnquiryAction());

        $username = '';
        $password = '';
        $client_id = '';
        $client_secret = '';
        $token = '';

        Http::assertSent(function (Request $request) use (&$username, &$password, &$client_id, &$client_secret, &$token) {
            if (array_key_exists('username', $request->data())) {
                $username = $request->data()['username'];
                $password = $request->data()['password'];
                $client_id = $request->data()['client_id'];
                $client_secret = $request->data()['client_secret'];
            }

            if (array_key_exists('Authorization', $request->headers())) {
                $token = $request->headers()['Authorization'][0];
            }

            return true;
        });

        $this->assertEquals('foo_username', $username);
        $this->assertEquals('foo_password', $password);
        $this->assertEquals('foo_client_id', $client_id);
        $this->assertEquals('foo_client_secret', $client_secret);
        $this->assertEquals('Bearer ABC123', $token);
    }

    public function testFailedTokenCall()
    {
        Http::fake([
            '*/token' => Http::response([
                'bad request'
            ], 400),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        (new SalesforceCrmApi(App::make(SalesforceCrmConfig::class)))->sendLead(new Enquiry(), new EnquiryAction());

        Http::assertSent(function (Request $request) use (&$username, &$password, &$client_id, &$client_secret, &$token) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return $request->url() === 'services/apexrest/enquiry';
        });
    }

    public function testSendLead()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123',
                'instance_url' => 'test.com',
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

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

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "selected_dealership"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "formType"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "message"]]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => $dealership->id],
                $q5->id => ['answer' => ''],
                $q6->id => ['answer' => 'my_message'],
            ],
            'source' => 'test.com',
        ]);

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

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

        Http::assertSent(function (Request $request) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return Str::contains($request->url(), 'test.com/services/apexrest/enquiry')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === 'my_message'
                && $request['enquiry']['testDriveRequestedDateTime'] == null
                && $request['enquiry']['pageUrl'] == 'test.com'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222';
        });

        $this->assertCount(1, ApiNotification::query()->where('provider', 'salesforce')->get());
    }

    public function testSendLeadWithLeadType()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123',
                'instance_url' => 'test.com',
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

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

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "selected_dealership"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "formType"]]);

        $enquiry_type = EnquiryType::factory()->create([
            'data' => [
                'salesforce_form_type' => 'form-type-from-enquiry-type-data',
            ],
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => $dealership->id],
                $q5->id => ['answer' => 'test-form-type'],
            ],
            'type_id' => $enquiry_type->id,
        ]);

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

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

        Http::assertSent(function (Request $request) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return Str::contains($request->url(), 'test.com/services/apexrest/enquiry')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'form-type-from-enquiry-type-data'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === null
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222';
        });

        $this->assertCount(1, ApiNotification::query()->where('provider', 'salesforce')->get());
    }

    public function testSendVehicleLead()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'bar',
            'group' => 'baz',
            'name' => 'buzz',
            'config_key' => 'vehicles-url-path',
            'type' => 'string',
            'value' => '/vehicle-{{MODEL}}',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "postcode"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "message"]]);

        $model = VehicleModel::factory()->create();
        $fuel_type = FuelType::factory()->create();
        $dealership = Dealership::factory()->create([
            'data' => [
                'salesforce-dealer-id' => '12345'
            ],
        ]);
        $vehicle = Vehicle::factory()->create([
            'uuid' => 'foo',
            'make_id' => $model->make->id,
            'model_id' => $model->id,
            'fuel_type_id' => $fuel_type->id,
            'type' => 'car',
            'dealership_id' => $dealership->id,
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => 'DD11DD'],
                $q5->id => ['answer' => ''],
            ],
            'reason_type' => 'vehicle',
            'reason_id' => $vehicle->id,
            'source' => Site::vehicleUrl($vehicle),
        ]);

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

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

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['pageUrl'] === Site::vehicleUrl($vehicle)
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === ''
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222'
                && $request['customer']['postCode'] === 'DD11DD'
                && $request['vehicleOfInterest']['vehicleSfId'] === $vehicle->uuid
                && $request['vehicleOfInterest']['make'] === $vehicle->make?->name
                && $request['vehicleOfInterest']['model'] === $vehicle->model?->name
                && $request['vehicleOfInterest']['regNo'] === $vehicle->vrm_condensed
                && $request['vehicleOfInterest']['year'] === $vehicle->manufacture_year
                && $request['vehicleOfInterest']['derivative'] === $vehicle->derivative
                && $request['vehicleOfInterest']['mileage'] === $vehicle->odometer_mi
                && $request['vehicleOfInterest']['fueltype'] === $vehicle->fuelType?->name
                && $request['vehicleOfInterest']['type'] == 'used car';
        });
    }

    public function testSendOfferLead()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'bar',
            'group' => 'baz',
            'name' => 'buzz',
            'config_key' => 'offers-url-path',
            'type' => 'string',
            'value' => '/offer-{{MODEL}}',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);

        $model = VehicleModel::factory()->create();
        $fuel_type = FuelType::factory()->create();
        $dealership = Dealership::factory()->create([
            'data' => [
                'salesforce-dealer-id' => '12345'
            ],
        ]);
        $vehicle = VehicleOffer::factory()->create([
            'make_id' => $model->make->id,
            'model_id' => $model->id,
            'fuel_type_id' => $fuel_type->id,
            'dealership_id' => $dealership->id,
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
            ],
            'reason_type' => 'offer',
            'reason_id' => $vehicle->id,
            'source' => Site::offerUrl($vehicle),
        ]);

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

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

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['pageUrl'] === Site::offerUrl($vehicle)
                && $request['enquiry']['dealerId'] === '12345'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222'
                && $request['vehicleOfInterest']['make'] === $vehicle->make?->name
                && $request['vehicleOfInterest']['model'] === $vehicle->model?->name
                && $request['vehicleOfInterest']['fueltype'] === $vehicle->fuelType?->name
                && $request['vehicleOfInterest']['derivative'] === $vehicle->derivative
                && $request['vehicleOfInterest']['type'] == 'new car';
        });
    }

    public function testSendReservationLead()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'app-timezone',
            'type' => 'string',
            'value' => 'Europe/London',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);

        $dealership = Dealership::factory()->create([
            'data' => [
                'salesforce-dealer-id' => '12345'
            ],
        ]);
        $vehicle = Vehicle::factory()->create([
            'is_new' => true,
            'registration_number' => 'ABC123',
            'uuid' => 'foo',
            'type' => 'car',
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'amount' => 99,
            'ingested_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        $enquiry_type = EnquiryType::factory()->create([
            'data' => [
                'salesforce_form_type' => 'Reserve a Car',
            ],
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
            ],
            'reason_type' => 'reservation',
            'reason_id' => $reservation->id,
            'type_id' => $enquiry_type->id,
        ]);

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

        Carbon::setTestNow('2025-06-01 12:34:56');

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

        Http::assertSent(function (Request $request) use ($vehicle) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Reserve a Car'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['reserveCarReservationDate'] === '2025-06-01T11:34:56Z'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222'
                && $request['vehicleOfInterest']['vehicleSfId'] === $vehicle->uuid
                && $request['vehicleOfInterest']['make'] === $vehicle->make?->name
                && $request['vehicleOfInterest']['model'] === $vehicle->model?->name
                && $request['vehicleOfInterest']['regNo'] === $vehicle->vrm_condensed
                && $request['vehicleOfInterest']['year'] === $vehicle->manufacture_year
                && $request['vehicleOfInterest']['derivative'] === $vehicle->derivative
                && $request['vehicleOfInterest']['mileage'] === $vehicle->odometer_mi
                && $request['vehicleOfInterest']['fueltype'] === $vehicle->fuelType?->name
                && $request['vehicleOfInterest']['type'] === 'new car';
        });
    }

    public function testSendValuationLead()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);

        $valuation = VehicleValuation::factory()->create([
            'clean_price' => 12345,
            'average_price' => 23456,
            'below_price' => 34567,
            'retail_price' => 45678,
        ]);

        $enquiry_type = EnquiryType::factory()->create([
            'data' => [
                'salesforce_form_type' => 'Valuation Enquiry Form',
            ],
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
            ],
            'reason_type' => 'valuation',
            'reason_id' => $valuation->id,
            'type_id' => $enquiry_type->id,
        ]);

        EnquiryObject::factory()->create([
            'enquiry_id' => $enquiry->id,
            'object_id' => $valuation->id,
            'object_type' => $valuation->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) use ($valuation) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Valuation Enquiry Form'
                && $request['enquiry']['valuationAmount'] === 23456
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222'
                && $request['vehicleTradeIn']['make'] === $valuation->make
                && $request['vehicleTradeIn']['model'] === $valuation->model
                && $request['vehicleTradeIn']['regNo'] === $valuation->registration
                && $request['vehicleTradeIn']['derivative'] === $valuation->derivative
                && $request['vehicleTradeIn']['mileage'] === $valuation->mileage
                && $request['vehicleTradeIn']['fueltype'] === $valuation->fuel_type
                && $request['vehicleTradeIn']['sellingType'] === 'Sell My Vehicle';
        });
    }

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

        $this->assertIsArray($fields);
        $this->assertArrayHasKey('salesforce-dealer-id', $fields);
    }

    public function testResponseMessageEmpty()
    {
        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*enquiry' => Http::response('{
                "reservationSfId": null,
                "errorMessage": null,
                "customerSfId": "awjfgujweofj"
            }', 200),
            '*' => Http::response(null, 400),
        ]);

        $api = new SalesforceCrmApi(App::make(SalesforceCrmConfig::class));
        $api->sendLead(new Enquiry(), new EnquiryAction());

        $this->assertEquals('', $api->getResponseMessage());
    }

    public function testResponseMessage()
    {
        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*enquiry' => Http::response('[
				{
					"message": "example message",
					"errorCode": "example code"
				}
			]', 200),
            '*' => Http::response(null, 400),
        ]);

        $api = new SalesforceCrmApi(App::make(SalesforceCrmConfig::class));
        $api->sendLead(new Enquiry(), new EnquiryAction());

        $this->assertEquals('example message', $api->getResponseMessage());
    }

    public function testResponseErrorMessage()
    {
        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123'
            ], 200),
            '*enquiry' => Http::response('{
                "reservationSfId": null,
                "errorMessage": "example message",
                "customerSfId": "awjfgujweofj"
            }', 200),
            '*' => Http::response(null, 400),
        ]);

        $api = new SalesforceCrmApi(App::make(SalesforceCrmConfig::class));
        $api->sendLead(new Enquiry(), new EnquiryAction());

        $this->assertEquals('example message', $api->getResponseMessage());
    }

    public function testSendTestDriveLead()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'app-timezone',
            'type' => 'string',
            'value' => 'Europe/London',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123',
                'instance_url' => 'test.com',
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

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

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "selected_dealership"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "formType"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "message"]]);
        $q7 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "testDriveDate"]]);
        $q8 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "testDriveTime"]]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => $dealership->id],
                $q5->id => ['answer' => ''],
                $q6->id => ['answer' => 'my_message'],
                $q7->id => ['answer' => '2025-01-01T00:00:00'],
                $q8->id => ['answer' => 'Afternoon'],
            ],
        ]);

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

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

        Http::assertSent(function (Request $request) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return Str::contains($request->url(), 'test.com/services/apexrest/enquiry')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === 'my_message'
                && $request['enquiry']['testDriveRequestedDateTime'] == '2025-01-01T13:00:00Z'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222';
        });

        $this->assertCount(1, ApiNotification::query()->where('provider', 'salesforce')->get());
    }

    public function testSendTestDriveLeadMorningSetting()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'app-timezone',
            'type' => 'string',
            'value' => 'Europe/London',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Booking time for "Morning"',
            'config_key' => 'salesforce-crm-booking-time-morning',
            'type' => 'string',
            'value' => '07:00:00',
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123',
                'instance_url' => 'test.com',
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

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

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "selected_dealership"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "formType"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "message"]]);
        $q7 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "testDriveDate"]]);
        $q8 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "testDriveTime"]]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => $dealership->id],
                $q5->id => ['answer' => ''],
                $q6->id => ['answer' => 'my_message'],
                $q7->id => ['answer' => '2025-06-01T00:00:00'],
                $q8->id => ['answer' => ['Morning','Evening']],
            ],
        ]);

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

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

        Http::assertSent(function (Request $request) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            return Str::contains($request->url(), 'test.com/services/apexrest/enquiry')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === 'my_message'
                && $request['enquiry']['testDriveRequestedDateTime'] == '2025-06-01T06:00:00Z'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222';
        });

        $this->assertCount(1, ApiNotification::query()->where('provider', 'salesforce')->get());
    }

    public function testUrlLimit()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-feedsource',
            'type' => 'string',
            'value' => 'test-feed-source',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Remove URL parameters from enquiry source page URL',
            'config_key' => 'salesforce-crm-remove-url-params',
            'type' => 'boolean',
            'value' => true,
        ]);

        Http::fake([
            '*/token' => Http::response([
                'access_token' => 'ABC123',
                'instance_url' => 'test.com',
            ], 200),
            '*/enquiry' => Http::response([
                'data' => 'example response data'
            ], 200),
            '*' => Http::response(null, 200),
        ]);

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

        $q1 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "firstName"]]);
        $q2 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "lastName"]]);
        $q3 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "mobile"]]);
        $q4 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "selected_dealership"]]);
        $q5 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "formType"]]);
        $q6 = FormQuestion::factory()->create(['data' => ["salesforce-field" => "message"]]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => '00000111222'],
                $q4->id => ['answer' => $dealership->id],
                $q5->id => ['answer' => ''],
                $q6->id => ['answer' => 'my_message'],
            ],
            'source' => 'test.com?param1=foo&param2=bar',
        ]);

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

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

        Http::assertSent(function (Request $request) {
            if (array_key_exists('password', $request->data())) {
                return false;
            }

            $expected_message = 'my_message [Original enquiry URL: test.com?param1=foo&param2=bar]';

            return Str::contains($request->url(), 'test.com/services/apexrest/enquiry')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Enquiry Form'
                && $request['enquiry']['dealerId'] === '12345'
                && $request['enquiry']['message'] === $expected_message
                && $request['enquiry']['testDriveRequestedDateTime'] == null
                && $request['enquiry']['pageUrl'] == 'test.com'
                && $request['customer']['firstName'] === 'Peter'
                && $request['customer']['lastName'] === 'Parker'
                && $request['customer']['email'] === 'foo@bar.com'
                && $request['customer']['mobile'] === '00000111222';
        });

        $this->assertCount(1, ApiNotification::query()->where('provider', 'salesforce')->get());
    }
}
