<?php

namespace Database\Seeders;

use App\Support\PermissionCatalog;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;

class PermissionSeeder extends Seeder
{
    public static function hierarchy(): array
    {
        return PermissionCatalog::hierarchy();
    }

    public static function permissionNames(): array
    {
        return PermissionCatalog::permissionNames();
    }

    public static function defaultEnabledPermissionNames(): array
    {
        return PermissionCatalog::defaultEnabledPermissionNames();
    }

    public static function defaultDisabledPermissionNames(): array
    {
        return PermissionCatalog::defaultDisabledPermissionNames();
    }

    public static function syncModelPermissions(): void
    {
        $now = now();
        $permissions = array_map(fn (string $permission) => array_merge(
            PermissionCatalog::metadata($permission),
            [
                'created_at' => $now,
                'updated_at' => $now,
            ]
        ), self::permissionNames());

        DB::table('model_permissions')
            ->upsert(
                $permissions,
                ['name'],
                ['module', 'sub_module', 'action', 'guard_name', 'is_active', 'updated_at']
            );
    }

    public function run(): void
    {
        // Reset Spatie's internal cache before rebuilding permissions.
        app()[PermissionRegistrar::class]->forgetCachedPermissions();

        $permissionNames = $this->enabledPermissionNames();

        foreach ($permissionNames as $permissionName) {
            Permission::firstOrCreate([
                'name' => $permissionName,
                'guard_name' => 'web',
            ]);
        }

        // Create Admin role and assign every enabled permission generated above
        $admin = Role::firstOrCreate(['name' => 'super_admin', 'guard_name' => 'web']);
        $admin->syncPermissions(Permission::whereIn('name', $permissionNames)->get());

        $disabledPermissionIds = Permission::whereIn(
            'name',
            array_values(array_diff(self::permissionNames(), $permissionNames))
        )->pluck('id');

        if ($disabledPermissionIds->isNotEmpty()) {
            DB::table('role_has_permissions')
                ->whereIn('permission_id', $disabledPermissionIds)
                ->delete();
            DB::table('model_has_permissions')
                ->whereIn('permission_id', $disabledPermissionIds)
                ->delete();
            Permission::whereIn('id', $disabledPermissionIds)->delete();
        }

    }

    private function enabledPermissionNames(): array
    {
        return self::defaultEnabledPermissionNames();
    }
}
