<?php

use App\Models\User;
use Illuminate\Database\QueryException;
use Livewire\Livewire;
use Modules\Catalog\Models\Destination;
use Modules\Routing\Filament\Resources\PopularRoutes\Pages\CreatePopularRoute;
use Modules\Routing\Filament\Resources\PopularRoutes\Pages\EditPopularRoute;
use Modules\Routing\Filament\Resources\PopularRoutes\Pages\ListPopularRoutes;
use Modules\Routing\Models\PopularRoute;
use Spatie\Permission\Models\Permission;

use function Pest\Laravel\assertDatabaseHas;

beforeEach(function () {
    Permission::findOrCreate('manage_routes', 'web');

    $this->admin = User::factory()->create()->givePermissionTo('manage_routes');
    $this->actingAs($this->admin);
});

test('can list popular routes', function () {
    $routes = PopularRoute::factory()->count(3)->create();

    Livewire::test(ListPopularRoutes::class)
        ->assertOk()
        ->assertCanSeeTableRecords($routes);
});

test('can create a popular route', function () {
    $from = Destination::factory()->create();
    $to = Destination::factory()->create();

    Livewire::test(CreatePopularRoute::class)
        ->fillForm([
            'from_destination_id' => $from->id,
            'to_destination_id' => $to->id,
            'description' => 'A scenic drive.',
            'mm_description' => 'သာယာသောခရီးစဉ်။',
            'is_active' => true,
        ])
        ->call('create')
        ->assertNotified()
        ->assertRedirect();

    assertDatabaseHas(PopularRoute::class, [
        'from_destination_id' => $from->id,
        'to_destination_id' => $to->id,
        'description' => 'A scenic drive.',
        'mm_description' => 'သာယာသောခရီးစဉ်။',
        'is_active' => true,
    ]);
});

test('from and to destinations must be different', function () {
    $destination = Destination::factory()->create();

    Livewire::test(CreatePopularRoute::class)
        ->fillForm([
            'from_destination_id' => $destination->id,
            'to_destination_id' => $destination->id,
        ])
        ->call('create')
        ->assertHasFormErrors(['to_destination_id' => 'different']);
});

test('the same from/to destination pair cannot be created twice', function () {
    $existing = PopularRoute::factory()->create();

    Livewire::test(CreatePopularRoute::class)
        ->fillForm([
            'from_destination_id' => $existing->from_destination_id,
            'to_destination_id' => $existing->to_destination_id,
        ])
        ->call('create')
        ->assertHasFormErrors(['to_destination_id' => 'unique']);
});

test('editing a popular route keeps its own from/to pair valid', function () {
    $popularRoute = PopularRoute::factory()->create();

    Livewire::test(EditPopularRoute::class, ['record' => $popularRoute->getRouteKey()])
        ->fillForm(['description' => 'Updated description.'])
        ->call('save')
        ->assertHasNoFormErrors();

    assertDatabaseHas(PopularRoute::class, [
        'id' => $popularRoute->id,
        'description' => 'Updated description.',
    ]);
});

test('a user without manage_routes is forbidden from the popular routes page', function () {
    $support = User::factory()->create();
    $this->actingAs($support);

    $this->get('/admin/popular-routes')->assertForbidden();
});

test('the model rejects saving with the same from and to destination directly', function () {
    $destination = Destination::factory()->create();

    expect(fn () => PopularRoute::factory()->create([
        'from_destination_id' => $destination->id,
        'to_destination_id' => $destination->id,
    ]))->toThrow(InvalidArgumentException::class);
});

test('the database rejects a duplicate from/to pair directly', function () {
    $existing = PopularRoute::factory()->create();

    expect(fn () => PopularRoute::factory()->create([
        'from_destination_id' => $existing->from_destination_id,
        'to_destination_id' => $existing->to_destination_id,
    ]))->toThrow(QueryException::class);
});
