<?php

namespace Tests\Feature;

use App\Models\User;
use Database\Seeders\PermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Tests\TestCase;

class AdminRoleControllerTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        // Seed roles and permissions
        $this->seed(PermissionSeeder::class);
    }

    public function test_authorized_super_admin_can_view_roles_index_and_json(): void
    {
        $superAdmin = User::factory()->create(['role' => 'admin']);
        $superAdmin->assignRole('Super Admin');

        $response = $this->actingAs($superAdmin)
            ->get(route('admin.roles.index'));

        $response->assertOk();

        // Check AJAX DataTable endpoint
        $ajaxResponse = $this->actingAs($superAdmin)
            ->getJson(route('admin.roles.index'), ['HTTP_X-Requested-With' => 'XMLHttpRequest']);

        $ajaxResponse->assertOk()
            ->assertJsonStructure(['draw', 'recordsTotal', 'recordsFiltered', 'data']);
    }

    public function test_authorized_super_admin_can_create_role(): void
    {
        $superAdmin = User::factory()->create(['role' => 'admin']);
        $superAdmin->assignRole('Super Admin');

        $response = $this->actingAs($superAdmin)
            ->post(route('admin.roles.store'), [
                'name' => 'Custom Moderator',
                'permissions' => ['products.view', 'products.create'],
            ]);

        $response->assertRedirect(route('admin.roles.index'));
        $this->assertDatabaseHas('roles', ['name' => 'Custom Moderator']);

        $role = Role::findByName('Custom Moderator', 'web');
        $this->assertTrue($role->hasPermissionTo('products.view'));
        $this->assertTrue($role->hasPermissionTo('products.create'));
        $this->assertFalse($role->hasPermissionTo('users.view'));
    }

    public function test_authorized_super_admin_can_edit_and_update_role(): void
    {
        $superAdmin = User::factory()->create(['role' => 'admin']);
        $superAdmin->assignRole('Super Admin');

        $role = Role::create(['name' => 'Legacy Editor', 'guard_name' => 'web']);
        $role->syncPermissions(['products.view']);

        $response = $this->actingAs($superAdmin)
            ->put(route('admin.roles.update', $role), [
                'name' => 'Updated Editor',
                'permissions' => ['products.view', 'categories.view'],
            ]);

        $response->assertRedirect(route('admin.roles.index'));
        $this->assertDatabaseHas('roles', ['name' => 'Updated Editor']);
        
        $role->refresh();
        $this->assertTrue($role->hasPermissionTo('products.view'));
        $this->assertTrue($role->hasPermissionTo('categories.view'));
    }

    public function test_super_admin_cannot_delete_system_roles(): void
    {
        $superAdmin = User::factory()->create(['role' => 'admin']);
        $superAdmin->assignRole('Super Admin');

        $systemRole = Role::findByName('Super Admin', 'web');

        $response = $this->actingAs($superAdmin)
            ->delete(route('admin.roles.destroy', $systemRole));

        $response->assertSessionHas('error');
        $this->assertDatabaseHas('roles', ['name' => 'Super Admin']);
    }

    public function test_super_admin_can_delete_custom_role(): void
    {
        $superAdmin = User::factory()->create(['role' => 'admin']);
        $superAdmin->assignRole('Super Admin');

        $customRole = Role::create(['name' => 'Temp Role', 'guard_name' => 'web']);

        $response = $this->actingAs($superAdmin)
            ->delete(route('admin.roles.destroy', $customRole));

        $response->assertRedirect(route('admin.roles.index'));
        $this->assertDatabaseMissing('roles', ['name' => 'Temp Role']);
    }

    public function test_unauthorized_staff_cannot_manage_roles(): void
    {
        $staffUser = User::factory()->create(['role' => 'admin']);
        $staffUser->assignRole('Staff'); // Staff does not have roles.view, roles.create, or roles.update/delete

        $this->actingAs($staffUser)
            ->get(route('admin.roles.index'))
            ->assertStatus(403);

        $this->actingAs($staffUser)
            ->get(route('admin.roles.create'))
            ->assertStatus(403);

        $this->actingAs($staffUser)
            ->post(route('admin.roles.store'), ['name' => 'Invalid'])
            ->assertStatus(403);
    }
}
