<?php

declare(strict_types=1);

use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Support\Facades\DB;

function grantViewAndManageAccessRights(User $user): void
{
    foreach (['view access rights', 'manage access rights', 'view user directory', 'manage user directory'] as $name) {
        Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
    }
    $user->givePermissionTo(['view access rights', 'manage access rights', 'view user directory', 'manage user directory']);
}

function queryCountDuring(callable $fn): int
{
    DB::enableQueryLog();
    DB::flushQueryLog();
    $fn();
    $count = count(DB::getQueryLog());
    DB::disableQueryLog();

    return $count;
}

test('users datatable query count is bounded regardless of row count', function () {
    $admin = User::factory()->create();
    grantViewAndManageAccessRights($admin);
    User::factory()->count(5)->create()->each(function ($u) {
        $u->assignRole(Role::firstOrCreate(['name' => 'member-'.$u->id, 'guard_name' => 'web'])->name);
    });

    $baselineCount = queryCountDuring(function () use ($admin) {
        $this->actingAs($admin)->getJson('/users?draw=1&start=0&length=10&columns[0][data]=id');
    });

    User::factory()->count(20)->create()->each(function ($u) {
        $u->assignRole(Role::firstOrCreate(['name' => 'member-'.$u->id, 'guard_name' => 'web'])->name);
    });

    $scaledCount = queryCountDuring(function () use ($admin) {
        $this->actingAs($admin)->getJson('/users?draw=1&start=0&length=10&columns[0][data]=id');
    });

    // 4x more rows should not 4x the query count — eager loading caps it.
    expect($scaledCount - $baselineCount)->toBeLessThan(10);
});

test('roles datatable eagerly loads permissions and creator', function () {
    $admin = User::factory()->create();
    grantViewAndManageAccessRights($admin);

    foreach (range(1, 5) as $i) {
        $r = Role::create(['name' => 'np1-role-'.$i, 'guard_name' => 'web']);
        $p = Permission::firstOrCreate(['name' => 'np1-perm-'.$i, 'guard_name' => 'web']);
        $r->givePermissionTo($p);
    }

    $count = queryCountDuring(function () use ($admin) {
        $this->actingAs($admin)->getJson('/roles?draw=1&start=0&length=10&columns[0][data]=id');
    });

    // Should not run a permission lookup per row.
    expect($count)->toBeLessThan(20);
});

test('permissions datatable eagerly loads roles and creator', function () {
    $admin = User::factory()->create();
    grantViewAndManageAccessRights($admin);

    foreach (range(1, 8) as $i) {
        Permission::firstOrCreate(['name' => 'eager-perm-'.$i, 'guard_name' => 'web']);
    }

    $count = queryCountDuring(function () use ($admin) {
        $this->actingAs($admin)->getJson('/permissions?draw=1&start=0&length=10&columns[0][data]=id');
    });

    expect($count)->toBeLessThan(20);
});
