<?php

namespace Tests\Feature;

use App\Facades\Settings;
use Carbon\Carbon;
use Database\Seeders\Tenant\FinanceSettingSeeder;
use Database\Seeders\Tenant\PeterVardyFinanceSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Finance\Contracts\FinanceRequestData;
use Mtc\MercuryDataModels\Finance\FinanceServiceHelper;
use Mtc\MercuryDataModels\Finance\Jobs\FetchVehicleFinanceData;
use Mtc\MercuryDataModels\Finance\Services\CodeWeaversPeterVardy;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleAttributeValue;
use Mtc\MercuryDataModels\VehicleFinance;
use Mtc\MercuryDataModels\VehicleMake;
use Tests\TenantTestCase;
use Tests\TestCase;

class CodeWeaversServiceTest extends TenantTestCase
{
    public function testGoodRequestCalculation()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('finance-codeweavers-api_key', 'foo-baz-bar');
        Settings::update('finance-codeweavers-username', 'lorem');
        Settings::update('finance-codeweavers-password', 'ipsum');
        $provider = FinanceServiceHelper::initializeForSite();

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
        ));

        Http::assertSent(function (Request $request) {
            return $request->hasHeader('Content-Type', 'application/json')
                && $request->hasHeader('X-CW-ApiKey', 'Codeweavers-foo-baz-bar')
                && $request->url() === 'https://services.codeweavers.net/public/v3/jsonfinance/calculate'
                && $request['Credentials']['Username'] === 'lorem'
                && $request['Parameters']['Term'] === 60
                && $request['VehicleRequests'][0]['Vehicle']['CashPrice'] == 23456
                && $request['Credentials']['Password'] === 'ipsum'
                && $request['VehicleRequests'][0]['Vehicle']['Vin'] == '';
        });

        $this->assertEquals(2, $result->count());
        $finance = $result->filter(fn($finance_example) => $finance_example->finance_type->value == 'PCP')->first();
        $this->assertEquals(123, $finance->monthly_price);
        $this->assertEquals(58, $finance->number_of_payments);
        $this->assertEquals(13, $finance->apr);
        $this->assertEquals(3000, $finance->total_deposit);
        $this->assertEquals(7000, $finance->cash_price);
        $this->assertEquals(0, $finance->dealer_deposit);
        $this->assertEquals(3000, $finance->customer_deposit);
        $this->assertEquals(8393.68, $finance->payable_amount);
        $this->assertEquals(0, $finance->option_to_purchase_fee);
        $this->assertEquals(456, $finance->documentation_fee);

        $total_credit = $finance->cash_price - $finance->total_deposit;
        $this->assertEquals($total_credit, $finance->total_credit_amount);
    }

    public function testPeterVardyCodeWeaversQuotes()
    {
        Http::fake(function (Request $request) {
            if (stripos($request['Parameters']['SpecificProductType'], 'HP') !== false) {
                return Http::response($this->responseHp(), 200);
            } elseif(stripos($request['Parameters']['SpecificProductType'], 'PCP') !== false) {
                return Http::response($this->responsePcp(), 200);
            } else {
                return Http::response([], 400);
            }
        });

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        $provider = FinanceServiceHelper::initializeForSite();

        $this->assertInstanceOf(CodeWeaversPeterVardy::class, $provider);

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
            finance_option: 3,
        ));

        Http::assertSent(function (Request $request) {
            return (stripos($request['Parameters']['SpecificProductType'], 'CAT_B_') !== false);
        });

        $this->assertCount(2, $result);
        $this->assertArrayHasKey('HP', $result);
        $this->assertArrayHasKey('PCP', $result);
        $this->assertEquals(456, $result['HP']->monthly_price);
        $this->assertEquals(789, $result['PCP']->monthly_price);
        $this->assertEquals('HP', $result['HP']->finance_type->name);
        $this->assertEquals('PCP', $result['PCP']->finance_type->name);
    }

    public function testPvCallPorsche()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'porsche test'
            ],
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            '',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                in_array(
                    $request['Parameters']['SpecificProductType'],
                    [
                        'HP',
                        'PCP',
                    ]
                )
                && !array_key_exists('CustomerSelectedCreditTier', $request['Parameters'])
            );
        });
    }

    public function testPvCallBmw()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'BMW test'
            ],
        ]);

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

        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            '',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_B_') !== false
                && !array_key_exists('CustomerSelectedCreditTier', $request['Parameters'])
            );
        });
    }

    public function testPvCallMini()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'mini test'
            ],
        ]);

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

        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            '',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_A_') !== false
                && !array_key_exists('CustomerSelectedCreditTier', $request['Parameters'])
            );
        });
    }

    public function testPvCallJaguar()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'jaguar test'
            ],
        ]);

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

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            '',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_A_') !== false
                && !array_key_exists('CustomerSelectedCreditTier', $request['Parameters'])
            );
        });
    }

    public function testPvCallLandRover()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'land rover test'
            ],
        ]);

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

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            '',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_A_') !== false
                && !array_key_exists('CustomerSelectedCreditTier', $request['Parameters'])
            );
        });
    }

    public function testPvCallCarz()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');


        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

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

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_A_') !== false
                && stripos($request['Parameters']['CustomerSelectedCreditTier'] ?? '', 'BelowAverage') !== false
            );
        });
    }

    public function testPvCallOmodaNew()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'carz test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

        $vehicle_make = VehicleMake::factory()->create([
            'name' => 'omoda'
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealer->id,
            'make_id' => $vehicle_make->id,
            'is_new' => true,
        ]);

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'OMODA_') !== false
            );
        });
    }

    public function testPvCallOmodaUsed()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'carz test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

        $vehicle_make = VehicleMake::factory()->create([
            'name' => 'omoda'
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealer->id,
            'make_id' => $vehicle_make->id,
            'is_new' => false,
        ]);

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                stripos($request['Parameters']['SpecificProductType'], 'CAT_A_') !== false
            );
        });
    }

    public function testVehicleMake()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'carz test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

        $vehicle_make = VehicleMake::factory()->create([
            'name' => 'omoda'
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealer->id,
            'make_id' => $vehicle_make->id,
            'is_new' => false,
        ]);

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                array_key_exists('Manufacturer', $request['VehicleRequests'][0]['Vehicle'])
                && strtolower($request['VehicleRequests'][0]['Vehicle']['Manufacturer']) == 'omoda'
            );
        });
    }

    public function testVehicleEmptyMake()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-per-dealer-keys'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'boolean',
            'value' => true,
            'config_key' => 'finance-risk-based-pricing-enabled'
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'type' => 'string',
            'value' => '1',
            'config_key' => 'finance-risk-based-pricing-finance-options'
        ]);

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'carz test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealer->id,
            'make_id' => null,
            'is_new' => false,
        ]);

        // add vehicle attribute for finance_option
        $attribute = VehicleAttribute::factory()->create([
            'name' => 'finance option',
            'model' => 'vehicle',
            'slug' => 'finance_option',
            'type' => 'string',
            'count' => 1
        ]);

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

        $this->dispatch(new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ));

        Http::assertSent(function (Request $request) {
            return (
                array_key_exists('Manufacturer', $request['VehicleRequests'][0]['Vehicle']) == false
            );
        });
    }

    /**
     * test solution for unpredictable codeweavers payment ordering
     *
     * @return void
     */
    public function testPaymentOrder()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('finance-codeweavers-api_key', 'foo-baz-bar');
        Settings::update('finance-codeweavers-username', 'lorem');
        Settings::update('finance-codeweavers-password', 'ipsum');
        $provider = FinanceServiceHelper::initializeForSite();

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
        ));

        Http::assertSent(function (Request $request) {
            return $request->hasHeader('Content-Type', 'application/json')
                && $request->hasHeader('X-CW-ApiKey', 'Codeweavers-foo-baz-bar')
                && $request->url() === 'https://services.codeweavers.net/public/v3/jsonfinance/calculate'
                && $request['Credentials']['Username'] === 'lorem'
                && $request['Parameters']['Term'] === 60
                && $request['VehicleRequests'][0]['Vehicle']['CashPrice'] == 23456
                && $request['Credentials']['Password'] === 'ipsum'
                && $request['VehicleRequests'][0]['Vehicle']['Vin'] == '';
        });

        $this->assertEquals(2, $result->count());
        $finance = $result->filter(fn($finance_example) => $finance_example->finance_type->value == 'PCP')->first();
        $this->assertEquals(132, $finance->first_payment);
        $this->assertEquals(123, $finance->monthly_price);
        $this->assertEquals(58, $finance->number_of_payments);
        $this->assertEquals(13, $finance->apr);
        $this->assertEquals(3000, $finance->total_deposit);
        $this->assertEquals(7000, $finance->cash_price);
        $this->assertEquals(0, $finance->dealer_deposit);
        $this->assertEquals(3000, $finance->customer_deposit);
        $this->assertEquals(8393.68, $finance->payable_amount);
        $this->assertEquals(0, $finance->option_to_purchase_fee);
        $this->assertEquals(456, $finance->documentation_fee);

        $total_credit = $finance->cash_price - $finance->total_deposit;
        $this->assertEquals($total_credit, $finance->total_credit_amount);
    }

    public function testTermsAndConditions()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->responseWithQuoteReference()),
            "https://services.codeweavers.net/api/finance/quote/*/termsandconditions" => Http::response($this->responseTermsAndConditions()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        $provider = FinanceServiceHelper::initializeForSite();

        $this->assertInstanceOf(CodeWeaversPeterVardy::class, $provider);

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
            finance_option: 3,
        ));

        $this->assertCount(2, $result);
        $this->assertArrayHasKey('HP', $result);
        $this->assertArrayHasKey('PCP', $result);
        $this->assertEquals('lorem ipsum', $result['HP']->terms_and_conditions);
        $this->assertEquals('lorem ipsum', $result['PCP']->terms_and_conditions);
    }

    public function testTermsAndConditionsFailedCall()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->responseWithQuoteReference()),
            "https://services.codeweavers.net/api/finance/quote/*/termsandconditions" => Http::response([], 400),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        $provider = FinanceServiceHelper::initializeForSite();

        $this->assertInstanceOf(CodeWeaversPeterVardy::class, $provider);

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
            finance_option: 3,
        ));

        $this->assertCount(2, $result);
        $this->assertArrayHasKey('HP', $result);
        $this->assertArrayHasKey('PCP', $result);
        $this->assertEquals('', $result['HP']->terms_and_conditions);
        $this->assertEquals('', $result['PCP']->terms_and_conditions);
    }

    public function testTermsAndConditionsEmpty()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->responseWithQuoteReference()),
            "https://services.codeweavers.net/api/finance/quote/*/termsandconditions" => Http::response($this->responseTermsAndConditionsEmpty()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        $provider = FinanceServiceHelper::initializeForSite();

        $this->assertInstanceOf(CodeWeaversPeterVardy::class, $provider);

        $result = $provider->calculate(new FinanceRequestData(
            uuid: 'abc123',
            registration_number: 'SD12 ABC',
            cap_id: 1231122,
            dealer_id: 'abc123',
            engine_size: 1999,
            condition: 'new',
            registration_date: Carbon::create(2020, 1, 1),
            term: 60,
            mileage: 100000,
            annual_mileage: 13000,
            price: 23456,
            deposit: 3000,
            credit_rating: 'excellent',
            finance_option: 3,
        ));

        $this->assertCount(2, $result);
        $this->assertArrayHasKey('HP', $result);
        $this->assertArrayHasKey('PCP', $result);
        $this->assertEquals('', $result['HP']->terms_and_conditions);
        $this->assertEquals('', $result['PCP']->terms_and_conditions);
    }

    public function testStoreDeletesOldQutoes()
    {
        Http::fake([
            "https://services.codeweavers.net/public/v3/jsonfinance/calculate" => Http::response($this->response()),
            "*" => Http::response([], 400),
        ]);

        $this->seed(FinanceSettingSeeder::class);
        $this->seed(PeterVardyFinanceSeeder::class);

        Settings::update('finance-codeweavers-enabled', true);
        Settings::update('vehicle-finance-type', 'peter-vardy');

        $dealer = Dealership::factory()->create([
            'id' => 99,
            'name' => 'porsche test',
            'data' => [
                'codeweavers' => 'carz test',
                'finance-risk-based-pricing' => true
            ],
        ]);

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

        VehicleFinance::factory(10)->create([
            'vehicle_id' => $vehicle->id
        ]);

        VehicleFinance::factory(5)->create([
            'vehicle_id' => ($vehicle->id + 1)
        ]);

        $this->assertCount(15, VehicleFinance::all());
        $this->assertCount(10, VehicleFinance::query()->where('vehicle_id', '=', $vehicle->id)->get());
        $this->assertCount(5, VehicleFinance::query()->where('vehicle_id', '=', $vehicle->id + 1)->get());

        (new FetchVehicleFinanceData(
            $vehicle,
            60,
            10000,
            10,
            'BELOW_AVERAGE',
            []
        ))->handle();

        $this->assertCount(7, VehicleFinance::all());
        $this->assertCount(2, VehicleFinance::query()->where('vehicle_id', '=', $vehicle->id)->get());
        $this->assertCount(5, VehicleFinance::query()->where('vehicle_id', '=', $vehicle->id + 1)->get());
    }

    private function responseTermsAndConditions(): array
    {
        return [
            'TermsAndConditions' => 'lorem ipsum'
        ];
    }

    private function responseTermsAndConditionsEmpty(): array
    {
        return [];
    }

    private function responseWithQuoteReference()
    {
        return [
            'VehicleResults' => [
                [
                    'FinanceProductResults' => [
                        [
                            'Product' => [
                                'Type' => 'HP',
                                'Name' => 'test HP',
                            ],
                            'Quote' => [
                                'QuoteReference' => 'foo',
                                'AllInclusiveRegularPayment' => 456,
                                'Term' => 60,
                                'Apr' => 13,
                                'TotalDeposit' => 3000,
                                'FinalPayment' => 1200,
                                'RateOfInterest' => 12,
                                'CashPrice' => 7000,
                                'TotalAmountPayable' => 8393.68,
                                'Payments' => [
                                    ['Amount' => 132],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                ],
                                'Fees' => [
                                    [
                                        'Amount' => 456,
                                        'DisplayText' => 'bar',
                                        'FeeType' => 'Admin',
                                        'Profile' => 'foo',
                                        'ExternalIdentifier' => 'baz'
                                    ],
                                ],
                            ]
                        ]
                    ],
                ],
            ]
        ];
    }

    private function response(): array
    {
        return [
            'VehicleResults' => [
                [
                    'FinanceProductResults' => [
                        [
                            'Product' => [
                                'Type' => 'Hire Purchase',
                                'Name' => 'test HP',
                            ],
                            'Quote' => [
                                'AllInclusiveRegularPayment' => 555,
                                'Term' => 60,
                                'Apr' => 13,
                                'TotalDeposit' => 3000,
                                'CashDeposit' => 3000,
                                'FinalPayment' => 1200,
                                'RateOfInterest' => 12,
                                'CashPrice' => 7000,
                                'TotalAmountPayable' => 8393.68,
                                'Payments' => [
                                    ['Amount' => 132],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                ],
                                'Fees' => [
                                    [
                                        'Amount' => 456,
                                        'DisplayText' => 'bar',
                                        'FeeType' => 'Admin',
                                        'Profile' => 'foo',
                                        'ExternalIdentifier' => 'baz'
                                    ],
                                ],
                            ]
                        ],
                        [
                            'Product' => [
                                'Type' => 'PCP',
                                'Name' => 'test',
                            ],
                            'Quote' => [
                                'AllInclusiveRegularPayment' => 123,
                                'Term' => 60,
                                'Apr' => 13,
                                'TotalDeposit' => 3000,
                                'CashDeposit' => 3000,
                                'Deposit' => 3000,
                                'FinalPayment' => 1200,
                                'RateOfInterest' => 12,
                                'CashPrice' => 7000,
                                'TotalAmountPayable' => 8393.68,
                                'Payments' => [
                                    [
                                        'Amount' => 132,
                                        'NumberOfPayments' => 1,
                                    ],
                                    [
                                        'Amount' => 123,
                                        'NumberOfPayments' => 58,
                                    ],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                ],
                                'Fees' => [
                                    [
                                        'Amount' => 456,
                                        'DisplayText' => 'bar',
                                        'FeeType' => 'Admin',
                                        'Profile' => 'foo',
                                        'ExternalIdentifier' => 'baz'
                                    ],
                                ],
                            ]
                        ]
                    ],
                ],
            ]
        ];
    }

    private function responseHp()
    {
        return [
            'VehicleResults' => [
                [
                    'FinanceProductResults' => [
                        [
                            'Product' => [
                                'Type' => 'HP',
                                'Name' => 'test HP',
                            ],
                            'Quote' => [
                                'AllInclusiveRegularPayment' => 456,
                                'Term' => 60,
                                'Apr' => 13,
                                'TotalDeposit' => 3000,
                                'FinalPayment' => 1200,
                                'RateOfInterest' => 12,
                                'CashPrice' => 7000,
                                'TotalAmountPayable' => 8393.68,
                                'Payments' => [
                                    ['Amount' => 132],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                ],
                                'Fees' => [
                                    [
                                        'Amount' => 456,
                                        'DisplayText' => 'bar',
                                        'FeeType' => 'Admin',
                                        'Profile' => 'foo',
                                        'ExternalIdentifier' => 'baz'
                                    ],
                                ],
                            ]
                        ]
                    ],
                ],
            ]
        ];
    }

    private function responsePcp()
    {
        return [
            'VehicleResults' => [
                [
                    'FinanceProductResults' => [
                        [
                            'Product' => [
                                'Type' => 'PCP',
                                'Name' => 'test PCP',
                            ],
                            'Quote' => [
                                'AllInclusiveRegularPayment' => 789,
                                'Term' => 60,
                                'Apr' => 13,
                                'TotalDeposit' => 3000,
                                'FinalPayment' => 1200,
                                'RateOfInterest' => 12,
                                'CashPrice' => 7000,
                                'TotalAmountPayable' => 8393.68,
                                'Payments' => [
                                    ['Amount' => 132],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                    ['Amount' => 123],
                                ],
                                'Fees' => [
                                    [
                                        'Amount' => 456,
                                        'DisplayText' => 'bar',
                                        'FeeType' => 'Admin',
                                        'Profile' => 'foo',
                                        'ExternalIdentifier' => 'baz'
                                    ],
                                ],
                            ]
                        ]
                    ],
                ],
            ]
        ];
    }
}
