<?php

namespace App\Support\Authorization;

final class PermissionCatalog
{
    public const GUARD = 'web';

    public const RISK_READ = 'read';
    public const RISK_OPERATE = 'operate';
    public const RISK_APPROVE = 'approve';
    public const RISK_FINANCIAL = 'financial';
    public const RISK_SECURITY = 'security';

    /**
     * @return array<int, array{
     *     name:string,
     *     display_name:string,
     *     group:string,
     *     description:?string,
     *     risk:string,
     *     deprecated:bool,
     *     replacement:array<int, string>,
     *     deprecation_reason:?string
     * }>
     */
    public static function definitions(): array
    {
        return [
            self::definition(PermissionName::DASHBOARD_VIEW, 'View dashboard', 'navigation', 'read'),
            self::definition(PermissionName::SEARCH_USE, 'Use global search', 'navigation', 'read'),
            self::definition(PermissionName::BUSINESS_SETTINGS_VIEW, 'View business settings', 'settings', 'read'),
            self::definition(PermissionName::BUSINESS_SETTINGS_UPDATE, 'Update business settings', 'settings', 'operate'),
            self::definition(PermissionName::SYSTEM_SETTINGS_MANAGE, 'Manage system settings', 'settings', 'security'),
            self::definition(PermissionName::BRANCHES_VIEW, 'View branches', 'branches', 'read'),
            self::definition(PermissionName::BRANCHES_CREATE, 'Create branches', 'branches', 'operate'),
            self::definition(PermissionName::BRANCHES_UPDATE, 'Update branches', 'branches', 'operate'),
            self::definition(PermissionName::USERS_VIEW, 'View staff users', 'staff', 'read'),
            self::definition(PermissionName::USERS_CREATE, 'Create staff users', 'staff', 'security'),
            self::definition(PermissionName::USERS_UPDATE, 'Update staff users', 'staff', 'security'),
            self::definition(PermissionName::ROLES_VIEW, 'View roles and permissions', 'security', 'read'),
            self::definition(PermissionName::ROLES_CREATE, 'Create custom roles', 'security', 'security'),
            self::definition(PermissionName::ROLES_UPDATE, 'Update custom role permissions', 'security', 'security'),
            self::definition(PermissionName::ROLES_DELETE, 'Delete unused custom roles', 'security', 'security'),
            self::definition(PermissionName::ROLES_ASSIGN, 'Assign roles within the actor delegation ceiling', 'security', 'security'),
            self::definition(PermissionName::ROLES_ASSIGN_SYSTEM, 'Assign protected system roles within the actor delegation ceiling', 'security', 'security'),
            self::definition(PermissionName::ROLES_ASSIGN_SUPER_ADMIN, 'Assign or remove the Super Administrator role', 'security', 'security'),
            self::definition(PermissionName::AUDIT_VIEW, 'View audit log', 'security', 'read'),
            self::definition(PermissionName::CUSTOMERS_MANAGE, 'Legacy full customer management', 'customers', 'operate', deprecated: true, replacement: ['customers.view', 'customers.create', 'customers.update', 'customers.documents', 'customers.guarantors', 'customers.watchlist'], deprecationReason: 'Legacy full-customer-management permission retained for compatibility while granular customer permissions already exist.'),
            self::definition(PermissionName::CUSTOMERS_VIEW, 'View customers', 'customers', 'read'),
            self::definition(PermissionName::CUSTOMERS_CREATE, 'Register customers', 'customers', 'operate'),
            self::definition(PermissionName::CUSTOMERS_UPDATE, 'Update customers', 'customers', 'operate'),
            self::definition(PermissionName::CUSTOMERS_DOCUMENTS, 'Manage customer documents', 'customers', 'operate'),
            self::definition(PermissionName::CUSTOMERS_GUARANTORS, 'Manage customer guarantors', 'customers', 'operate'),
            self::definition(PermissionName::CUSTOMERS_WATCHLIST, 'Manage customer blacklist and watchlist', 'customers', 'operate'),
            self::definition(PermissionName::CREDIT_SCORE_VIEW, 'View customer credit scores', 'customers', 'read'),
            self::definition(PermissionName::CREDIT_SCORE_HISTORY, 'View customer credit score history', 'customers', 'read'),
            self::definition(PermissionName::CREDIT_SCORE_RECALCULATE, 'Recalculate customer credit scores', 'customers', 'operate'),
            self::definition(PermissionName::LOAN_PRODUCTS_VIEW, 'View loan products', 'loans', 'read'),
            self::definition(PermissionName::LOAN_PRODUCTS_MANAGE, 'Manage loan products', 'loans', 'operate'),
            self::definition(PermissionName::COLLATERAL_VIEW, 'View collateral and custody history', 'collateral', 'read'),
            self::definition(PermissionName::COLLATERAL_MANAGE, 'Register and update collateral and categories', 'collateral', 'operate'),
            self::definition(PermissionName::COLLATERAL_CUSTODY, 'Change collateral status and storage location', 'collateral', 'operate'),
            self::definition(PermissionName::COLLATERAL_DOCUMENTS, 'Manage collateral photos and documents', 'collateral', 'operate'),
            self::definition(PermissionName::LOANS_VIEW, 'View loan applications and schedules', 'loans', 'read'),
            self::definition(PermissionName::LOANS_CREATE, 'Create loan applications', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_UPDATE, 'Update and progress loan applications', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_CONTRACT, 'Generate loan contracts', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_DOCUMENTS, 'Manage loan application and signed contract documents', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_INSTALLMENTS_EXCUSE, 'Record approved payment-deadline excuses before penalties are charged', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_APPROVE, 'Review, approve or reject loan applications', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_MANAGER_APPROVE, 'Approve loans that exceed the manager approval threshold', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_AUTO_APPROVE, 'Use authorized auto approval when business settings allow it', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_DISBURSE, 'Disburse approved loans from branch financial accounts', 'loans', 'financial'),
            self::definition(PermissionName::LOANS_TOP_UP_VIEW, 'View loan top-up applications and history', 'loans', 'read'),
            self::definition(PermissionName::LOANS_TOP_UP_CREATE, 'Create loan top-up applications', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_TOP_UP_EXECUTE, 'Execute approved loan top-ups', 'loans', 'financial'),
            self::definition(PermissionName::LOANS_TOP_UP_OVERRIDE, 'Override configured loan top-up eligibility with reason', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_ADJUSTMENTS_VIEW, 'View early settlement and restructuring history', 'loans', 'read'),
            self::definition(PermissionName::LOANS_SETTLEMENT_EXECUTE, 'Execute full early settlements', 'loans', 'financial'),
            self::definition(PermissionName::LOANS_SETTLEMENT_ADJUST, 'Apply authorized early-settlement adjustments', 'loans', 'financial'),
            self::definition(PermissionName::LOANS_RESTRUCTURE_CREATE, 'Create loan restructuring proposals', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_RESTRUCTURE_APPROVE, 'Approve or reject loan restructuring proposals', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_WRITEOFF_VIEW, 'View loan write-off and recovery history', 'loans', 'read'),
            self::definition(PermissionName::LOANS_WRITEOFF_REQUEST, 'Request full loan write-offs with supporting evidence', 'loans', 'operate'),
            self::definition(PermissionName::LOANS_WRITEOFF_APPROVE, 'Approve or reject loan write-off requests', 'loans', 'approve'),
            self::definition(PermissionName::LOANS_WRITEOFF_RECOVER, 'Post recoveries against approved written-off loans', 'loans', 'financial'),
            self::definition(PermissionName::PAYMENTS_RECEIVE, 'Receive loan payments', 'payments', 'financial'),
            self::definition(PermissionName::PAYMENTS_REMOTE_SUBMIT, 'Submit remote payment evidence', 'payments', 'operate'),
            self::definition(PermissionName::PAYMENTS_REMOTE_VERIFY, 'Verify and approve or reject remote payments', 'payments', 'approve'),
            self::definition(PermissionName::NOTIFICATIONS_VIEW, 'View reminder notification logs', 'notifications', 'read'),
            self::definition(PermissionName::NOTIFICATIONS_RETRY, 'Retry failed reminder notifications', 'notifications', 'operate'),
            self::definition(PermissionName::NOTIFICATIONS_MANAGE, 'Manage business-wide reminder policy and templates', 'notifications', 'operate'),
            self::definition(PermissionName::ARREARS_VIEW, 'View overdue loans and arrears history', 'collections', 'read'),
            self::definition(PermissionName::ARREARS_FOLLOW_UP, 'Record collection follow-ups and promises to pay', 'collections', 'operate'),
            self::definition(PermissionName::ACCOUNTS_VIEW, 'View financial accounts and statements', 'accounting', 'read'),
            self::definition(PermissionName::ACCOUNTS_MANAGE, 'Create and update financial accounts', 'accounting', 'operate'),
            self::definition(PermissionName::ACCOUNTS_CAPITAL, 'Post business capital injections', 'accounting', 'financial'),
            self::definition(PermissionName::ACCOUNTS_TRANSFER, 'Transfer funds between financial accounts', 'accounting', 'financial'),
            self::definition(PermissionName::ACCOUNTING_VIEW, 'View accounting ledger entries', 'accounting', 'read'),
            self::definition(PermissionName::FIXED_ASSETS_VIEW, 'View fixed asset register, depreciation, maintenance and reports', 'accounting', 'read'),
            self::definition(PermissionName::FIXED_ASSETS_MANAGE, 'Register and update fixed assets', 'accounting', 'operate'),
            self::definition(PermissionName::FIXED_ASSETS_DEPRECIATE, 'Post fixed asset depreciation', 'accounting', 'financial'),
            self::definition(PermissionName::FIXED_ASSETS_MAINTENANCE, 'Record fixed asset maintenance and costs', 'accounting', 'operate'),
            self::definition(PermissionName::FIXED_ASSETS_REPORTS_VIEW, 'View fixed asset reports', 'accounting', 'read'),
            self::definition(PermissionName::FIXED_ASSETS_REPORTS_EXPORT, 'Export fixed asset reports', 'accounting', 'read'),
            self::definition(PermissionName::EXPENSES_MANAGE, 'Legacy full expense management', 'accounting', 'operate', deprecated: true, replacement: ['expenses.view', 'expenses.create', 'expenses.approve', 'expenses.categories.manage', 'expenses.recurring.manage'], deprecationReason: 'Legacy full-expense-management permission retained for compatibility while granular expense permissions already exist.'),
            self::definition(PermissionName::EXPENSES_VIEW, 'View expenses and reminders', 'accounting', 'read'),
            self::definition(PermissionName::EXPENSES_CREATE, 'Enter expense requests', 'accounting', 'operate'),
            self::definition(PermissionName::EXPENSES_APPROVE, 'Approve, reject and financially post expenses', 'accounting', 'approve'),
            self::definition(PermissionName::EXPENSES_CATEGORIES_MANAGE, 'Manage expense categories', 'accounting', 'operate'),
            self::definition(PermissionName::EXPENSES_RECURRING_MANAGE, 'Manage recurring expenses and reminder schedules', 'accounting', 'operate'),
            self::definition(PermissionName::REPORTS_VIEW, 'View financial and loan reports', 'reports', 'read'),
            self::definition(PermissionName::REPORTS_EXPORT, 'Export financial and loan reports', 'reports', 'read'),
            self::definition(PermissionName::COLLECTIONS_MANAGE, 'Manage debt collection', 'collections', 'operate', deprecated: true, replacement: ['arrears.view', 'arrears.follow-up'], deprecationReason: 'Broad collections capability retained until the collection workflow is fully decomposed.'),
            self::definition(PermissionName::PAYROLL_MANAGE, 'Manage payroll', 'payroll', 'operate', deprecated: true, replacement: ['payroll.view', 'payroll.compensation.manage', 'payroll.periods.create', 'payroll.approve', 'payroll.pay'], deprecationReason: 'Older broad payroll permission retained while the active payroll routes use granular payroll permissions.'),
            self::definition(PermissionName::PAYROLL_VIEW, 'View payroll periods, entries and payslips', 'payroll', 'read'),
            self::definition(PermissionName::PAYROLL_COMPENSATION_MANAGE, 'Manage employee compensation settings', 'payroll', 'operate'),
            self::definition(PermissionName::PAYROLL_PERIODS_CREATE, 'Create payroll periods and edit draft payroll entries', 'payroll', 'operate'),
            self::definition(PermissionName::PAYROLL_APPROVE, 'Approve or reject payroll periods', 'payroll', 'approve'),
            self::definition(PermissionName::PAYROLL_PAY, 'Pay approved payroll from financial accounts', 'payroll', 'financial'),
            self::definition(PermissionName::CASH_CLOSING_VIEW, 'View cash reconciliations and daily closings', 'accounting', 'read'),
            self::definition(PermissionName::CASH_RECONCILIATION_PERFORM, 'Perform and recount physical cash reconciliations', 'accounting', 'financial'),
            self::definition(PermissionName::DAILY_CLOSING_PREPARE, 'Prepare or refresh branch daily closing', 'accounting', 'financial'),
            self::definition(PermissionName::DAILY_CLOSING_CONFIRM, 'Manager-confirm branch daily closing', 'accounting', 'approve'),
            self::definition(PermissionName::TASKS_VIEW, 'View branch tasks and assignments', 'tasks', 'read'),
            self::definition(PermissionName::TASKS_MANAGE, 'Legacy full task management', 'tasks', 'operate', deprecated: true, replacement: ['tasks.create', 'tasks.update', 'tasks.assign', 'tasks.update-status'], deprecationReason: 'Phase 8 replaces broad task management with explicit creation, editing, assignment and status permissions.'),
            self::definition(PermissionName::TASKS_CREATE, 'Create branch tasks', 'tasks', 'operate'),
            self::definition(PermissionName::TASKS_UPDATE, 'Edit branch tasks', 'tasks', 'operate'),
            self::definition(PermissionName::TASKS_ASSIGN, 'Assign branch tasks and manage assignee-controlled status', 'tasks', 'operate'),
            self::definition(PermissionName::TASKS_UPDATE_STATUS, 'Update status of assigned tasks', 'tasks', 'operate'),
            self::definition(PermissionName::CALENDAR_VIEW, 'View operational management calendar', 'tasks', 'read'),
            self::definition(PermissionName::APPOINTMENTS_MANAGE, 'Legacy appointment management', 'tasks', 'operate', deprecated: true, replacement: ['appointments.create', 'appointments.update', 'appointments.manage-status'], deprecationReason: 'Phase 8 replaces broad appointment management with explicit create, update and status capabilities.'),
            self::definition(PermissionName::APPOINTMENTS_CREATE, 'Create customer appointments', 'tasks', 'operate'),
            self::definition(PermissionName::APPOINTMENTS_UPDATE, 'Update customer appointments', 'tasks', 'operate'),
            self::definition(PermissionName::APPOINTMENTS_MANAGE_STATUS, 'Update customer appointment status', 'tasks', 'operate'),
            self::definition(PermissionName::MANAGEMENT_ALERTS_VIEW, 'View management alerts', 'management', 'read'),
            self::definition(PermissionName::MANAGEMENT_ALERTS_MANAGE, 'Legacy management alert control', 'management', 'operate', deprecated: true, replacement: ['management-alerts.acknowledge', 'management-alerts.resolve', 'management-alerts.settings'], deprecationReason: 'Phase 8 separates routine alert handling from business-wide threshold and automation settings.'),
            self::definition(PermissionName::MANAGEMENT_ALERTS_ACKNOWLEDGE, 'Acknowledge management alerts', 'management', 'operate'),
            self::definition(PermissionName::MANAGEMENT_ALERTS_RESOLVE, 'Resolve management alerts', 'management', 'operate'),
            self::definition(PermissionName::MANAGEMENT_ALERTS_SETTINGS, 'Manage alert thresholds and task automation settings', 'management', 'security'),
        ];
    }

    /** @return array<int, string> */
    public static function names(): array
    {
        return array_column(self::definitions(), 'name');
    }

    /** @return array<string, array<string, mixed>> */
    public static function byName(): array
    {
        return collect(self::definitions())->keyBy('name')->all();
    }

    /** @return array<string, array{reason:string,replacement:array<int, string>}> */
    public static function legacyPermissions(): array
    {
        return collect(self::definitions())
            ->filter(fn (array $permission): bool => $permission['deprecated'])
            ->mapWithKeys(fn (array $permission): array => [
                $permission['name'] => [
                    'reason' => (string) $permission['deprecation_reason'],
                    'replacement' => $permission['replacement'],
                ],
            ])
            ->all();
    }

    /**
     * @param array<int, string> $replacement
     * @return array{name:string,display_name:string,group:string,description:?string,risk:string,deprecated:bool,replacement:array<int,string>,deprecation_reason:?string}
     */
    private static function definition(
        PermissionName $name,
        string $displayName,
        string $group,
        string $risk,
        ?string $description = null,
        bool $deprecated = false,
        array $replacement = [],
        ?string $deprecationReason = null,
    ): array {
        return [
            'name' => $name->value,
            'display_name' => $displayName,
            'group' => $group,
            'description' => $description,
            'risk' => $risk,
            'deprecated' => $deprecated,
            'replacement' => $replacement,
            'deprecation_reason' => $deprecationReason,
        ];
    }
}
