<?php

namespace Database\Seeders;

use App\Domain\Identity\Services\RoleRegistry;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;

/**
 * Seeds the default system roles with their scoped permission grants (§66A).
 *
 * Only permissions and scopes of *system* roles are re-synced; roles created or
 * edited by administrators in the UI are never overwritten here.
 */
class RoleSeeder extends Seeder
{
    public function run(): void
    {
        $guard = config('auth.defaults.guard', 'web');
        $permissionIds = Permission::where('guard_name', $guard)->pluck('id', 'name');

        DB::transaction(function () use ($guard, $permissionIds) {
            foreach (RoleRegistry::roles() as $name => $definition) {
                $role = Role::updateOrCreate(
                    ['name' => $name, 'guard_name' => $guard],
                    [
                        'label' => $definition['label'],
                        'description' => $definition['description'],
                        'level' => $definition['level'],
                        'is_system' => true,
                        'is_active' => true,
                    ],
                );

                $grants = RoleRegistry::resolvePermissions($definition['permissions']);
                $role->syncPermissions(array_keys($grants));

                $scopes = [];
                foreach ($grants as $permission => $scope) {
                    if (! isset($permissionIds[$permission])) {
                        continue;
                    }

                    $scopes[] = [
                        'role_id' => $role->id,
                        'permission_id' => $permissionIds[$permission],
                        'scope' => $scope,
                        'created_at' => now(),
                        'updated_at' => now(),
                    ];
                }

                DB::table('role_permission_scopes')->where('role_id', $role->id)->delete();
                foreach (array_chunk($scopes, 500) as $chunk) {
                    DB::table('role_permission_scopes')->insert($chunk);
                }
            }
        });

        app(PermissionRegistrar::class)->forgetCachedPermissions();
    }
}
