<?php

namespace App\Filament\Resources\RoleResource\Pages;

use App\Filament\Resources\RoleResource;
use App\Models\Role;
use App\Services\AuditLog;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Support\Facades\Auth;

class EditRole extends EditRecord
{
    protected static string $resource = RoleResource::class;

    /** @var array<int, string> */
    protected array $oldPermissionNames = [];

    /** @var array<int, string> */
    protected array $newPermissionNames = [];

    protected function mutateFormDataBeforeFill(array $data): array
    {
        /** @var Role $role */
        $role = $this->record;

        $data['permissions'] = $role->permissions()->pluck('permissions.name')->all();

        return $data;
    }

    protected function mutateFormDataBeforeSave(array $data): array
    {
        /** @var Role $role */
        $role = $this->record;

        $this->oldPermissionNames = $role->permissions()->pluck('permissions.name')->all();
        // Livewire syncs an all-unchecked PermissionPicker back as `false`
        // rather than `[]` — `?? []` alone doesn't catch that, and assigning
        // it to this typed array property would otherwise throw.
        $this->newPermissionNames = is_array($data['permissions'] ?? null) ? $data['permissions'] : [];
        unset($data['permissions']);

        $data['updated_by'] = Auth::id();
        // Ported rule: a full-admin role is always active, regardless of input.
        $data['is_active'] = $role->is_full_admin ? true : ($data['is_active'] ?? $role->is_active);

        return $data;
    }

    protected function afterSave(): void
    {
        /** @var Role $role */
        $role = $this->record;

        // Permissions are computed, so the change flows to every member at
        // once — no sync happens (or is meaningful) for a full-admin role.
        if (! $role->is_full_admin) {
            $role->permissions()->sync(RoleResource::permissionIdsFor($this->newPermissionNames));
        }

        RoleResource::flushRoleMembers($role);

        AuditLog::record('role.updated', $role, [
            'added' => array_values(array_diff($this->newPermissionNames, $this->oldPermissionNames)),
            'removed' => array_values(array_diff($this->oldPermissionNames, $this->newPermissionNames)),
        ]);
    }
}
