<?php
namespace App\Security;

class RbacCatalog
{
    public const SCOPE_TYPES = ['none', 'self', 'selected_users', 'all'];

    public static function resources(): array
    {
        return [

            // kind=entity  -> Read + Write(create/edit/delete) + special actions
            // kind=action  -> Read + special actions only (no auto CRUD)
            'dashboard' => ['title' => 'Dashboard', 'sort' => 10, 'kind' => 'action'],
            'leads' => ['title' => 'Leads', 'sort' => 20, 'kind' => 'entity'],
            'deals' => ['title' => 'Deals', 'sort' => 30, 'kind' => 'entity'],
            'payments' => ['title' => 'Payments', 'sort' => 40, 'kind' => 'entity'],
            'activities' => ['title' => 'Activities', 'sort' => 50, 'kind' => 'entity'],
            'reminders' => ['title' => 'Reminders', 'sort' => 60, 'kind' => 'action'],
            'support' => ['title' => 'Support', 'sort' => 70, 'kind' => 'entity'],
            'customer_access' => ['title' => 'Customer access requests', 'sort' => 75, 'kind' => 'action'],
            'satisfaction' => ['title' => 'Satisfaction', 'sort' => 80, 'kind' => 'entity'],
            'referrals' => ['title' => 'Referrals', 'sort' => 90, 'kind' => 'action'],
            'persons' => ['title' => 'Persons', 'sort' => 100, 'kind' => 'entity'],
            'users' => ['title' => 'Users', 'sort' => 110, 'kind' => 'entity'],
            'lookups' => ['title' => 'Lookups', 'sort' => 120, 'kind' => 'entity'],
            'field_config' => ['title' => 'Field configuration', 'sort' => 130, 'kind' => 'entity'],
            'products' => ['title' => 'Products', 'sort' => 140, 'kind' => 'entity'],
            'settings' => ['title' => 'Settings', 'sort' => 150, 'kind' => 'action'],
            'exports' => ['title' => 'Exports', 'sort' => 160, 'kind' => 'action'],
            'audit_logs' => ['title' => 'Audit logs', 'sort' => 170, 'kind' => 'action'],
            'sync' => ['title' => 'Sync', 'sort' => 180, 'kind' => 'action'],
            'migration' => ['title' => 'Migration', 'sort' => 190, 'kind' => 'action'],
            'kpi' => ['title' => 'KPI', 'sort' => 200, 'kind' => 'action'],
            'performance' => ['title' => 'Performance', 'sort' => 210, 'kind' => 'action'],
            'financial_dashboard' => ['title' => 'Financial dashboard', 'sort' => 220, 'kind' => 'action'],
            'notifications' => ['title' => 'Notifications', 'sort' => 230, 'kind' => 'action'],
            'maintenance' => ['title' => 'Maintenance', 'sort' => 240, 'kind' => 'action'],
            'operation_manager' => ['title' => 'Operation manager', 'sort' => 250, 'kind' => 'action'],
            'lead_pools' => ['title' => 'Lead pools', 'sort' => 260, 'kind' => 'entity'],
            'cheques' => ['title' => 'Cheques (financial)', 'sort' => 270, 'kind' => 'entity'],

        ];
    }

    /**
     * Resources that own real data records and therefore expose create/edit/delete.
     * Everything else is an "action" module: a Read (view) gate plus explicit
     * special-action toggles, with no auto-generated CRUD.
     */
    public static function isEntityResource(string $resourceKey): bool
    {
        $resource = self::resources()[$resourceKey] ?? null;
        return $resource !== null && (string)($resource['kind'] ?? 'action') === 'entity';
    }

    public static function resourceKeys(): array
    {
        return array_keys(self::resources());
    }

    public static function isValidResource(string $resourceKey): bool
    {
        return isset(self::resources()[$resourceKey]);
    }

    public static function isValidScopeType(string $scopeType): bool
    {
        return in_array($scopeType, self::SCOPE_TYPES, true);
    }

    public static function capabilities(): array
    {
        $caps = [
            // Menus
            ['key' => 'menu.dashboard', 'title' => 'Menu: Dashboard', 'cat' => 'menu', 'module' => 'dashboard', 'parent' => null, 'sort' => 10],
            ['key' => 'menu.performance_dashboard', 'title' => 'Menu: Performance dashboard', 'cat' => 'menu', 'module' => 'performance', 'parent' => null, 'sort' => 20],
            ['key' => 'menu.leads', 'title' => 'Menu: Leads', 'cat' => 'menu', 'module' => 'leads', 'parent' => null, 'sort' => 30],
            ['key' => 'menu.blataklif_leads', 'title' => 'Menu: Outstanding leads', 'cat' => 'menu', 'module' => 'leads', 'parent' => null, 'sort' => 40],
            ['key' => 'menu.deals', 'title' => 'Menu: Deals', 'cat' => 'menu', 'module' => 'deals', 'parent' => null, 'sort' => 50],
            ['key' => 'menu.legacy_deals', 'title' => 'Menu: Legacy deals', 'cat' => 'menu', 'module' => 'deals', 'parent' => null, 'sort' => 60],
            ['key' => 'menu.referrals', 'title' => 'Menu: Referrals', 'cat' => 'menu', 'module' => 'referrals', 'parent' => null, 'sort' => 70],
            ['key' => 'menu.persons', 'title' => 'Menu: Persons', 'cat' => 'menu', 'module' => 'persons', 'parent' => null, 'sort' => 80],
            ['key' => 'menu.reminders', 'title' => 'Menu: Reminders', 'cat' => 'menu', 'module' => 'reminders', 'parent' => null, 'sort' => 90],
            ['key' => 'menu.settings', 'title' => 'Menu: Settings', 'cat' => 'menu', 'module' => 'settings', 'parent' => null, 'sort' => 100],
            ['key' => 'menu.lookups', 'title' => 'Menu: Lookups', 'cat' => 'menu', 'module' => 'lookups', 'parent' => null, 'sort' => 110],
            ['key' => 'menu.exports', 'title' => 'Menu: Exports', 'cat' => 'menu', 'module' => 'exports', 'parent' => null, 'sort' => 120],
            ['key' => 'menu.audit_logs', 'title' => 'Menu: Audit logs', 'cat' => 'menu', 'module' => 'audit_logs', 'parent' => null, 'sort' => 130],
            ['key' => 'menu.users', 'title' => 'Menu: Users', 'cat' => 'menu', 'module' => 'users', 'parent' => null, 'sort' => 140],
            ['key' => 'menu.financial_dashboard', 'title' => 'Menu: Financial dashboard', 'cat' => 'menu', 'module' => 'financial_dashboard', 'parent' => null, 'sort' => 150],
            ['key' => 'menu.kpi_dashboard', 'title' => 'Menu: KPI dashboard', 'cat' => 'menu', 'module' => 'kpi', 'parent' => null, 'sort' => 160],

            ['key' => 'menu.customer_access', 'title' => 'Menu: Customer access requests', 'cat' => 'menu', 'module' => 'customer_access', 'parent' => null, 'sort' => 170],
            ['key' => 'menu.operation_manager', 'title' => 'Menu: Operation manager', 'cat' => 'menu', 'module' => 'operation_manager', 'parent' => null, 'sort' => 175],
            ['key' => 'menu.maintenance', 'title' => 'Menu: Database maintenance', 'cat' => 'menu', 'module' => 'maintenance', 'parent' => null, 'sort' => 176],

        ];

        $caps = array_merge($caps, [
            ['key' => 'dashboard.view', 'title' => 'View dashboard', 'cat' => 'dashboard', 'module' => 'dashboard', 'parent' => 'menu.dashboard', 'sort' => 180],

            ['key' => 'leads.view', 'title' => 'View leads', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'menu.leads', 'sort' => 200],
            ['key' => 'leads.profile.view', 'title' => 'View lead profile', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.view', 'sort' => 201],
            ['key' => 'leads.lookup_phone', 'title' => 'Lookup lead phone', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.view', 'sort' => 202],
            ['key' => 'leads.create', 'title' => 'Create lead', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.view', 'sort' => 203],
            ['key' => 'leads.edit', 'title' => 'Edit lead', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.view', 'sort' => 204],
            ['key' => 'leads.delete', 'title' => 'Delete lead', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.view', 'sort' => 205],
            ['key' => 'leads.transfer_owner', 'title' => 'Transfer lead owner', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.edit', 'sort' => 206],
            ['key' => 'leads.backfill_products', 'title' => 'Backfill lead products', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.edit', 'sort' => 207],

            ['key' => 'deals.view', 'title' => 'View deals', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'menu.deals', 'sort' => 220],
            ['key' => 'deals.detail.view', 'title' => 'View deal details', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.view', 'sort' => 221],
            ['key' => 'deals.create', 'title' => 'Create deal', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.view', 'sort' => 222],
            ['key' => 'deals.edit', 'title' => 'Edit deal', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.view', 'sort' => 223],
            ['key' => 'deals.delete', 'title' => 'Delete deal', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.view', 'sort' => 224],
            ['key' => 'deals.status.edit', 'title' => 'Edit deal status', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 225],
            ['key' => 'deals.pipeline.edit', 'title' => 'Edit deal pipeline', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 226],
            ['key' => 'deals.course.edit', 'title' => 'Edit course status', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 227],
            ['key' => 'deals.reactivate', 'title' => 'Reactivate deal', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 228],
            ['key' => 'deals.reconcile', 'title' => 'Reconcile deals', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 229],
            ['key' => 'deals.force_success', 'title' => 'Force deal success', 'cat' => 'deals', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 230],

            ['key' => 'payments.create', 'title' => 'Create payment', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'deals.edit', 'sort' => 240],
            ['key' => 'payments.edit', 'title' => 'Edit payment', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'deals.edit', 'sort' => 241],
            ['key' => 'payments.delete', 'title' => 'Delete payment', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'deals.edit', 'sort' => 242],
            ['key' => 'payments.owner_override', 'title' => 'Override locked payment owner', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'payments.edit', 'sort' => 243],

            // C9: financial cheque workflow
            ['key' => 'menu.cheques', 'title' => 'Menu: Cheques', 'cat' => 'menu', 'module' => 'cheques', 'parent' => null, 'sort' => 205],
            ['key' => 'cheques.view', 'title' => 'View cheques (financial)', 'cat' => 'cheques', 'module' => 'cheques', 'parent' => 'menu.cheques', 'sort' => 244],
            ['key' => 'cheques.review', 'title' => 'Approve/Reject cheque', 'cat' => 'cheques', 'module' => 'cheques', 'parent' => 'cheques.view', 'sort' => 245],
            ['key' => 'cheques.collect', 'title' => 'Set cheque collection status', 'cat' => 'cheques', 'module' => 'cheques', 'parent' => 'cheques.view', 'sort' => 246],
            ['key' => 'financial_payments.view', 'title' => 'View financial payments', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'menu.cheques', 'sort' => 247],
            ['key' => 'financial_payments.sepidar', 'title' => 'Mark payment registered in Sepidar', 'cat' => 'payments', 'module' => 'payments', 'parent' => 'financial_payments.view', 'sort' => 248],

            ['key' => 'activities.view', 'title' => 'View activities', 'cat' => 'activities', 'module' => 'activities', 'parent' => null, 'sort' => 260],
            ['key' => 'activities.create', 'title' => 'Create activity', 'cat' => 'activities', 'module' => 'activities', 'parent' => 'activities.view', 'sort' => 261],
            ['key' => 'activities.edit', 'title' => 'Edit activity', 'cat' => 'activities', 'module' => 'activities', 'parent' => 'activities.view', 'sort' => 262],
            ['key' => 'activities.delete', 'title' => 'Delete activity', 'cat' => 'activities', 'module' => 'activities', 'parent' => 'activities.view', 'sort' => 263],
            ['key' => 'activities.types.view', 'title' => 'View activity types', 'cat' => 'activities', 'module' => 'activities', 'parent' => 'activities.view', 'sort' => 264],

            ['key' => 'support.view', 'title' => 'View support', 'cat' => 'support', 'module' => 'support', 'parent' => null, 'sort' => 280],
            ['key' => 'support.create', 'title' => 'Create support', 'cat' => 'support', 'module' => 'support', 'parent' => 'support.view', 'sort' => 281],
            ['key' => 'support.edit', 'title' => 'Edit support', 'cat' => 'support', 'module' => 'support', 'parent' => 'support.view', 'sort' => 282],
            ['key' => 'support.delete', 'title' => 'Delete support', 'cat' => 'support', 'module' => 'support', 'parent' => 'support.view', 'sort' => 283],
            ['key' => 'satisfaction.view', 'title' => 'View satisfaction', 'cat' => 'satisfaction', 'module' => 'satisfaction', 'parent' => null, 'sort' => 290],
            ['key' => 'satisfaction.create', 'title' => 'Create satisfaction', 'cat' => 'satisfaction', 'module' => 'satisfaction', 'parent' => 'satisfaction.view', 'sort' => 291],
            ['key' => 'customer_access.view', 'title' => 'View customer access requests', 'cat' => 'customer_access', 'module' => 'customer_access', 'parent' => null, 'sort' => 295],
            ['key' => 'customer_access.create', 'title' => 'Create customer access request', 'cat' => 'customer_access', 'module' => 'customer_access', 'parent' => 'customer_access.view', 'sort' => 296],
            ['key' => 'customer_access.resolve', 'title' => 'Resolve customer access request', 'cat' => 'customer_access', 'module' => 'customer_access', 'parent' => 'customer_access.view', 'sort' => 297],
            ['key' => 'referrals.view', 'title' => 'View referrals', 'cat' => 'referrals', 'module' => 'referrals', 'parent' => 'menu.referrals', 'sort' => 300],

            ['key' => 'users.view', 'title' => 'View users', 'cat' => 'users', 'module' => 'users', 'parent' => 'menu.users', 'sort' => 320],
            ['key' => 'users.create', 'title' => 'Create users', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.view', 'sort' => 321],
            ['key' => 'users.edit', 'title' => 'Edit users', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.view', 'sort' => 322],
            ['key' => 'users.delete', 'title' => 'Delete users', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.view', 'sort' => 323],
            ['key' => 'users.roles.edit', 'title' => 'Edit user roles', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.edit', 'sort' => 324],
            ['key' => 'users.passwords.change', 'title' => 'Change user passwords', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.edit', 'sort' => 325],
            ['key' => 'users.transfer_data', 'title' => 'Transfer user data', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.edit', 'sort' => 326],
            ['key' => 'users.sync_didar', 'title' => 'Sync Didar users', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.edit', 'sort' => 327],
            ['key' => 'users.scope_options.view', 'title' => 'View users for scopes', 'cat' => 'users', 'module' => 'users', 'parent' => 'users.view', 'sort' => 328],

            ['key' => 'lookups.view', 'title' => 'View lookups', 'cat' => 'lookups', 'module' => 'lookups', 'parent' => 'menu.lookups', 'sort' => 340],
            ['key' => 'lookups.manage', 'title' => 'Manage lookups', 'cat' => 'lookups', 'module' => 'lookups', 'parent' => 'lookups.view', 'sort' => 341],
            ['key' => 'lookups.create', 'title' => 'Create lookups', 'cat' => 'lookups', 'module' => 'lookups', 'parent' => 'lookups.view', 'sort' => 342],
            ['key' => 'lookups.edit', 'title' => 'Edit lookups', 'cat' => 'lookups', 'module' => 'lookups', 'parent' => 'lookups.view', 'sort' => 343],
            ['key' => 'lookups.delete', 'title' => 'Delete lookups', 'cat' => 'lookups', 'module' => 'lookups', 'parent' => 'lookups.view', 'sort' => 344],
            ['key' => 'field_config.view', 'title' => 'View field config', 'cat' => 'field_config', 'module' => 'field_config', 'parent' => null, 'sort' => 350],
            ['key' => 'field_config.manage', 'title' => 'Manage field config', 'cat' => 'field_config', 'module' => 'field_config', 'parent' => 'field_config.view', 'sort' => 351],
            ['key' => 'field_config.create', 'title' => 'Create field config', 'cat' => 'field_config', 'module' => 'field_config', 'parent' => 'field_config.view', 'sort' => 352],
            ['key' => 'field_config.edit', 'title' => 'Edit field config', 'cat' => 'field_config', 'module' => 'field_config', 'parent' => 'field_config.view', 'sort' => 353],
            ['key' => 'field_config.delete', 'title' => 'Delete field config', 'cat' => 'field_config', 'module' => 'field_config', 'parent' => 'field_config.view', 'sort' => 354],
            ['key' => 'products.view', 'title' => 'View products', 'cat' => 'products', 'module' => 'products', 'parent' => null, 'sort' => 360],
            ['key' => 'products.manage', 'title' => 'Manage products', 'cat' => 'products', 'module' => 'products', 'parent' => 'products.view', 'sort' => 361],
            ['key' => 'products.create', 'title' => 'Create products', 'cat' => 'products', 'module' => 'products', 'parent' => 'products.view', 'sort' => 362],
            ['key' => 'products.edit', 'title' => 'Edit products', 'cat' => 'products', 'module' => 'products', 'parent' => 'products.view', 'sort' => 363],
            ['key' => 'products.delete', 'title' => 'Delete products', 'cat' => 'products', 'module' => 'products', 'parent' => 'products.view', 'sort' => 364],
            ['key' => 'products.service_links.manage', 'title' => 'Manage service/product links', 'cat' => 'products', 'module' => 'products', 'parent' => 'products.edit', 'sort' => 365],

            ['key' => 'settings.didar_write.manage', 'title' => 'Manage Didar write settings', 'cat' => 'settings', 'module' => 'settings', 'parent' => 'menu.settings', 'sort' => 380],
            ['key' => 'settings.auto_migration.manage', 'title' => 'Manage auto migration settings', 'cat' => 'settings', 'module' => 'settings', 'parent' => 'menu.settings', 'sort' => 381],
            ['key' => 'settings.external_api.manage', 'title' => 'Manage external API settings', 'cat' => 'settings', 'module' => 'settings', 'parent' => 'menu.settings', 'sort' => 382],
            ['key' => 'settings.master_password.manage', 'title' => 'Manage master password', 'cat' => 'settings', 'module' => 'settings', 'parent' => 'menu.settings', 'sort' => 383],
            ['key' => 'notifications.view', 'title' => 'View notifications', 'cat' => 'notifications', 'module' => 'notifications', 'parent' => null, 'sort' => 390],
            ['key' => 'notifications.manage', 'title' => 'Manage notifications', 'cat' => 'notifications', 'module' => 'notifications', 'parent' => 'notifications.view', 'sort' => 391],
            ['key' => 'reminders.view', 'title' => 'View reminders', 'cat' => 'reminders', 'module' => 'reminders', 'parent' => 'menu.reminders', 'sort' => 400],
            ['key' => 'reminders.manage', 'title' => 'Manage reminders', 'cat' => 'reminders', 'module' => 'reminders', 'parent' => 'reminders.view', 'sort' => 401],
            ['key' => 'audit_logs.view', 'title' => 'View audit logs', 'cat' => 'audit_logs', 'module' => 'audit_logs', 'parent' => 'menu.audit_logs', 'sort' => 410],
            ['key' => 'audit_logs.recover', 'title' => 'Recover audit records', 'cat' => 'audit_logs', 'module' => 'audit_logs', 'parent' => 'audit_logs.view', 'sort' => 411],
            ['key' => 'sync.run', 'title' => 'Run sync', 'cat' => 'sync', 'module' => 'sync', 'parent' => null, 'sort' => 420],
            ['key' => 'migration.preview', 'title' => 'Preview migration', 'cat' => 'migration', 'module' => 'migration', 'parent' => null, 'sort' => 430],
            ['key' => 'migration.run', 'title' => 'Run migration', 'cat' => 'migration', 'module' => 'migration', 'parent' => 'migration.preview', 'sort' => 431],
            ['key' => 'maintenance.backup', 'title' => 'Create database backup', 'cat' => 'maintenance', 'module' => 'maintenance', 'parent' => 'maintenance.view', 'sort' => 432],
            ['key' => 'maintenance.restore', 'title' => 'Restore database backup', 'cat' => 'maintenance', 'module' => 'maintenance', 'parent' => 'maintenance.backup', 'sort' => 433],
            ['key' => 'maintenance.backfill.preview', 'title' => 'Preview payment ledger / tafsili backfill', 'cat' => 'maintenance', 'module' => 'maintenance', 'parent' => 'maintenance.view', 'sort' => 434],
            ['key' => 'maintenance.backfill.run', 'title' => 'Run payment ledger / tafsili backfill', 'cat' => 'maintenance', 'module' => 'maintenance', 'parent' => 'maintenance.backfill.preview', 'sort' => 435],
            ['key' => 'maintenance.backfill.verify', 'title' => 'Verify payment ledger / tafsili backfill', 'cat' => 'maintenance', 'module' => 'maintenance', 'parent' => 'maintenance.view', 'sort' => 436],
            ['key' => 'activity_repair.preview', 'title' => 'Preview activity repair', 'cat' => 'maintenance', 'module' => 'activities', 'parent' => null, 'sort' => 440],
            ['key' => 'activity_repair.run', 'title' => 'Run activity repair', 'cat' => 'maintenance', 'module' => 'activities', 'parent' => 'activity_repair.preview', 'sort' => 441],

            ['key' => 'operation_manager.view', 'title' => 'View operation manager', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'menu.operation_manager', 'sort' => 460],
            ['key' => 'operation_manager.preview', 'title' => 'Preview operations', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'operation_manager.view', 'sort' => 461],
            ['key' => 'operation_manager.execute', 'title' => 'Execute operations', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'operation_manager.preview', 'sort' => 462],
            ['key' => 'operation_manager.rules.view', 'title' => 'View operation rules', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'operation_manager.view', 'sort' => 463],
            ['key' => 'operation_manager.rules.manage', 'title' => 'Manage operation rules', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'operation_manager.rules.view', 'sort' => 464],
            ['key' => 'operation_manager.automation.run', 'title' => 'Run operation automation', 'cat' => 'operation_manager', 'module' => 'operation_manager', 'parent' => 'operation_manager.rules.manage', 'sort' => 465],
            ['key' => 'lead_pools.view', 'title' => 'View lead pools', 'cat' => 'lead_pools', 'module' => 'operation_manager', 'parent' => 'operation_manager.view', 'sort' => 470],
            ['key' => 'lead_pools.claim', 'title' => 'Claim pool leads', 'cat' => 'lead_pools', 'module' => 'operation_manager', 'parent' => 'lead_pools.view', 'sort' => 471],
            ['key' => 'lead_pools.assign', 'title' => 'Assign pool leads', 'cat' => 'lead_pools', 'module' => 'operation_manager', 'parent' => 'lead_pools.view', 'sort' => 472],
            ['key' => 'lead_pools.manage', 'title' => 'Manage lead pools', 'cat' => 'lead_pools', 'module' => 'operation_manager', 'parent' => 'lead_pools.view', 'sort' => 473],
            ['key' => 'lead_owner_history.view', 'title' => 'View lead owner history', 'cat' => 'leads', 'module' => 'leads', 'parent' => 'leads.profile.view', 'sort' => 474],
        ]);

        $caps = array_merge($caps, self::moduleCrudCapabilities(), self::analyticsCapabilities(), self::exportCapabilities(), self::legacyAliases());
        $unique = [];
        foreach ($caps as $cap) {
            $unique[$cap['key']] = $cap;
        }
        return array_values($unique);
    }

    private static function moduleCrudCapabilities(): array
    {
        $caps = [];
        foreach (self::resources() as $resourceKey => $resource) {
            $sort = (int)($resource['sort'] ?? 900);
            $title = (string)($resource['title'] ?? $resourceKey);

            // Every module gets a Read (view) gate.
            $actions = ['view' => ['View', 0, null]];

            // Only data-owning modules expose create/edit/delete. Action/report
            // modules rely on their explicit special-action capabilities instead.
            if (self::isEntityResource($resourceKey)) {
                $actions += [
                    'create' => ['Create', 1, $resourceKey . '.view'],
                    'edit' => ['Edit', 2, $resourceKey . '.view'],
                    'delete' => ['Delete', 3, $resourceKey . '.view'],
                ];
            }

            foreach ($actions as $action => $meta) {
                [$verb, $offset, $parent] = $meta;
                $caps[] = [
                    'key' => $resourceKey . '.' . $action,
                    'title' => $verb . ' ' . $title,
                    'cat' => $resourceKey,
                    'module' => $resourceKey,
                    'parent' => $parent,
                    'sort' => ($sort * 10) + $offset,
                ];
            }
        }
        return $caps;
    }

    private static function analyticsCapabilities(): array
    {
        $caps = [
            ['key' => 'kpi.view', 'title' => 'View KPI dashboard', 'cat' => 'kpi', 'module' => 'kpi', 'parent' => 'menu.kpi_dashboard', 'sort' => 500],
            ['key' => 'kpi.drilldown', 'title' => 'KPI drilldown', 'cat' => 'kpi', 'module' => 'kpi', 'parent' => 'kpi.view', 'sort' => 501],
            ['key' => 'kpi.targets.manage', 'title' => 'Manage KPI targets', 'cat' => 'kpi', 'module' => 'kpi', 'parent' => 'kpi.view', 'sort' => 502],
            ['key' => 'kpi.deals.details', 'title' => 'KPI deal details', 'cat' => 'kpi', 'module' => 'kpi', 'parent' => 'kpi.view', 'sort' => 503],
            ['key' => 'performance.view', 'title' => 'View performance dashboard', 'cat' => 'performance', 'module' => 'performance', 'parent' => 'menu.performance_dashboard', 'sort' => 520],
            ['key' => 'performance.drilldown', 'title' => 'Performance drilldown', 'cat' => 'performance', 'module' => 'performance', 'parent' => 'performance.view', 'sort' => 521],
            ['key' => 'performance.ceo_report', 'title' => 'Performance CEO report', 'cat' => 'performance', 'module' => 'performance', 'parent' => 'performance.view', 'sort' => 522],
        ];
        foreach ([
            'chart.daily_sales', 'chart.daily_activities', 'chart.deal_status', 'chart.product_share', 'chart.conversion_funnel',
            'card.sales_total', 'card.outstanding_amount_sum', 'card.settled_count', 'card.lost_count', 'card.won_count', 'card.open_pipeline_count', 'card.without_payment_count',
            'card.registered_payments_count', 'card.total_deposits_amount', 'card.balance_previous_amount', 'card.cheque_collected_amount', 'card.access_granted_count',
            'table.activity_summary', 'table.activity_type_details', 'table.deal_status', 'table.lead_status', 'table.conversion_status', 'table.payment_mix', 'table.payment_status', 'table.product_status',
            'table.product_sold_by_owner_day', 'table.product_requests_by_owner_day', 'table.product_failed_by_owner_day', 'table.failure_reasons',
            'table.ceo_cash_composition', 'table.ceo_product_sales', 'table.ceo_registered_deals_sources', 'table.ceo_access_grants', 'table.ceo_cheque_status',
        ] as $idx => $suffix) {
            $caps[] = ['key' => 'performance.' . $suffix, 'title' => 'Performance ' . $suffix, 'cat' => 'performance_widget', 'module' => 'performance', 'parent' => 'performance.view', 'sort' => 530 + $idx];
        }
        return $caps;
    }

    private static function exportCapabilities(): array
    {
        return [
            ['key' => 'export.catalog', 'title' => 'View export catalog', 'cat' => 'export', 'module' => 'exports', 'parent' => 'menu.exports', 'sort' => 600],
            ['key' => 'export.dataset.leads', 'title' => 'Export leads', 'cat' => 'export', 'module' => 'exports', 'parent' => 'export.catalog', 'sort' => 601],
            ['key' => 'export.dataset.deals', 'title' => 'Export deals', 'cat' => 'export', 'module' => 'exports', 'parent' => 'export.catalog', 'sort' => 602],
            ['key' => 'export.dataset.payments', 'title' => 'Export payments', 'cat' => 'export', 'module' => 'exports', 'parent' => 'export.catalog', 'sort' => 603],
        ];
    }

    private static function legacyAliases(): array
    {
        return [
            ['key' => 'action.leads.create', 'title' => 'Alias: Create lead', 'cat' => 'legacy_alias', 'module' => 'leads', 'parent' => 'leads.create', 'sort' => 700],
            ['key' => 'action.leads.edit', 'title' => 'Alias: Edit lead', 'cat' => 'legacy_alias', 'module' => 'leads', 'parent' => 'leads.edit', 'sort' => 701],
            ['key' => 'action.leads.delete', 'title' => 'Alias: Delete lead', 'cat' => 'legacy_alias', 'module' => 'leads', 'parent' => 'leads.delete', 'sort' => 702],
            ['key' => 'action.deals.create', 'title' => 'Alias: Create deal', 'cat' => 'legacy_alias', 'module' => 'deals', 'parent' => 'deals.create', 'sort' => 703],
            ['key' => 'action.deals.edit', 'title' => 'Alias: Edit deal', 'cat' => 'legacy_alias', 'module' => 'deals', 'parent' => 'deals.edit', 'sort' => 704],
            ['key' => 'action.deals.delete', 'title' => 'Alias: Delete deal', 'cat' => 'legacy_alias', 'module' => 'deals', 'parent' => 'deals.delete', 'sort' => 705],
            ['key' => 'action.payments.create', 'title' => 'Alias: Create payment', 'cat' => 'legacy_alias', 'module' => 'payments', 'parent' => 'payments.create', 'sort' => 706],
            ['key' => 'action.payments.edit', 'title' => 'Alias: Edit payment', 'cat' => 'legacy_alias', 'module' => 'payments', 'parent' => 'payments.edit', 'sort' => 707],
            ['key' => 'action.payments.delete', 'title' => 'Alias: Delete payment', 'cat' => 'legacy_alias', 'module' => 'payments', 'parent' => 'payments.delete', 'sort' => 708],
        ];
    }

    public static function aliasMap(): array
    {
        return [
            'menu.dashboard' => 'dashboard.view',
            'menu.leads' => 'leads.view',
            'menu.deals' => 'deals.view',
            'menu.performance_dashboard' => 'performance.view',
            'menu.kpi_dashboard' => 'kpi.view',
            'menu.operation_manager' => 'operation_manager.view',
            'menu.maintenance' => 'maintenance.view',
            'action.leads.create' => 'leads.create',
            'action.leads.edit' => 'leads.edit',
            'action.leads.delete' => 'leads.delete',
            'action.deals.create' => 'deals.create',
            'action.deals.edit' => 'deals.edit',
            'action.deals.delete' => 'deals.delete',
            'action.payments.create' => 'payments.create',
            'action.payments.edit' => 'payments.edit',
            'action.payments.delete' => 'payments.delete',
        ];
    }

    public static function defaultGrants(): array
    {
        $all = array_map(static fn($cap) => $cap['key'], self::capabilities());
        $readOnly = array_values(array_filter($all, static function ($key) {
            $key = (string)$key;
            foreach (['.create', '.edit', '.delete', '.manage', '.run', '.recover', '.repair', '.targets'] as $writeToken) {
                if (strpos($key, $writeToken) !== false) {
                    return false;
                }
            }
            foreach (['create', 'edit', 'delete', 'manage', 'run', 'recover', 'repair'] as $writePrefix) {
                if (strpos($key, $writePrefix . '.') === 0) {
                    return false;
                }
            }
            return true;
        }));
        $agent = [
            'menu.dashboard', 'menu.performance_dashboard', 'menu.leads', 'menu.blataklif_leads', 'menu.deals', 'menu.legacy_deals', 'menu.persons', 'menu.reminders', 'menu.settings',
            'dashboard.view',
            'leads.view', 'leads.profile.view', 'leads.lookup_phone', 'leads.edit',
            'deals.view', 'deals.detail.view', 'deals.create', 'deals.edit', 'deals.status.edit', 'deals.pipeline.edit', 'deals.course.edit',
            'payments.create', 'payments.edit',
            'activities.view', 'activities.create', 'activities.edit', 'activities.types.view',
            'customer_access.view', 'customer_access.create',
            'notifications.view', 'notifications.manage', 'reminders.view', 'reminders.manage',
            'users.scope_options.view',
            'lookups.view',
            'products.view',
            'performance.view', 'performance.drilldown',
        ];
        foreach (self::analyticsCapabilities() as $cap) {
            if (strpos($cap['key'], 'performance.') === 0) {
                $agent[] = $cap['key'];
            }
        }
        $salesManager = array_values(array_unique(array_merge($agent, [
            'menu.exports', 'menu.users',
            'leads.create', 'leads.delete', 'leads.transfer_owner', 'leads.backfill_products',
            'deals.delete', 'deals.reactivate', 'deals.reconcile', 'deals.force_success',
            'payments.delete',
            'activities.delete',
            'users.view', 'users.scope_options.view',
            'export.catalog', 'export.dataset.leads', 'export.dataset.deals',
        ])));
        $management = array_values(array_unique(array_merge($salesManager, [
            'menu.referrals', 'menu.audit_logs', 'menu.kpi_dashboard',
            'support.view', 'support.create', 'support.edit',
            'satisfaction.view', 'satisfaction.create',
            'menu.customer_access', 'customer_access.view', 'customer_access.create', 'customer_access.resolve',
            'referrals.view',
            'audit_logs.view',
            'kpi.view', 'kpi.drilldown', 'kpi.deals.details',
            'export.dataset.payments',
        ])));
        return [
            // admin is read-only by default, but may create/resolve customer-access tickets.
            'admin' => array_values(array_unique(array_merge($readOnly, [
                'customer_access.create',
                'customer_access.resolve',
                'maintenance.backup',
                'maintenance.restore',
                'maintenance.backfill.preview',
                'maintenance.backfill.run',
                'maintenance.backfill.verify',
            ]))),
            'system' => $all,

            'accountant' => ['menu.exports', 'export.catalog', 'export.dataset.payments', 'lookups.view', 'products.view',
                'menu.cheques', 'cheques.view', 'cheques.review', 'cheques.collect', 'financial_payments.view', 'financial_payments.sepidar'],
            'sales_manager' => $salesManager,
            'management' => $management,
            'support' => [
                'menu.dashboard', 'menu.leads', 'menu.deals', 'menu.reminders', 'menu.settings', 'menu.customer_access',
                'dashboard.view',
                'leads.view', 'leads.profile.view', 'leads.lookup_phone',
                'deals.view', 'deals.detail.view',
                'activities.view', 'activities.create', 'activities.edit', 'activities.types.view',
                'support.view', 'support.create', 'support.edit',
                'customer_access.view', 'customer_access.resolve',
                'notifications.view', 'notifications.manage', 'reminders.view', 'reminders.manage',
                'users.scope_options.view', 'lookups.view', 'products.view',
            ],

            'crm_specialist' => [
                'menu.dashboard', 'menu.leads', 'menu.blataklif_leads', 'menu.deals', 'menu.legacy_deals', 'menu.referrals', 'menu.persons', 'menu.reminders', 'menu.settings', 'menu.exports',
                'dashboard.view',
                'leads.view', 'leads.profile.view', 'leads.lookup_phone', 'deals.view', 'deals.detail.view', 'deals.edit', 'deals.status.edit', 'deals.pipeline.edit', 'deals.course.edit',
                'payments.create', 'payments.edit',
                'activities.view', 'activities.types.view',
                'support.view', 'support.create', 'satisfaction.view', 'satisfaction.create', 'referrals.view',
                'customer_access.view', 'customer_access.create',
                'export.catalog', 'export.dataset.payments', 'notifications.view', 'notifications.manage', 'reminders.view', 'users.scope_options.view', 'lookups.view', 'products.view',
                'operation_manager.view', 'operation_manager.preview', 'operation_manager.rules.view', 'lead_pools.view', 'lead_pools.claim', 'lead_owner_history.view',
            ],
            'agent' => array_values(array_unique(array_merge($agent, [
                'action.leads.edit', 'action.deals.create', 'action.deals.edit', 'action.payments.create', 'action.payments.edit',
            ]))),
        ];
    }

    public static function defaultScopeTypeForRole(string $roleKey): string
    {
        return in_array($roleKey, ['admin', 'system', 'crm_specialist', 'accountant', 'sales_manager', 'management'], true) ? 'all' : 'self';
    }
}
