<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use App\Http\Resources\VehicleViewResource;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Setting;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleAttributeValue;
use Mtc\MercuryDataModels\VehicleFinance;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class VehicleAttributeTest extends TenantTestCase
{
    use UserForTenant;

    public function testVehicleAttributes()
    {
        $vehicle = Vehicle::factory()->create();

        $this->assertNotEmpty($vehicle);

        // try setting attribute
        $vehicle_attribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'model' => 'vehicle',
                    'name' => 'lez_compliant',
                ],
                [
                    'slug' => 'lez_compliant',
                    'type' => 'boolean',
                    'validation' => [],
                    'data' => []
                ]
            );

        // assert that vehicle doesn't have any attributes
        $example_vehicle_lez_compliant = $vehicle->attributeValues()->where('attribute_id', '=',
            $vehicle_attribute->id)->first();

        $this->assertEmpty($example_vehicle_lez_compliant);

        // add an attribute value for the vehicle
        $vehicle_attribute_value = VehicleAttributeValue::query()->updateOrCreate(
            [
                'attribute_id' => $vehicle_attribute->id,
                'owner_id' => $vehicle->id,
                'owner_type' => 'vehicle',
            ],
            [
                'value' => true
            ]
        );

        $this->assertEquals(1, VehicleAttributeValue::count());
        $this->assertEquals($vehicle->id, $vehicle_attribute_value->owner_id);
        $this->assertEquals($vehicle_attribute->id, $vehicle_attribute_value->attribute_id);
        $this->assertGreaterThan(0, $vehicle->attributeValues->count());

        // check that looking up the vehicle attribute works as expected
        $example_vehicle_lez_compliant = $vehicle->attributeValues()
            ->whereHas('attribute', function ($query) {
                $query->where('name', '=', 'lez_compliant');
            })->first();

        $this->assertNotEmpty($example_vehicle_lez_compliant);
        $this->assertEquals('lez_compliant', $example_vehicle_lez_compliant->attribute->name);
        $this->assertEquals(1, $example_vehicle_lez_compliant->value);

        // ensure that asking for values for missing vehicle attributes is handled gracefully
        $test_missing_value = $vehicle->attributeValues()
            ->whereHas('attribute', function ($query) {
                $query->where('name', '=', 'missing_value');
            })->first();

        $this->assertNull($test_missing_value);

        $vehicle_resource_array = new VehicleViewResource(Vehicle::factory()->create())->toArray(request());
        $extras = $vehicle_resource_array['vehicle']['extra'];
        $lez_compliant = collect($extras)->where('name', '=', 'lez_compliant');
        $missing_value = collect($extras)->where('name', '=', 'my_missing_value');

        $this->assertFalse($lez_compliant->isEmpty());
        $this->assertTrue($missing_value->isEmpty());
    }

    public function testVehicleResource()
    {
        $vehicle_resource_array = new VehicleViewResource(Vehicle::factory()->create())->toArray(null);
        $extras = $vehicle_resource_array['vehicle']['extra'];
        $lez_compliant = collect($extras)->where('name', '=', 'lez_compliant');

        $this->assertEmpty($lez_compliant);
    }

    public function testSavingsLoaded()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled',
            'value' => true,
            'type' => 'bool',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled-previous-price',
            'value' => true,
            'type' => 'bool',
        ]);

        $this->assertEquals(true, Settings::get('vehicle-savings-enabled'));

        $vehicle = Vehicle::factory()->create([
            'price' => 11000,
            'original_price' => 12000,
        ]);

        $vehicle_resource_array = new VehicleViewResource($vehicle)->toArray(null);

        $this->assertArrayHasKey('vehicle', $vehicle_resource_array);
        $this->assertArrayHasKey('extra', $vehicle_resource_array['vehicle']);

        $this->assertTrue(collect($vehicle_resource_array['vehicle']['extra'])
                ->where('slug', 'saving_original_price')->count() > 0);
        $this->assertEquals(1000, collect($vehicle_resource_array['vehicle']['extra'])
            ->where('slug', 'saving_original_price')->first()['value'][0]['value']);
    }

    public function testPVSavingsLoaded()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled',
            'value' => true,
            'type' => 'bool',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled-previous-price',
            'value' => true,
            'type' => 'bool',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-type',
            'value' => 'peter-vardy',
            'type' => 'string',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled-finance-saving',
            'value' => true,
            'type' => 'bool',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-pv-finance-saving-pounds-per-thousand',
            'value' => 25,
            'type' => 'int',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-enabled-finance-contribution',
            'value' => true,
            'type' => 'bool',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-pv-finance-contribution-percent-ice',
            'value' => 2,
            'type' => 'int',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-pv-finance-contribution-percent-electric',
            'value' => 5,
            'type' => 'int',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-pv-finance-contribution-max-ice',
            'value' => 600,
            'type' => 'int',
        ]);

        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicle-savings-pv-finance-contribution-max-electric',
            'value' => 1000,
            'type' => 'int',
        ]);

        $this->assertEquals(true, Settings::get('vehicle-savings-enabled'));

        Dealership::factory()->create([
            'id' => 1,
            'location_stock' => 'VE',
            'name' => 'Carz Edinburgh'
        ]);

        $make = VehicleMake::factory()->create([
            'name' => 'Audi'
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => 1,
            'type' => 'car',
            'price' => 11000,
            'original_price' => 12000,
            'previous_price' => 12000,
            'rrp_price' => 0,
            'is_vat_applicable' => true,
            'first_registration_date' => date('Y-m-d', strtotime('-24 months'))
        ]);

        $finance_quote = VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'monthly_price' => 200,
            'total_credit_amount' => 91000
        ]);

        $vehicle->make_id = $make->id;
        $vehicle->type = 'car';
        $vehicle->save();
        $vehicle->refresh();

        $expected_finance_rate_saving = 25 * ($finance_quote->total_credit_amount / 1000);

        // capped at £600 for combustion engines
        $expected_finance_contribution = 600;

        $vehicle_resource_array = new VehicleViewResource($vehicle)->toArray(null);

        $extra = collect($vehicle_resource_array['vehicle']['extra']);

        $this->assertTrue($extra->where('slug', 'saving_original_price')->count() > 0);
        $this->assertTrue($extra->where('slug', 'saving_rrp')->count() > 0);
        $this->assertTrue($extra->where('slug', 'saving_finance_rate')->count() > 0);
        $this->assertTrue($extra->where('slug', 'saving_finance_contribution')->count() > 0);

        $this->assertEquals(1000, $extra->where('slug', 'saving_original_price')->first()['value'][0]['value']);
        $this->assertNull($extra->where('slug', 'saving_rrp')->first()['value'][0]['value']);
        $this->assertNotNull($extra->where('slug', 'saving_finance_rate')->first()['value'][0]['value']);
        $this->assertNotNull($extra->where('slug', 'saving_finance_contribution')->first()['value'][0]['value']);

        $this->assertEquals($expected_finance_rate_saving,
            $extra->where('slug', 'saving_finance_rate')->first()['value'][0]['value']);
        $this->assertEquals($expected_finance_contribution,
            $extra->where('slug', 'saving_finance_contribution')->first()['value'][0]['value']);
    }

    public function testVehicleAttributeCanAddSortableSetting()
    {
        $slug = 'sortable';
        $vehicleAttribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'Sortable Boolean Attribute',
                ],
                [
                    'type' => 'boolean',
                    'slug' => $slug,
                    'validation' => [],
                    'data' => [],
                    'sortable' => false
                ]
            );

        $vehicleAttribute->sortable = true;
        $vehicleAttribute->save();

        $setting = Settings::get('automotive-vehicle-sorting-' . $slug);

        $this->assertNotNull($setting);
        $this->assertTrue($setting);
    }

    public function testVehicleAttributeCanAddFilterableSetting()
    {
        $slug = 'sortable';
        $vehicleAttribute = VehicleAttribute::query()
            ->firstOrCreate(
                [
                    'name' => 'Filterable Boolean Attribute',
                ],
                [
                    'type' => 'boolean',
                    'slug' => $slug,
                    'validation' => [],
                    'data' => [],
                    'filterable' => false
                ]
            );

        $vehicleAttribute->filterable = true;
        $vehicleAttribute->save();

        $setting = Settings::get('automotive-vehicle-filters-'.$slug);

        $this->assertNotNull($setting);
        $this->assertTrue($setting);
    }
}
