<?php

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

class UserMorph_Switcher
{

    public function __construct()
    {
        add_action('init', array($this, 'handle_switch_request'));
        add_action('init', array($this, 'handle_switch_back_request'));
        add_action('init', array($this, 'handle_switch_off_request'));
    }

    /**
     * Handle request to switch to another user
     */
    public function handle_switch_request()
    {
        if (!isset($_GET['usermorph_action']) || 'switch_to' !== $_GET['usermorph_action']) {
            return;
        }

        if (!isset($_GET['user_id']) || !isset($_GET['_wpnonce'])) {
            return;
        }

        $user_id = intval($_GET['user_id']);
        $nonce = sanitize_text_field(wp_unslash($_GET['_wpnonce']));

        if (!wp_verify_nonce($nonce, 'usermorph_switch_to_' . $user_id)) {
            wp_die('Security check failed.');
        }

        if (!current_user_can('edit_users')) {
            wp_die('You do not have permission to switch users.');
        }

        $this->switch_user($user_id);
    }

    /**
     * Handle request to switch back to original user
     */
    public function handle_switch_back_request()
    {
        if (!isset($_GET['usermorph_action']) || 'switch_back' !== $_GET['usermorph_action']) {
            return;
        }

        $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';

        if (!wp_verify_nonce($nonce, 'usermorph_switch_back')) {
            wp_die('Security check failed.');
        }

        $this->switch_back();
    }

    /**
     * Handle request to switch off (logout temporarily)
     */
    public function handle_switch_off_request()
    {
        if (!isset($_GET['usermorph_action']) || 'switch_off' !== $_GET['usermorph_action']) {
            return;
        }

        $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';

        if (!wp_verify_nonce($nonce, 'usermorph_switch_off')) {
            wp_die('Security check failed.');
        }

        $this->switch_off();
    }

    /**
     * Perform the switch
     */
    private function switch_user($user_id)
    {
        $current_user_id = get_current_user_id();

        // If we are already switched (or switched off), don't overwrite the original admin cookie provided it exists
        if (!isset($_COOKIE['usermorph_original_user']) && $current_user_id) {
            $this->set_original_user_cookie($current_user_id);
        }

        wp_set_auth_cookie($user_id);

        // Redirect to dashboard or homepage
        wp_safe_redirect(admin_url());
        exit;
    }

    /**
     * Switch back to the original user
     */
    private function switch_back()
    {
        if (!isset($_COOKIE['usermorph_original_user']) || !isset($_COOKIE['usermorph_original_token'])) {
            wp_die('Could not find original user.');
        }

        $original_user = sanitize_text_field(wp_unslash($_COOKIE['usermorph_original_user']));
        $token = sanitize_text_field(wp_unslash($_COOKIE['usermorph_original_token']));

        $original_user_id = intval($original_user);

        if (!$this->verify_token($original_user_id, $token)) {
            wp_die('Security token mismatch.');
        }

        // Clear cookies
        $this->clear_original_user_cookie();

        wp_set_auth_cookie($original_user_id);

        wp_safe_redirect(admin_url('users.php'));
        exit;
    }

    /**
     * Switch off (logout but keep original user cookie)
     */
    private function switch_off()
    {
        $current_user_id = get_current_user_id();

        if (!isset($_COOKIE['usermorph_original_user']) && $current_user_id) {
            $this->set_original_user_cookie($current_user_id);
        } else if (isset($_COOKIE['usermorph_original_user'])) {
            // Refresh cookie timestamp if already set
            $original_user = sanitize_text_field(wp_unslash($_COOKIE['usermorph_original_user']));
            $this->set_original_user_cookie($original_user);
        }

        wp_logout();

        // Redirect to login page
        wp_safe_redirect(wp_login_url());
        exit;
    }

    private function set_original_user_cookie($user_id)
    {
        $token = $this->generate_token($user_id);
        setcookie('usermorph_original_user', $user_id, time() + 3600 * 48, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
        setcookie('usermorph_original_token', $token, time() + 3600 * 48, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
    }

    private function clear_original_user_cookie()
    {
        setcookie('usermorph_original_user', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
        setcookie('usermorph_original_token', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
    }

    /**
     * Simple token generation
     */
    private function generate_token($user_id)
    {
        return hash_hmac('sha256', $user_id . 'usermorph_salt', wp_salt());
    }

    private function verify_token($user_id, $token)
    {
        return hash_equals($this->generate_token($user_id), $token);
    }
}

new UserMorph_Switcher();
