<?php
/**
 * Name: View Admin as Role
 * Description: View WordPress admin interface as any user role for testing permissions, menu visibility, and UI elements without switching accounts or logging out temporarily
 * Category: User Management
 * Icon: -
  * UseCases: [
 *   {
 *     "title": "Test User Experience",
 *     "description": "Switch between different role views to see exactly what each user type sees without creating test accounts."
 *   },
 *   {
 *     "title": "Debug Permissions",
 *     "description": "Quickly identify permission issues by viewing the admin as different roles to see what\'s missing or broken."
 *   }
 * ]
 * Added: 2025-09-10
 * Tags: testing, roles, permissions, capabilities, admin, development
 * WhereToFind: {
 *   "location": "Admin Bar (top)",
 *   "url": "",
 *   "instructions": "Click 'View as Role' in admin bar to switch perspective",
 *   "newTab": false
 * }
 *
 * @package Switchboard
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

class SwitchboardViewAdminAsRole {
    
    private $option_name = 'switchboard_view_as_role';
    private $session_key = 'switchboard_simulated_role';
    private $filtering = false; // Prevent infinite loops
    
    public function __construct() {
        // Handle role switching - use admin_init for admin pages, init for frontend
        add_action('admin_init', [$this, 'handle_role_switch'], 1);
        add_action('init', [$this, 'handle_role_switch'], 999);
        
        // Filter capabilities when simulating
        add_filter('user_has_cap', [$this, 'filter_capabilities'], 10, 4);
        
        // Admin bar menu
        add_action('admin_bar_menu', [$this, 'add_admin_bar_menu'], 100);
        
        // Add styles
        add_action('admin_enqueue_scripts', [$this, 'enqueue_styles']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_styles']);
        
        // AJAX handler for role switching
        add_action('wp_ajax_switchboard_switch_role', [$this, 'ajax_switch_role']);
    }
    
    /**
     * Check if user can view as role
     */
    private function can_view_as_role() {
        // Prevent infinite loop by checking directly
        $user = wp_get_current_user();
        if (!$user || !$user->exists()) {
            return false;
        }
        
        // Check if user has administrator role directly
        return in_array('administrator', (array) $user->roles);
    }
    
    /**
     * Get simulated role
     */
    private function get_simulated_role() {
        $user_id = get_current_user_id();
        if (!$user_id) {
            return false;
        }
        
        // Use user meta instead of sessions for reliability
        $role = get_user_meta($user_id, $this->session_key, true);
        return $role ? $role : false;
    }
    
    /**
     * Set simulated role
     */
    private function set_simulated_role($role) {
        $user_id = get_current_user_id();
        if (!$user_id) {
            return;
        }
        
        if ($role) {
            update_user_meta($user_id, $this->session_key, $role);
        } else {
            delete_user_meta($user_id, $this->session_key);
        }
    }
    
    /**
     * Add admin bar menu
     */
    public function add_admin_bar_menu($wp_admin_bar) {
        if (!$this->can_view_as_role()) {
            return;
        }
        
        $simulated_role = $this->get_simulated_role();
        
        $current_user = wp_get_current_user();

        // Main menu item - use dashicon for better compatibility
        $title = $simulated_role
            ? sprintf(esc_html__('Viewing as: %s', 'wpswitchboard'), ucfirst($simulated_role))
            : esc_html__('View as Role', 'wpswitchboard');
        
        $wp_admin_bar->add_node([
            'id'    => 'view-as-role',
            'title' => '<span class="ab-icon dashicons dashicons-visibility"></span><span class="ab-label">' . $title . '</span>',
            'href'  => '#',
            'meta'  => [
                'class' => $simulated_role ? 'switchboard-viewing-as-active' : '',
            ],
        ]);
        
        // Get all roles
        $roles = wp_roles()->roles;
        
        // Add role options
        foreach ($roles as $role_slug => $role_data) {
            // Skip current user's actual role to avoid confusion
            if (in_array($role_slug, $current_user->roles)) {
                continue;
            }
            
            $is_active = ($simulated_role === $role_slug);
            
            $switch_url = wp_nonce_url(
                add_query_arg('switchboard_view_as', $role_slug),
                'switchboard_view_as_role'
            );
            
            $wp_admin_bar->add_node([
                'parent' => 'view-as-role',
                'id'     => 'view-as-' . $role_slug,
                'title'  => ($is_active ? '[Active] ' : '') . $role_data['name'],
                'href'   => $switch_url,
                'meta'   => [
                    'class' => $is_active ? 'switchboard-active-role' : '',
                ],
            ]);
        }
        
        // Add "Reset to Normal" option if currently simulating
        if ($simulated_role) {
            $wp_admin_bar->add_node([
                'parent' => 'view-as-role',
                'id'     => 'view-as-reset',
                'title'  => '<strong>' . esc_html__('Reset to Normal View', 'wpswitchboard') . '</strong>',
                'href'   => wp_nonce_url(
                    add_query_arg('switchboard_view_as', 'reset'),
                    'switchboard_view_as_role'
                ),
                'meta'   => [
                    'class' => 'switchboard-reset-role',
                ],
            ]);
        }
    }
    
    /**
     * Handle role switching
     */
    public function handle_role_switch() {
        if (!$this->can_view_as_role()) {
            return;
        }
        
        if (!isset($_GET['switchboard_view_as']) || !isset($_GET['_wpnonce'])) {
            return;
        }
        
        if (!wp_verify_nonce($_GET['_wpnonce'], 'switchboard_view_as_role')) {
            wp_die(esc_html__('Security check failed', 'wpswitchboard'));
        }
        
        $role = sanitize_key($_GET['switchboard_view_as']);
        
        if ($role === 'reset') {
            $this->set_simulated_role(false);
            $redirect_url = remove_query_arg(['switchboard_view_as', '_wpnonce']);
            wp_safe_redirect($redirect_url);
            exit;
        }
        
        // Verify role exists
        $roles = wp_roles()->roles;
        if (!isset($roles[$role])) {
            wp_die(sprintf(esc_html__('Invalid role: %s', 'wpswitchboard'), esc_html($role)));
        }
        
        $this->set_simulated_role($role);
        
        // Redirect to admin dashboard or current page
        $redirect_url = remove_query_arg(['switchboard_view_as', '_wpnonce']);
        
        // If we're on the Switchboard settings page, redirect to dashboard for clearer view
        if (strpos($redirect_url, 'page=switchboard') !== false) {
            $redirect_url = admin_url();
        }
        
        wp_safe_redirect($redirect_url);
        exit;
    }
    
    /**
     * Filter user capabilities when simulating
     */
    public function filter_capabilities($allcaps, $caps, $args, $user) {
        // Prevent infinite recursion
        if ($this->filtering) {
            return $allcaps;
        }
        
        $this->filtering = true;
        
        // Only filter for current user and only if they're an admin
        $current_user = wp_get_current_user();
        if (!$current_user || !$current_user->exists() || $user->ID !== $current_user->ID) {
            $this->filtering = false;
            return $allcaps;
        }
        
        // Check if user is administrator directly (without using current_user_can)
        if (!in_array('administrator', (array) $current_user->roles)) {
            $this->filtering = false;
            return $allcaps;
        }
        
        $simulated_role = $this->get_simulated_role();
        
        if (!$simulated_role) {
            $this->filtering = false;
            return $allcaps;
        }
        
        // Get capabilities for simulated role
        $role_obj = get_role($simulated_role);
        
        if (!$role_obj) {
            $this->filtering = false;
            return $allcaps;
        }
        
        // Replace capabilities with simulated role's capabilities
        // But keep some critical capabilities to prevent lockout
        $critical_caps = [
            'read' => true, // Basic read access
        ];
        
        $this->filtering = false;
        return array_merge($critical_caps, $role_obj->capabilities);
    }
    
    /**
     * AJAX handler for role switching
     */
    public function ajax_switch_role() {
        check_ajax_referer('switchboard_view_as_role', 'nonce');

        if (!$this->can_view_as_role()) {
            wp_send_json_error(esc_html__('Insufficient permissions', 'wpswitchboard'));
        }

        $role = isset($_POST['role']) ? sanitize_key($_POST['role']) : '';

        if ($role === 'reset') {
            $this->set_simulated_role(false);
            wp_send_json_success(['message' => esc_html__('Reset to normal view', 'wpswitchboard')]);
        }

        // Verify role exists
        $roles = wp_roles()->roles;
        if (!isset($roles[$role])) {
            wp_send_json_error(esc_html__('Invalid role', 'wpswitchboard'));
        }

        $this->set_simulated_role($role);
        wp_send_json_success(['message' => sprintf(esc_html__('Now viewing as: %s', 'wpswitchboard'), $roles[$role]['name'])]);
    }
    
    /**
     * Enqueue styles
     */
    public function enqueue_styles() {
        if (!$this->can_view_as_role()) {
            return;
        }
        
        $simulated_role = $this->get_simulated_role();
        
        if (!$simulated_role) {
            return;
        }
        
        // Add visual indicator bar with close button
        $reset_url = wp_nonce_url(
            add_query_arg('switchboard_view_as', 'reset'),
            'switchboard_view_as_role'
        );

        // Add the bar HTML and styles
        add_action('admin_footer', function() use ($simulated_role, $reset_url) {
            ?>
            <div id="switchboard-role-bar" style="position: fixed; top: 32px; left: 0; right: 0; background: #d63638; color: #fff; text-align: center; padding: 8px 50px; font-weight: 600; z-index: 99998; font-size: 12px; letter-spacing: 1px; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">
                <?php echo sprintf(esc_html__('VIEWING AS: %s', 'wpswitchboard'), strtoupper($simulated_role)); ?>
                <a href="<?php echo esc_url($reset_url); ?>" style="position: absolute; right: 15px; top: 50%; transform: translateY(-50%); color: #fff; text-decoration: none; font-size: 20px; line-height: 1; opacity: 0.8; transition: opacity 0.2s;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.8'" title="<?php esc_attr_e('Reset to normal view', 'wpswitchboard'); ?>">×</a>
            </div>
            <style>
                body.admin-bar {
                    margin-top: 48px !important;
                }
                @media screen and (max-width: 782px) {
                    #switchboard-role-bar {
                        top: 46px !important;
                    }
                }
            </style>
            <?php
        }, 999);

        add_action('wp_footer', function() use ($simulated_role, $reset_url) {
            ?>
            <div id="switchboard-role-bar" style="position: fixed; top: 32px; left: 0; right: 0; background: #d63638; color: #fff; text-align: center; padding: 8px 50px; font-weight: 600; z-index: 99998; font-size: 12px; letter-spacing: 1px; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">
                <?php echo sprintf(esc_html__('VIEWING AS: %s', 'wpswitchboard'), strtoupper($simulated_role)); ?>
                <a href="<?php echo esc_url($reset_url); ?>" style="position: absolute; right: 15px; top: 50%; transform: translateY(-50%); color: #fff; text-decoration: none; font-size: 20px; line-height: 1; opacity: 0.8; transition: opacity 0.2s;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.8'" title="<?php esc_attr_e('Reset to normal view', 'wpswitchboard'); ?>">×</a>
            </div>
            <style>
                body.admin-bar {
                    margin-top: 48px !important;
                }
                @media screen and (max-width: 782px) {
                    #switchboard-role-bar {
                        top: 46px !important;
                    }
                }
            </style>
            <?php
        }, 999);

        $custom_css = "
            #wpadminbar #wp-admin-bar-view-as-role.switchboard-viewing-as-active > .ab-item {
                background-color: #d63638 !important;
                color: #fff !important;
            }
            #wpadminbar #wp-admin-bar-view-as-role .switchboard-active-role > .ab-item {
                font-weight: 600;
            }
            #wpadminbar #wp-admin-bar-view-as-role .switchboard-reset-role > .ab-item {
                color: #d63638;
            }
        ";

        wp_add_inline_style('admin-bar', $custom_css);
    }

    /**
     * Register data locations for cleanup system
     */
    public function register_data_locations() {
        return [
            'options' => [],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [],
            'user_meta' => [
                'switchboard_simulated_role',
            ],
        ];
    }

    /**
     * Render settings panel for View Admin as Role
     * 
     * Displays comprehensive informational UI explaining how to use the module with:
     * - Step-by-step usage instructions (access menu, select role, visual confirmation, reset)
     * - "Perfect For" section with use cases (testing permissions, verifying UI, demos)
     * - Important notes section with warnings and reminders
     * - Current status indicator showing module is active
     * 
     * This is a configuration-free module (no user settings to save). It automatically
     * adds a "View as Role" menu to the WordPress admin bar that allows administrators
     * to temporarily view the admin interface as any user role for testing purposes.
     * 
     * The module works by:
     * - Adding admin bar menu with all available roles (admin_bar_menu hook)
     * - Storing selected role in user meta (switchboard_simulated_role)
     * - Filtering capabilities via user_has_cap to simulate role permissions
     * - Displaying prominent red banner when viewing as another role
     * - Providing "Reset to Normal View" option to exit simulation
     * 
     * Security features:
     * - Only users with manage_options capability can use this feature
     * - Simulation only affects frontend/admin visibility, not actual permissions
     * - Session stored in user meta, cleared on reset or logout
     * - Nonce verification for role switching requests
     * 
     * The settings panel serves as an informational guide to help users understand
     * how to access and use the feature, what it's useful for, and important caveats
     * about the simulation being visual only.
     * 
     * @param array $settings Current module settings (unused - no settings to save)
     * @return void Outputs HTML directly
     */
    public function render_settings($settings = []) {
        ?>
        <input type="hidden" name="module" value="view-admin-as-role">

        <div class="sb-sp-info-box sb-sp-info-box-info" style="margin-bottom: 24px;">
            <h4 class="sb-sp-heading-sm">How It Works</h4>
            <p class="sb-sp-description" style="margin: 0;">View the WordPress admin interface as any user role for testing permissions, menu visibility, and UI elements without switching accounts or logging out. This is a visual simulation tool - you remain logged in as yourself.</p>
        </div>

        <div class="sb-sp-group" style="margin-bottom: 24px;">
            <h3 class="sb-sp-heading">How to Use</h3>
            <ol class="sb-sp-list" style="margin: 0; padding-left: 20px;">
                <li class="sb-sp-list-item"><strong><?php esc_html_e('Access the Menu:', 'wpswitchboard'); ?></strong> <?php esc_html_e('Look for "View as Role" in the admin bar (top left)', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><strong><?php esc_html_e('Select a Role:', 'wpswitchboard'); ?></strong> <?php esc_html_e('Click any role name to switch to that view', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><strong><?php esc_html_e('Visual Confirmation:', 'wpswitchboard'); ?></strong> <?php esc_html_e('A red banner will appear showing which role you\'re viewing as', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><strong><?php esc_html_e('Reset:', 'wpswitchboard'); ?></strong> <?php esc_html_e('Click "Reset to Normal View" to return to your admin view', 'wpswitchboard'); ?></li>
            </ol>
        </div>

        <div class="sb-sp-info-box sb-sp-info-box-tip" style="margin-bottom: 24px;">
            <h4 class="sb-sp-heading-sm">Perfect For</h4>
            <ul class="sb-sp-list">
                <li class="sb-sp-list-item"><?php esc_html_e('Testing permissions and capabilities', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Seeing what different roles can access', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Verifying UI visibility for various user types', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Client demonstrations without creating test accounts', 'wpswitchboard'); ?></li>
            </ul>
        </div>

        <div class="sb-sp-info-box sb-sp-info-box-tip">
            <h4 class="sb-sp-heading-sm">Important Notes</h4>
            <ul class="sb-sp-list">
                <li class="sb-sp-list-item"><?php esc_html_e('This is a testing tool - you\'re still logged in as yourself', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('The simulation only affects what you see, not your actual permissions', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Always reset to normal view when done testing', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('A prominent red banner will remind you when viewing as another role', 'wpswitchboard'); ?></li>
            </ul>
        </div>

        <div class="sb-sp-info-box sb-sp-info-box-success" style="margin-top: 24px;">
            <p class="sb-sp-description" style="margin: 0;"><strong><?php esc_html_e('Current Status:', 'wpswitchboard'); ?></strong> <?php esc_html_e('Module is active and ready to use! No additional configuration needed. Just keep this module enabled and access it from the admin bar.', 'wpswitchboard'); ?></p>
        </div>
        <?php
    }
}

// Initialize
$switchboard_instance = new SwitchboardViewAdminAsRole();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);
