<?php

use App\Enums\PermissionSlug;
use App\Enums\RoleSlug;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Database\Seeders\PermissionSeeder;
use Database\Seeders\RoleSeeder;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Gate;

uses(LazilyRefreshDatabase::class);

beforeEach(function () {
    $this->withHeaders([
        'Origin' => 'http://localhost:3000',
        'Referer' => 'http://localhost:3000/',
    ]);
});

it('assigns platform users a role relationship', function () {
    $user = User::factory()->admin()->create();

    expect($user->role)->toBeInstanceOf(Role::class)
        ->and($user->role->slug)->toBe(RoleSlug::Admin)
        ->and($user->isAdmin())->toBeTrue()
        ->and($user->isManager())->toBeFalse();
});

it('defaults new platform users to the manager role', function () {
    $user = User::factory()->create();

    expect($user->role->slug)->toBe(RoleSlug::Manager)
        ->and($user->hasRole(RoleSlug::Manager))->toBeTrue()
        ->and($user->hasAnyRole(RoleSlug::Admin))->toBeFalse();
});

it('scopes users by role', function () {
    User::factory()->admin()->create();
    User::factory()->manager()->create();

    expect(User::query()->withRole(RoleSlug::Admin)->count())->toBe(1)
        ->and(User::query()->withAnyRole(RoleSlug::Admin, RoleSlug::Manager)->count())->toBe(2);
});

it('authorizes abilities through the role gate', function () {
    $manager = User::factory()->manager()->create();
    $admin = User::factory()->admin()->create();

    expect(Gate::forUser($manager)->allows('role', RoleSlug::Manager))->toBeTrue()
        ->and(Gate::forUser($manager)->allows('role', [RoleSlug::Admin, RoleSlug::Manager]))->toBeTrue()
        ->and(Gate::forUser($admin)->allows('role', RoleSlug::Admin))->toBeTrue()
        ->and(Gate::forUser($manager)->allows('role', RoleSlug::Admin))->toBeFalse();
});

it('seeds admin and manager roles with platform permissions', function () {
    $this->seed([
        PermissionSeeder::class,
        RoleSeeder::class,
    ]);

    $admin = Role::query()->where('slug', RoleSlug::Admin)->first();
    $manager = Role::query()->where('slug', RoleSlug::Manager)->first();

    expect($admin)->not->toBeNull()
        ->and($manager)->not->toBeNull()
        ->and(Permission::query()->count())->toBe(count(PermissionSlug::cases()))
        ->and($admin->permissions()->count())->toBe(count(PermissionSlug::cases()))
        ->and($manager->permissions()->count())->toBe(count(RoleSlug::Manager->permissions()));
});

it('authorizes abilities through the permission gate', function () {
    $this->seed([
        PermissionSeeder::class,
        RoleSeeder::class,
    ]);

    $admin = User::factory()->admin()->create();
    $manager = User::factory()->manager()->create();

    expect(Gate::forUser($admin)->allows('permission', PermissionSlug::UsersDelete))->toBeTrue()
        ->and(Gate::forUser($admin)->allows('permission', PermissionSlug::ReportsView))->toBeTrue()
        ->and(Gate::forUser($manager)->allows('permission', PermissionSlug::CustomersCreate))->toBeTrue()
        ->and(Gate::forUser($manager)->allows('permission', PermissionSlug::BookingsCancel))->toBeFalse()
        ->and(Gate::forUser($manager)->allows('permission', PermissionSlug::UsersDelete))->toBeFalse()
        ->and(Gate::forUser($manager)->allows('permission', PermissionSlug::AgentsDelete))->toBeFalse();
});
