<?php

namespace Tests\Tenant;

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

class SrpFeaturedVehicleFilterTest extends TenantTestCase
{
    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();
        $this->seed();
        $this->seed(FilterSettingSeed::class);
        $this->withoutExceptionHandling();

        $this->enableFeature();
        $this->seedMaxFeatured(2);
    }

    public function testFeaturedVehicleAppearsFirstOnPageOne(): void
    {
        Queue::fake();

        $featured = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $first = $response->json('results.data.0');
        $this->assertEquals($featured->id, $first['id']);
        $this->assertTrue($first['is_featured']);
    }

    public function testNonFeaturedVehiclesHaveIsFeaturedFalse(): void
    {
        Queue::fake();

        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $nonFeatured = collect($response->json('results.data'))
            ->filter(fn ($item) => $item['is_featured'] === false);

        $this->assertCount(4, $nonFeatured);
    }

    public function testFeaturedVehicleNotDuplicatedInPaginatedResults(): void
    {
        Queue::fake();

        $featured = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $data = $response->json('results.data');
        $featuredCount = collect($data)->where('id', $featured->id)->count();

        $this->assertEquals(1, $featuredCount);
    }

    public function testTotalCountIncludesFeaturedVehicle(): void
    {
        Queue::fake();

        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);
        $this->assertEquals(5, $response->json('results.total'));
        $this->assertCount(5, $response->json('results.data'));
        $this->assertEquals(15, $response->json('results.per_page'));
        $this->assertEquals(1, $response->json('results.last_page'));
    }

    public function testMultipleFeaturedVehiclesAppearAtTopInOrder(): void
    {
        Queue::fake();

        $featuredA = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        $featuredB = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $data = $response->json('results.data');
        $this->assertTrue($data[0]['is_featured']);
        $this->assertTrue($data[1]['is_featured']);
        $this->assertFalse($data[2]['is_featured']);
    }

    public function testCapIsRespected(): void
    {
        Queue::fake();

        // 3 featured but cap is 2
        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(2, $featuredInResults);
    }

    public function testFeaturedVehiclesNotInjectedOnPageTwo(): void
    {
        Queue::fake();

        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(20)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
    }

    public function testFeatureFlagOffNoInjection(): void
    {
        Queue::fake();

        Settings::update('automotive-srp-featured-vehicles', false);

        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
    }

    public function testMaxSetToZeroNoInjection(): void
    {
        Queue::fake();

        $this->seedMaxFeatured(0);

        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
    }

    public function testFeaturedVehicleExcludedByActiveFilter(): void
    {
        Queue::fake();

        $make1 = VehicleMake::factory()->create();
        $make2 = VehicleMake::factory()->create();

        // Featured vehicle is make1
        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $make1->id]);
        // Regular vehicles are make2
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false, 'make_id' => $make2->id]);

        // Filter for make2 — featured vehicle should not appear
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'make', 'value' => $make2->slug],
            ],
        ]);

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
        $this->assertEquals(4, $response->json('results.total'));
    }

    public function testFeaturedVehicleMatchingFilterIsInjected(): void
    {
        Queue::fake();

        $make = VehicleMake::factory()->create();

        $featured = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $make->id]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false, 'make_id' => $make->id]);

        // Filter for the same make — featured vehicle should appear
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'make', 'value' => $make->slug],
            ],
        ]);

        $response->assertStatus(200);

        $first = $response->json('results.data.0');
        $this->assertEquals($featured->id, $first['id']);
        $this->assertTrue($first['is_featured']);
    }

    public function testPaginationMetadataCorrectWithFeaturedVehicles(): void
    {
        Queue::fake();

        Vehicle::factory(2)->create(['is_published' => true, 'srp_featured' => true]);
        Vehicle::factory(28)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);
        $this->assertEquals(30, $response->json('results.total'));
        $this->assertCount(15, $response->json('results.data'));
        $this->assertEquals(15, $response->json('results.per_page'));
        $this->assertEquals(2, $response->json('results.last_page'));
        $this->assertEquals(1, $response->json('results.from'));
        $this->assertEquals(15, $response->json('results.to'));
    }

    public function testPaginationMetadataCorrectWithoutFeaturedVehicles(): void
    {
        Queue::fake();

        Vehicle::factory(28)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);
        $this->assertEquals(28, $response->json('results.total'));
        $this->assertCount(15, $response->json('results.data'));
        $this->assertEquals(15, $response->json('results.per_page'));
        $this->assertEquals(2, $response->json('results.last_page'));
        $this->assertEquals(1, $response->json('results.from'));
        $this->assertEquals(15, $response->json('results.to'));
    }

    public function testFilterAwarePoolPicksMatchingFeaturedFromLargerPool(): void
    {
        Queue::fake();

        $ford = VehicleMake::factory()->create();
        $bmw = VehicleMake::factory()->create();
        $mercedes = VehicleMake::factory()->create();

        // Pool of featured vehicles across multiple makes
        $featuredFord = Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $ford->id]);
        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $bmw->id]);
        Vehicle::factory()->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $mercedes->id]);

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

        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'make', 'value' => $ford->slug],
            ],
        ]);

        $response->assertStatus(200);

        $first = $response->json('results.data.0');
        $this->assertEquals($featuredFord->id, $first['id']);
        $this->assertTrue($first['is_featured']);
    }

    public function testFilterAwarePoolReturnsNoneWhenPoolHasNoMatch(): void
    {
        Queue::fake();

        $bmw = VehicleMake::factory()->create();
        $mercedes = VehicleMake::factory()->create();

        // Pool only has BMW featured
        Vehicle::factory(5)->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $bmw->id]);

        // Non-featured Mercedes vehicles
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false, 'make_id' => $mercedes->id]);

        // Filter for Mercedes - no featured should appear
        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'make', 'value' => $mercedes->slug],
            ],
        ]);

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
    }

    public function testFilterAwarePoolRespectsCapAcrossMatchingFeatured(): void
    {
        Queue::fake();

        $ford = VehicleMake::factory()->create();

        // 5 featured Fords, but cap is 2
        Vehicle::factory(5)->create(['is_published' => true, 'srp_featured' => true, 'make_id' => $ford->id]);

        // Some non-featured Fords
        Vehicle::factory(3)->create(['is_published' => true, 'srp_featured' => false, 'make_id' => $ford->id]);

        $response = $this->postJson(route('vehicles.index'), [
            'selections' => [
                ['type' => 'make', 'value' => $ford->slug],
            ],
        ]);

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        // Only 2 should be displayed despite 5 matching featured Fords
        $this->assertCount(2, $featuredInResults);
    }

    public function testUnpublishedFeaturedVehicleNotShown(): void
    {
        Queue::fake();

        Vehicle::factory()->create(['is_published' => false, 'srp_featured' => true]);
        Vehicle::factory(4)->create(['is_published' => true, 'srp_featured' => false]);

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

        $response->assertStatus(200);

        $featuredInResults = collect($response->json('results.data'))
            ->where('is_featured', true);

        $this->assertCount(0, $featuredInResults);
        $this->assertEquals(4, $response->json('results.total'));
    }

    private function enableFeature(): void
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'General',
            'name' => 'SRP Featured Vehicles',
            'config_key' => 'automotive-srp-featured-vehicles',
            'type' => 'boolean',
            'value' => true,
        ]);
    }

    private function seedMaxFeatured(int $value): void
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Filter',
            'group' => 'General',
            'name' => 'Max SRP Featured Vehicles',
            'config_key' => 'automotive-srp-featured-max',
            'type' => 'integer',
            'value' => $value,
        ]);
    }
}
