<?php

namespace Tests\Tenant;

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

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

    public function testStockProviderSortingAppliedOnAllowedSort()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['auto-trader', 'pinewood'], ['latest']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'pinewood',
            'created_at' => Carbon::now(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now()->subDay(),
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'other-provider',
            'created_at' => Carbon::now()->subHour(),
        ]);

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

        $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 testStockProviderSortingNotAppliedOnDisallowedSort()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['auto-trader', 'pinewood'], ['latest']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'other-provider',
            'price' => 100,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'price' => 200,
        ]);

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

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

    public function testStockProviderSortingWithDefaultProvider()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['default', 'auto-trader'], ['latest']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => null,
            'created_at' => Carbon::now()->subDay(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now(),
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'pinewood',
            'created_at' => Carbon::now()->subHour(),
        ]);

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

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

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

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Sorting',
            'name' => 'Pre sort by stock provider',
            'config_key' => 'filter-results-order-by-stock-provider',
            'type' => 'boolean',
            'value' => false,
        ]);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'other-provider',
            'created_at' => Carbon::now(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now()->subDay(),
        ]);

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

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

    public function testStockProviderSortingWithSecondarySortWithinProviderGroup()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['auto-trader'], ['latest']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now()->subWeek(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now(),
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'pinewood',
            'created_at' => Carbon::now()->subDay(),
        ]);

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

        $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 testStockProviderSortingWithPriceDesc()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['auto-trader', 'pinewood'], ['price-desc']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'pinewood',
            'price' => 50000,
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'price' => 10000,
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'price' => 30000,
        ]);
        $vehicle4 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'other-provider',
            'price' => 99000,
        ]);

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

        $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'));
        $this->assertEquals($vehicle4->id, $response->json('results.data.3.id'));
    }

    public function testStockProviderSortingOnStockAndOffersRoute()
    {
        $this->seed(SortingSettingSeed::class);
        $this->enableStockProviderSorting(['auto-trader', 'pinewood'], ['latest']);

        $vehicle1 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'pinewood',
            'created_at' => Carbon::now(),
        ]);
        $vehicle2 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'auto-trader',
            'created_at' => Carbon::now()->subDay(),
        ]);
        $vehicle3 = Vehicle::factory()->create([
            'is_published' => true,
            'stock_provider' => 'other-provider',
            'created_at' => Carbon::now()->subHour(),
        ]);

        $response = $this->postJson(route('vehicles.stock-and-offers'), [
            'sort_by' => 'latest',
            'selections' => [],
        ]);

        $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'));
    }

    private function enableStockProviderSorting(array $providers, array $sortOptions): void
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Sorting',
            'name' => 'Pre sort by stock provider',
            'config_key' => 'filter-results-order-by-stock-provider',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Sorting',
            'name' => 'Stock provider priority',
            'config_key' => 'filter-results-stock-provider-priority',
            'type' => 'list',
            'value' => $providers,
        ]);
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'Sorting',
            'name' => 'Stock provider sort options',
            'config_key' => 'filter-results-stock-provider-sort-options',
            'type' => 'list',
            'value' => $sortOptions,
        ]);
    }
}
