<?php

use App\Enums\ResponseStatus;
use App\Models\VehicleDataSource;
use App\Models\VehicleRecord;
use App\Models\Website;
use App\Services\DvlaService;
use Illuminate\Support\Facades\Http;

use function Pest\Laravel\assertDatabaseHas;
use function Pest\Laravel\postJson;

beforeEach(function (): void {
    $tier = \App\Models\Tier::factory()->create([
        'allowed_fields' => ['registrationNumber', 'make', 'colour'],
    ]);

    $this->website = Website::factory()->create([
        'domain' => 'example.com',
        'tier_id' => $tier->id,
        'cache_hit_rate_limit' => 100,
        'external_api_rate_limit' => 10,
        'is_active' => true,
    ]);

    $this->token = $this->website->createToken('test')->plainTextToken;

    $this->headers = [
        'Authorization' => "Bearer {$this->token}",
        'Origin' => 'https://example.com',
    ];
});

test('requires authentication', function (): void {
    postJson('/api/vehicle-enquiry', [
        'registration_number' => 'ABC123',
    ])->assertUnauthorized();
});

test('requires registration number', function (): void {
    postJson('/api/vehicle-enquiry', [], $this->headers)
        ->assertUnprocessable()
        ->assertJsonValidationErrors(['registration_number']);
});

test('returns cached vehicle data when found', function (): void {
    $vehicle = VehicleRecord::create([
        'registration_number' => 'ABC123',
        'data' => [
            'registrationNumber' => 'ABC123',
            'make' => 'ROVER',
            'colour' => 'BLUE',
            'fuelType' => 'PETROL',
        ],
    ]);

    $response = postJson('/api/vehicle-enquiry', [
        'registration_number' => 'abc123',
    ], $this->headers);

    $response->assertSuccessful()
        ->assertJson([
            'success' => true,
            'data' => [
                'registrationNumber' => 'ABC123',
                'make' => 'ROVER',
                'colour' => 'BLUE',
            ],
        ]);

    assertDatabaseHas('api_requests', [
        'website_id' => $this->website->id,
        'registration_number' => 'ABC123',
        'response_status' => ResponseStatus::CacheHit->value,
    ]);
});

test('filters response by tier fields', function (): void {
    VehicleRecord::create([
        'registration_number' => 'ABC123',
        'data' => [
            'registrationNumber' => 'ABC123',
            'make' => 'ROVER',
            'colour' => 'BLUE',
            'fuelType' => 'PETROL',
            'engineCapacity' => 2494,
        ],
    ]);

    $response = postJson('/api/vehicle-enquiry', [
        'registration_number' => 'ABC123',
    ], $this->headers);

    $response->assertSuccessful()
        ->assertJson([
            'success' => true,
            'data' => [
                'registrationNumber' => 'ABC123',
                'make' => 'ROVER',
                'colour' => 'BLUE',
            ],
        ])->assertJsonMissing(['fuelType', 'engineCapacity']);
});

test('fetches from dvla when not cached', function (): void {
    Http::fake([
        'driver-vehicle-licensing.api.gov.uk/*' => Http::response([
            'registrationNumber' => 'XYZ789',
            'make' => 'FORD',
            'colour' => 'RED',
            'fuelType' => 'DIESEL',
        ], 200),
    ]);

    $response = postJson('/api/vehicle-enquiry', [
        'registration_number' => 'XYZ789',
        'contact_data' => [
            'name' => 'John Doe',
            'email' => 'john@example.com',
        ],
    ], $this->headers);

    $response->assertSuccessful()
        ->assertJson([
            'success' => true,
            'data' => [
                'registrationNumber' => 'XYZ789',
                'make' => 'FORD',
                'colour' => 'RED',
            ],
        ]);

    assertDatabaseHas('vehicle_records', [
        'registration_number' => 'XYZ789',
    ]);

    assertDatabaseHas('vehicle_data_sources', [
        'source_name' => 'dvla',
    ]);

    assertDatabaseHas('api_requests', [
        'website_id' => $this->website->id,
        'registration_number' => 'XYZ789',
        'response_status' => ResponseStatus::ApiFetched->value,
    ]);
});

test('returns 404 when vehicle not found in dvla', function (): void {
    Http::fake([
        'driver-vehicle-licensing.api.gov.uk/*' => Http::response([], 404),
    ]);

    $response = postJson('/api/vehicle-enquiry', [
        'registration_number' => 'ZZ99ZZZ',
    ], $this->headers);

    $response->assertNotFound()
        ->assertJson([
            'message' => 'Vehicle not found',
        ]);

    assertDatabaseHas('api_requests', [
        'response_status' => ResponseStatus::NotFound->value,
    ]);
});

test('respects cache hit rate limit', function (): void {
    $this->website->update(['cache_hit_rate_limit' => 2]);

    VehicleRecord::create([
        'registration_number' => 'ABC123',
        'data' => ['registrationNumber' => 'ABC123', 'make' => 'ROVER'],
    ]);

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], $this->headers)->assertSuccessful();

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], $this->headers)->assertSuccessful();

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], $this->headers)->assertStatus(429)
        ->assertJson([
            'message' => 'Rate limit exceeded',
        ]);
});

test('respects external api rate limit', function (): void {
    $this->website->update(['external_api_rate_limit' => 1]);

    Http::fake([
        'driver-vehicle-licensing.api.gov.uk/*' => Http::response([
            'registrationNumber' => 'XYZ789',
            'make' => 'FORD',
        ], 200),
    ]);

    postJson('/api/vehicle-enquiry', ['registration_number' => 'NEW1'], $this->headers)->assertSuccessful();

    postJson('/api/vehicle-enquiry', ['registration_number' => 'NEW2'], $this->headers)->assertStatus(429)
        ->assertJson([
            'message' => 'External API rate limit exceeded',
        ]);
});

test('inactive website cannot make requests', function (): void {
    $this->website->update(['is_active' => false]);

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], $this->headers)->assertForbidden()
        ->assertJson([
            'message' => 'Account inactive',
        ]);
});

test('rejects request when origin does not match website domain', function (): void {
    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], [
        'Authorization' => "Bearer {$this->token}",
        'Origin' => 'https://malicious-site.com',
    ])->assertForbidden()
        ->assertJson(['message' => 'Forbidden']);
});

test('rejects request when no origin or referer header is present', function (): void {
    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], [
        'Authorization' => "Bearer {$this->token}",
    ])->assertForbidden()
        ->assertJson(['message' => 'Forbidden']);
});

test('accepts request with referer header matching website domain', function (): void {
    VehicleRecord::create([
        'registration_number' => 'ABC123',
        'data' => ['registrationNumber' => 'ABC123', 'make' => 'ROVER', 'colour' => 'BLUE'],
    ]);

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], [
        'Authorization' => "Bearer {$this->token}",
        'Referer' => 'https://example.com/some/page',
    ])->assertSuccessful();
});

test('bypass_rate_limit website skips origin validation', function (): void {
    $this->website->update(['bypass_rate_limit' => true]);

    VehicleRecord::create([
        'registration_number' => 'ABC123',
        'data' => ['registrationNumber' => 'ABC123', 'make' => 'ROVER', 'colour' => 'BLUE'],
    ]);

    postJson('/api/vehicle-enquiry', ['registration_number' => 'ABC123'], [
        'Authorization' => "Bearer {$this->token}",
    ])->assertSuccessful();
});
