<?php
/**
 * Name: Username Changer
 * Description: Allow users to change their username from profile page without admin intervention for sites where username updates should be self-service capability
 * Category: User Management
 * Icon: -
 * UseCases: [
 *   {
 *     "title": "Fix Username Mistakes",
 *     "description": "Let users or admins change usernames after registration to fix typos or unprofessional choices without creating new accounts."
 *   },
 *   {
 *     "title": "Rebranding User Accounts",
 *     "description": "Update usernames to match new branding or naming conventions on membership sites with hundreds of users."
 *   },
 *   {
 *     "title": "Professional Name Changes",
 *     "description": "Allow users to update their username after marriage, business name change, or other life events without losing post history."
 *   }
 * ]
 * Added: 2025-09-26
 * Tags: username, user, profile, change, edit, account
 * WhereToFind: {
 *   "location": "User Profile",
 *   "url": "profile.php",
 *   "instructions": "Username change field appears in profile editor",
 *   "newTab": false
 * }
 */

// Prevent direct access
if (!defined('ABSPATH')) exit;

class SwitchboardUsernameChanger {
    
    public function __construct() {
        add_action('show_user_profile', [$this, 'add_username_field']);
        add_action('edit_user_profile', [$this, 'add_username_field']);
        add_action('personal_options_update', [$this, 'save_username']);
        add_action('edit_user_profile_update', [$this, 'save_username']);
        
        // Register with data registry
        $this->register_with_data_registry();
    }
    
    private function register_with_data_registry() {
        if (class_exists('Switchboard_Data_Registry')) {
            $registry = Switchboard_Data_Registry::get_instance();
            $registry->auto_register($this, __FILE__);
        }
    }
    
    public function register_data_locations() {
        return [
            'options' => [],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [],
            'user_meta' => [],
            'term_meta' => [],
            'transients' => []
        ];
    }

    public function add_username_field($user) {
        if (!current_user_can('edit_users') && get_current_user_id() !== $user->ID) {
            return;
        }
        ?>
        <h3><?php esc_html_e('Change Username', 'wpswitchboard'); ?> <span class="switchboard-badge">SWITCHBOARD</span></h3>
        <table class="form-table">
            <tr>
                <th><label for="new_username"><?php esc_html_e('New Username', 'wpswitchboard'); ?></label></th>
                <td>
                    <p class="description" style="margin-bottom: 8px;">
                        <?php
                        /* translators: %s: current username */
                        printf(esc_html__('Current username: %s', 'wpswitchboard'), '<code>' . esc_html($user->user_login) . '</code>');
                        ?>
                    </p>
                    <input type="text" name="new_username" id="new_username" value="" class="sb-sp-input" placeholder="<?php esc_attr_e('Enter new username...', 'wpswitchboard'); ?>" />
                    <p class="description"><?php esc_html_e('Leave empty to keep current username. Must be unique if changing.', 'wpswitchboard'); ?></p>
                    <?php wp_nonce_field('change_username_' . $user->ID, 'username_nonce'); ?>
                </td>
            </tr>
        </table>
        <?php
    }
    
    public function save_username($user_id) {
        if (!current_user_can('edit_user', $user_id)) {
            return;
        }

        // Verify nonce for CSRF protection
        if (!isset($_POST['username_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['username_nonce'])), 'change_username_' . $user_id)) {
            return;
        }

        if (empty($_POST['new_username'])) {
            return;
        }

        $new_username = sanitize_user(wp_unslash($_POST['new_username']));
        $user = get_user_by('id', $user_id);

        if ($new_username === $user->user_login) {
            return;
        }

        if (username_exists($new_username)) {
            add_action('admin_notices', function() {
                echo '<div class="notice notice-error is-dismissible"><p>' . esc_html__('Username already exists!', 'wpswitchboard') . '</p></div>';
            });
            return;
        }

        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- No WP API for changing user_login
        $result = $wpdb->update(
            $wpdb->users,
            ['user_login' => $new_username],
            ['ID' => $user_id]
        );

        if ($result !== false) {
            add_action('admin_notices', function() use ($new_username) {
                /* translators: %s: new username */
                echo '<div class="notice notice-success is-dismissible"><p>' . sprintf(esc_html__('Username updated successfully to: %s', 'wpswitchboard'), '<strong>' . esc_html($new_username) . '</strong>') . '</p></div>';
            });
        } else {
            add_action('admin_notices', function() {
                echo '<div class="notice notice-error is-dismissible"><p>' . esc_html__('Failed to update username. Please try again.', 'wpswitchboard') . '</p></div>';
            });
        }
    }
}

// Initialize and register with data system
$switchboard_instance = new SwitchboardUsernameChanger();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);