<?php

namespace Tests\Tenant;

use App\Facades\Feature;
use App\Facades\Settings;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\KeyloopFleetKompactOptionAvailabilityType;
use Mtc\MercuryDataModels\KeyloopFleetKompactOptionType;
use Mtc\MercuryDataModels\KeyloopLeaseOption;
use Mtc\MercuryDataModels\KeyloopLeaseOptionCategory;
use Mtc\MercuryDataModels\KeyloopLeaseResidualValue;
use Mtc\MercuryDataModels\KeyloopLeaseVariantOptionMapping;
use Mtc\MercuryDataModels\KeyloopLeaseVehicleVariant;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\LeaseVehicleLabel;
use Mtc\MercuryDataModels\SeoDefault;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Tests\LeaseFilterSettingSeed;
use Tests\TenantTestCase;

class LeaseVehicleTest extends TenantTestCase
{
    public function testList()
    {
        Queue::fake();
        $this->seed();
        $this->seed(LeaseFilterSettingSeed::class);

        KeyloopLeaseVehicleVariant::factory(5)->create([
            'is_cheapest_variant' => true,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('lease-vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $this->assertArrayHasKey('id', $response->json('results.data.0'));
        $this->assertArrayHasKey('make', $response->json('results.data.0'));
        $this->assertArrayHasKey('model', $response->json('results.data.0'));
        $this->assertArrayHasKey('slug', $response->json('results.data.0'));
    }

    public function testImaginStudioImage()
    {
        Queue::fake();
        $this->seed();
        $this->seed(LeaseFilterSettingSeed::class);

        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);

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

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

        $model = VehicleModel::factory()->create([
            'name' => 'bar',
        ]);

        KeyloopLeaseVehicleVariant::factory(5)->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'is_cheapest_variant' => true,
        ]);

        // No makes specified
        $response = $this
            ->postJson(route('lease-vehicles.index'));

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));

        $this->assertArrayHasKey('imagin_studio_base_url', $response->json('results.data.0'));
        $this->assertStringContainsString('cdn.imagin.studio/getImage', $response->json('results.data.0.imagin_studio_base_url'));
    }

    public function testLeaseVehicleResource()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Enabled',
            'config_key' => 'leasing-keyloop-fleet-kompact-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Provider Type',
            'config_key' => 'leasing-keyloop-fleet-kompact-provider-type',
            'type' => 'string',
            'value' => 'kearys',
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'VAT percentage in decimal',
            'description' => 'For use in finance calculations. Decimal representation of a percentage. 7% should be entered as 0.07',
            'config_key' => 'leasing-keyloop-fleet-kompact-vat-rate',
            'type' => 'number',
            'value' => 0.23,
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Interest rate percentage in decimal',
            'description' => 'For use in finance calculations. Decimal representation of a percentage. 7% should be entered as 0.07',
            'config_key' => 'leasing-keyloop-fleet-kompact-interest-rate',
            'type' => 'number',
            'value' => 0.07,
        ]);

        Feature::setEnabled(tenant(), ['imagin-studio-placeholders']);

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

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

        $model = VehicleModel::factory()->create([
            'name' => 'baz',
        ]);

        $variant = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo',
            'make_id' => $make->id,
            'model_id' => $model->id,
            'door_count' => 3,
            'is_cheapest_variant' => true,
            'price_ex_vat_ex_vrt' => 34766.33,
            'price_inc_vat_inc_vrt' => 55000,
            'delivery_ex_vat_ex_vrt' => 0,
            'vehicle_vrt' => 100,
            'finance_recently_updated' => false,
            'cheapest_monthly_price_ex_vat' => 0,
            'cheapest_monthly_price_inc_vat' => 0,
        ]);

        KeyloopLeaseResidualValue::factory()->create([
            'external_variant_id' => $variant->external_variant_id,
            'contract_length' => 36,
            'annual_mileage' => 15000,
            'residual_value_excluding_vat' => 11871.43,
            'residual_value_including_vat' => 11871.43 * 1.23,
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', $variant));

        $response->assertStatus(200);

        $this->assertArrayHasKey('data', $response->json());

        $this->assertArrayHasKey('slug', $response->json('data'));
        $this->assertEquals('foo', $response->json('data.slug'));

        $this->assertArrayHasKey('spec', $response->json('data'));
        $this->assertArrayHasKey('options', $response->json('data'));
        $this->assertArrayHasKey('colours', $response->json('data'));
        $this->assertArrayHasKey('trims', $response->json('data'));
        $this->assertArrayHasKey('door_count', $response->json('data'));
        $this->assertArrayHasKey('delivery_ex_vat_ex_vrt', $response->json('data'));
        $this->assertEquals(55000, $response->json('data.rrp'));

        $this->assertEquals(3, $response->json('data.door_count'));

        $this->assertArrayHasKey('finance_options', $response->json('data'));
        $this->assertEquals(735.15, $response->json('data.finance_options.monthly_prices.36-15000-12.monthly_price_ex_vat'));
        $this->assertEquals(735.15, $response->json('data.finance_options.cheapest_monthly_price.monthly_price_ex_vat'));

        $this->assertArrayHasKey('finance_settings', $response->json('data'));
        $this->assertArrayHasKey('contract_terms', $response->json('data.finance_settings'));
        $this->assertArrayHasKey('deposit_quantity_months', $response->json('data.finance_settings'));
        $this->assertArrayHasKey('annual_mileages', $response->json('data.finance_settings'));
        $this->assertArrayHasKey('seo', $response->json('data'));
    }

    public function testSeo()
    {
        SeoDefault::factory()->create([
            'section' => 'lease-vehicle',
            'title' => 'Lease a {{MAKE}} {{MODEL}}',
            'description' => 'more info on {{MAKE}} {{MODEL}}',
        ]);

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

        $model = VehicleModel::factory()->create([
            'name' => 'bar',
        ]);

        $variant = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo',
            'make_id' => $make->id,
            'model_id' => $model->id,
            'door_count' => 3,
            'is_cheapest_variant' => true,
            'price_ex_vat_ex_vrt' => 34766.33,
            'delivery_ex_vat_ex_vrt' => 0,
            'vehicle_vrt' => 100,
            'finance_recently_updated' => false,
            'cheapest_monthly_price_ex_vat' => 0,
            'cheapest_monthly_price_inc_vat' => 0,
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', $variant));

        $response->assertStatus(200);

        $this->assertEquals('Lease a foo bar', $response->json('data.seo.title'));
        $this->assertEquals('more info on foo bar', $response->json('data.seo.description'));
    }

    public function testFeaturedVariants()
    {
        KeyloopLeaseVehicleVariant::factory(3)->create([
            'featured' => true,
        ]);

        KeyloopLeaseVehicleVariant::factory(5)->create([
            'featured' => false,
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.featured'));

        $response->assertStatus(200);

        $vehicles = collect($response->json('items'))->reject(fn ($value, $key) => $key == 'finance_settings');
        $this->assertCount(3, $vehicles);
    }

    public function testVehicleApplicableLabel()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'valuation-auto-trader-enabled',
            'value' => false,
            'type' => 'boolean',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'lease-vehicle-labels-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $label = Label::factory()->create([
            'name' => 'applicable',
            'type' => 'fpa'
        ]);

        $vehicle = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo-baz-bar',
        ]);

        LeaseVehicleLabel::create([
            'vehicle_id' => $vehicle->id,
            'label_id' => $label->id
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'foo-baz-bar'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertArrayHasKey('labels', $response->json('data'));
        $this->assertCount(1, $response->json('data.labels'));
    }

    public function testDerivative()
    {
        // test derivative with make and duplicate model
        $make = VehicleMake::factory()->create([
            'name' => 'Audi',
            'slug' => 'audi',
        ]);

        $model = VehicleModel::factory()->create([
            'name' => 'A3',
            'slug' => 'a3',
        ]);

        $vehicle = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo',
            'make_id' => $make->id,
            'model_id' => $model->id,
            'name' => 'Audi A3 A3 SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'foo'));

        $response->assertStatus(200);
        $this->assertEquals('SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));

        // test derivatives without make
        $vehicle->update([
            'name' => 'A3 A3 SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'foo'));

        $response->assertStatus(200);
        $this->assertEquals('SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));

        // test derivatives without duplicate models
        $vehicle->update([
            'name' => 'Audi A3 SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'foo'));

        $response->assertStatus(200);
        $this->assertEquals('SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));

        // test derivatives where derivative doesn't need to be changed
        $vehicle->update([
            'name' => 'SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'foo'));

        $response->assertStatus(200);
        $this->assertEquals('SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));

        // test where vehicle has no make
        KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'bar',
            'make_id' => null,
            'model_id' => $model->id,
            'name' => 'Audi A3 A3 SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'bar'));

        $response->assertStatus(200);
        $this->assertEquals('Audi A3 A3 SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));

        // test where vehicle has no model
        KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'baz',
            'make_id' => $make->id,
            'model_id' => null,
            'name' => 'Audi A3 A3 SB 40 TFSIE 204HP S-T SLINE',
        ]);

        $response = $this
            ->getJson(route('lease-vehicles.show', 'baz'));

        $response->assertStatus(200);
        $this->assertEquals('Audi A3 A3 SB 40 TFSIE 204HP S-T SLINE', $response->json('data.derivative'));
    }

    public function testSpec()
    {
        $make = VehicleMake::factory()->create([
            'name' => 'bar',
        ]);

        $model = VehicleModel::factory()->create([
            'name' => 'baz',
        ]);

        $variant = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo',
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);

        $this->setupOptions($variant->external_variant_id, $make->id, $model->id);

        $response = $this
            ->getJson(route('lease-vehicles.show', $variant));

        $response->assertStatus(200);

        $this->assertCount(3, $response->json('data.spec'));
        $this->assertArrayHasKey('comfort', $response->json('data.spec'));
        $this->assertArrayHasKey('exterior', $response->json('data.spec'));
        $this->assertArrayHasKey('Miscellaneous', $response->json('data.spec'));
        $this->assertEquals('heated seats', $response->json('data.spec.comfort.0'));
        $this->assertContains('sunroof', $response->json('data.spec.exterior'));
        $this->assertContains('spoiler', $response->json('data.spec.exterior'));
        $this->assertContains('stereo', $response->json('data.spec.Miscellaneous'));
    }

    public function testRoadTax()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Enabled',
            'config_key' => 'leasing-keyloop-fleet-kompact-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Provider Type',
            'config_key' => 'leasing-keyloop-fleet-kompact-provider-type',
            'type' => 'string',
            'value' => 'kearys',
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'VAT percentage in decimal',
            'description' => 'For use in finance calculations. Decimal representation of a percentage. 7% should be entered as 0.07',
            'config_key' => 'leasing-keyloop-fleet-kompact-vat-rate',
            'type' => 'number',
            'value' => 0.23,
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Leasing',
            'group' => 'Keyloop Fleet Kompact',
            'name' => 'Interest rate percentage in decimal',
            'description' => 'For use in finance calculations. Decimal representation of a percentage. 7% should be entered as 0.07',
            'config_key' => 'leasing-keyloop-fleet-kompact-interest-rate',
            'type' => 'number',
            'value' => 0.07,
        ]);

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

        $model = VehicleModel::factory()->create([
            'name' => 'baz',
        ]);

        $variant = KeyloopLeaseVehicleVariant::factory()->create([
            'slug' => 'foo',
            'make_id' => $make->id,
            'model_id' => $model->id,
            'road_fund_licence' => 190,
        ]);

        $this->setupOptions($variant->external_variant_id, $make->id, $model->id);

        $response = $this
            ->getJson(route('lease-vehicles.show', $variant));

        $response->assertStatus(200);

        $this->assertArrayHasKey('road_tax_monthly', $response->json('data'));
        $this->assertEquals(15.83, $response->json('data.road_tax_monthly'));
    }

    private function setupOptions(string $external_variant_id, int $make_id, int $model_id)
    {
        KeyloopLeaseOption::query()->create([
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'AAA',
            'name' => 'heated seats',
        ]);

        KeyloopLeaseOption::query()->create([
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'BBB',
            'name' => 'sunroof',
        ]);

        KeyloopLeaseOption::query()->create([
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'CCC',
            'name' => 'spoiler',
        ]);

        KeyloopLeaseOption::query()->create([
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'DDD',
            'name' => 'not applicable',
        ]);

        KeyloopLeaseOption::query()->create([
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'EEE',
            'name' => 'stereo',
        ]);

        KeyloopLeaseVariantOptionMapping::query()->create([
            'external_variant_id' => $external_variant_id,
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'AAA',
            'option_availability_code' => KeyloopFleetKompactOptionAvailabilityType::STANDARD,
        ]);

        KeyloopLeaseVariantOptionMapping::query()->create([
            'external_variant_id' => $external_variant_id,
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'BBB',
            'option_availability_code' => KeyloopFleetKompactOptionAvailabilityType::STANDARD,
        ]);

        KeyloopLeaseVariantOptionMapping::query()->create([
            'external_variant_id' => $external_variant_id,
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'CCC',
            'option_availability_code' => KeyloopFleetKompactOptionAvailabilityType::STANDARD,
        ]);

        KeyloopLeaseVariantOptionMapping::query()->create([
            'external_variant_id' => $external_variant_id,
            'make_id' => $make_id,
            'model_id' => $model_id,
            'option_type' => KeyloopFleetKompactOptionType::FACTORY_OPTION,
            'option_code' => 'EEE',
            'option_availability_code' => KeyloopFleetKompactOptionAvailabilityType::STANDARD,
        ]);

        KeyloopLeaseOptionCategory::query()->create([
            'option_code' => 'AAA',
            'name' => 'comfort',
        ]);

        KeyloopLeaseOptionCategory::query()->create([
            'option_code' => 'BBB',
            'name' => 'exterior',
        ]);

        KeyloopLeaseOptionCategory::query()->create([
            'option_code' => 'CCC',
            'name' => 'exterior',
        ]);

        KeyloopLeaseOptionCategory::query()->create([
            'option_code' => 'DDD',
            'name' => 'exterior',
        ]);
    }
}
