<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Tests\TenantTestCase;

class TopTaxonomiesTest extends TenantTestCase
{
    public function testTopMakes()
    {
        $m1 = VehicleMake::factory()->create();
        $m2 = VehicleMake::factory()->create();
        $m3 = VehicleMake::factory()->create();
        Vehicle::factory(5)->create(['make_id' => $m1->id, 'is_published' => true]);
        Vehicle::factory(7)->create(['make_id' => $m2->id, 'is_published' => true]);
        Vehicle::factory(3)->create(['make_id' => $m3->id, 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['makes']
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('makes', $response->json());
        $this->assertCount(3, $response->json('makes'));
        $this->assertEquals(7, $response->json('makes.0.count'));
        $this->assertEquals($m2->slug, $response->json('makes.0.slug'));
        $this->assertEquals(5, $response->json('makes.1.count'));
        $this->assertEquals($m1->slug, $response->json('makes.1.slug'));
    }

    public function testTopBodyTypes()
    {
        $t1 = BodyStyleType::factory()->create();
        $t2 = BodyStyleType::factory()->create();
        $t3 = BodyStyleType::factory()->create();
        Vehicle::factory(5)->create(['body_style_id' => $t1->id, 'is_published' => true]);
        Vehicle::factory(7)->create(['body_style_id' => $t2->id, 'is_published' => true]);
        Vehicle::factory(3)->create(['body_style_id' => $t3->id, 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['body_types']
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('body_types', $response->json());
        $this->assertCount(3, $response->json('body_types'));
        $this->assertEquals(7, $response->json('body_types.0.count'));
        $this->assertEquals($t2->slug, $response->json('body_types.0.slug'));
        $this->assertEquals(5, $response->json('body_types.1.count'));
        $this->assertEquals($t1->slug, $response->json('body_types.1.slug'));
    }

    public function testFuelBodyTypes()
    {
        $t1 = FuelType::factory()->create();
        $t2 = FuelType::factory()->create();
        $t3 = FuelType::factory()->create();
        Vehicle::factory(5)->create(['fuel_type_id' => $t1->id, 'is_published' => true]);
        Vehicle::factory(7)->create(['fuel_type_id' => $t2->id, 'is_published' => true]);
        Vehicle::factory(3)->create(['fuel_type_id' => $t3->id, 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['fuel_types']
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('fuel_types', $response->json());
        $this->assertCount(3, $response->json('fuel_types'));
        $this->assertEquals(7, $response->json('fuel_types.0.count'));
        $this->assertEquals($t2->slug, $response->json('fuel_types.0.slug'));
        $this->assertEquals(5, $response->json('fuel_types.1.count'));
        $this->assertEquals($t1->slug, $response->json('fuel_types.1.slug'));
    }

    public function testTopBodyTypesFilteredByMake()
    {
        $m1 = VehicleMake::factory()->create();
        $m2 = VehicleMake::factory()->create();
        $t1 = BodyStyleType::factory()->create();
        $t2 = BodyStyleType::factory()->create();
        $t3 = BodyStyleType::factory()->create();
        Vehicle::factory(5)->create([
            'make_id' => $m1->id,
            'body_style_id' => $t1->id,
            'is_published' => true,
        ]);
        Vehicle::factory(2)->create([
            'make_id' => $m1->id,
            'body_style_id' => $t2->id,
            'is_published' => true,
        ]);
        Vehicle::factory(7)->create([
            'make_id' => $m2->id,
            'body_style_id' => $t3->id,
            'is_published' => true,
        ]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['body_types'],
                'make' => $m1->slug,
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('body_types', $response->json());
        $this->assertCount(2, $response->json('body_types'));
        $this->assertEquals(5, $response->json('body_types.0.count'));
        $this->assertEquals($t1->slug, $response->json('body_types.0.slug'));
        $this->assertEquals(2, $response->json('body_types.1.count'));
        $this->assertEquals($t2->slug, $response->json('body_types.1.slug'));
    }

    public function testTopFuelTypesFilteredByMake()
    {
        $m1 = VehicleMake::factory()->create();
        $m2 = VehicleMake::factory()->create();
        $f1 = FuelType::factory()->create();
        $f2 = FuelType::factory()->create();
        $f3 = FuelType::factory()->create();
        Vehicle::factory(4)->create([
            'make_id' => $m1->id,
            'fuel_type_id' => $f1->id,
            'is_published' => true,
        ]);
        Vehicle::factory(3)->create([
            'make_id' => $m1->id,
            'fuel_type_id' => $f2->id,
            'is_published' => true,
        ]);
        Vehicle::factory(8)->create([
            'make_id' => $m2->id,
            'fuel_type_id' => $f3->id,
            'is_published' => true,
        ]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['fuel_types'],
                'make' => $m1->slug,
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('fuel_types', $response->json());
        $this->assertCount(2, $response->json('fuel_types'));
        $this->assertEquals(4, $response->json('fuel_types.0.count'));
        $this->assertEquals($f1->slug, $response->json('fuel_types.0.slug'));
        $this->assertEquals(3, $response->json('fuel_types.1.count'));
        $this->assertEquals($f2->slug, $response->json('fuel_types.1.slug'));
    }

    public function testTopMakesFilteredByVehicleType(): void
    {
        $m1 = VehicleMake::factory()->create();
        $m2 = VehicleMake::factory()->create();
        $m3 = VehicleMake::factory()->create();
        Vehicle::factory(5)->create(['make_id' => $m1->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(3)->create(['make_id' => $m2->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(7)->create(['make_id' => $m3->id, 'type' => 'lcv', 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['makes'],
                'vehicle_type' => 'car',
            ]);

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('makes'));
        $this->assertEquals($m1->slug, $response->json('makes.0.slug'));
        $this->assertEquals(5, $response->json('makes.0.count'));
        $this->assertEquals($m2->slug, $response->json('makes.1.slug'));
        $this->assertEquals(3, $response->json('makes.1.count'));
    }

    public function testTopBodyTypesFilteredByVehicleType(): void
    {
        $t1 = BodyStyleType::factory()->create();
        $t2 = BodyStyleType::factory()->create();
        $t3 = BodyStyleType::factory()->create();
        Vehicle::factory(4)->create(['body_style_id' => $t1->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(2)->create(['body_style_id' => $t2->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(9)->create(['body_style_id' => $t3->id, 'type' => 'lcv', 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['body_types'],
                'vehicle_type' => 'car',
            ]);

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('body_types'));
        $this->assertEquals($t1->slug, $response->json('body_types.0.slug'));
        $this->assertEquals(4, $response->json('body_types.0.count'));
        $this->assertEquals($t2->slug, $response->json('body_types.1.slug'));
        $this->assertEquals(2, $response->json('body_types.1.count'));
    }

    public function testTopFuelTypesFilteredByVehicleType(): void
    {
        $f1 = FuelType::factory()->create();
        $f2 = FuelType::factory()->create();
        $f3 = FuelType::factory()->create();
        Vehicle::factory(6)->create(['fuel_type_id' => $f1->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(4)->create(['fuel_type_id' => $f2->id, 'type' => 'car', 'is_published' => true]);
        Vehicle::factory(10)->create(['fuel_type_id' => $f3->id, 'type' => 'lcv', 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['fuel_types'],
                'vehicle_type' => 'car',
            ]);

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('fuel_types'));
        $this->assertEquals($f1->slug, $response->json('fuel_types.0.slug'));
        $this->assertEquals(6, $response->json('fuel_types.0.count'));
        $this->assertEquals($f2->slug, $response->json('fuel_types.1.slug'));
        $this->assertEquals(4, $response->json('fuel_types.1.count'));
    }

    public function testTopBodyTypesFilteredByMakeAndVehicleType(): void
    {
        $m1 = VehicleMake::factory()->create();
        $m2 = VehicleMake::factory()->create();
        $t1 = BodyStyleType::factory()->create();
        $t2 = BodyStyleType::factory()->create();
        Vehicle::factory(3)->create([
            'make_id' => $m1->id, 'body_style_id' => $t1->id, 'type' => 'car', 'is_published' => true,
        ]);
        Vehicle::factory(5)->create([
            'make_id' => $m1->id, 'body_style_id' => $t2->id, 'type' => 'lcv', 'is_published' => true,
        ]);
        Vehicle::factory(8)->create([
            'make_id' => $m2->id, 'body_style_id' => $t1->id, 'type' => 'car', 'is_published' => true,
        ]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['body_types'],
                'make' => $m1->slug,
                'vehicle_type' => 'car',
            ]);

        $response->assertStatus(200);
        $this->assertCount(1, $response->json('body_types'));
        $this->assertEquals($t1->slug, $response->json('body_types.0.slug'));
        $this->assertEquals(3, $response->json('body_types.0.count'));
    }

    public function testBodyTypeOverride()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'foo',
            'group' => 'bar',
            'name' => 'baz',
            'config_key' => 'body-type-vehicle-type-override-suv',
            'type' => 'string',
            'value' => '',
        ]);

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'foo',
            'group' => 'bar',
            'name' => 'baz',
            'config_key' => 'body-type-vehicle-type-override-mpv',
            'type' => 'string',
            'value' => 'car',
        ]);

        $t1 = BodyStyleType::factory()->create([
            'name' => 'suv',
            'type' => 'car',
        ]);
        $t2 = BodyStyleType::factory()->create(
            [
                'name' => 'mpv',
                'type' => 'lcv',
            ]
        );
        Vehicle::factory(5)->create(['body_style_id' => $t1->id, 'is_published' => true]);
        Vehicle::factory(7)->create(['body_style_id' => $t2->id, 'is_published' => true]);

        $response = $this
            ->postJson(route('top-taxonomies'), [
                'taxonomies' => ['body_types']
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('body_types', $response->json());
        $this->assertCount(2, $response->json('body_types'));
        $this->assertEquals(7, $response->json('body_types.0.count'));
        $this->assertEquals('mpv', $response->json('body_types.0.name'));
        $this->assertEquals('car', $response->json('body_types.0.type'));

        $this->assertEquals(5, $response->json('body_types.1.count'));
        $this->assertEquals('suv', $response->json('body_types.1.name'));
        $this->assertEquals('car', $response->json('body_types.0.type'));
    }
}
