<?php

namespace WPUltimateSecurity\UltimateSecurity\Infrastructure\Security;

/**
 * Plugin Capabilities
 *
 * Defines granular capabilities for the Ultimate Security plugin.
 * Provides fine-grained access control beyond the basic `manage_options` capability.
 *
 * Usage:
 * ```php
 * // Check if user can view dashboard
 * if (Capabilities::currentUserCan(Capabilities::VIEW_DASHBOARD)) {
 *     // Show dashboard
 * }
 *
 * // In REST API permission callback
 * 'permission_callback' => [Capabilities::class, 'canManage2FA'],
 * ```
 *
 * @package WPUltimateSecurity\UltimateSecurity\Infrastructure\Security
 * @since 2.0.0
 */
class Capabilities
{
    /**
     * Capability: View the security dashboard.
     */
    public const VIEW_DASHBOARD = 'ultimate_security_view_dashboard';

    /**
     * Capability: Manage two-factor authentication settings.
     */
    public const MANAGE_2FA = 'ultimate_security_manage_2fa';

    /**
     * Capability: Manage login security settings.
     */
    public const MANAGE_LOGIN = 'ultimate_security_manage_login';

    /**
     * Capability: View security logs and activity.
     */
    public const VIEW_LOGS = 'ultimate_security_view_logs';

    /**
     * Capability: Manage general plugin settings.
     */
    public const MANAGE_SETTINGS = 'ultimate_security_manage_settings';

    /**
     * Capability: Manage security hardening settings.
     */
    public const MANAGE_HARDENING = 'ultimate_security_manage_hardening';

    /**
     * Capability: Manage protection features (rate limiting, CAPTCHA).
     */
    public const MANAGE_PROTECTION = 'ultimate_security_manage_protection';

    /**
     * Capability: Manage maintenance features (updates, cleanup).
     */
    public const MANAGE_MAINTENANCE = 'ultimate_security_manage_maintenance';

    /**
     * Capability: Run security scans.
     */
    public const RUN_SCANS = 'ultimate_security_run_scans';

    /**
     * Capability: Export/import settings.
     */
    public const EXPORT_IMPORT = 'ultimate_security_export_import';

    /**
     * All plugin capabilities.
     *
     * @var array<string>
     */
    private static array $capabilities = [
        self::VIEW_DASHBOARD,
        self::MANAGE_2FA,
        self::MANAGE_LOGIN,
        self::VIEW_LOGS,
        self::MANAGE_SETTINGS,
        self::MANAGE_HARDENING,
        self::MANAGE_PROTECTION,
        self::MANAGE_MAINTENANCE,
        self::RUN_SCANS,
        self::EXPORT_IMPORT,
    ];

    /**
     * Capability groups for role assignment.
     *
     * @var array<string, array<string>>
     */
    private static array $capabilityGroups = [
        'administrator' => [
            self::VIEW_DASHBOARD,
            self::MANAGE_2FA,
            self::MANAGE_LOGIN,
            self::VIEW_LOGS,
            self::MANAGE_SETTINGS,
            self::MANAGE_HARDENING,
            self::MANAGE_PROTECTION,
            self::MANAGE_MAINTENANCE,
            self::RUN_SCANS,
            self::EXPORT_IMPORT,
        ],
        'security_manager' => [
            self::VIEW_DASHBOARD,
            self::MANAGE_2FA,
            self::MANAGE_LOGIN,
            self::VIEW_LOGS,
            self::MANAGE_HARDENING,
            self::MANAGE_PROTECTION,
            self::RUN_SCANS,
        ],
        'viewer' => [
            self::VIEW_DASHBOARD,
            self::VIEW_LOGS,
        ],
    ];

    /**
     * Install capabilities for the administrator role.
     *
     * @return void
     */
    public static function install(): void
    {
        $role = get_role('administrator');

        if ($role === null) {
            return;
        }

        foreach (self::$capabilities as $capability) {
            $role->add_cap($capability);
        }

        // Fire action for custom role setups
        do_action('ultimate_security_capabilities_installed', self::$capabilities);
    }

    /**
     * Remove all plugin capabilities.
     *
     * @return void
     */
    public static function uninstall(): void
    {
        $role = get_role('administrator');

        if ($role === null) {
            return;
        }

        foreach (self::$capabilities as $capability) {
            $role->remove_cap($capability);
        }

        // Fire action for cleanup
        do_action('ultimate_security_capabilities_uninstalled', self::$capabilities);
    }

    /**
     * Check if the current user has a capability.
     *
     * Falls back to `manage_options` for backward compatibility.
     *
     * @param string $capability The capability to check.
     *
     * @return bool
     */
    public static function currentUserCan(string $capability): bool
    {
        // First check the specific capability
        if (current_user_can($capability)) {
            return true;
        }

        // Fall back to manage_options for backward compatibility
        return current_user_can('manage_options');
    }

    /**
     * Check if a user has a capability.
     *
     * @param int    $userId     The user ID.
     * @param string $capability The capability to check.
     *
     * @return bool
     */
    public static function userCan(int $userId, string $capability): bool
    {
        if (user_can($userId, $capability)) {
            return true;
        }

        return user_can($userId, 'manage_options');
    }

    /**
     * Permission callback for viewing the dashboard.
     *
     * @return bool
     */
    public static function canViewDashboard(): bool
    {
        return self::currentUserCan(self::VIEW_DASHBOARD);
    }

    /**
     * Permission callback for managing 2FA.
     *
     * @return bool
     */
    public static function canManage2FA(): bool
    {
        return self::currentUserCan(self::MANAGE_2FA);
    }

    /**
     * Permission callback for managing login security.
     *
     * @return bool
     */
    public static function canManageLogin(): bool
    {
        return self::currentUserCan(self::MANAGE_LOGIN);
    }

    /**
     * Permission callback for viewing logs.
     *
     * @return bool
     */
    public static function canViewLogs(): bool
    {
        return self::currentUserCan(self::VIEW_LOGS);
    }

    /**
     * Permission callback for managing settings.
     *
     * @return bool
     */
    public static function canManageSettings(): bool
    {
        return self::currentUserCan(self::MANAGE_SETTINGS);
    }

    /**
     * Permission callback for managing hardening.
     *
     * @return bool
     */
    public static function canManageHardening(): bool
    {
        return self::currentUserCan(self::MANAGE_HARDENING);
    }

    /**
     * Permission callback for managing protection.
     *
     * @return bool
     */
    public static function canManageProtection(): bool
    {
        return self::currentUserCan(self::MANAGE_PROTECTION);
    }

    /**
     * Permission callback for managing maintenance.
     *
     * @return bool
     */
    public static function canManageMaintenance(): bool
    {
        return self::currentUserCan(self::MANAGE_MAINTENANCE);
    }

    /**
     * Permission callback for running scans.
     *
     * @return bool
     */
    public static function canRunScans(): bool
    {
        return self::currentUserCan(self::RUN_SCANS);
    }

    /**
     * Permission callback for export/import.
     *
     * @return bool
     */
    public static function canExportImport(): bool
    {
        return self::currentUserCan(self::EXPORT_IMPORT);
    }

    /**
     * Get all plugin capabilities.
     *
     * @return array<string>
     */
    public static function getCapabilities(): array
    {
        return self::$capabilities;
    }

    /**
     * Get capability groups.
     *
     * @return array<string, array<string>>
     */
    public static function getCapabilityGroups(): array
    {
        return self::$capabilityGroups;
    }

    /**
     * Assign a capability group to a role.
     *
     * @param string $roleName The WordPress role name.
     * @param string $group    The capability group name.
     *
     * @return bool True on success.
     */
    public static function assignGroupToRole(string $roleName, string $group): bool
    {
        $role = get_role($roleName);

        if ($role === null || !isset(self::$capabilityGroups[$group])) {
            return false;
        }

        foreach (self::$capabilityGroups[$group] as $capability) {
            $role->add_cap($capability);
        }

        return true;
    }

    /**
     * Create a permission callback for REST API routes.
     *
     * @param string $capability The required capability.
     *
     * @return callable
     */
    public static function requireCapability(string $capability): callable
    {
        return function () use ($capability) {
            return self::currentUserCan($capability);
        };
    }
}
