<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Services;

use App\Enums\AdminRoleStatus;
use App\Models\DberpAdminPermission;
use App\Models\DberpUserPermissionGrant;
use App\Models\User;
use DomainException;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

final class DberpPermissionService
{
    public const VIEW_SYSTEM_SETTINGS = 'system_settings_view';

    public const VIEW_SITE_ONBOARDING = 'view_site_onboarding';

    public const OPERATE_SITE_ONBOARDING = 'host_site_onboarding.operate';

    public const VIEW_HOST_SYSTEM_LICENSE = 'host_system_license.view';

    public const SYNC_HOST_SYSTEM_LICENSE = 'host_system_license.sync';

    public const VIEW_HOST_SYSTEM_UPDATE = 'host_system_update.view';

    public const CHECK_HOST_SYSTEM_UPDATE = 'host_system_update.check';

    public const DOWNLOAD_HOST_SYSTEM_UPDATE = 'host_system_update.download';

    public const EXECUTE_HOST_SYSTEM_UPDATE = 'host_system_update.execute';

    public const ROLLBACK_HOST_SYSTEM_UPDATE = 'host_system_update.rollback';

    public const VIEW_HOST_PLUGIN_CENTER = 'host_plugin_center.view';

    public const INSTALL_HOST_PLUGIN = 'host_plugin.install';

    public const ENABLE_HOST_PLUGIN = 'host_plugin.enable';

    public const DISABLE_HOST_PLUGIN = 'host_plugin.disable';

    public const UPDATE_HOST_PLUGIN = 'host_plugin.update';

    public const CONFIGURE_HOST_PLUGIN = 'host_plugin.configure';

    public static function pluginConfigurePermission(string $alias): string
    {
        return 'plugin.'.str_replace('-', '_', trim($alias)).'.configure';
    }

    public const VIEW_ADMIN_USER = 'admin_user_view';

    public const CREATE_ADMIN_USER = 'admin_user_create';

    public const EDIT_ADMIN_USER = 'admin_user_edit';

    public const DISABLE_ADMIN_USER = 'admin_user_disable';

    public const RESET_ADMIN_USER_PASSWORD = 'admin_user_password_reset';

    public const DELETE_ADMIN_USER = 'admin_user_delete';

    public const VIEW_ADMIN_ROLE = 'admin_role_view';

    public const CREATE_ADMIN_ROLE = 'admin_role_create';

    public const EDIT_ADMIN_ROLE = 'admin_role_edit';

    public const DISABLE_ADMIN_ROLE = 'admin_role_disable';

    public const COPY_ADMIN_ROLE = 'admin_role_copy';

    public const DELETE_ADMIN_ROLE = 'admin_role_delete';

    public const MANAGE_ADMIN_ROLE_PERMISSIONS = 'admin_role_permission_manage';

    public const VIEW_CUSTOMER_RECEIVABLE = 'view_customer_receivable';

    public const VIEW_SUPPLIER_PAYABLE = 'view_supplier_payable';

    public const CREATE_RECEIPT_ORDER = 'create_receipt_order';

    public const CREATE_PAYMENT_ORDER = 'create_payment_order';

    public const CONFIRM_RECEIPT_PAYMENT = 'confirm_receipt_payment';

    public const WRITE_OFF = 'write_off';

    public const REVERSE_WRITE_OFF = 'reverse_write_off';

    public const CREATE_SETTLEMENT_ADJUSTMENT = 'create_settlement_adjustment';

    public const CONFIRM_SETTLEMENT_STATEMENT = 'confirm_settlement_statement';

    public const EXPORT = 'export';

    public const VIEW_WORKBENCH_OVERVIEW = 'view_workbench_overview';

    public const MANAGE_SETTLEMENT_PERMISSIONS = 'manage_settlement_permissions';

    public const VIEW_AUDIT_LOG = 'view_audit_log';

    public const PURGE_AUDIT_LOG = 'purge_audit_log';

    public const VIEW_DATA_INITIALIZATION_IMPORT = 'view_data_initialization_import';

    public const EXECUTE_DATA_INITIALIZATION_IMPORT = 'execute_data_initialization_import';

    public const VIEW_DATA_IMPORT_BATCH = 'view_data_import_batch';

    public const DELETE_DATA_IMPORT_BATCH = 'delete_data_import_batch';

    public const VIEW_SALES_QUOTE = 'view_sales_quote';

    public const CREATE_SALES_QUOTE = 'create_sales_quote';

    public const EDIT_SALES_QUOTE = 'edit_sales_quote';

    public const ACTIVATE_SALES_QUOTE = 'activate_sales_quote';

    public const VOID_SALES_QUOTE = 'void_sales_quote';

    public const CONVERT_SALES_QUOTE = 'convert_sales_quote';

    public const VIEW_CUSTOMER_PRICE_RULE = 'view_customer_price_rule';

    public const CREATE_CUSTOMER_PRICE_RULE = 'create_customer_price_rule';

    public const EDIT_CUSTOMER_PRICE_RULE = 'edit_customer_price_rule';

    public const DISABLE_CUSTOMER_PRICE_RULE = 'disable_customer_price_rule';

    public const VIEW_CUSTOMER_CREDIT_CONTROL = 'view_customer_credit_control';

    public const OVERRIDE_CUSTOMER_CREDIT = 'override_customer_credit';

    public const VIEW_INVENTORY_BATCH = 'view_inventory_batch';

    public const MANAGE_INVENTORY_BATCH = 'manage_inventory_batch';

    public const DISABLE_INVENTORY_BATCH = 'disable_inventory_batch';

    public const VIEW_INVENTORY_SERIAL_NUMBER = 'view_inventory_serial_number';

    public const MANAGE_INVENTORY_SERIAL_NUMBER = 'manage_inventory_serial_number';

    public const DISABLE_INVENTORY_SERIAL_NUMBER = 'disable_inventory_serial_number';

    public const VIEW_INVENTORY_RULE = 'view_inventory_rule';

    public const EDIT_INVENTORY_RULE = 'edit_inventory_rule';

    public const DELETE_INVENTORY_RULE = 'delete_inventory_rule';

    public const VIEW_REPLENISHMENT_SUGGESTION = 'view_replenishment_suggestion';

    public const HANDLE_REPLENISHMENT_SUGGESTION = 'handle_replenishment_suggestion';

    public const VIEW_STOCKTAKE_DIFFERENCE = 'view_stocktake_difference';

    public const HANDLE_STOCKTAKE_DIFFERENCE = 'handle_stocktake_difference';

    public const CONFIRM_STOCKTAKE_DIFFERENCE = 'confirm_stocktake_difference';

    public const VIEW_INVENTORY_EXCEPTION = 'view_inventory_exception';

    public const HANDLE_INVENTORY_EXCEPTION = 'handle_inventory_exception';

    public const VIEW_INVENTORY_ALERT = 'view_inventory_alert';

    public const VIEW_PURCHASE_REQUEST = 'view_purchase_request';

    public const CREATE_PURCHASE_REQUEST = 'create_purchase_request';

    public const EDIT_PURCHASE_REQUEST = 'edit_purchase_request';

    public const CONVERT_PURCHASE_REQUEST = 'convert_purchase_request';

    public const VIEW_PURCHASE_INQUIRY_QUOTE = 'view_purchase_inquiry_quote';

    public const CREATE_PURCHASE_INQUIRY_QUOTE = 'create_purchase_inquiry_quote';

    public const EDIT_PURCHASE_INQUIRY_QUOTE = 'edit_purchase_inquiry_quote';

    public const VIEW_PURCHASE_ORDER = 'view_purchase_order';

    public const CREATE_PURCHASE_ORDER = 'create_purchase_order';

    public const EDIT_PURCHASE_ORDER = 'edit_purchase_order';

    public const VIEW_PURCHASE_RECEIPT = 'view_purchase_receipt';

    public const CREATE_PURCHASE_RECEIPT = 'create_purchase_receipt';

    public const EDIT_PURCHASE_RECEIPT = 'edit_purchase_receipt';

    public const VIEW_PURCHASE_RETURN = 'view_purchase_return';

    public const CREATE_PURCHASE_RETURN = 'create_purchase_return';

    public const EDIT_PURCHASE_RETURN = 'edit_purchase_return';

    public const VIEW_PURCHASE_EXCEPTION = 'view_purchase_exception';

    public const HANDLE_PURCHASE_EXCEPTION = 'handle_purchase_exception';

    public const VIEW_SUPPLIER_PERFORMANCE = 'view_supplier_performance';

    public const VIEW_PURCHASE_PRICE_REFERENCE = 'view_purchase_price_reference';

    public const VIEW_MASTER_CUSTOMER = 'view_master_customer';

    public const CREATE_MASTER_CUSTOMER = 'create_master_customer';

    public const EDIT_MASTER_CUSTOMER = 'edit_master_customer';

    public const DELETE_MASTER_CUSTOMER = 'delete_master_customer';

    public const VIEW_MASTER_CUSTOMER_CATEGORY = 'view_master_customer_category';

    public const CREATE_MASTER_CUSTOMER_CATEGORY = 'create_master_customer_category';

    public const EDIT_MASTER_CUSTOMER_CATEGORY = 'edit_master_customer_category';

    public const DELETE_MASTER_CUSTOMER_CATEGORY = 'delete_master_customer_category';

    public const VIEW_MASTER_SUPPLIER = 'view_master_supplier';

    public const CREATE_MASTER_SUPPLIER = 'create_master_supplier';

    public const EDIT_MASTER_SUPPLIER = 'edit_master_supplier';

    public const DELETE_MASTER_SUPPLIER = 'delete_master_supplier';

    public const VIEW_MASTER_SUPPLIER_CATEGORY = 'view_master_supplier_category';

    public const CREATE_MASTER_SUPPLIER_CATEGORY = 'create_master_supplier_category';

    public const EDIT_MASTER_SUPPLIER_CATEGORY = 'edit_master_supplier_category';

    public const DELETE_MASTER_SUPPLIER_CATEGORY = 'delete_master_supplier_category';

    public const VIEW_MASTER_EMPLOYEE = 'view_master_employee';

    public const CREATE_MASTER_EMPLOYEE = 'create_master_employee';

    public const EDIT_MASTER_EMPLOYEE = 'edit_master_employee';

    public const DELETE_MASTER_EMPLOYEE = 'delete_master_employee';

    public const VIEW_MASTER_DEPARTMENT = 'view_master_department';

    public const CREATE_MASTER_DEPARTMENT = 'create_master_department';

    public const EDIT_MASTER_DEPARTMENT = 'edit_master_department';

    public const DELETE_MASTER_DEPARTMENT = 'delete_master_department';

    public const VIEW_MASTER_POSITION = 'view_master_position';

    public const CREATE_MASTER_POSITION = 'create_master_position';

    public const EDIT_MASTER_POSITION = 'edit_master_position';

    public const DELETE_MASTER_POSITION = 'delete_master_position';

    public const VIEW_MASTER_SALESPERSON = 'view_master_salesperson';

    public const CREATE_MASTER_SALESPERSON = 'create_master_salesperson';

    public const EDIT_MASTER_SALESPERSON = 'edit_master_salesperson';

    public const DELETE_MASTER_SALESPERSON = 'delete_master_salesperson';

    public const VIEW_MASTER_UNIT = 'view_master_unit';

    public const CREATE_MASTER_UNIT = 'create_master_unit';

    public const EDIT_MASTER_UNIT = 'edit_master_unit';

    public const DELETE_MASTER_UNIT = 'delete_master_unit';

    public const VIEW_MASTER_REGION = 'view_master_region';

    public const CREATE_MASTER_REGION = 'create_master_region';

    public const EDIT_MASTER_REGION = 'edit_master_region';

    public const DELETE_MASTER_REGION = 'delete_master_region';

    public const VIEW_DICTIONARY_TYPE = 'view_dictionary_type';

    public const CREATE_DICTIONARY_TYPE = 'create_dictionary_type';

    public const EDIT_DICTIONARY_TYPE = 'edit_dictionary_type';

    public const DELETE_DICTIONARY_TYPE = 'delete_dictionary_type';

    public const VIEW_PRODUCT = 'view_product';

    public const CREATE_PRODUCT = 'create_product';

    public const EDIT_PRODUCT = 'edit_product';

    public const DELETE_PRODUCT = 'delete_product';

    public const VIEW_PRODUCT_CATEGORY = 'view_product_category';

    public const CREATE_PRODUCT_CATEGORY = 'create_product_category';

    public const EDIT_PRODUCT_CATEGORY = 'edit_product_category';

    public const DELETE_PRODUCT_CATEGORY = 'delete_product_category';

    public const VIEW_PRODUCT_BRAND = 'view_product_brand';

    public const CREATE_PRODUCT_BRAND = 'create_product_brand';

    public const EDIT_PRODUCT_BRAND = 'edit_product_brand';

    public const DELETE_PRODUCT_BRAND = 'delete_product_brand';

    public const VIEW_WAREHOUSE = 'view_warehouse';

    public const CREATE_WAREHOUSE = 'create_warehouse';

    public const EDIT_WAREHOUSE = 'edit_warehouse';

    public const DELETE_WAREHOUSE = 'delete_warehouse';

    public const VIEW_INVENTORY_TRANSFER = 'view_inventory_transfer';

    public const CREATE_INVENTORY_TRANSFER = 'create_inventory_transfer';

    public const EDIT_INVENTORY_TRANSFER = 'edit_inventory_transfer';

    public const DELETE_INVENTORY_TRANSFER = 'delete_inventory_transfer';

    public const VIEW_STOCKTAKE_ORDER = 'view_stocktake_order';

    public const CREATE_STOCKTAKE_ORDER = 'create_stocktake_order';

    public const EDIT_STOCKTAKE_ORDER = 'edit_stocktake_order';

    public const DELETE_STOCKTAKE_ORDER = 'delete_stocktake_order';

    public const VIEW_OTHER_STOCK_IN_ORDER = 'view_other_stock_in_order';

    public const CREATE_OTHER_STOCK_IN_ORDER = 'create_other_stock_in_order';

    public const EDIT_OTHER_STOCK_IN_ORDER = 'edit_other_stock_in_order';

    public const DELETE_OTHER_STOCK_IN_ORDER = 'delete_other_stock_in_order';

    public const VIEW_OTHER_STOCK_OUT_ORDER = 'view_other_stock_out_order';

    public const CREATE_OTHER_STOCK_OUT_ORDER = 'create_other_stock_out_order';

    public const EDIT_OTHER_STOCK_OUT_ORDER = 'edit_other_stock_out_order';

    public const DELETE_OTHER_STOCK_OUT_ORDER = 'delete_other_stock_out_order';

    public const VIEW_INVENTORY_BALANCE = 'view_inventory_balance';

    public const EDIT_INVENTORY_BALANCE = 'edit_inventory_balance';

    public const VIEW_SALES_ORDER = 'view_sales_order';

    public const CREATE_SALES_ORDER = 'create_sales_order';

    public const EDIT_SALES_ORDER = 'edit_sales_order';

    public const DELETE_SALES_ORDER = 'delete_sales_order';

    public const VIEW_SALES_OUTBOUND = 'view_sales_outbound';

    public const CREATE_SALES_OUTBOUND = 'create_sales_outbound';

    public const EDIT_SALES_OUTBOUND = 'edit_sales_outbound';

    public const DELETE_SALES_OUTBOUND = 'delete_sales_outbound';

    public const VIEW_SALES_RETURN = 'view_sales_return';

    public const CREATE_SALES_RETURN = 'create_sales_return';

    public const EDIT_SALES_RETURN = 'edit_sales_return';

    public const DELETE_SALES_RETURN = 'delete_sales_return';

    public const VIEW_NUMBER_SEQUENCE = 'view_number_sequence';

    public const EDIT_NUMBER_SEQUENCE = 'edit_number_sequence';

    public const VIEW_SETTLEMENT_STATEMENT = 'view_settlement_statement';

    public const VIEW_SETTLEMENT_ADJUSTMENT = 'view_settlement_adjustment';

    public const VIEW_SETTLEMENT_WRITE_OFF = 'view_settlement_write_off';

    public const VIEW_RECEIPT_ORDER = 'view_receipt_order';

    public const VIEW_PAYMENT_ORDER = 'view_payment_order';

    public const VIEW_INTEGRATION_SYNC_LOG = 'view_integration_sync_log';

    public const VIEW_INTEGRATION_RETRY_HANDLING = 'view_integration_retry_handling';

    public const MANAGE_INTEGRATION_RETRY_HANDLING = 'manage_integration_retry_handling';

    public const VIEW_INTEGRATION_MAPPING_GOVERNANCE = 'view_integration_mapping_governance';

    public const MANAGE_INTEGRATION_MAPPING_GOVERNANCE = 'manage_integration_mapping_governance';

    public const VIEW_INTEGRATION_DBSHOP_SYNC = 'view_integration_dbshop_sync';

    /** 菜单级：报表分析页 / 业务查询入口（与侧栏一致；可与原业务权限双轨并存） */
    public const NAV_SALES_ANALYSIS = 'nav_sales_analysis';

    public const NAV_PURCHASE_ANALYSIS = 'nav_purchase_analysis';

    public const NAV_INVENTORY_ANALYSIS = 'nav_inventory_analysis';

    public const NAV_SETTLEMENT_ANALYSIS = 'nav_settlement_analysis';

    public const NAV_COMPREHENSIVE_SUMMARY_ANALYSIS = 'nav_comprehensive_summary_analysis';

    public const NAV_INVENTORY_SUMMARY = 'nav_inventory_summary';

    public const NAV_SETTLEMENT_AGING_ANALYSIS = 'nav_settlement_aging_analysis';

    public const NAV_DOCUMENT_QUERY = 'nav_document_query';

    public const NAV_INVENTORY_TRANSACTION_QUERY = 'nav_inventory_transaction_query';

    public const NAV_SALES_STATISTICS = 'nav_sales_statistics';

    public const NAV_PURCHASE_STATISTICS = 'nav_purchase_statistics';

    public const NAV_CUSTOMER_SALES_RANKING = 'nav_customer_sales_ranking';

    public const NAV_SUPPLIER_PURCHASE_RANKING = 'nav_supplier_purchase_ranking';

    public const NAV_PRODUCT_SALES_RANKING = 'nav_product_sales_ranking';

    public const NAV_PRODUCT_PURCHASE_RANKING = 'nav_product_purchase_ranking';

    public const NAV_PRODUCT_BUSINESS_QUERY = 'nav_product_business_query';

    public const NAV_RECEIPT_PAYMENT_QUERY = 'nav_receipt_payment_query';

    public const NAV_PURCHASE_INQUIRY_COMPARISON = 'nav_purchase_inquiry_comparison';

    public function __construct(
        private readonly DberpPermissionRegistry $permissionRegistry,
        private readonly DberpAuditService $auditService,
    ) {}

    /**
     * @return array<string, string>
     */
    public function options(): array
    {
        return $this->permissionRegistry->options();
    }

    public function allows(?Authenticatable $user, string $permissionCode): bool
    {
        if (! $user instanceof User) {
            return false;
        }

        if (! $user->isAdminEnabled()) {
            return false;
        }

        if ($user->isSuperAdmin()) {
            return true;
        }

        $permissions = $this->grantedPermissionCodes($user);

        if ($permissions === []) {
            return false;
        }

        return in_array($permissionCode, $permissions, true);
    }

    /**
     * @param  list<string>  $permissionCodes
     */
    public function allowsAny(?Authenticatable $user, array $permissionCodes): bool
    {
        foreach ($permissionCodes as $permissionCode) {
            if ($this->allows($user, $permissionCode)) {
                return true;
            }
        }

        return false;
    }

    public function allowsReportAccess(?Authenticatable $user, string $reportKey): bool
    {
        $permissionCodes = $this->reportAccessPermissionCodes($reportKey);

        if ($permissionCodes === []) {
            return false;
        }

        return $this->allowsAny($user, $permissionCodes);
    }

    public function allowsReportExport(?Authenticatable $user, string $reportKey): bool
    {
        if (! $this->allows($user, self::EXPORT)) {
            return false;
        }

        $permissionCodes = $this->reportAccessPermissionCodes($reportKey);

        if ($permissionCodes === []) {
            return false;
        }

        return $this->allowsAny($user, $permissionCodes);
    }

    /**
     * @return list<string>
     */
    public function grantedPermissionCodes(User $user): array
    {
        $userId = (int) $user->getKey();

        // once() 按调用点缓存，不能区分不同 user。按 userId 放入同一请求级 ArrayObject，避免同一 PHP 进程内串权。
        /** @var \ArrayObject<int, list<string>> $grantedByUserId */
        $grantedByUserId = once(static fn (): \ArrayObject => new \ArrayObject);

        if (! $grantedByUserId->offsetExists($userId)) {
            $grantedByUserId[$userId] = $this->loadGrantedPermissionCodes($user);
        }

        return $grantedByUserId[$userId];
    }

    /**
     * @return list<string>
     */
    private function loadGrantedPermissionCodes(User $user): array
    {
        $grants = DberpUserPermissionGrant::query()
            ->where('user_id', $user->getKey())
            ->orderBy('permission_code')
            ->get();

        $rolePermissions = DberpAdminPermission::query()
            ->select('core_permissions.name')
            ->join('core_role_permissions', 'core_role_permissions.permission_id', '=', 'core_permissions.id')
            ->join('core_roles', 'core_roles.id', '=', 'core_role_permissions.role_id')
            ->join('core_user_roles', function ($join) use ($user): void {
                $join->on('core_user_roles.role_id', '=', 'core_roles.id')
                    ->where('core_user_roles.user_id', '=', $user->getKey())
                    ->where('core_user_roles.user_type', '=', User::class)
                    ->where('core_user_roles.guard_name', '=', (string) config('dberp.admin.guard', 'web'));
            })
            ->where('core_roles.status', AdminRoleStatus::Enabled->value)
            ->orderBy('core_permissions.sort_order')
            ->orderBy('core_permissions.id')
            ->pluck('core_permissions.name')
            ->all();

        $validCodes = $this->permissionRegistry->codes();

        return collect($rolePermissions)
            ->merge($grants->pluck('permission_code')->all())
            ->filter(fn (mixed $code): bool => is_string($code) && in_array($code, $validCodes, true))
            ->unique()
            ->values()
            ->all();
    }

    /**
     * @param  list<string>  $permissionCodes
     */
    public function syncPermissions(User $user, array $permissionCodes, ?int $grantedBy = null, ?string $remark = null): void
    {
        if ($user->isBootstrapInstallAdmin()) {
            throw new DomainException((string) __('dberp.errors.bootstrap_admin_permissions_locked'));
        }

        $validPermissionCodes = array_values(array_intersect($permissionCodes, $this->permissionRegistry->codes()));

        DB::transaction(function () use ($user, $validPermissionCodes, $grantedBy, $remark): void {
            /** @var Collection<string, DberpUserPermissionGrant> $existingGrants */
            $existingGrants = DberpUserPermissionGrant::query()
                ->where('user_id', $user->getKey())
                ->get()
                ->keyBy('permission_code');

            $existingCodes = $existingGrants->keys()->all();

            foreach (array_diff($existingCodes, $validPermissionCodes) as $permissionCode) {
                $existingGrants->get($permissionCode)?->delete();
            }

            foreach (array_diff($validPermissionCodes, $existingCodes) as $permissionCode) {
                DberpUserPermissionGrant::query()->create([
                    'user_id' => $user->getKey(),
                    'permission_code' => $permissionCode,
                    'granted_by' => $grantedBy,
                    'remark' => $remark,
                ]);
            }
        });

        $this->auditService->log('dberp.admin.direct_permissions_synced', $user, null, [
            'permissions' => $validPermissionCodes,
            'remark' => $remark,
        ]);
    }

    /**
     * @return list<string>
     */
    private function reportAccessPermissionCodes(string $reportKey): array
    {
        return match ($reportKey) {
            'sales-analysis' => [
                self::NAV_SALES_ANALYSIS,
                self::VIEW_SALES_ORDER,
                self::VIEW_SALES_OUTBOUND,
                self::VIEW_SALES_RETURN,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_PRICE_RULE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_CUSTOMER_CREDIT_CONTROL,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'sales-statistics' => [
                self::NAV_SALES_STATISTICS,
                self::VIEW_SALES_ORDER,
                self::VIEW_SALES_OUTBOUND,
                self::VIEW_SALES_RETURN,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_PRICE_RULE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_CUSTOMER_CREDIT_CONTROL,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'customer-sales-ranking' => [
                self::NAV_CUSTOMER_SALES_RANKING,
                self::VIEW_SALES_ORDER,
                self::VIEW_SALES_OUTBOUND,
                self::VIEW_SALES_RETURN,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_PRICE_RULE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_CUSTOMER_CREDIT_CONTROL,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'product-sales-ranking' => [
                self::NAV_PRODUCT_SALES_RANKING,
                self::VIEW_SALES_ORDER,
                self::VIEW_SALES_OUTBOUND,
                self::VIEW_SALES_RETURN,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_PRICE_RULE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_CUSTOMER_CREDIT_CONTROL,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'sales-quote', 'customer-price-rule' => [
                self::VIEW_SALES_ORDER,
                self::VIEW_SALES_OUTBOUND,
                self::VIEW_SALES_RETURN,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_PRICE_RULE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_CUSTOMER_CREDIT_CONTROL,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'settlement-aging-analysis' => [
                self::NAV_SETTLEMENT_AGING_ANALYSIS,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_SUPPLIER_PAYABLE,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'purchase-analysis' => [
                self::NAV_PURCHASE_ANALYSIS,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'purchase-statistics' => [
                self::NAV_PURCHASE_STATISTICS,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'supplier-purchase-ranking' => [
                self::NAV_SUPPLIER_PURCHASE_RANKING,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'product-purchase-ranking' => [
                self::NAV_PRODUCT_PURCHASE_RANKING,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'supplier-performance' => [
                self::VIEW_SUPPLIER_PERFORMANCE,
            ],
            'purchase-price-reference' => [
                self::VIEW_PURCHASE_PRICE_REFERENCE,
            ],
            'inventory-analysis' => [
                self::NAV_INVENTORY_ANALYSIS,
                self::VIEW_INVENTORY_ALERT,
                self::VIEW_INVENTORY_EXCEPTION,
                self::VIEW_STOCKTAKE_DIFFERENCE,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'inventory-summary' => [
                self::NAV_INVENTORY_SUMMARY,
                self::VIEW_INVENTORY_ALERT,
                self::VIEW_INVENTORY_EXCEPTION,
                self::VIEW_STOCKTAKE_DIFFERENCE,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'inventory-transaction-query' => [
                self::NAV_INVENTORY_TRANSACTION_QUERY,
                self::VIEW_INVENTORY_ALERT,
                self::VIEW_INVENTORY_EXCEPTION,
                self::VIEW_STOCKTAKE_DIFFERENCE,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'inventory-warning-report' => [
                self::VIEW_INVENTORY_ALERT,
            ],
            'settlement-analysis' => [
                self::NAV_SETTLEMENT_ANALYSIS,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_SUPPLIER_PAYABLE,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'customer-settlement-query' => [
                self::VIEW_CUSTOMER_RECEIVABLE,
            ],
            'supplier-settlement-query' => [
                self::VIEW_SUPPLIER_PAYABLE,
            ],
            'receipt-payment-query' => [
                self::NAV_RECEIPT_PAYMENT_QUERY,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_SUPPLIER_PAYABLE,
                self::CREATE_RECEIPT_ORDER,
                self::CREATE_PAYMENT_ORDER,
                self::CONFIRM_RECEIPT_PAYMENT,
                self::WRITE_OFF,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'comprehensive-summary-analysis' => [
                self::NAV_COMPREHENSIVE_SUMMARY_ANALYSIS,
                self::VIEW_WORKBENCH_OVERVIEW,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_SUPPLIER_PAYABLE,
                self::VIEW_INVENTORY_ALERT,
            ],
            'document-query' => [
                self::NAV_DOCUMENT_QUERY,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_SUPPLIER_PAYABLE,
                self::VIEW_INVENTORY_ALERT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'product-business-query' => [
                self::NAV_PRODUCT_BUSINESS_QUERY,
                self::VIEW_PURCHASE_ORDER,
                self::VIEW_PURCHASE_RECEIPT,
                self::VIEW_SALES_QUOTE,
                self::VIEW_CUSTOMER_RECEIVABLE,
                self::VIEW_INVENTORY_ALERT,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'integration-sync-log' => [
                self::VIEW_INTEGRATION_SYNC_LOG,
                self::VIEW_WORKBENCH_OVERVIEW,
            ],
            'audit-log' => [
                self::VIEW_AUDIT_LOG,
                self::PURGE_AUDIT_LOG,
            ],
            default => [],
        };
    }
}
