<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Tests\TenantTestCase;

class SimilarVehicleTest extends TenantTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        Queue::fake();
    }

    public function testSimilarMake()
    {
        $this->enableSimilarVehicles('make');

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

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

        $vehicle_foo = Vehicle::factory()->create([
            'is_published' => true,
            'make_id' => $make_foo->id,
        ]);

        $vehicle_bar = Vehicle::factory()->create([
            'is_published' => true,
            'make_id' => $make_bar->id,
        ]);

        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make_foo->id,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'make_id' => $make_bar->id,
        ]);

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_foo->slug));

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('items'));

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_bar->slug));

        $response->assertStatus(200);
        $this->assertCount(3, $response->json('items'));
    }

    public function testSimilarModel()
    {
        $this->enableSimilarVehicles('make-model');

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

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

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

        $vehicle_bar = Vehicle::factory()->create([
            'make_id' => $make_foo->id,
            'model_id' => $model_bar->id,
        ]);

        $vehicle_baz = Vehicle::factory()->create([
            'make_id' => $make_foo->id,
            'model_id' => $model_baz->id,
        ]);

        Vehicle::factory(2)->create([
            'is_published' => true,
            'make_id' => $make_foo->id,
            'model_id' => $model_bar->id,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'make_id' => $make_foo->id,
            'model_id' => $model_baz->id,
        ]);

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_bar->slug));

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('items'));

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_baz->slug));

        $response->assertStatus(200);
        $this->assertCount(3, $response->json('items'));
    }

    public function testSimilarPrice()
    {
        $this->enableSimilarVehicles('price');

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 100
        ]);

        Vehicle::factory(10)->create([
            'is_published' => true,
            'price' => 200
        ]);

        Vehicle::factory(2)->create([
            'is_published' => true,
            'price' => 500
        ]);

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle->slug));

        $response->assertStatus(200);

        foreach ($response->json('items') as $item) {
            $this->assertEquals(200, $item['price']);
        }
    }

    public function testSimilarPriceRange()
    {
        $this->enableSimilarVehicles('price-20');

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 100
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 50
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 150
        ]);

        $this->assertCount(3, Vehicle::query()->get());

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertCount(0, $response->json('items'));

        // remove our testing vehicles
        Vehicle::query()->delete();
        $this->assertCount(0, Vehicle::query()->get());

        $vehicle = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 100
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 85
        ]);

        Vehicle::factory()->create([
            'is_published' => true,
            'price' => 115
        ]);

        $this->assertCount(3, Vehicle::query()->get());

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle->slug));

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('items'));
    }

    public function testSimilarBodyType()
    {
        $this->enableSimilarVehicles('body-type');

        $body_saloon = BodyStyleType::factory()->create([
            'name' => 'saloon'
        ]);

        $body_coupe = BodyStyleType::factory()->create([
            'name' => 'coupe'
        ]);

        $vehicle_coupe = Vehicle::factory()->create([
            'is_published' => true,
            'body_style_id' => $body_coupe->id
        ]);

        $vehicle_saloon = Vehicle::factory()->create([
            'is_published' => true,
            'body_style_id' => $body_saloon->id
        ]);

        Vehicle::factory(2)->create([
            'is_published' => true,
            'body_style_id' => $body_coupe
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'body_style_id' => $body_saloon
        ]);

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_coupe->slug));

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('items'));

        $response = $this
            ->getJson(route('vehicles.similar', $vehicle_saloon->slug));

        $response->assertStatus(200);
        $this->assertCount(3, $response->json('items'));
    }

    public function testSearchResultNoCrossSell()
    {
        $this->enableSimilarVehicles();

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $this->assertArrayHasKey('cross_sell', $response->json('results'));
        $this->assertEmpty($response->json('results.cross_sell'));
    }

    public function testSearchResult()
    {
        $this->enableSimilarVehicles();

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-location',
            'type' => 'string',
            'value' => 'all',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true
        ]);

        $response = $this
            ->postJson(route('vehicles.index'));
        $response->assertStatus(200);

        $this->assertArrayHasKey('cross_sell', $response->json('results'));
        $this->assertNotEmpty($response->json('results.cross_sell'));
    }

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

        $vehicle = Vehicle::factory()->create([
            'is_published' => true
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));
        $response->assertStatus(200);

        $this->assertArrayHasKey('cross_sell', $response->json());
        $this->assertEmpty($response->json('cross_sell'));
    }

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

        $this->enableSimilarVehicles();

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-location',
            'type' => 'string',
            'value' => 'srp',
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));
        $response->assertStatus(200);

        $this->assertArrayHasKey('cross_sell', $response->json());
        $this->assertEmpty($response->json('cross_sell'));
    }

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

        $this->enableSimilarVehicles();

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-location',
            'type' => 'string',
            'value' => 'fpa',
        ]);

        $vehicle = Vehicle::factory()->create([
            'is_published' => true
        ]);

        $response = $this
            ->getJson(route('vehicles.show', $vehicle->slug));
        $response->assertStatus(200);

        $this->assertArrayHasKey('cross_sell', $response->json());
        $this->assertNotEmpty($response->json('cross_sell'));
    }

    private function enableSimilarVehicles($type = '')
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'vehicles-cross-sell-type',
            'type' => 'string',
            'value' => $type,
        ]);
    }
}
