<?php

namespace Tests\Feature;

use App\Enums\Role;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Gate;
use Tests\TestCase;

/**
 * RBAC foundation: the Role enum hierarchy, the User helpers, the Gates, and the first-user
 * bootstrap all agree that admin > operator > viewer. This is the base every later `can:` /
 * abort_unless / @can builds on.
 */
class RoleFoundationTest extends TestCase
{
    use RefreshDatabase;

    public function test_role_hierarchy_at_least(): void
    {
        $this->assertTrue(Role::Admin->atLeast(Role::Operator));
        $this->assertFalse(Role::Viewer->atLeast(Role::Operator));
    }

    public function test_user_role_helpers(): void
    {
        $admin = User::factory()->create();
        $this->assertTrue($admin->isAdmin());
        $this->assertTrue($admin->roleAtLeast(Role::Operator));

        $operator = User::factory()->operator()->create();
        $this->assertFalse($operator->isAdmin());
        $this->assertTrue($operator->roleAtLeast(Role::Operator));
        $this->assertFalse($operator->roleAtLeast(Role::Admin));

        $viewer = User::factory()->viewer()->create();
        $this->assertFalse($viewer->roleAtLeast(Role::Operator));
    }

    public function test_gates_follow_the_hierarchy(): void
    {
        $admin = User::factory()->create();
        $this->assertTrue(Gate::forUser($admin)->allows('manage-panel'));
        $this->assertTrue(Gate::forUser($admin)->allows('operate'));

        $operator = User::factory()->operator()->create();
        $this->assertFalse(Gate::forUser($operator)->allows('manage-panel'));
        $this->assertTrue(Gate::forUser($operator)->allows('operate'));

        $viewer = User::factory()->viewer()->create();
        $this->assertFalse(Gate::forUser($viewer)->allows('operate'));
    }

    public function test_install_creates_first_user_as_admin(): void
    {
        $this->assertSame(0, Artisan::call('clusev:install', ['--email' => 'admin@example.test']));

        $user = User::first();
        $this->assertNotNull($user);
        $this->assertTrue($user->isAdmin());
    }
}
