<?php

namespace App\Filament\Pages;

use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use BackedEnum;
use UnitEnum;

class RolePermissions extends Page
{
    protected static ?string $navigationLabel = 'Role Permissions';
    protected static string|BackedEnum|null $navigationIcon  = null;
    protected static string|UnitEnum|null $navigationGroup = 'Administration';
    protected static ?int    $navigationSort  = 2;

    // Livewire state — array of [roleName => [permissionName => bool]]
    public array $matrix = [];

    // Roles editable in the UI (super_admin is always all — not shown as editable)
    public array $editableRoles = ['admin', 'accountant', 'cashier', 'warehouse', 'staff', 'director'];

    // Permissions grouped for display
    public array $groups = [
        'Cargo'          => ['view_shipments', 'create_shipments', 'edit_shipments', 'delete_shipments', 'view_consignments', 'create_consignments', 'edit_consignments'],
        'Accounts'       => ['view_invoices', 'view_payments', 'create_payments', 'view_expenses', 'create_expenses', 'edit_expenses', 'delete_expenses'],
        'Warehouse'      => ['view_stock', 'release_goods'],
        'Documents'      => ['print_documents'],
        'Administration' => ['manage_users', 'manage_settings'],
    ];

    public function getView(): string
    {
        return 'filament.pages.role-permissions';
    }

    public static function canAccess(): bool
    {
        return auth()->user()?->hasRole(['super_admin', 'admin']) ?? false;
    }

    public function mount(): void
    {
        $roles = Role::whereIn('name', $this->editableRoles)->with('permissions')->get()->keyBy('name');

        foreach ($this->editableRoles as $roleName) {
            $role = $roles->get($roleName);
            $rolePerms = $role ? $role->permissions->pluck('name')->toArray() : [];

            foreach ($this->allPermissions() as $perm) {
                $this->matrix[$roleName][$perm] = in_array($perm, $rolePerms);
            }
        }
    }

    public function save(): void
    {
        foreach ($this->editableRoles as $roleName) {
            $role = Role::where('name', $roleName)->first();
            if (! $role) continue;

            $granted = array_keys(array_filter($this->matrix[$roleName] ?? []));
            $role->syncPermissions($granted);
        }

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

        Notification::make()
            ->title('Role permissions saved')
            ->success()
            ->send();
    }

    public function allPermissions(): array
    {
        return array_merge(...array_values($this->groups));
    }

    public function permissionLabel(string $perm): string
    {
        return ucwords(str_replace('_', ' ', $perm));
    }
}
