<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Queue;
use Mtc\Filter\Contracts\FilterInstance;
use Mtc\MercuryDataModels\Vehicle;
use Tests\SortingSettingSeed;
use Tests\TenantTestCase;

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

    public function testSortByLatest()
    {
        $this->seed(SortingSettingSeed::class);
        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'created_at' => Carbon::now()->subWeek(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'created_at' => Carbon::now()->subDay(),
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'created_at' => Carbon::now(),
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'latest',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle3->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle2->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.2.id'));
    }

    public function testSortByPriceAsc()
    {
        $this->seed(SortingSettingSeed::class);
        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 10200,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 24000,
            ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'price' => 8900,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-asc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle3->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle2->id, $response->json('results.data.2.id'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'price-desc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle2->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.2.id'));
    }

    public function testSortByMonthlyPriceAsc()
    {
        $this->seed(SortingSettingSeed::class);
        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 123,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 321,
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'monthly_price' => 222,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'monthly-price-asc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle1->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle2->id, $response->json('results.data.2.id'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'monthly-price-desc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle2->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.2.id'));
    }

    public function testSortByMileageAsc()
    {
        $this->seed(SortingSettingSeed::class);
        Settings::make([
            'tab' => 'foo',
            'section' => 'automotive',
            'group' => 'General',
            'name' => 'Distance measurement',
            'config_key' => 'automotive-distance_measurement',
            'type' => 'string',
            'value' => 'mi',
        ]);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 50000,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 65000,
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'odometer_mi' => 60000,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'mileage-asc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle1->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle2->id, $response->json('results.data.2.id'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'mileage-desc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle2->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.2.id'));
    }

    public function testSortByAgeAsc()
    {
        $this->seed(SortingSettingSeed::class);
        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2020,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2018,
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'manufacture_year' => 2021,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'age-asc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle2->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.2.id'));

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'age-desc',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle3->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle2->id, $response->json('results.data.2.id'));
    }

    public function testSortByRelevance()
    {
        $this->seed(SortingSettingSeed::class);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'order' => 3,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'order' => 1,
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'order' => 2,
        ]);

        $response = $this
            ->postJson(route('vehicles.index'), [
                'sort_by' => 'relevance',
            ]);

        $response->assertStatus(200);
        $this->assertEquals($vehicle2->id, $response->json('results.data.0.id'));
        $this->assertEquals($vehicle3->id, $response->json('results.data.1.id'));
        $this->assertEquals($vehicle1->id, $response->json('results.data.2.id'));
    }

    public function testFiltersAreEnabledBySettings()
    {
        $this->seed(SortingSettingSeed::class);
        $sort_choices = App::make(FilterInstance::class)->getSortOptions();
        $this->assertCount(10, $sort_choices);

        Settings::update('automotive-vehicle-sorting-price-asc', false);
        Settings::update('automotive-vehicle-sorting-mileage-asc', false);
        $sort_choices = App::make(FilterInstance::class)->getSortOptions();
        $this->assertCount(8, $sort_choices);
        $this->assertArrayNotHasKey('mileage-asc', $sort_choices);
        $this->assertArrayNotHasKey('price-asc', $sort_choices);
    }
}
