<?php

namespace Tests\Feature;

use App\Models\AdminPermission;
use App\Models\AdminRole;
use App\Models\AdminUser;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;

class AdminManagementTest extends TestCase
{
    use RefreshDatabase;

    public function test_admin_can_create_update_toggle_and_delete_admin_user(): void
    {
        $manager = $this->managerAdmin();
        $role = AdminRole::query()->create(['name' => 'Catalog Manager', 'slug' => 'catalog-manager']);
        $permission = AdminPermission::query()->create(['name' => 'Manage Products', 'slug' => 'products.manage']);

        $this->actingAs($manager, 'admin')
            ->post('/admin/admin-users', [
                'name' => 'Operations Admin',
                'email' => 'operations.admin@example.com',
                'password' => 'secret-password',
                'role_ids' => [$role->id],
                'permission_ids' => [$permission->id],
                'is_active' => '1',
            ])
            ->assertRedirect(route('admin.admin-users.index'));

        $adminUser = AdminUser::query()->where('email', 'operations.admin@example.com')->firstOrFail();

        $this->assertTrue($adminUser->roles()->whereKey($role->id)->exists());
        $this->assertTrue($adminUser->permissions()->whereKey($permission->id)->exists());

        $this->actingAs($manager, 'admin')
            ->patch("/admin/admin-users/{$adminUser->id}", [
                'name' => 'Updated Operations Admin',
                'email' => 'updated.operations.admin@example.com',
                'role_ids' => [],
                'permission_ids' => [$permission->id],
            ])
            ->assertRedirect(route('admin.admin-users.index'));

        $this->assertDatabaseHas('admin_users', [
            'id' => $adminUser->id,
            'name' => 'Updated Operations Admin',
            'email' => 'updated.operations.admin@example.com',
            'is_active' => false,
        ]);

        $this->actingAs($manager, 'admin')
            ->patch("/admin/admin-users/{$adminUser->id}/toggle")
            ->assertSessionHas('status');

        $this->assertTrue($adminUser->fresh()->is_active);

        $this->actingAs($manager, 'admin')
            ->delete("/admin/admin-users/{$adminUser->id}")
            ->assertSessionHas('status');

        $this->assertDatabaseMissing('admin_users', ['id' => $adminUser->id]);
    }

    public function test_admin_can_manage_roles_with_permissions(): void
    {
        $manager = $this->managerAdmin();
        $permissionA = AdminPermission::query()->create(['name' => 'Manage Customers', 'slug' => 'customers.manage']);
        $permissionB = AdminPermission::query()->create(['name' => 'Manage Settings', 'slug' => 'settings.manage']);

        $this->actingAs($manager, 'admin')
            ->post('/admin/roles', [
                'name' => 'Support Manager',
                'permission_ids' => [$permissionA->id, $permissionB->id],
            ])
            ->assertRedirect(route('admin.roles.index'));

        $role = AdminRole::query()->where('slug', 'support-manager')->firstOrFail();
        $this->assertSame(2, $role->permissions()->count());

        $this->actingAs($manager, 'admin')
            ->patch("/admin/roles/{$role->id}", [
                'name' => 'Support Lead',
                'permission_ids' => [$permissionA->id],
            ])
            ->assertRedirect(route('admin.roles.index'));

        $this->assertDatabaseHas('admin_roles', [
            'id' => $role->id,
            'name' => 'Support Lead',
            'slug' => 'support-lead',
        ]);
        $this->assertSame([$permissionA->id], $role->fresh()->permissions()->pluck('admin_permissions.id')->all());

        $this->actingAs($manager, 'admin')
            ->delete("/admin/roles/{$role->id}")
            ->assertSessionHas('status');

        $this->assertDatabaseMissing('admin_roles', ['id' => $role->id]);
    }

    public function test_super_admin_role_and_user_are_hidden_and_protected(): void
    {
        $manager = $this->managerAdmin();
        $superRole = AdminRole::query()->create(['name' => 'Super Admin', 'slug' => AdminRole::SUPER_ADMIN]);
        $superUser = AdminUser::query()->create([
            'name' => 'Hidden Super Admin',
            'email' => 'hidden.super.admin@example.com',
            'password' => Hash::make('secret-password'),
            'is_active' => true,
        ]);
        $superUser->roles()->attach($superRole);

        $this->actingAs($manager, 'admin')
            ->get('/admin/roles')
            ->assertOk()
            ->assertDontSee('Super Admin');

        $this->actingAs($manager, 'admin')
            ->get('/admin/admin-users')
            ->assertOk()
            ->assertDontSee('hidden.super.admin@example.com');

        $this->actingAs($manager, 'admin')
            ->get("/admin/roles/{$superRole->id}/edit")
            ->assertNotFound();

        $this->actingAs($manager, 'admin')
            ->get("/admin/admin-users/{$superUser->id}/edit")
            ->assertNotFound();
    }

    public function test_admin_without_permissions_cannot_access_admin_management_modules(): void
    {
        $admin = AdminUser::query()->create([
            'name' => 'Orders Admin',
            'email' => 'orders.only.admin@example.com',
            'password' => Hash::make('secret-password'),
            'is_active' => true,
        ]);
        $admin->permissions()->attach(
            AdminPermission::query()->create(['name' => 'Manage Orders', 'slug' => 'orders.manage'])
        );

        $this->actingAs($admin, 'admin')
            ->get('/admin/admin-users')
            ->assertForbidden();

        $this->actingAs($admin, 'admin')
            ->get('/admin/roles')
            ->assertForbidden();
    }

    private function managerAdmin(): AdminUser
    {
        $admin = AdminUser::query()->create([
            'name' => 'Management Admin',
            'email' => 'management.admin@example.com',
            'password' => Hash::make('secret-password'),
            'is_active' => true,
        ]);

        $admin->permissions()->attach([
            AdminPermission::query()->create(['name' => 'Manage Admin Users', 'slug' => 'admin-users.manage'])->id,
            AdminPermission::query()->create(['name' => 'Manage Roles', 'slug' => 'roles.manage'])->id,
        ]);

        return $admin;
    }
}
