<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class RbacController extends Controller
{
    /**
     * Display a listing of the roles and permissions.
     */
    public function index(): Response
    {
        // Fetch all roles with their assigned permission names
        $roles = Role::with('permissions')
            ->get()
            ->map(function ($role) {
                return [
                    'id' => $role->id,
                    'name' => $role->name,
                    'permissions' => $role->permissions->pluck('name')->toArray(),
                    'is_system' => in_array($role->name, ['Super Admin', 'Admin', 'Manager', 'User'], true),
                ];
            });

        $permissions = Permission::all()->map(function ($permission) {
            return [
                'id' => $permission->id,
                'name' => $permission->name,
                'is_system' => in_array($permission->name, ['view dashboard', 'manage users', 'manage settings', 'view logs'], true),
                // Categorize for easier layout display
                'category' => $this->getPermissionCategory($permission->name),
            ];
        });

        return Inertia::render('Rbac/Index', [
            'roles' => $roles,
            'permissions' => $permissions,
        ]);
    }

    /**
     * Store a newly created role in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:roles,name'],
        ]);

        $role = Role::create([
            'name' => $request->name,
        ]);

        // Audit Logging
        activity()
            ->performedOn($role)
            ->causedBy($request->user())
            ->log("Created security role: {$role->name}");

        return redirect()->back()->with('success', 'Security role created successfully.');
    }

    /**
     * Update the specified role and its permissions.
     */
    public function update(Request $request, Role $role): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:roles,name,' . $role->id],
            'permissions' => ['nullable', 'array'],
            'permissions.*' => ['string', 'exists:permissions,name'],
        ]);

        $isSystemRole = in_array($role->name, ['Super Admin', 'Admin', 'Manager', 'User'], true);

        // Lock down Super Admin renaming
        if ($role->name === 'Super Admin' && $request->name !== 'Super Admin') {
            return redirect()->back()->with('error', 'The Super Admin role name cannot be modified.');
        }

        // Rename role if it is not a protected system role name
        $oldName = $role->name;
        if (!$isSystemRole || $role->name === 'Super Admin') {
            $role->update([
                'name' => $request->name,
            ]);
        }

        // Sync permissions if provided
        if ($request->has('permissions')) {
            // Prevent changing Super Admin permissions in UI to maintain system integrity
            if ($role->name === 'Super Admin') {
                return redirect()->back()->with('error', 'Super Admin permissions are locked and cannot be customized.');
            }

            $oldPermissions = $role->permissions->pluck('name')->toArray();
            $role->syncPermissions($request->permissions);

            // Audit Logging
            activity()
                ->performedOn($role)
                ->causedBy($request->user())
                ->withProperties([
                    'role_name' => $role->name,
                    'old_permissions' => $oldPermissions,
                    'new_permissions' => $request->permissions,
                ])
                ->log("Updated permissions for role: {$role->name}");
        }

        return redirect()->back()->with('success', 'Role settings updated successfully.');
    }

    /**
     * Remove the specified role from storage.
     */
    public function destroy(Request $request, Role $role): RedirectResponse
    {
        $systemRoles = ['Super Admin', 'Admin', 'Manager', 'User'];

        if (in_array($role->name, $systemRoles, true)) {
            return redirect()->back()->with('error', "System role '{$role->name}' is protected and cannot be deleted.");
        }

        $roleName = $role->name;

        // Audit Logging
        activity()
            ->performedOn($role)
            ->causedBy($request->user())
            ->log("Deleted security role: {$roleName}");

        $role->delete();

        return redirect()->back()->with('success', 'Security role deleted successfully.');
    }

    /**
     * Categorize permissions based on prefix/name.
     */
    protected function getPermissionCategory(string $name): string
    {
        if (str_contains($name, 'user')) {
            return 'User Management';
        }
        if (str_contains($name, 'setting')) {
            return 'System Settings';
        }
        if (str_contains($name, 'log')) {
            return 'Audit Logs';
        }
        if (str_contains($name, 'dashboard') || str_contains($name, 'view')) {
            return 'Navigation & View';
        }
        return 'General';
    }

    /**
     * Store a newly created permission in storage.
     */
    public function storePermission(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:permissions,name'],
        ]);

        $permission = Permission::create([
            'name' => $request->name,
            'guard_name' => 'web',
        ]);

        // Clear Spatie cache
        app(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();

        // Audit Logging
        activity()
            ->performedOn($permission)
            ->causedBy($request->user())
            ->log("Created security permission: {$permission->name}");

        return redirect()->back()->with('success', 'Security permission created successfully.');
    }

    /**
     * Update the specified permission in storage.
     */
    public function updatePermission(Request $request, Permission $permission): RedirectResponse
    {
        $systemPermissions = ['view dashboard', 'manage users', 'manage settings', 'view logs'];

        if (in_array($permission->name, $systemPermissions, true)) {
            return redirect()->back()->with('error', 'Core system permissions are protected and cannot be renamed.');
        }

        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:permissions,name,' . $permission->id],
        ]);

        $oldName = $permission->name;
        $permission->update([
            'name' => $request->name,
        ]);

        // Clear Spatie cache
        app(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();

        // Audit Logging
        activity()
            ->performedOn($permission)
            ->causedBy($request->user())
            ->log("Updated security permission: {$oldName} to {$permission->name}");

        return redirect()->back()->with('success', 'Security permission renamed successfully.');
    }

    /**
     * Remove the specified permission from storage.
     */
    public function destroyPermission(Request $request, Permission $permission): RedirectResponse
    {
        $systemPermissions = ['view dashboard', 'manage users', 'manage settings', 'view logs'];

        if (in_array($permission->name, $systemPermissions, true)) {
            return redirect()->back()->with('error', "Core system permission '{$permission->name}' is protected and cannot be deleted.");
        }

        $permissionName = $permission->name;

        // Audit Logging
        activity()
            ->performedOn($permission)
            ->causedBy($request->user())
            ->log("Deleted security permission: {$permissionName}");

        $permission->delete();

        // Clear Spatie cache
        app(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();

        return redirect()->back()->with('success', 'Security permission deleted successfully.');
    }
}
