<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Illuminate\Http\Client\Request;
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\FormQuestion;
use Mtc\MercuryDataModels\ApiNotification;
use Mtc\MercuryDataModels\Booking;
use Mtc\MercuryDataModels\BookingDeliveryOption;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\NewCar;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleValuation;
use Mtc\VehicleReservations\Reservation;
use Tests\TenantTestCase;

class PinewoodCrmTest extends TenantTestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        Http::preventStrayRequests();
    }

    public function testEnabled()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Enabled',
            'config_key' => 'pinewood-crm-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $action = Enquiries::makeAction('send-to-pinewood');
        $this->assertTrue($action->enabled());
    }

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

        $action = Enquiries::makeAction('send-to-pinewood');
        $this->assertFalse($action->enabled());
    }

    public function testFormQuestionDataFields()
    {
        $action = Enquiries::makeAction('send-to-pinewood');
        $fields = $action->formQuestionDataFields();

        $this->assertArrayHasKey('pinewood-field', $fields);
        $this->assertArrayHasKey('choices', $fields['pinewood-field']);
        $this->assertArrayHasKey('first_name', $fields['pinewood-field']['choices']);
        $this->assertArrayHasKey('last_name', $fields['pinewood-field']['choices']);
        $this->assertArrayHasKey('email', $fields['pinewood-field']['choices']);
        $this->assertArrayHasKey('phone', $fields['pinewood-field']['choices']);
        $this->assertArrayHasKey('notes', $fields['pinewood-field']['choices']);
    }

    public function testSendLead()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'last_name']]);
        $q3 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'phone']]);
        $q4 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'email']]);
        $q5 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'notes']]);

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

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

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->handle($action, $enquiry);

        $this->assertTrue($result);

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return $request->url() === 'https://api.pinewooddms.com/APIv2/CRM/Lead'
                && $request->hasHeader('UserName', 'test_username')
                && $request->hasHeader('Password', 'test_password')
                && ($data['Customer']['Forename'] ?? null) === 'Peter'
                && ($data['Customer']['Surname'] ?? null) === 'Parker'
                && ($data['Customer']['EmailAddress1'] ?? null) === 'foo@bar.com'
                && ($data['Customer']['ContactNumber_Mobile']['Number'] ?? null) === '00000111222'
                && Str::contains($data['ContactHistory']['Notes'] ?? '', 'I am interested')
                && Str::contains($data['ContactHistory']['Notes'] ?? '', 'View in Autonomy:')
                && ($data['EnquirySource']['EnquirySource'] ?? null) === 'Website'
                && Str::startsWith($data['LeadReferenceID'] ?? '', 'ENQ-')
                && ($data['EnquiryType']['EnquiryType'] ?? null) === 'Sales';
        });

        $notification = ApiNotification::query()->where('provider', 'pinewood-crm')->first();
        $this->assertNotNull($notification);
        $this->assertTrue($notification->processed);
        $this->assertEquals(200, $notification->data['status']);
        $this->assertEquals('DEFAULT-LOC-001', $notification->data['location']);
    }

    public function testSendLeadForVehicle()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'last_name']]);
        $q3 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'email']]);

        $make = VehicleMake::factory()->create(['name' => 'BMW']);
        $model = VehicleModel::factory()->create(['name' => 'X5']);
        $vehicle = Vehicle::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'type' => 'car',
            'is_new' => 0,
            'price' => 25000,
            'registration_number' => 'AB12 CDE',
            'vrm_condensed' => 'AB12CDE',
            'derivative' => 'xDrive30d M Sport',
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
                $q3->id => ['answer' => 'foo@bar.com'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $vehicle->id,
            'object_type' => $vehicle->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return $request->url() === 'https://api.pinewooddms.com/APIv2/CRM/Lead'
                && ($data['DesiredVehicle']['Make'] ?? null) === 'BMW'
                && ($data['DesiredVehicle']['Model'] ?? null) === 'X5'
                && ($data['DesiredVehicle']['RegistrationNumber'] ?? null) === 'AB12CDE'
                && ($data['DesiredVehicle']['PriceRangeHigh'] ?? null) == 25000
                && ($data['DesiredVehicle']['Specification'] ?? null) === 'xDrive30d M Sport'
                && ($data['ContactHistory']['VehicleType'] ?? null) === 'Used'
                && Str::contains($data['ContactHistory']['Notes'] ?? '', 'AB12 CDE')
                && Str::contains($data['ContactHistory']['Notes'] ?? '', 'View in Autonomy:');
        });

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

    public function testSendLeadForOffer()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'last_name']]);

        $make = VehicleMake::factory()->create(['name' => 'Audi']);
        $model = VehicleModel::factory()->create(['name' => 'A6']);
        $offer = VehicleOffer::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'name' => 'Exclusive Lease Deal',
            'price' => 35000,
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $offer->id,
            'object_type' => $offer->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return ($data['DesiredVehicle']['Make'] ?? null) === 'Audi'
                && ($data['DesiredVehicle']['Model'] ?? null) === 'A6'
                && ($data['DesiredVehicle']['Specification'] ?? null) === 'Offer: Exclusive Lease Deal'
                && ($data['ContactHistory']['VehicleType'] ?? null) === 'New';
        });
    }

    public function testSendLeadForNewCar()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'last_name']]);

        $make = VehicleMake::factory()->create(['name' => 'Ford']);
        $model = VehicleModel::factory()->create(['name' => 'Puma']);
        $newCar = NewCar::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'name' => 'ST-Line X',
            'price' => 28500,
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $newCar->id,
            'object_type' => $newCar->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return ($data['DesiredVehicle']['Make'] ?? null) === 'Ford'
                && ($data['DesiredVehicle']['Model'] ?? null) === 'Puma'
                && ($data['DesiredVehicle']['Specification'] ?? null) === 'New Vehicle: ST-Line X'
                && ($data['ContactHistory']['VehicleType'] ?? null) === 'New';
        });
    }

    public function testSendLeadForValuation()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'last_name']]);

        $valuation = VehicleValuation::query()->create([
            'provider' => 'test',
            'registration' => 'FO25FAZ',
            'mileage' => 30000,
            'make' => 'Volkswagen',
            'model' => 'Golf',
            'average_price' => 15000,
            'derivative' => 'GTI',
            'engine_size' => '2000',
            'fuel_type' => 'Petrol',
            'colour' => 'White',
            'date_of_registration' => '2020-01-15',
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'Parker'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $valuation->id,
            'object_type' => $valuation->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return isset($data['PresentVehicle'])
                && ($data['PresentVehicle']['Make'] ?? null) === 'Volkswagen'
                && ($data['PresentVehicle']['Model'] ?? null) === 'Golf'
                && ($data['PresentVehicle']['RegistrationNumber'] ?? null) === 'FO25FAZ'
                && ($data['PresentVehicle']['Odometer'] ?? null) == 30000
                && ($data['PresentVehicle']['Specification'] ?? null) === 'GTI'
                && ($data['PresentVehicle']['EngineSize'] ?? null) === '2000'
                && ($data['PresentVehicle']['Colour'] ?? null) === 'White';
        });

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

    public function testSendLeadWithLocationFromDealership()
    {
        $this->addSettingsAndHttpFake();

        $dealership = Dealership::factory()->create([
            'data' => ['pinewood-crm-location-id' => 'DEALER-LOC-123'],
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $dealership->id,
            'object_type' => $dealership->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            return $request->hasHeader('OrganisationalUnit_UID', 'DEALER-LOC-123');
        });
    }

    public function testSendLeadWithLocationFromVehicleDealership()
    {
        $this->addSettingsAndHttpFake();

        $dealership = Dealership::factory()->create([
            'data' => ['pinewood-crm-location-id' => 'VEH-DEALER-LOC-456'],
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $make = VehicleMake::factory()->create(['name' => 'BMW']);
        $model = VehicleModel::factory()->create(['name' => 'X3']);
        $vehicle = Vehicle::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'dealership_id' => $dealership->id,
        ]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
            ],
            'source' => 'test.com',
        ]);
        $enquiry->objects()->create([
            'object_id' => $vehicle->id,
            'object_type' => $vehicle->getMorphClass(),
        ]);

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

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

        Http::assertSent(function (Request $request) {
            return $request->hasHeader('OrganisationalUnit_UID', 'VEH-DEALER-LOC-456');
        });
    }

    public function testSendLeadWithFallbackLocation()
    {
        $this->addSettingsAndHttpFake();

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Fallback Location ID',
            'config_key' => 'pinewood-fallback-location-id',
            'type' => 'string',
            'value' => 'FALLBACK-LOC-789',
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
            ],
            'source' => 'test.com',
        ]);

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

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

        Http::assertSent(function (Request $request) {
            return $request->hasHeader('OrganisationalUnit_UID', 'FALLBACK-LOC-789');
        });
    }

    public function testSendReservation()
    {
        $this->addSettingsAndHttpFake([
            'https://api.pinewooddms.com/*' => Http::response([
                'Lead_UID' => 'PINE-RES-123',
            ], 200),
        ]);

        $dealership = Dealership::factory()->create([
            'data' => ['pinewood-crm-location-id' => 'RES-LOC-001'],
        ]);

        $make = VehicleMake::factory()->create(['name' => 'Audi']);
        $model = VehicleModel::factory()->create(['name' => 'A4']);
        $vehicle = Vehicle::factory()->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'dealership_id' => $dealership->id,
            'type' => 'car',
            'is_new' => 0,
            'price' => 22000,
            'registration_number' => 'RE25 SRV',
            'vrm_condensed' => 'RE25SRV',
            'derivative' => 'S Line',
        ]);

        $reservation = Reservation::factory()->create([
            'contact_number' => '07123456789',
            'email' => 'res@example.com',
            'vehicle_id' => $vehicle->id,
            'name' => 'John Doe',
        ]);

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->sendReservation($reservation);

        $this->assertTrue($result);

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            $notes = $data['ContactHistory']['Notes'] ?? '';

            return $request->url() === 'https://api.pinewooddms.com/APIv2/CRM/Lead'
                && $request->hasHeader('OrganisationalUnit_UID', 'RES-LOC-001')
                && ($data['Customer']['Forename'] ?? null) === 'John'
                && ($data['Customer']['Surname'] ?? null) === 'Doe'
                && ($data['Customer']['EmailAddress1'] ?? null) === 'res@example.com'
                && ($data['DesiredVehicle']['Make'] ?? null) === 'Audi'
                && ($data['DesiredVehicle']['Model'] ?? null) === 'A4'
                && ($data['DesiredVehicle']['RegistrationNumber'] ?? null) === 'RE25SRV'
                && ($data['EnquiryType']['EnquiryType'] ?? null) === 'Vehicle reservation'
                && Str::startsWith($data['LeadReferenceID'] ?? '', 'RES-')
                && Str::contains($notes, 'RE25 SRV')
                && Str::contains($notes, '22000')
                && Str::contains($notes, 'View in Autonomy:');
        });

        $reservation->refresh();
        $this->assertEquals('PINE-RES-123', $reservation->crm_reference);

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

    public function testSendServiceBooking()
    {
        $this->addSettingsAndHttpFake([
            'https://api.pinewooddms.com/*' => Http::response([
                'Lead_UID' => 'PINE-SRV-456',
            ], 200),
        ]);

        $dealership = Dealership::factory()->create([
            'data' => ['pinewood-crm-location-id' => 'SRV-LOC-001'],
        ]);

        $booking = Booking::factory()->create([
            'uuid' => Str::uuid()->toString(),
            'first_name' => 'Jane',
            'last_name' => 'Smith',
            'email' => 'jane@example.com',
            'phone_number' => '07999888777',
            'registration_number' => 'SB12CDE',
            'mileage' => 45000,
            'location_id' => $dealership->id,
            'booking_time' => '2024-03-15 10:00:00',
            'vehicle_data' => [
                'make' => 'Ford',
                'model' => 'Focus',
                'transmission' => 'Manual',
                'fuel_type' => 'Petrol',
            ],
        ]);

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->sendServiceBooking($booking);

        $this->assertTrue($result);

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            $notes = $data['ContactHistory']['Notes'] ?? '';

            return $request->url() === 'https://api.pinewooddms.com/APIv2/CRM/Lead'
                && $request->hasHeader('OrganisationalUnit_UID', 'SRV-LOC-001')
                && ($data['Customer']['Forename'] ?? null) === 'Jane'
                && ($data['Customer']['Surname'] ?? null) === 'Smith'
                && ($data['Customer']['EmailAddress1'] ?? null) === 'jane@example.com'
                && ($data['EnquiryType']['EnquiryType'] ?? null) === 'Service booking'
                && Str::startsWith($data['LeadReferenceID'] ?? '', 'SRV-')
                && isset($data['PresentVehicle'])
                && ($data['PresentVehicle']['Make'] ?? null) === 'Ford'
                && ($data['PresentVehicle']['Model'] ?? null) === 'Focus'
                && Str::contains($notes, 'SB12CDE')
                && Str::contains($notes, 'View in Autonomy:');
        });

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

    public function testSendServiceBookingIncludesDeliveryOption()
    {
        $this->addSettingsAndHttpFake([
            'https://api.pinewooddms.com/*' => Http::response([
                'Lead_UID' => 'PINE-SRV-789',
            ], 200),
        ]);

        $dealership = Dealership::factory()->create([
            'data' => ['pinewood-crm-location-id' => 'SRV-LOC-002'],
        ]);

        $deliveryOption = BookingDeliveryOption::query()->create([
            'name' => 'Collect and deliver',
            'description' => 'We collect and deliver your vehicle',
            'price' => 25.00,
        ]);

        $booking = Booking::factory()->create([
            'uuid' => Str::uuid()->toString(),
            'first_name' => 'Sam',
            'last_name' => 'Jones',
            'email' => 'sam@example.com',
            'phone_number' => '07111222333',
            'registration_number' => 'DL66ZZZ',
            'mileage' => 30000,
            'location_id' => $dealership->id,
            'delivery_option_id' => $deliveryOption->id,
            'booking_time' => '2024-04-01 09:00:00',
            'vehicle_data' => [
                'make' => 'Volvo',
                'model' => 'XC60',
            ],
        ]);

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->sendServiceBooking($booking);

        $this->assertTrue($result);

        Http::assertSent(function (Request $request) {
            $notes = $request->data()['ContactHistory']['Notes'] ?? '';

            return Str::contains($notes, 'Delivery: Collect and deliver');
        });
    }

    public function testExpiredActionReturnsNull()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
            ],
        ]);

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

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->handle($action, $enquiry);

        $this->assertNull($result);
        Http::assertNothingSent();
    }

    public function testApiNotificationLoggedOnFailure()
    {
        $this->addSettingsAndHttpFake([
            'https://api.pinewooddms.com/*' => Http::response(['error' => 'Invalid lead data'], 400),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
            ],
            'source' => 'test.com',
        ]);

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

        $enquiryAction = Enquiries::makeAction('send-to-pinewood');
        $result = $enquiryAction->handle($action, $enquiry);

        $this->assertFalse($result);

        $notification = ApiNotification::query()->where('provider', 'pinewood-crm')->first();
        $this->assertNotNull($notification);
        $this->assertFalse($notification->processed);
        $this->assertEquals(400, $notification->data['status']);
        $this->assertArrayHasKey('request', $notification->data);
        $this->assertArrayHasKey('result', $notification->data);
    }

    public function testSuccessDetailsReturnsLeadReference()
    {
        $this->addSettingsAndHttpFake([
            'https://api.pinewooddms.com/*' => Http::response([
                'Lead_UID' => 'PINE-LEAD-999',
            ], 200),
        ]);

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [$q1->id => ['answer' => 'Peter']],
            'source' => 'test.com',
        ]);

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

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

        $this->assertStringContainsString('PINE-LEAD-999', $enquiryAction->successDetails());
    }

    public function testPreferredContactMethods()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'preferredContactMethods']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => 'email,sms'],
            ],
            'source' => 'test.com',
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return ($data['Customer']['AllowEmail'] ?? null) === true
                && ($data['Customer']['AllowSMS'] ?? null) === true;
        });
    }

    public function testAddressFields()
    {
        $this->addSettingsAndHttpFake();

        $q1 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'first_name']]);
        $q2 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'address1']]);
        $q3 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'city']]);
        $q4 = FormQuestion::factory()->create(['data' => ['pinewood-field' => 'postcode']]);

        $enquiry = Enquiry::factory()->create([
            'email' => 'foo@bar.com',
            'details' => [
                $q1->id => ['answer' => 'Peter'],
                $q2->id => ['answer' => '123 Main St'],
                $q3->id => ['answer' => 'Manchester'],
                $q4->id => ['answer' => 'M1 1AA'],
            ],
            'source' => 'test.com',
        ]);

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

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

        Http::assertSent(function (Request $request) {
            $data = $request->data();

            return ($data['Customer']['Address']['Address1'] ?? null) === '123 Main St'
                && ($data['Customer']['Address']['PostTown'] ?? null) === 'Manchester'
                && ($data['Customer']['Address']['PostCode'] ?? null) === 'M1 1AA';
        });
    }

    private function addSettingsAndHttpFake(?array $httpFake = null)
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Enabled',
            'config_key' => 'pinewood-crm-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Username',
            'config_key' => 'pinewood-crm-username',
            'type' => 'string',
            'value' => 'test_username',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Password',
            'config_key' => 'pinewood-crm-password',
            'type' => 'secret',
            'value' => 'test_password',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'Fallback Location ID',
            'config_key' => 'pinewood-fallback-location-id',
            'type' => 'string',
            'value' => 'DEFAULT-LOC-001',
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Pinewood',
            'name' => 'CRM Fallback Location ID',
            'config_key' => 'pinewood-crm-fallback-location-id',
            'type' => 'string',
            'value' => 'DEFAULT-LOC-001',
        ]);

        Http::fake($httpFake ?? [
            'https://api.pinewooddms.com/*' => Http::response([
                'Lead_UID' => 'TEST-LEAD-001',
            ], 200),
        ]);
    }
}
