<?php
/**
 * TamRank PRO Feature Tour
 *
 * Cross-page guided tour that highlights PRO features after license activation.
 * Uses localStorage for step tracking and wp_option for permanent dismissal.
 *
 * @package TamRank
 * @since 8.3.0
 */

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

class TamRank_Tour {

    private static $instance = null;

    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function __construct() {
        add_action('admin_enqueue_scripts', array($this, 'maybe_enqueue'), 99);
        add_action('wp_ajax_tam_rank_tour_done', array($this, 'ajax_tour_done'));
        add_action('wp_ajax_tam_rank_tour_reset', array($this, 'ajax_tour_reset'));
    }

    /**
     * Decide which tour (if any) should run for the current user.
     *
     * - PRO tour: licensed user who has not finished the PRO tour. Highlights
     *   the unlocked PRO features. Triggered after licence activation.
     * - FREE tour: any user who has not finished the FREE tour. Walks through
     *   the FREE features. Triggered after the onboarding wizard.
     *
     * The legacy single `tam_rank_tour_done` flag counts as "both done" so
     * existing users who already completed the old combined tour see nothing.
     *
     * @return string|null 'pro' | 'free' | null
     */
    private function active_tour_type() {
        $legacy_done = get_option('tam_rank_tour_done') === '1';
        $licensed    = function_exists('tam_rank_license_active') && tam_rank_license_active();

        if ($licensed && !$legacy_done && get_option('tam_rank_tour_done_pro') !== '1') {
            return 'pro';
        }
        if (!$legacy_done && get_option('tam_rank_tour_done_free') !== '1') {
            return 'free';
        }
        return null;
    }

    /**
     * Enqueue tour assets for the active tour on a page where it can run.
     * PRO tour runs on TamRank admin pages; the FREE tour additionally runs on
     * the post editor (its meta-box step lives on post-new.php / post.php).
     */
    public function maybe_enqueue($hook) {
        $type = $this->active_tour_type();
        if (!$type) {
            return;
        }

        $pagenow         = isset($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
        $is_tamrank_page = strpos($hook, 'tam-rank') !== false;
        $is_editor       = in_array($pagenow, array('post-new.php', 'post.php'), true);

        // FREE tour step 2 highlights the meta-box on the editor screen; the PRO
        // tour only ever runs on TamRank admin pages.
        $allowed = $is_tamrank_page || ($type === 'free' && $is_editor);
        if (!$allowed) {
            return;
        }

        wp_enqueue_style(
            'tamrank-tour',
            TAM_RANK_PLUGIN_URL . 'assets/css/tamrank-tour.css',
            array('tamrank-admin-global', 'tamrank-variables-late'),
            TAM_RANK_VERSION
        );

        wp_enqueue_script(
            'tamrank-tour',
            TAM_RANK_PLUGIN_URL . 'assets/js/tamrank-tour.js',
            array('jquery'),
            TAM_RANK_VERSION,
            true
        );

        // FREE owns the engine and the FREE steps. The PRO add-on supplies its
        // own delta-only steps via this filter (it returns nothing when PRO is
        // not loaded, so a licensed-but-PRO-absent edge case simply shows no
        // tour rather than a broken one).
        $steps  = ($type === 'pro')
            ? apply_filters('tam_rank_tour_pro_steps', array())
            : $this->get_free_steps();
        $finish = ($type === 'pro')
            ? tamrank__('tour_pro_finish', 'Open my dashboard')
            : tamrank__('tour_free_finish', 'Get started');

        // Current screen: the ?page= slug on TamRank pages, else the editor file
        // (post-new.php / post.php) so the FREE editor step knows it has arrived.
        $current = isset($_GET['page']) && $_GET['page'] !== '' // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only screen detection; no state-changing action.
            ? sanitize_text_field(wp_unslash($_GET['page'])) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            : $pagenow;

        wp_localize_script('tamrank-tour', 'tamrankTour', array(
            'steps'       => $steps,
            'tourType'    => $type,
            'currentPage' => $current,
            'urls'        => array(
                'dashboard'    => admin_url('admin.php?page=tam-rank-dashboard'),
                'pagespeed'    => admin_url('admin.php?page=tam-rank-pagespeed'),
                'audit'        => admin_url('admin.php?page=tam-rank-audit'),
                'redirects'         => admin_url('admin.php?page=tam-rank-redirects'),
                'settings'          => admin_url('admin.php?page=tam-rank-settings'),
                // The site-identity step lands on the Global Settings tab; the
                // schema page opens that tab from ?tab= on its own.
                'schema'            => admin_url('admin.php?page=tam-rank-schema&tab=instellingen'),
                'gsc-pages'         => admin_url('admin.php?page=tam-rank-page-insights'),
                // PRO tour destinations (slug minus the tam-rank- prefix).
                'page-insights'     => admin_url('admin.php?page=tam-rank-page-insights'),
                'topical-authority' => admin_url('admin.php?page=tam-rank-topical-authority'),
                'post-new.php'      => admin_url('post-new.php'),
            ),
            'i18n' => array(
                'next'     => tamrank__('tour_next', 'Next'),
                'skip'     => tamrank__('tour_skip', 'Skip'),
                'finish'   => $finish,
                'step_of'  => tamrank__('tour_step_of', 'Step %1$s of %2$s'),
            ),
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce'   => wp_create_nonce('tam_rank_tour_nonce'),
        ));
    }

    /**
     * FREE onboarding tour — a welcome card plus 6 steps through the FREE
     * features. Shown after the onboarding wizard (see
     * Plugin/Tour-Split-FREE-Handback.md). No PRO mention; ends on the WebP
     * "gift" step with a calm "Get started" finish button.
     */
    private function get_free_steps() {
        $steps = $this->get_free_feature_steps();
        array_unshift($steps, $this->get_free_welcome_step(count($steps)));
        return $steps;
    }

    /**
     * The card the tour opens with: says this is a tour, how many steps follow
     * and offers to skip right there.
     *
     * Deliberately without a 'page', so it appears on whichever TamRank screen
     * the user lands on when the wizard arms the tour — the tour introduces
     * itself before it moves anyone to another screen. It is also 'uncounted':
     * it announces the numbered steps rather than being one of them, so the
     * number promised here matches the "Step 1 of 6" the user sees next.
     *
     * @param int $feature_count Number of numbered steps that follow.
     * @return array
     */
    private function get_free_welcome_step($feature_count) {
        $text = tamrank__(
            'tour_free_welcome_text',
            'This is a short tour of TamRank. In %1$s steps you see where your site stands, how you improve a page, and what TamRank sorts out for you in the background. Rather look around on your own? Skip the tour.'
        );

        return array(
            'type'      => 'card',
            'uncounted' => true,
            'title'     => tamrank__('tour_free_welcome_title', 'Welcome to your tour of TamRank'),
            // str_replace rather than sprintf: the translated string is data,
            // and a stray percent sign in it would make sprintf throw.
            'text'      => str_replace('%1$s', (string) $feature_count, $text),
            'nextLabel' => tamrank__('tour_free_welcome_start', 'Start the tour'),
            'skipLabel' => tamrank__('tour_free_welcome_skip', 'Skip the tour'),
        );
    }

    /**
     * The six numbered FREE feature steps, in tour order.
     */
    private function get_free_feature_steps() {
        return array(
            array(
                'page'     => 'tam-rank-audit',
                'target'   => '.tr-scan-banner',
                'title'    => tamrank__('tour_free_audit_title', 'Your whole site at a glance'),
                'text'     => tamrank__('tour_free_audit_text', 'Here you see every page with its SEO status and the most important things to improve. So you know in one look where to start.'),
                'position' => 'bottom',
                'type'     => 'tooltip',
            ),
            array(
                'page'     => 'post-new.php',
                // Target the score + improvements column, not the whole meta box,
                // so the highlight matches what this step is about.
                'target'   => '.tam-seo-sidebar',
                // In the block editor the classic meta boxes sit in a drawer at
                // the bottom of the canvas that WordPress keeps collapsed, so
                // the target is in the DOM with no layout and the step used to
                // drop to a centered card with nothing to look at. 'prepare'
                // opens the drawer (and the box inside it) first, so the step
                // lands on the thing the copy is about.
                'prepare'  => 'metabox',
                'title'    => tamrank__('tour_free_editor_title', 'A score that actually helps'),
                'text'     => tamrank__('tour_free_editor_text', 'Under every page you get a score with concrete steps. TamRank tells you not just what to improve, but exactly how to fix it. The right schema is detected automatically.'),
                'position' => 'right',
                'type'     => 'tooltip',
            ),
            array(
                'page'     => 'tam-rank-redirects',
                'target'   => '.tr-redir-page-header',
                'title'    => tamrank__('tour_free_redirects_title', 'No more broken links'),
                'text'     => tamrank__('tour_free_redirects_text', 'Delete or rename a page and TamRank sets up a redirect right away. In the 404 monitor you see which links visitors still run into.'),
                'position' => 'bottom',
                'type'     => 'tooltip',
            ),
            array(
                'page'     => 'tam-rank-dashboard',
                'target'   => '.tam-header-gsc-metrics',
                'title'    => tamrank__('tour_free_gsc_title', 'Your Google numbers, free'),
                'text'     => tamrank__('tour_free_gsc_text', 'Connect Search Console and see clicks, impressions and positions right in your dashboard. No more separate tab.'),
                'position' => 'bottom',
                'type'     => 'tooltip',
            ),
            // Site identity. The migration brings across what the old plugin
            // actually stored; what it could not find stays empty, and nothing
            // in the wizard points at where the rest lives. This step does -
            // which is why SITE-ID part 2 is a tour item and not a fifth wizard
            // screen: the entity cards already exist, a second UI would only
            // duplicate them.
            //
            // Uses 'click' rather than 'hash': the schema page's tabs are
            // <button data-tab>, not the <a href="#..."> pills the hash branch
            // looks for. The ?tab= in the URL already opens the panel; the click
            // is the belt to that braces, and harmless when the tab is active.
            array(
                'page'     => 'tam-rank-schema',
                'click'    => '.tr-pill-nav .tr-pill[data-tab="instellingen"]',
                // The entity chooser, not the whole card: the identity card runs
                // taller than the viewport in LocalBusiness mode, and a highlight
                // that tall pins the tooltip to the middle of a form with its own
                // subject scrolled off the top. This row IS "organisation or
                // person", and the fields the copy names sit right under it.
                'target'   => '.tr-entity-grid',
                'title'    => tamrank__('tour_free_identity_title', 'Tell search engines who you are'),
                'text'     => tamrank__('tour_free_identity_text', 'Your organisation or person, with the name, the logo, your social profiles and the image shown when someone shares a page that has none of its own. A migration brings across what it can find; this is where you complete the rest.'),
                'position' => 'bottom',
                'type'     => 'tooltip',
            ),
            array(
                'page'     => 'tam-rank-settings',
                'hash'     => '#technical',
                'target'   => '#tr-webp-row',
                'title'    => tamrank__('tour_free_webp_title', 'Faster images in one click'),
                'text'     => tamrank__('tour_free_webp_text', 'Turn on WebP and TamRank automatically creates lighter versions of your images. Pages load faster, and speed counts for Google.'),
                'position' => 'bottom',
                'type'     => 'tooltip',
            ),
        );
    }

    /**
     * AJAX: Mark a tour as completed. The tour type ('free' | 'pro') is passed
     * from the engine so each tour is dismissed independently — a FREE user who
     * later upgrades still gets the PRO tour.
     */
    public function ajax_tour_done() {
        check_ajax_referer('tam_rank_tour_nonce', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => tamrank__('error_permission_denied', 'You do not have permission for this action.'), 'code' => 'permission_denied'));
        }

        $type = isset($_POST['tourType']) ? sanitize_key(wp_unslash($_POST['tourType'])) : '';
        if ($type === 'pro') {
            update_option('tam_rank_tour_done_pro', '1');
        } elseif ($type === 'free') {
            update_option('tam_rank_tour_done_free', '1');
        } else {
            update_option('tam_rank_tour_done', '1'); // legacy fallback
        }
        wp_send_json_success();
    }

    /**
     * AJAX: Reset tours (for testing) — clears both per-tour flags + legacy flag.
     */
    public function ajax_tour_reset() {
        check_ajax_referer('tam_rank_tour_nonce', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => tamrank__('error_permission_denied', 'You do not have permission for this action.'), 'code' => 'permission_denied'));
        }

        delete_option('tam_rank_tour_done');
        delete_option('tam_rank_tour_done_free');
        delete_option('tam_rank_tour_done_pro');
        wp_send_json_success();
    }
}
