<?php

/**
 * LoginAsUser Frontend Bar
 *
 * Renders a notification bar on the frontend and a toolbar link in the
 * admin bar when an admin is impersonating a customer.
 *
 * @package ArraySubs\Features\LoginAsUser\Services
 * @since 1.0.0
 */

namespace ArraySubs\Features\LoginAsUser\Services;

defined('ABSPATH') || exit;

use ArraySubs\Supports\Config;

/**
 * Frontend impersonation bar.
 */
class FrontendBar
{
    /**
     * Enable auto-loading.
     *
     * @var bool
     */
    public static $loadable = true;

    /**
     * Track whether the bar has already rendered for this request.
     *
     * @var bool
     */
    private bool $bar_rendered = false;

    /**
     * Constructor.
     */
    public function __construct()
    {
        // Frontend hooks.
        add_action('wp_enqueue_scripts', [$this, 'enqueueStyles']);
        add_action('wp_body_open', [$this, 'renderBar'], 1);
        add_action('wp_footer', [$this, 'renderBar'], 1);

        // Admin hooks (bar should also show when impersonating in wp-admin).
        add_action('admin_enqueue_scripts', [$this, 'enqueueStyles']);
        add_action('admin_footer', [$this, 'renderBar'], 1);

        // Toolbar link works on both frontend and admin.
        add_action('admin_bar_menu', [$this, 'addToolbarLink'], 999);
    }

    /**
     * Enqueue public styles when impersonating.
     *
     * @return void
     */
    public function enqueueStyles(): void
    {
        $old_user = Impersonator::getOldUser();

        if (!$old_user instanceof \WP_User) {
            return;
        }

        $asset_file = Config::get('plugin.public_path') . 'build/login-as-user-frontend.asset.php';
        $asset_version = file_exists($asset_file)
            ? (require $asset_file)['version'] ?? ARRAYSUBS_VERSION
            : ARRAYSUBS_VERSION;

        wp_enqueue_style(
            'arraysubs-login-as-user-frontend',
            Config::get('plugin.public_url') . 'build/login-as-user-frontend.css',
            [],
            $asset_version
        );

        wp_register_style('arraysubs-login-as-user-inline', false);
        wp_enqueue_style('arraysubs-login-as-user-inline');

        $this->addInlineBarStyles();
    }

    /**
     * Add inline CSS adjustments for body offset and bar positioning.
     *
     * @return void
     */
    private function addInlineBarStyles(): void
    {
        if (is_admin_bar_showing()) {
            $css = 'body { margin-top: 60px !important; padding-top: 70px !important; }'
                . '.arraysubs-login-as-user-bar { top: 32px !important; }'
                . '@media only screen and (max-width: 782px) { .arraysubs-login-as-user-bar { top: 46px !important; } }';
        } else {
            $css = 'body { padding-top: 70px !important; }'
                . '@media only screen and (max-width: 420px) { body { padding-top: 120px !important; } }';
        }

        wp_add_inline_style('arraysubs-login-as-user-inline', $css);
    }

    /**
     * Render the impersonation notification bar in the footer.
     *
     * @return void
     */
    public function renderBar(): void
    {
        if ($this->bar_rendered) {
            return;
        }

        $old_user = Impersonator::getOldUser();

        if (!$old_user instanceof \WP_User) {
            return;
        }

        $this->bar_rendered = true;

        $back_url = Impersonator::buildBackUrl($old_user);

        $current_user = wp_get_current_user();
        $current_name = '';

        if ($current_user && $current_user->display_name) {
            $current_name = sprintf(
                /* translators: 1: display name 2: login name */
                __('%1$s (%2$s)', 'arraysubs'),
                $current_user->display_name,
                $current_user->user_login
            );
        }

        $back_label = sprintf(
            /* translators: 1: admin display name 2: admin email */
            __('Go back as %1$s (%2$s)', 'arraysubs'),
            $old_user->display_name,
            $old_user->user_email
        );
?>
        <div class="arraysubs-login-as-user-bar arraysubs-login-as-user-bar--top">
            <div class="arraysubs-login-as-user-bar__inner">
                <div class="arraysubs-login-as-user-bar__content">
                    <span class="arraysubs-login-as-user-bar__message">
                        <?php
                        printf(
                            /* translators: %s: current impersonated user name */
                            esc_html__('You are logged in as %s', 'arraysubs'),
                            '<strong>' . esc_html($current_name) . '</strong>'
                        );
                        ?>
                    </span>
                    <a class="arraysubs-login-as-user-bar__back-btn" href="<?php echo esc_url($back_url); ?>">
                        <?php echo esc_html($back_label); ?>
                    </a>
                </div>
            </div>
        </div>
<?php
    }

    /**
     * Add a "Go back to admin" link in the WordPress admin toolbar.
     *
     * @param \WP_Admin_Bar $wp_admin_bar Admin bar instance.
     * @return void
     */
    public function addToolbarLink($wp_admin_bar): void
    {
        if (!is_admin_bar_showing()) {
            return;
        }

        $old_user = Impersonator::getOldUser();

        if (!$old_user instanceof \WP_User) {
            return;
        }

        $back_url = Impersonator::buildBackUrl($old_user);

        $wp_admin_bar->add_node([
            'id' => 'arraysubs-login-as-user-back',
            'title' => sprintf(
                /* translators: %s: admin display name */
                __('Go back as %s', 'arraysubs'),
                $old_user->display_name
            ),
            'href' => esc_url($back_url),
            'meta' => [
                'class' => 'arraysubs-login-as-user-toolbar',
                'title' => sprintf(
                    /* translators: %s: admin display name */
                    __('End impersonation and return as %s', 'arraysubs'),
                    $old_user->display_name
                ),
            ],
        ]);
    }
}
