<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

class RoleManagementTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        
        // Create permissions
        $permissionMatrix = [
            'users' => 'Users',
            'roles' => 'Roles',
            'products' => 'Products',
        ];

        $abilities = ['view', 'create', 'update', 'delete'];

        foreach ($permissionMatrix as $module => $label) {
            foreach ($abilities as $ability) {
                Permission::create([
                    'name' => "{$module}.{$ability}",
                    'guard_name' => 'web',
                ]);
            }
        }

        // Create admin role with all permissions
        $adminRole = Role::create(['name' => 'admin', 'guard_name' => 'web']);
        $adminRole->givePermissionTo(Permission::all());

        // Create admin user
        $admin = User::create([
            'name' => 'Admin User',
            'mobile' => '9876543210',
            'email' => 'admin@test.com',
            'password' => bcrypt('password'),
            'mobile_verified_at' => now(),
        ]);
        $admin->assignRole('admin');
    }

    public function test_admin_can_view_roles_index(): void
    {
        $admin = User::where('mobile', '9876543210')->first();
        
        $response = $this->actingAs($admin)
            ->get(route('admin.roles.index'));

        $response->assertStatus(200);
        $response->assertSee('Roles');
    }

    public function test_admin_can_create_role(): void
    {
        $admin = User::where('mobile', '9876543210')->first();
        
        $response = $this->actingAs($admin)
            ->post(route('admin.roles.store'), [
                'name' => 'manager',
                'permissions' => ['users.view', 'products.view'],
            ]);

        $response->assertRedirect(route('admin.roles.index'));
        $response->assertSessionHas('success');
        
        $this->assertDatabaseHas('roles', [
            'name' => 'manager',
        ]);
    }

    public function test_admin_can_update_role(): void
    {
        $admin = User::where('mobile', '9876543210')->first();
        
        $role = Role::create(['name' => 'editor', 'guard_name' => 'web']);
        
        $response = $this->actingAs($admin)
            ->put(route('admin.roles.update', $role), [
                'name' => 'editor',
                'permissions' => ['users.view', 'users.create'],
            ]);

        $response->assertRedirect(route('admin.roles.index'));
        $response->assertSessionHas('success');
        
        $this->assertEquals(2, $role->fresh()->permissions()->count());
    }

    public function test_admin_cannot_delete_role_assigned_to_users(): void
    {
        $admin = User::where('mobile', '9876543210')->first();
        
        $role = Role::create(['name' => 'test-role', 'guard_name' => 'web']);
        
        $user = User::create([
            'name' => 'Test User',
            'mobile' => '9876543211',
            'password' => bcrypt('password'),
            'mobile_verified_at' => now(),
        ]);
        $user->assignRole($role);
        
        $response = $this->actingAs($admin)
            ->delete(route('admin.roles.destroy', $role));

        $response->assertRedirect(route('admin.roles.index'));
        $response->assertSessionHas('error');
        
        $this->assertDatabaseHas('roles', [
            'name' => 'test-role',
        ]);
    }

    public function test_admin_can_delete_unassigned_role(): void
    {
        $admin = User::where('mobile', '9876543210')->first();
        
        $role = Role::create(['name' => 'unused-role', 'guard_name' => 'web']);
        
        $response = $this->actingAs($admin)
            ->delete(route('admin.roles.destroy', $role));

        $response->assertRedirect(route('admin.roles.index'));
        $response->assertSessionHas('success');
        
        $this->assertDatabaseMissing('roles', [
            'name' => 'unused-role',
        ]);
    }
}
