<?php

namespace Tests\Feature;

use App\Crm\Config\DealerWebConfig;
use App\Facades\Settings;
use App\Jobs\ProcessIncomingReservationJob;
use App\Services\DealershipDetection;
use App\Services\DealerWebLmsApi;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\VehicleReservations\Console\Commands\IngestReservations;
use Mtc\VehicleReservations\Reservation;
use Tests\TestCase;
use Tests\UserForTenant;

class VehicleReservationTest extends TestCase
{
    use DatabaseMigrations;
    use UserForTenant;

    protected $tenancy = true;

    public function testReservationIngest()
    {
        Bus::fake();

        Reservation::factory()->create([
            'ingested_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        $command = $this->artisan(IngestReservations::class);
        $command->run();

        Bus::assertDispatched(ProcessIncomingReservationJob::class);
        Bus::assertNotDispatched(\Mtc\VehicleReservations\Jobs\ProcessIncomingReservationJob::class);
    }

    public function testDealerWebReservationData()
    {
        $debug_endpoint = 'dealerweb-debug-endpoint';

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Dealer Web LMS',
            'name' => 'Dealer Web Endpoint',
            'config_key' => 'dealerweblms-endpoint',
            'type' => 'string',
            'value' => $debug_endpoint,
            'description' => 'Dealer Web LMS endpoint',
        ]);

        Http::fake([
            $debug_endpoint => Http::response('<AddLeadResult>
                <CustomerID>123456</CustomerID>
                <ErrorCode>0</ErrorCode>
                <ErrorMessage />
            </AddLeadResult>
            '),
            "*" => Http::response([], 400),
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_new' => true,
            'registration_number' => 'ABC123',
        ]);

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

        (new DealerWebLmsApi(new DealerWebConfig(), new DealershipDetection()))->sendReservation($reservation);

        Http::assertSent(function (Request $request) {
            return Str::contains($request->body(), 'Amount Paid: 99')
                && Str::contains($request->body(), 'Vehicle Registration: ABC123');
        });
    }

    public function testProcessJobCallsDealerweb()
    {
        $debug_endpoint = 'dealerweb-debug-endpoint';

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Dealer Web LMS',
            'name' => 'Dealer Web Endpoint',
            'config_key' => 'dealerweblms-endpoint',
            'type' => 'string',
            'value' => $debug_endpoint,
        ]);

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Dealer Web LMS',
            'name' => 'Dealer Web Endpoint',
            'config_key' => 'dealerweblms-send-reservations',
            'type' => 'boolean',
            'value' => true,
        ]);

        Http::fake([
            $debug_endpoint => Http::response('<AddLeadResult>
                <CustomerID>123456</CustomerID>
                <ErrorCode>0</ErrorCode>
                <ErrorMessage />
            </AddLeadResult>
            '),
            "*" => Http::response([], 400),
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_new' => true,
            'registration_number' => 'ABC123',
        ]);

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

        (new ProcessIncomingReservationJob($reservation))->handle();

        Http::assertSent(function (Request $request) use ($debug_endpoint) {
            return Str::contains($request->url(), $debug_endpoint);
        });
    }

    public function testProcessJobCallsEnquiryMax()
    {
        Config::set('services.enquiry-max.mode', 'live');

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'enquiry max',
            'name' => 'enquiry max',
            'config_key' => 'crm-enquiry-max-send-reservations',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'enquiry max',
            'name' => 'enquiry max',
            'config_key' => 'crm-enquiry-max-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'enquiry max',
            'name' => 'enquiry max',
            'config_key' => 'crm-enquiry-max-client-id',
            'type' => 'string',
            'value' => '123',
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'enquiry max',
            'name' => 'enquiry max',
            'config_key' => 'crm-enquiry-max-client-secret',
            'type' => 'string',
            'value' => '456',
        ]);

        Http::fake([
            'https://api.enquirymax.net/*' => Http::response([
                'accessToken' => 'foo',
            ]),
            "*" => Http::response([], 400),
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_new' => true,
            'registration_number' => 'ABC123',
        ]);

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

        (new ProcessIncomingReservationJob($reservation))->handle();

        Http::assertSent(function (Request $request) {
            return Str::contains($request->url(), 'https://api.enquirymax.net');
        });
    }

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

        Settings::make([
            'tab' => 'CRM',
            'section' => 'Integrations',
            'group' => 'Salesforce',
            'name' => 'Enabled',
            'config_key' => 'salesforce-crm-send-reservations',
            'type' => 'boolean',
            'value' => true,
        ]);

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

        Http::fake([
            '*' => Http::response([
                'access_token' => 'foo',
                'instance_url' => 'https://test.salesforce.com',
            ]),
            //"*" => Http::response([], 400),
        ]);

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

        $vehicle = Vehicle::factory()->create([
            'is_new' => true,
            'registration_number' => 'ABC123',
            'uuid' => '123456',
            'dealership_id' => $dealership->id,
        ]);

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

        (new ProcessIncomingReservationJob($reservation))->handle();

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

            return Str::contains($request->url(), 'https://test.salesforce.com')
                && $request['enquiry']['feedSource'] === 'test-feed-source'
                && $request['enquiry']['formType'] === 'Reserve a Car'
                && $request['enquiry']['dealerId'] === '12345'
                && empty($request['customer']['firstName'])
                && $request['customer']['lastName'] === $reservation->name
                && $request['customer']['email'] === $reservation->email
                && $request['customer']['mobile'] === $reservation->contact_number
                && $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;
        });
    }
}
