<?php

namespace Tests\Tenant\Controllers;

use App\Http\Middleware\ApiAuthenticatedRequest;
use App\Http\Middleware\InitializeTenancyBySiteInRequest;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleFinance;
use Tests\TenantTestCase;

class ApiVehicleControllerTest extends TenantTestCase
{
    private array $excludedMiddlewares = [
        InitializeTenancyBySiteInRequest::class,
        ApiAuthenticatedRequest::class,
    ];

    public function testLookupByVrmReturnsVehicle(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'AB12CDE',
            ]);

        $response->assertStatus(200);
        $response->assertJsonFragment(['id' => $vehicle->id]);
        $response->assertJsonFragment(['registration_number' => 'AB12 CDE']);
    }

    public function testLookupByVrmMatchesWithSpaces(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'XY34 FGH',
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'XY34 FGH',
            ]);

        $response->assertStatus(200);
        $response->assertJsonFragment(['id' => $vehicle->id]);
    }

    public function testLookupByVrmIsCaseInsensitive(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'ab12cde',
            ]);

        $response->assertStatus(200);
        $response->assertJsonFragment(['id' => $vehicle->id]);
    }

    public function testLookupByVrmReturns404WhenNotFound(): void
    {
        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'ZZ99ZZZ',
            ]);

        $response->assertStatus(404);
        $response->assertJson(['message' => 'Vehicle not found.']);
    }

    public function testLookupByVrmReturns422WhenVrmMissing(): void
    {
        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), []);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('vrm');
    }

    public function testLookupByVrmReturns422WhenVrmTooLong(): void
    {
        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'ABCDEFGHIJK',
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('vrm');
    }

    public function testLookupByVrmIncludesVehicleFields(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
            'price' => 18995,
            'seats' => 5,
            'door_count' => 5,
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'AB12CDE',
            ]);

        $response->assertStatus(200);

        $data = $response->json();

        $this->assertEquals($vehicle->id, $data['id']);
        $this->assertEquals($vehicle->uuid, $data['uuid']);
        $this->assertEquals($vehicle->slug, $data['slug']);
        $this->assertEquals($vehicle->title, $data['title']);
        $this->assertEquals($vehicle->derivative, $data['derivative']);
        $this->assertEquals('AB12 CDE', $data['registration_number']);
        $this->assertEquals($vehicle->vin, $data['vin']);
        $this->assertEquals($vehicle->colour, $data['colour']);
        $this->assertEquals(18995, $data['price']);
        $this->assertEquals(5, $data['seats']);
        $this->assertEquals(5, $data['door_count']);
        $this->assertEquals($vehicle->manufacture_year, $data['manufacture_year']);
        $this->assertEquals($vehicle->odometer_mi, $data['odometer_mi']);
        $this->assertEquals($vehicle->odometer_km, $data['odometer_km']);
        $this->assertEquals($vehicle->engine_size_cc, $data['engine_size_cc']);
    }

    public function testLookupByVrmIncludesRelationships(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'AB12CDE',
            ]);

        $response->assertStatus(200);

        $data = $response->json();

        $this->assertArrayHasKey('specs', $data);
        $this->assertArrayHasKey('features', $data);
        $this->assertArrayHasKey('highlights', $data);
        $this->assertArrayHasKey('equipment', $data);
        $this->assertArrayHasKey('media_uses', $data);
        $this->assertArrayHasKey('dealership', $data);
        $this->assertArrayHasKey('financeExamples', $data);
        $this->assertArrayHasKey('labels', $data);
        $this->assertArrayHasKey('age_identifier', $data);
        $this->assertArrayHasKey('monthly_cost_type', $data);
    }

    public function testLookupByVrmIncludesMediaUses(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
        ]);

        $media = Media::factory()->create();
        $vehicle->mediaUses()->create(['media_id' => $media->id]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'AB12CDE',
            ]);

        $response->assertStatus(200);

        $mediaUses = $response->json('media_uses');
        $this->assertNotEmpty($mediaUses);
        $this->assertArrayHasKey('id', $mediaUses[0]);
        $this->assertArrayHasKey('src_large', $mediaUses[0]);
        $this->assertArrayHasKey('src_medium', $mediaUses[0]);
        $this->assertArrayHasKey('src_thumbnail', $mediaUses[0]);
        $this->assertArrayHasKey('type', $mediaUses[0]);
    }

    public function testLookupByVrmIncludesFinanceExamples(): void
    {
        $vehicle = Vehicle::factory()->create([
            'registration_number' => 'AB12 CDE',
        ]);

        VehicleFinance::factory()->create([
            'vehicle_id' => $vehicle->id,
            'finance_type' => 'PCP',
            'monthly_price' => 249,
            'term' => 48,
        ]);

        $response = $this->withoutMiddleware($this->excludedMiddlewares)
            ->postJson(route('api.vehicles.vrm-lookup', tenant('id')), [
                'vrm' => 'AB12CDE',
            ]);

        $response->assertStatus(200);

        $financeExamples = $response->json('financeExamples');
        $this->assertArrayHasKey('PCP', $financeExamples);
        $this->assertEquals('PCP', $financeExamples['PCP']['finance_type']);
        $this->assertEquals(249, $financeExamples['PCP']['monthly_price']);
        $this->assertEquals(48, $financeExamples['PCP']['term']);
    }
}
