<?php
namespace Bookaro\Controller\Admin;

defined( 'ABSPATH' ) || exit;

// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Wizard reads are sanitized step/nav params (step submissions verify nonces, flagged separately as .Missing); the booking-count SELECT targets a custom plugin table ($wpdb->prefix) and binds values via prepare().

use Bookaro\Controller\Admin\Settings\GeneralTab;
use Bookaro\Repository\OptionRepository;
use Bookaro\Utils\AdminLaneSummary;
use Bookaro\Utils\GenericPresetProfiles;
use Bookaro\Utils\TemplateLoader;

/**
 * Admin setup wizard.
 */
class SetupWizardController
{
    private const GENERIC_PRESET_SUMMARY_NOTICE_KEY = 'bookaro_generic_preset_summary_notice';
    private const GENERIC_PRESET_CONFLICT_NOTICE_KEY = 'bookaro_generic_preset_conflict_notice';
    private const GENERIC_CONFIRMATION_NOTICE_KEY = 'bookaro_generic_confirmation_notice';
    private const GENERIC_LAUNCH_NOTICE_KEY = 'bookaro_generic_launch_validation_notice';

    private OptionRepository $options;

    public function __construct( OptionRepository $options )
    {
        $this->options = $options;
    }

    private function admin_menu_capability(): string
    {
        return function_exists( 'bookaro_get_admin_menu_capability' )
            ? bookaro_get_admin_menu_capability()
            : 'manage_options';
    }

    private function can_manage_admin(): bool
    {
        if ( function_exists( 'bookaro_current_user_can_manage_admin' ) ) {
            return bookaro_current_user_can_manage_admin();
        }
        return current_user_can( 'manage_options' );
    }

    public function register_hooks(): void
    {
        if ( ! $this->wizard_enabled() ) {
            return;
        }
        add_action( 'admin_menu', [ $this, 'register_admin_menu' ], 30 );
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
        add_action( 'admin_post_bookaro_setup_wizard', [ $this, 'handle_wizard_submit' ] );
        add_action( 'wp_ajax_bookaro_setup_wizard', [ $this, 'handle_wizard_ajax' ] );
        add_action( 'admin_notices', [ $this, 'maybe_show_notice' ] );
    }

    public function register_admin_menu(): void
    {
        add_submenu_page(
            'bookaro-bookings',
            __( 'Setup Wizard', 'mybookaro' ),
            __( 'Setup Wizard', 'mybookaro' ),
            $this->admin_menu_capability(),
            'bookaro-setup-wizard',
            [ $this, 'render_page' ]
        );
    }

    public function maybe_show_notice(): void
    {
        if ( ! $this->can_manage_admin() ) {
            return;
        }

        $opts = $this->options->get_all();
        $generic_confirmation_required = $this->generic_confirmation_required( $opts );
        $generic_legacy_fallback_active = $this->is_generic_legacy_fallback_active( $opts );
        if ( $generic_confirmation_required ) {
            $this->render_admin_notice(
                'warning',
                $this->get_generic_confirmation_required_notice_message(),
                $this->get_generic_confirmation_required_notice_url(),
                $this->get_generic_confirmation_required_notice_action_label()
            );
        } elseif ( $generic_legacy_fallback_active && $this->is_bookaro_admin_page() ) {
            $this->render_admin_notice(
                'warning',
                $this->get_generic_legacy_review_notice_message(),
                $this->get_generic_confirmation_required_notice_url(),
                $this->get_generic_legacy_review_notice_action_label()
            );
        }

        $mode = $this->wizard_mode();

        if ( 'generic' === $mode ) {
            if ( ! $this->is_bookaro_admin_page() ) {
                return;
            }

            $rendered_generic_notice = false;
            $generic_summary_notice = get_transient( self::GENERIC_PRESET_SUMMARY_NOTICE_KEY );
            if ( is_array( $generic_summary_notice ) ) {
                delete_transient( self::GENERIC_PRESET_SUMMARY_NOTICE_KEY );
                $this->render_generic_preset_summary_notice( $generic_summary_notice );
                $rendered_generic_notice = true;
            }

            $generic_preset_conflict_notice = get_transient( self::GENERIC_PRESET_CONFLICT_NOTICE_KEY );
            if ( ! $rendered_generic_notice && is_array( $generic_preset_conflict_notice ) ) {
                delete_transient( self::GENERIC_PRESET_CONFLICT_NOTICE_KEY );
                $type = sanitize_html_class( (string) ( $generic_preset_conflict_notice['type'] ?? 'error' ) );
                $message = (string) ( $generic_preset_conflict_notice['message'] ?? '' );
                $action_url = isset( $generic_preset_conflict_notice['action_url'] ) ? (string) $generic_preset_conflict_notice['action_url'] : '';
                $action_label = isset( $generic_preset_conflict_notice['action_label'] ) ? (string) $generic_preset_conflict_notice['action_label'] : '';
                $actions = isset( $generic_preset_conflict_notice['actions'] ) && is_array( $generic_preset_conflict_notice['actions'] ) ? $generic_preset_conflict_notice['actions'] : [];
                $this->render_admin_notice( $type, $message, $action_url, $action_label, $actions );
                $rendered_generic_notice = ( '' !== trim( $message ) );
            }

            $generic_confirmation_notice = get_transient( self::GENERIC_CONFIRMATION_NOTICE_KEY );
            if ( ! $rendered_generic_notice && is_array( $generic_confirmation_notice ) ) {
                delete_transient( self::GENERIC_CONFIRMATION_NOTICE_KEY );
                $type = sanitize_html_class( (string) ( $generic_confirmation_notice['type'] ?? 'warning' ) );
                $message = (string) ( $generic_confirmation_notice['message'] ?? '' );
                $action_url = isset( $generic_confirmation_notice['action_url'] ) ? (string) $generic_confirmation_notice['action_url'] : '';
                $action_label = isset( $generic_confirmation_notice['action_label'] ) ? (string) $generic_confirmation_notice['action_label'] : '';
                $actions = isset( $generic_confirmation_notice['actions'] ) && is_array( $generic_confirmation_notice['actions'] ) ? $generic_confirmation_notice['actions'] : [];
                $this->render_admin_notice( $type, $message, $action_url, $action_label, $actions );
                $rendered_generic_notice = ( '' !== trim( $message ) );
            }

            if ( ! $rendered_generic_notice ) {
                $generic_notice = get_transient( self::GENERIC_LAUNCH_NOTICE_KEY );
                if ( is_array( $generic_notice ) ) {
                    delete_transient( self::GENERIC_LAUNCH_NOTICE_KEY );
                    $type = sanitize_html_class( (string) ( $generic_notice['type'] ?? 'warning' ) );
                    $message = (string) ( $generic_notice['message'] ?? '' );
                    $action_url = isset( $generic_notice['action_url'] ) ? (string) $generic_notice['action_url'] : '';
                    $action_label = isset( $generic_notice['action_label'] ) ? (string) $generic_notice['action_label'] : '';
                    $actions = isset( $generic_notice['actions'] ) && is_array( $generic_notice['actions'] ) ? $generic_notice['actions'] : [];
                    $actions = array_merge( $actions, $this->get_support_handoff_notice_actions( $action_url ) );
                    $this->render_admin_notice( $type, $message, $action_url, $action_label, $actions );
                    $rendered_generic_notice = ( '' !== trim( $message ) );
                }
            }

            if ( ! $rendered_generic_notice ) {
                $generic_validation_prompt = $this->get_generic_validation_prompt( $opts );
                $runtime_failed_count = $this->get_generic_runtime_validation_failed_count();
                $needs_validation_refresh = ! empty( $generic_validation_prompt['active'] ) && ! empty( $generic_validation_prompt['needs_validation'] );

                if ( $runtime_failed_count > 0 ) {
                    $this->render_admin_notice(
                        'error',
                        $this->get_generic_runtime_validation_blocked_notice_message( $runtime_failed_count, $needs_validation_refresh ),
                        $this->get_generic_validation_status_url(),
                        $this->get_generic_runtime_validation_blocked_notice_action_label(),
                        $this->get_support_handoff_notice_actions( $this->get_generic_validation_status_url() )
                    );
                } elseif ( $needs_validation_refresh ) {
                    $this->render_admin_notice(
                        'warning',
                        $this->get_generic_launch_readiness_notice_message(),
                        $this->get_generic_validation_status_url(),
                        $this->get_generic_launch_readiness_notice_action_label(),
                        $this->get_support_handoff_notice_actions( $this->get_generic_validation_status_url() )
                    );
                }
            }
            return;
        }

        if ( 'mylisting' !== $mode ) {
            return;
        }

        $opts = $this->options->get_all();
        if ( ! empty( $opts['mylisting_setup_completed'] ) ) {
            return;
        }

        $wizard_url = admin_url( 'admin.php?page=bookaro-setup-wizard' );
        $message = sprintf(
            /* translators: %s: setup wizard URL */
            __( 'Finish configuring MyBookaro. <a href="%s">Run the setup wizard</a>.', 'mybookaro' ),
            esc_url( $wizard_url )
        );

        echo '<div class="notice notice-info"><p>' . wp_kses_post( $message ) . '</p></div>';
    }

    private function render_admin_notice( string $type, string $message, string $action_url = '', string $action_label = '', array $actions = [] ): void
    {
        $message = trim( $message );
        if ( '' === $message ) {
            return;
        }

        $actions = $this->normalize_notice_actions( $action_url, $action_label, $actions );

        echo '<div class="notice notice-' . esc_attr( sanitize_html_class( $type ) ) . '"><p>' . esc_html( $message ) . '</p>';
        if ( ! empty( $actions ) ) {
            echo '<p>';
            foreach ( $actions as $index => $action ) {
                if ( $index > 0 ) {
                    echo ' ';
                }
                echo '<a class="button button-secondary" href="' . esc_url( (string) $action['url'] ) . '">' . esc_html( (string) $action['label'] ) . '</a>';
            }
            echo '</p>';
        }
        echo '</div>';
    }

    private function render_generic_preset_summary_notice( array $notice ): void
    {
        $title = trim( (string) ( $notice['title'] ?? __( 'Generic setup summary', 'mybookaro' ) ) );
        $summary = trim( (string) ( $notice['summary'] ?? '' ) );
        $current_model = trim( (string) ( $notice['current_model'] ?? '' ) );
        $top_blocker = trim( (string) ( $notice['top_blocker'] ?? '' ) );
        $provider_mapping = trim( (string) ( $notice['provider_mapping'] ?? '' ) );
        $services_model = trim( (string) ( $notice['services_model'] ?? '' ) );
        $placement_strategy = trim( (string) ( $notice['placement_strategy'] ?? '' ) );
        $next_step_detail = trim( (string) ( $notice['next_step_detail'] ?? '' ) );
        $next_step_label = trim( (string) ( $notice['next_step_label'] ?? '' ) );
        $next_step_url = trim( (string) ( $notice['next_step_url'] ?? '' ) );
        $legacy_note = trim( (string) ( $notice['legacy_note'] ?? '' ) );

        if ( '' === $current_model && '' !== $provider_mapping ) {
            $current_model = sprintf(
                /* translators: 1: provider routing label, 2: services source label, 3: placement strategy label */
                __( 'Provider routing: %1$s | Services source: %2$s | Placement: %3$s', 'mybookaro' ),
                $provider_mapping,
                $services_model !== '' ? $services_model : __( 'Not set', 'mybookaro' ),
                $placement_strategy !== '' ? $placement_strategy : __( 'Not set', 'mybookaro' )
            );
        }

        if ( '' === $top_blocker ) {
            $top_blocker = $legacy_note;
        }

        if ( '' === $current_model && '' === $top_blocker && '' === $next_step_detail ) {
            return;
        }

        echo '<div class="notice notice-info">';
        echo '<div class="bookaro-note bookaro-note--info bookaro-setup-note">';
        if ( '' !== $title ) {
            echo '<strong>' . esc_html( $title ) . '</strong>';
        }
        if ( '' !== $summary ) {
            echo '<p class="description">' . esc_html( $summary ) . '</p>';
        }
        echo '<ul style="margin:8px 0 0; padding-left:18px; list-style:disc;">';
        if ( '' !== $current_model ) {
            echo '<li><strong>' . esc_html__( 'Current lane profile', 'mybookaro' ) . ':</strong> ' . esc_html( $current_model ) . '</li>';
        }
        if ( '' !== $top_blocker ) {
            echo '<li><strong>' . esc_html__( 'Main blocker', 'mybookaro' ) . ':</strong> ' . esc_html( $top_blocker ) . '</li>';
        }
        if ( '' !== $next_step_detail ) {
            echo '<li><strong>' . esc_html__( 'Required next step', 'mybookaro' ) . ':</strong> ' . esc_html( $next_step_detail ) . '</li>';
        }
        echo '</ul>';
        if ( '' !== $legacy_note && strtolower( $legacy_note ) !== strtolower( $top_blocker ) ) {
            echo '<p class="description" style="margin-top:8px;">' . esc_html( $legacy_note ) . '</p>';
        }
        if ( '' !== $next_step_label && '' !== $next_step_url ) {
            echo '<p style="margin-top:8px;">';
            echo '<a class="button button-secondary" href="' . esc_url( $next_step_url ) . '">' . esc_html( $next_step_label ) . '</a>';
            echo '</p>';
        }
        echo '</div>';
        echo '</div>';
    }

    private function normalize_notice_actions( string $action_url = '', string $action_label = '', array $actions = [] ): array
    {
        $normalized_actions = [];
        $seen = [];

        if ( '' !== trim( $action_url ) && '' !== trim( $action_label ) ) {
            $normalized_actions[] = [
                'url' => $action_url,
                'label' => $action_label,
            ];
            $seen[ trim( $action_url ) . '|' . trim( $action_label ) ] = true;
        }

        foreach ( $actions as $action ) {
            if ( ! is_array( $action ) ) {
                continue;
            }

            $url = trim( (string) ( $action['url'] ?? '' ) );
            $label = trim( (string) ( $action['label'] ?? '' ) );
            if ( '' === $url || '' === $label ) {
                continue;
            }

            $key = $url . '|' . $label;
            if ( isset( $seen[ $key ] ) ) {
                continue;
            }

            $normalized_actions[] = [
                'url' => $url,
                'label' => $label,
            ];
            $seen[ $key ] = true;
        }

        return $normalized_actions;
    }

    private function get_support_handoff_notice_actions( string $primary_action_url = '' ): array
    {
        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        $actions = [];
        $primary_action_url = trim( $primary_action_url );

        $support_snapshot_url = (string) ( $support_touchpoints['support_snapshot_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-snapshot' ) );
        if ( $primary_action_url !== trim( $support_snapshot_url ) ) {
            $actions[] = [
                'label' => __( 'Open masked snapshot first', 'mybookaro' ),
                'url' => $support_snapshot_url,
            ];
        }

        if ( false === strpos( $primary_action_url, 'page=bookaro-system-status' ) ) {
            $actions[] = [
                'label' => __( 'Open System Status', 'mybookaro' ),
                'url' => (string) ( $support_touchpoints['system_status_url'] ?? admin_url( 'admin.php?page=bookaro-system-status' ) ),
            ];
        }

        $support_bundle_url = (string) ( $support_touchpoints['support_bundle_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-bundle' ) );
        if ( $primary_action_url !== trim( $support_bundle_url ) ) {
            $actions[] = [
                'label' => __( 'Open Support Bundle (if requested)', 'mybookaro' ),
                'url' => $support_bundle_url,
            ];
        }

        return $actions;
    }

    private function get_support_touchpoint_actions( bool $include_validation = false ): array
    {
        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        $actions = [
            [
                'label' => __( 'Open masked snapshot first', 'mybookaro' ),
                'url' => (string) ( $support_touchpoints['support_snapshot_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-snapshot' ) ),
            ],
            [
                'label' => __( 'Open System Status', 'mybookaro' ),
                'url' => (string) ( $support_touchpoints['system_status_url'] ?? admin_url( 'admin.php?page=bookaro-system-status' ) ),
            ],
        ];

        if ( $include_validation ) {
            $actions[] = [
                'label' => __( 'Open validation results', 'mybookaro' ),
                'url' => (string) ( $support_touchpoints['generic_validation_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' ) ),
            ];
        }

        $actions[] = [
            'label' => __( 'Open Support Bundle (if requested)', 'mybookaro' ),
            'url' => (string) ( $support_touchpoints['support_bundle_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-bundle' ) ),
        ];

        return $actions;
    }

    private function is_current_wizard_page(): bool
    {
        $page = sanitize_key( wp_unslash( $_GET['page'] ?? '' ) );
        return ( 'bookaro-setup-wizard' === $page );
    }

    private function is_bookaro_admin_page(): bool
    {
        $page = sanitize_key( wp_unslash( $_GET['page'] ?? '' ) );
        if ( '' === $page ) {
            return false;
        }

        return 0 === strpos( $page, 'bookaro' );
    }

    public function enqueue_assets( string $hook ): void
    {
        $is_wizard_page = ( 'bookaro-bookings_page_bookaro-setup-wizard' === $hook );
        if ( ! $is_wizard_page && function_exists( 'get_current_screen' ) ) {
            $screen = get_current_screen();
            if ( $screen && ! empty( $screen->id ) ) {
                $is_wizard_page = ( 'bookaro-bookings_page_bookaro-setup-wizard' === $screen->id );
            }
        }
        if ( ! $is_wizard_page ) {
            $page = sanitize_key( wp_unslash( $_GET['page'] ?? '' ) );
            $is_wizard_page = ( 'bookaro-setup-wizard' === $page );
        }
        if ( ! $is_wizard_page ) {
            return;
        }

        $css_rel = 'assets/css/admin-settings.css';
        $css_path = $this->plugin_asset_path( $css_rel );
        $css_ver = file_exists( $css_path ) ? (string) filemtime( $css_path ) : ( defined( 'BOOKARO_VERSION' ) ? BOOKARO_VERSION : '1.0.0' );
        wp_enqueue_style( 'bookaro-admin-settings', $this->plugin_asset_url( $css_rel ), [], $css_ver );

        $theme_defaults = [
            'accent' => '#0f766e',
            'accent_soft' => '#ccfbf1',
            'accent_text' => '#134e4a',
            'surface' => '#ffffff',
            'surface_alt' => '#f8fafc',
            'surface_muted' => '#f1f5f9',
            'border' => '#e2e8f0',
            'text' => '#0f172a',
            'muted' => '#64748b',
            'danger' => '#dc2626',
            'warning' => '#f59e0b',
            'success' => '#16a34a',
            'shadow' => 'rgba(15, 23, 42, 0.08)',
        ];
        $theme = apply_filters( 'bookaro_admin_settings_theme', $theme_defaults );
        if ( ! is_array( $theme ) ) {
            $theme = $theme_defaults;
        }
        $vars = [
            'bookaro-accent' => $this->sanitize_css_var( $theme['accent'] ?? $theme_defaults['accent'], $theme_defaults['accent'] ),
            'bookaro-accent-soft' => $this->sanitize_css_var( $theme['accent_soft'] ?? $theme_defaults['accent_soft'], $theme_defaults['accent_soft'] ),
            'bookaro-accent-text' => $this->sanitize_css_var( $theme['accent_text'] ?? $theme_defaults['accent_text'], $theme_defaults['accent_text'] ),
            'bookaro-surface' => $this->sanitize_css_var( $theme['surface'] ?? $theme_defaults['surface'], $theme_defaults['surface'] ),
            'bookaro-surface-alt' => $this->sanitize_css_var( $theme['surface_alt'] ?? $theme_defaults['surface_alt'], $theme_defaults['surface_alt'] ),
            'bookaro-surface-muted' => $this->sanitize_css_var( $theme['surface_muted'] ?? $theme_defaults['surface_muted'], $theme_defaults['surface_muted'] ),
            'bookaro-border' => $this->sanitize_css_var( $theme['border'] ?? $theme_defaults['border'], $theme_defaults['border'] ),
            'bookaro-text' => $this->sanitize_css_var( $theme['text'] ?? $theme_defaults['text'], $theme_defaults['text'] ),
            'bookaro-muted' => $this->sanitize_css_var( $theme['muted'] ?? $theme_defaults['muted'], $theme_defaults['muted'] ),
            'bookaro-danger' => $this->sanitize_css_var( $theme['danger'] ?? $theme_defaults['danger'], $theme_defaults['danger'] ),
            'bookaro-warning' => $this->sanitize_css_var( $theme['warning'] ?? $theme_defaults['warning'], $theme_defaults['warning'] ),
            'bookaro-success' => $this->sanitize_css_var( $theme['success'] ?? $theme_defaults['success'], $theme_defaults['success'] ),
            'bookaro-shadow' => $this->sanitize_css_var( $theme['shadow'] ?? $theme_defaults['shadow'], $theme_defaults['shadow'] ),
        ];
        $theme_css = '.bookaro-admin{';
        foreach ( $vars as $name => $value ) {
            if ( $value === '' ) {
                continue;
            }
            $theme_css .= '--' . $name . ':' . $value . ';';
        }
        $theme_css .= '}';
        wp_add_inline_style( 'bookaro-admin-settings', $theme_css );

        wp_register_script( 'bookaro-setup-wizard', '', [], defined( 'BOOKARO_VERSION' ) ? BOOKARO_VERSION : '1.0.0', true );
        wp_enqueue_script( 'bookaro-setup-wizard' );
        $dependency_js = <<<'JS'
window.bookaroSetupWizardRefresh=function(){var t=document.querySelector('.bookaro-setup-wizard');if(!t)return;var e=[].slice.call(t.querySelectorAll('[data-bookaro-setting]'));var r=[].slice.call(t.querySelectorAll('[data-bookaro-depends]'));var n=function(a){if(!a)return null;try{return JSON.parse(a)}catch(o){return null}};var i=function(a){if(!a)return'';if(a.type==='checkbox'){return a.checked}if(a.type==='radio'){return a.checked?a.value:''}if(a.tagName==='SELECT'&&a.multiple){return[].slice.call(a.options).filter(function(o){return o.selected}).map(function(o){return o.value})}return a.value!==undefined?a.value:''};var s=function(a){var o=[].slice.call(t.querySelectorAll('[data-bookaro-setting="'+a+'"]'));if(!o.length){return''}var d=o.filter(function(u){return u.type==='radio'});if(d.length){var c=d.find(function(u){return u.checked});return c?i(c):''}return i(o[0])};var l=function(a){var o=a.operator||'truthy';var d=s(a.field||'');var u=a.value;var c=function(m){return m===null||m===undefined?''+m:String(m)};if(o==='equals'){if(Array.isArray(d)){return d.map(c).indexOf(c(u))!==-1}return c(d)===c(u)}if(o==='not_equals'){if(Array.isArray(d)){return d.map(c).indexOf(c(u))===-1}return c(d)!==c(u)}if(o==='in'){var m=Array.isArray(u)?u:[u];m=m.map(c);if(Array.isArray(d)){return d.map(c).some(function(f){return m.indexOf(f)!==-1})}return m.indexOf(c(d))!==-1}if(o==='not_in'){var p=Array.isArray(u)?u:[u];p=p.map(c);if(Array.isArray(d)){return d.map(c).every(function(f){return p.indexOf(f)===-1})}return p.indexOf(c(d))===-1}if(o==='contains'){if(Array.isArray(d)){return d.map(c).indexOf(c(u))!==-1}if(typeof d==='string'){return d.indexOf(c(u))!==-1}return false}if(o==='falsy'){if(Array.isArray(d)){return d.length===0}return !d}if(Array.isArray(d)){return d.length>0}return !!d};var v=function(a){if(!a){return true}var o=a.rules||a;var d=a.mode||'all';if(!Array.isArray(o)||!o.length){return true}var u=o.map(l);return d==='any'?u.some(Boolean):u.every(Boolean)};var b=function(){r.forEach(function(a){var o=n(a.getAttribute('data-bookaro-depends'));var d=v(o);var u=a.closest('tr')||a;if(d){u.classList.remove('bookaro-setting-hidden')}else{u.classList.add('bookaro-setting-hidden')}})};e.forEach(function(a){if(a._bookaroDependsBound){return}a.addEventListener('change',b);a.addEventListener('input',b);a._bookaroDependsBound=true});b()};
document.addEventListener('DOMContentLoaded',function(){if(window.bookaroSetupWizardRefresh){window.bookaroSetupWizardRefresh()}});
JS;
        wp_add_inline_script( 'bookaro-setup-wizard', $dependency_js );

        $wizard_js = <<<'JS'
document.addEventListener('DOMContentLoaded',function(){
    var root=document.querySelector('.bookaro-setup-wizard');
    if(!root||typeof window.ajaxurl==='undefined'){return}
    var panelSelector='.bookaro-setup-panel';
    var stepperSelector='.bookaro-stepper';
    var messageNode=null;
    var requestInFlight=false;
    var loadInFlight=false;
    var lastButton=null;

    var getMessageNode=function(){
        if(messageNode){return messageNode}
        messageNode=root.querySelector('.bookaro-setup-message');
        if(!messageNode){
            messageNode=document.createElement('div');
            messageNode.className='bookaro-setup-message';
            root.insertBefore(messageNode,root.firstChild);
        }
        return messageNode;
    };

    var showMessage=function(text,type){
        var node=getMessageNode();
        var cls=type==='success'?'notice notice-success':'notice notice-error';
        node.innerHTML='<div class="'+cls+'"><p>'+text+'</p></div>';
    };

    var clearMessage=function(){
        if(messageNode){messageNode.innerHTML=''}
    };

    var getStepFromUrl=function(url){
        try{
            var nextUrl=new URL(url,window.location.href);
            return nextUrl.searchParams.get('step');
        }catch(e){
            return null;
        }
    };

    var setButtonLoading=function(btn){
        if(!btn){return}
        lastButton=btn;
        if(!btn.getAttribute('data-original-label')){
            var original=btn.tagName==='INPUT'?btn.value:btn.textContent;
            btn.setAttribute('data-original-label',original);
        }
        var loadingLabel=btn.getAttribute('data-loading-label')||'Saving...';
        if(btn.tagName==='INPUT'){
            btn.value=loadingLabel;
        }else{
            btn.textContent=loadingLabel;
        }
        btn.classList.add('bookaro-button-loading');
        btn.setAttribute('aria-busy','true');
        btn.disabled=true;
    };

    var resetButton=function(btn){
        if(!btn){return}
        var original=btn.getAttribute('data-original-label');
        if(original!==null){
            if(btn.tagName==='INPUT'){
                btn.value=original;
            }else{
                btn.textContent=original;
            }
            btn.removeAttribute('data-original-label');
        }
        btn.classList.remove('bookaro-button-loading');
        btn.removeAttribute('aria-busy');
        btn.disabled=false;
    };

    var loadStep=function(step){
        if(!step||loadInFlight){return}
        loadInFlight=true;
        var nextUrl=new URL(window.location.href);
        nextUrl.searchParams.set('page','bookaro-setup-wizard');
        nextUrl.searchParams.set('step',step);
        fetch(nextUrl.toString(),{credentials:'same-origin'}).then(function(resp){
            return resp.text();
        }).then(function(html){
            var doc=new DOMParser().parseFromString(html,'text/html');
            var panel=doc.querySelector(panelSelector);
            var stepper=doc.querySelector(stepperSelector);
            if(panel){
                var currentPanel=root.querySelector(panelSelector);
                if(currentPanel){currentPanel.replaceWith(panel)}
            }
            if(stepper){
                var currentStepper=root.querySelector(stepperSelector);
                if(currentStepper){currentStepper.replaceWith(stepper)}
            }
            window.history.replaceState(null,'',nextUrl.toString());
            if(typeof window.bookaroSetupWizardRefresh==='function'){
                window.bookaroSetupWizardRefresh();
            }
            lastButton=null;
        }).catch(function(){
            showMessage('Unable to load the next step. Please refresh.','error');
            resetButton(lastButton);
        }).finally(function(){
            loadInFlight=false;
        });
    };

    root.addEventListener('submit',function(evt){
        var form=evt.target;
        if(!(form instanceof HTMLFormElement)||!form.classList.contains('bookaro-setup-form')){
            return;
        }
        evt.preventDefault();
        if(requestInFlight){return}
        requestInFlight=true;
        clearMessage();
        var submitButton=form.querySelector('.bookaro-next-button')||form.querySelector('button[type="submit"], input[type="submit"]');
        setButtonLoading(submitButton);
        var data=new FormData(form);
        data.set('action','bookaro_setup_wizard');
        fetch(window.ajaxurl,{method:'POST',credentials:'same-origin',body:data}).then(function(resp){
            return resp.json();
        }).then(function(resp){
            if(!resp||!resp.success){
                var msg=resp&&resp.data&&resp.data.message?resp.data.message:'Unable to save this step.';
                showMessage(msg,'error');
                resetButton(submitButton);
                return;
            }
            var payload=resp.data||{};
            if(payload.redirect){
                window.location=payload.redirect;
                return;
            }
            if(payload.next_step){
                loadStep(payload.next_step);
                return;
            }
            resetButton(submitButton);
        }).catch(function(){
            showMessage('Unable to save this step. Please try again.','error');
            resetButton(submitButton);
        }).finally(function(){
            requestInFlight=false;
        });
    });

    root.addEventListener('click',function(evt){
        var link=evt.target.closest('a');
        if(!link||!link.href){return}
        if(link.getAttribute('target')==='_blank'){return}
        if(link.href.indexOf('page=bookaro-setup-wizard')===-1){return}
        var step=getStepFromUrl(link.href);
        if(!step){return}
        evt.preventDefault();
        clearMessage();
        loadStep(step);
    });
});
JS;
        wp_add_inline_script( 'bookaro-setup-wizard', $wizard_js );
    }

    public function handle_wizard_submit(): void
    {
        if ( ! $this->wizard_enabled() ) {
            wp_die(
                esc_html__( 'The setup wizard is disabled.', 'mybookaro' ),
                esc_html__( 'Not available', 'mybookaro' ),
                [ 'response' => 403 ]
            );
        }
        if ( ! $this->can_manage_admin() ) {
            wp_die( esc_html__( 'You do not have permission to perform this action.', 'mybookaro' ) );
        }

        check_admin_referer( 'bookaro_setup_wizard' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $opts = $this->options->get_all();
        $mode = $this->wizard_mode();
        if ( 'mylisting' === $mode ) {
            $step = sanitize_text_field( $payload['step'] ?? '' );
            $next = $this->handle_mylisting_wizard_submit( $payload, $opts );
            if ( 'mylisting_finish' === $step ) {
                wp_safe_redirect( $this->get_mylisting_finish_redirect_url() );
                exit;
            }
            wp_safe_redirect(
                add_query_arg(
                    [
                        'page' => 'bookaro-setup-wizard',
                        'step' => $next,
                    ],
                    admin_url( 'admin.php' )
                )
            );
            exit;
        }

        $next = $this->handle_generic_wizard_submit( $payload, $opts );
        if ( 'done' === $next ) {
            wp_safe_redirect( $this->get_wizard_completion_redirect_url( $this->options->get_all() ) );
            exit;
        }
        wp_safe_redirect(
            add_query_arg(
                [
                    'page' => 'bookaro-setup-wizard',
                    'step' => $next,
                ],
                admin_url( 'admin.php' )
            )
        );
        exit;
    }

    public function handle_wizard_ajax(): void
    {
        if ( ! $this->wizard_enabled() ) {
            wp_send_json_error(
                [ 'message' => __( 'The setup wizard is disabled.', 'mybookaro' ) ],
                403
            );
        }
        if ( ! $this->can_manage_admin() ) {
            wp_send_json_error(
                [ 'message' => __( 'You do not have permission to perform this action.', 'mybookaro' ) ],
                403
            );
        }
        if ( ! check_ajax_referer( 'bookaro_setup_wizard', '_wpnonce', false ) ) {
            wp_send_json_error(
                [ 'message' => __( 'Security check failed. Please refresh and try again.', 'mybookaro' ) ],
                403
            );
        }

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $opts = $this->options->get_all();
        $mode = $this->wizard_mode();

        if ( 'mylisting' === $mode ) {
            $step = sanitize_text_field( $payload['step'] ?? '' );
            $next = $this->handle_mylisting_wizard_submit( $payload, $opts );
            if ( 'mylisting_finish' === $step ) {
                wp_send_json_success(
                    [ 'redirect' => $this->get_mylisting_finish_redirect_url() ]
                );
            }
            wp_send_json_success( [ 'next_step' => $next ] );
        }

        $next = $this->handle_generic_wizard_submit( $payload, $opts );
        if ( 'done' === $next ) {
            wp_send_json_success(
                [ 'redirect' => $this->get_wizard_completion_redirect_url( $this->options->get_all() ) ]
            );
        }
        wp_send_json_success( [ 'next_step' => $next ] );
    }

    private function handle_generic_wizard_submit( array $payload, array $opts ): string
    {
        $opts_before = $opts;
        $step = sanitize_text_field( $payload['step'] ?? 'listings' );
        $next = 'listings';
        $generic_advanced_setup_enabled = $this->is_generic_advanced_setup_enabled( $opts, $payload );
        $generic_setup_preset = $this->resolve_generic_setup_preset( $opts, $payload );
        $preset_defaults = $this->get_generic_setup_preset_defaults( $generic_setup_preset, $opts );

        if ( 'modes' === $step ) {
            $site_type = $this->resolve_site_type_from_options( $opts, $payload );
            $advanced_preset_requested = ( 'single_business' !== $site_type ) && ! empty( $payload['generic_advanced_setup_enabled'] );
            if ( $advanced_preset_requested ) {
                $site_type = 'advanced_mapping';
            }
            $integration_mode = sanitize_key( $payload['integration_mode'] ?? 'auto' );
            if ( ! in_array( $integration_mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
                $integration_mode = 'auto';
            }
            if ( in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true ) ) {
                $integration_mode = 'generic';
            }

            $ui_mode_default = $this->get_default_ui_mode_for_integration( $integration_mode );
            $ui_mode = sanitize_key( $payload['ui_mode'] ?? $ui_mode_default );
            if ( ! in_array( $ui_mode, [ 'shortcodes', 'woocommerce' ], true ) ) {
                $ui_mode = $ui_mode_default;
            }

            $previous_mode = $opts['integration_mode'] ?? '';
            $opts['site_type'] = $site_type;
            $opts['integration_mode'] = $integration_mode;
            $opts['ui_mode'] = $ui_mode;
            if ( 'advanced_mapping' === $site_type ) {
                $opts['generic_advanced_setup_enabled'] = 1;
            } elseif ( 'single_business' === $site_type ) {
                $opts['generic_advanced_setup_enabled'] = 0;
            } else {
                $opts['generic_advanced_setup_enabled'] = ! empty( $payload['generic_advanced_setup_enabled'] ) ? 1 : 0;
            }
            // A saved Lane step confirms the Generic lane in two cases: when the
            // admin explicitly selects "Generic Directory", AND when the lane is
            // left on "Auto-select" but resolves to Generic because MyListing is
            // not active. Previously only the explicit selection wrote the
            // confirmation metadata, so an admin who followed the on-screen
            // guidance literally ("review this lane step and save once to
            // confirm Generic Directory") without changing the dropdown never
            // cleared the "legacy fallback / lane confirmation missing" notice.
            $lane_resolves_to_generic = ( 'generic' === $integration_mode )
                || ( 'auto' === $integration_mode && ! $this->is_mylisting_detected() );
            if ( $lane_resolves_to_generic ) {
                $opts['generic_setup_preset'] = ( 'single_business' === $site_type )
                    ? 'author_provider'
                    : $generic_setup_preset;
                $opts['generic_setup_confirmed'] = 1;
                $opts['generic_setup_confirmed_at'] = time();
                $opts['generic_setup_confirmation_source'] = 'wizard_modes';
            }
            if ( 'single_business' === $site_type ) {
                $opts['provider_resolution_mode'] = 'author';
                $opts['provider_meta_key'] = '';
                $opts['services_model'] = 'provider_only';
                $opts['generic_services_mode'] = 'provider_only';
                $opts['provider_services_enabled'] = 1;
                $opts['allow_provider_custom_services'] = 0;
                $opts['allow_provider_override_catalog'] = 0;
            }
            $this->options->update( $opts );

            if ( $previous_mode !== $integration_mode && function_exists( 'flush_rewrite_rules' ) ) {
                flush_rewrite_rules();
            }

            if ( $this->generic_confirmation_required( $opts ) ) {
                set_transient(
                    self::GENERIC_CONFIRMATION_NOTICE_KEY,
                    [
                        'type' => 'warning',
                        'message' => $this->get_generic_confirmation_required_notice_message(),
                        'action_url' => $this->get_generic_confirmation_required_notice_url(),
                        'action_label' => $this->get_generic_confirmation_required_notice_action_label(),
                    ],
                    10 * MINUTE_IN_SECONDS
                );
                $next = 'modes';
            } else {
                $next = 'listings';
            }
        } elseif ( 'roles' === $step ) {
            $provider_role = sanitize_text_field( $payload['provider_role'] ?? '' );
            $owner_role    = sanitize_text_field( $payload['owner_role'] ?? '' );

            $opts['provider_role'] = $provider_role;
            $opts['owner_role']    = $owner_role;
            $this->options->update( $opts );

            if ( function_exists( 'bookaro_sync_role_caps' ) ) {
                bookaro_sync_role_caps( $provider_role, $owner_role );
            }

            $next = 'listings';
        } elseif ( 'listings' === $step ) {
            $site_type = $this->resolve_site_type_from_options( $opts, $payload );
            $single_business = ( 'single_business' === $site_type );
            $opts['site_type'] = $site_type;
            $default_provider_id = absint( $payload['default_provider_id'] ?? $opts['default_provider_id'] ?? 0 );
            if ( $default_provider_id > 0 && ! get_user_by( 'ID', $default_provider_id ) ) {
                $default_provider_id = 0;
            }
            if ( $single_business && $default_provider_id < 1 ) {
                $fallback_provider_id = get_current_user_id();
                if ( $fallback_provider_id > 0 && get_user_by( 'ID', $fallback_provider_id ) ) {
                    $default_provider_id = $fallback_provider_id;
                }
            }
            $listing_options = $this->get_listing_post_type_options();
            $available_listing_types = array_keys( $listing_options );
            $default_listing_type = ( $single_business && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) )
                ? sanitize_key( (string) BOOKARO_PROVIDER_POST_TYPE )
                : BOOKARO_PROVIDER_POST_TYPE;
            if ( ! empty( $available_listing_types ) ) {
                $default_listing_type = (string) $available_listing_types[0];
            }

            $raw_listing_types = $payload['allowed_listing_post_types'] ?? [];
            if ( ! is_array( $raw_listing_types ) ) {
                $raw_listing_types = [ $raw_listing_types ];
            }
            $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $raw_listing_types ) ) ) );
            if ( ! empty( $available_listing_types ) ) {
                $selected_listing_types = array_values( array_intersect( $selected_listing_types, $available_listing_types ) );
            }
            if ( empty( $selected_listing_types ) && ! $single_business ) {
                $selected_listing_types = [ $default_listing_type ];
            }

            $raw_allowed_pages = $payload['allowed_listing_pages'] ?? [];
            if ( ! is_array( $raw_allowed_pages ) ) {
                $raw_allowed_pages = [ $raw_allowed_pages ];
            }
            $allowed_pages = [];
            foreach ( $raw_allowed_pages as $page_id ) {
                $page_id = absint( $page_id );
                if ( $page_id < 1 ) {
                    continue;
                }
                if ( 'page' !== get_post_type( $page_id ) ) {
                    continue;
                }
                $allowed_pages[] = $page_id;
            }
            $allowed_pages = array_values( array_unique( $allowed_pages ) );

            if ( $generic_advanced_setup_enabled ) {
                $provider_resolution_mode = sanitize_key( $payload['provider_resolution_mode'] ?? '' );
                if ( ! in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true ) ) {
                    $provider_resolution_mode = '';
                }
                $provider_meta_key = sanitize_key( $payload['provider_meta_key'] ?? '' );
                if ( '' === $provider_resolution_mode ) {
                    $provider_resolution_mode = $provider_meta_key !== '' ? 'meta_key' : 'author';
                }
            } else {
                $provider_resolution_mode = sanitize_key( (string) ( $preset_defaults['provider_resolution_mode'] ?? 'author' ) );
                $provider_meta_key = sanitize_key( (string) ( $preset_defaults['provider_meta_key'] ?? '' ) );
            }
            if ( $single_business ) {
                $provider_resolution_mode = 'author';
                $provider_meta_key = '';
            }

            $opts['allowed_listing_post_types'] = $selected_listing_types;
            if ( ! empty( $selected_listing_types ) ) {
                $opts['listing_post_type'] = $selected_listing_types[0];
            } elseif ( $single_business && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
                $opts['listing_post_type'] = sanitize_key( (string) BOOKARO_PROVIDER_POST_TYPE );
            } else {
                $opts['listing_post_type'] = $default_listing_type;
            }
            $opts['allowed_listing_pages'] = array_map( 'strval', $allowed_pages );
            $opts['generic_setup_preset'] = $single_business ? 'author_provider' : $generic_setup_preset;
            $opts['provider_resolution_mode'] = $provider_resolution_mode;
            $opts['provider_meta_key'] = $provider_meta_key;
            $opts['default_provider_id'] = $default_provider_id;
            if ( $provider_meta_key !== '' ) {
                $opts['listing_provider_meta_key'] = $provider_meta_key;
            }
            $this->options->update( $opts );

            $next = 'services';
        } elseif ( 'services' === $step ) {
            $site_type = $this->resolve_site_type_from_options( $opts, $payload );
            $single_business = ( 'single_business' === $site_type );
            $opts['site_type'] = $site_type;
            if ( $generic_advanced_setup_enabled ) {
                $services_model = sanitize_key( $payload['services_model'] ?? '' );
                if ( 'admin_catalog' === $services_model ) {
                    $services_model = 'admin_only';
                }
                if ( ! in_array( $services_model, [ 'admin_only', 'provider_only', 'hybrid' ], true ) ) {
                    $services_model = 'hybrid';
                }
            } else {
                $services_model = sanitize_key( (string) ( $preset_defaults['services_model'] ?? 'provider_only' ) );
                if ( ! in_array( $services_model, [ 'admin_only', 'provider_only', 'hybrid' ], true ) ) {
                    $services_model = 'provider_only';
                }
            }

            if ( $generic_advanced_setup_enabled ) {
                $auto_insert_enabled = ! empty( $payload['auto_insert_booking_button_enabled'] ) ? 1 : 0;
                $auto_insert_mode = sanitize_key( $payload['auto_insert_booking_button'] ?? '' );
                if ( ! in_array( $auto_insert_mode, [ 'before_content', 'after_content', 'selector' ], true ) ) {
                    $auto_insert_mode = '';
                }
                if ( $auto_insert_enabled && '' === $auto_insert_mode ) {
                    $auto_insert_mode = 'after_content';
                }
                $auto_insert_selector = sanitize_text_field( $payload['auto_insert_booking_button_selector'] ?? '' );
            } else {
                $auto_insert_enabled = ! empty( $preset_defaults['auto_insert_booking_button_enabled'] ) ? 1 : 0;
                $auto_insert_mode = sanitize_key( (string) ( $preset_defaults['auto_insert_booking_button'] ?? 'after_content' ) );
                if ( $auto_insert_enabled && '' === $auto_insert_mode ) {
                    $auto_insert_mode = 'after_content';
                }
                if ( ! in_array( $auto_insert_mode, [ 'before_content', 'after_content', 'selector' ], true ) ) {
                    $auto_insert_mode = 'after_content';
                }
                $auto_insert_selector = sanitize_text_field( (string) ( $preset_defaults['auto_insert_booking_button_selector'] ?? '' ) );
            }
            if ( $single_business ) {
                $services_model = 'provider_only';
            }

            $opts['generic_setup_preset'] = $single_business ? 'author_provider' : $generic_setup_preset;
            $opts['services_model'] = $services_model;
            $opts['generic_services_mode'] = ( 'admin_only' === $services_model ) ? 'admin_catalog' : $services_model;
            $opts['auto_insert_booking_button_enabled'] = $auto_insert_enabled;
            $opts['auto_insert_booking_button'] = $auto_insert_mode;
            $opts['auto_insert_booking_button_selector'] = $auto_insert_selector;
            if ( $generic_advanced_setup_enabled ) {
                if ( ! array_key_exists( 'provider_services_enabled', $opts ) ) {
                    $opts['provider_services_enabled'] = 1;
                }
                if ( ! array_key_exists( 'allow_provider_custom_services', $opts ) ) {
                    $opts['allow_provider_custom_services'] = 0;
                }
                if ( ! array_key_exists( 'allow_provider_override_catalog', $opts ) ) {
                    $opts['allow_provider_override_catalog'] = 0;
                }
            } else {
                $opts['provider_services_enabled'] = ! empty( $preset_defaults['provider_services_enabled'] ) ? 1 : 0;
                $opts['allow_provider_custom_services'] = ! empty( $preset_defaults['allow_provider_custom_services'] ) ? 1 : 0;
                $opts['allow_provider_override_catalog'] = ! empty( $preset_defaults['allow_provider_override_catalog'] ) ? 1 : 0;
            }
            if ( $single_business ) {
                $opts['provider_services_enabled'] = 1;
                $opts['allow_provider_custom_services'] = 0;
                $opts['allow_provider_override_catalog'] = 0;
            }

            // Booking placement strategy is surfaced on this step for every lane
            // (not only advanced setup) so the operator can choose where the
            // booking entry renders — the launch validation points here for it.
            // Single Business has no listings, so directory_template is coerced to
            // normal_page to match the front-end resolver and the launch check.
            if ( isset( $payload['booking_placement_strategy'] ) ) {
                $placement_choice = sanitize_key( (string) $payload['booking_placement_strategy'] );
                if ( in_array( $placement_choice, [ 'directory_template', 'normal_page', 'shortcode_only', 'css_selector' ], true ) ) {
                    if ( $single_business && 'directory_template' === $placement_choice ) {
                        $placement_choice = 'normal_page';
                    }
                    $opts['booking_placement_strategy'] = $placement_choice;
                }
            }

            $this->options->update( $opts );

            $next = 'pages';
        } elseif ( 'catalog' === $step ) {
            $provider_user_id = absint( $payload['provider_user_id'] ?? get_current_user_id() );
            $existing_listing_id = absint( $payload['existing_listing_id'] ?? 0 );
            $create_listing = ! empty( $payload['create_provider_listing'] );

            $listing_id = 0;
            if ( $existing_listing_id > 0 ) {
                $listing_id = $existing_listing_id;
            } elseif ( $create_listing ) {
                $listing_id = $this->create_provider_listing( $provider_user_id, $payload );
            } else {
                $listing_id = $this->find_provider_listing( $provider_user_id );
            }

            $service_id = 0;
            if ( ! empty( $payload['create_service'] ) && $listing_id > 0 ) {
                $service_id = $this->create_service( $listing_id, $provider_user_id, $payload );
            }

            if ( $provider_user_id > 0 ) {
                $opts['generic_setup_provider_user_id'] = $provider_user_id;
            }
            $opts['generic_setup_listing_id'] = $listing_id;
            $opts['generic_setup_service_id'] = $service_id;
            $this->options->update( $opts );

            if ( ! empty( $payload['assign_provider_role'] ) && $provider_user_id > 0 ) {
                $role = $opts['provider_role'] ?? '';
                if ( '' === $role ) {
                    $role = 'bookaro_provider';
                }
                $this->assign_role_to_user( $provider_user_id, $role );
            }

            $next = 'pages';
        } elseif ( 'pages' === $step ) {
            $listing_id = absint( $opts['generic_setup_listing_id'] ?? 0 );
            $default_provider_id = absint( $opts['default_provider_id'] ?? 0 );
            if ( $default_provider_id > 0 && ! get_user_by( 'ID', $default_provider_id ) ) {
                $default_provider_id = 0;
            }

            $booking_selection = sanitize_text_field( $payload['booking_page_id'] ?? '' );
            $provider_selection = sanitize_text_field( $payload['provider_dashboard_page_id'] ?? '' );
            $customer_selection = sanitize_text_field( $payload['customer_dashboard_page_id'] ?? '' );
            $services_selection = sanitize_text_field( $payload['services_page_id'] ?? '' );

            $page_ids = [];
            $page_ids['booking'] = $this->resolve_page_selection(
                $booking_selection,
                'bookaro-booking',
                __( 'Book a Service', 'mybookaro' ),
                $this->build_booking_form_block( $listing_id, $default_provider_id )
            );
            $page_ids['provider_dashboard'] = $this->resolve_page_selection(
                $provider_selection,
                'bookaro-provider-dashboard',
                __( 'MyBookaro Provider Dashboard', 'mybookaro' ),
                $this->build_provider_dashboard_block()
            );
            $page_ids['customer_dashboard'] = $this->resolve_page_selection(
                $customer_selection,
                'bookaro-customer-dashboard',
                __( 'MyBookaro Customer Dashboard', 'mybookaro' ),
                $this->build_customer_dashboard_block()
            );
            $page_ids['services'] = $this->resolve_page_selection(
                $services_selection,
                'bookaro-services',
                __( 'MyBookaro Services', 'mybookaro' ),
                $this->build_services_cards_block( $listing_id, $default_provider_id )
            );

            foreach ( $page_ids as $key => $page_id ) {
                if ( $page_id > 0 ) {
                    $opts[ "generic_setup_{$key}_page_id" ] = $page_id;
                }
            }

            $overrides = $opts['listing_post_type_pages'] ?? [];
            if ( ! is_array( $overrides ) ) {
                $overrides = [];
            }
            $listing_types = $opts['allowed_listing_post_types'] ?? [];
            if ( ! is_array( $listing_types ) ) {
                $listing_types = [ $listing_types ];
            }
            $listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $listing_types ) ) ) );
            foreach ( $listing_types as $post_type ) {
                $row = $overrides[ $post_type ] ?? [];
                if ( ! is_array( $row ) ) {
                    $row = [];
                }
                if ( $page_ids['booking'] > 0 ) {
                    $row['booking'] = $page_ids['booking'];
                }
                if ( $page_ids['provider_dashboard'] > 0 ) {
                    $row['provider_dashboard'] = $page_ids['provider_dashboard'];
                }
                if ( $page_ids['customer_dashboard'] > 0 ) {
                    $row['customer_dashboard'] = $page_ids['customer_dashboard'];
                }
                $overrides[ $post_type ] = $row;
            }
            $opts['listing_post_type_pages'] = $overrides;

            if ( ! empty( $payload['create_demo_content'] ) ) {
                $this->create_demo_content( $listing_id, $default_provider_id );
            }

            $opts['generic_setup_completed'] = 1;
            $opts['generic_setup_confirmed'] = 1;
            if ( absint( $opts['generic_setup_confirmed_at'] ?? 0 ) < 1 ) {
                $opts['generic_setup_confirmed_at'] = time();
            }
            if ( empty( $opts['generic_setup_confirmation_source'] ) ) {
                $opts['generic_setup_confirmation_source'] = 'wizard_pages';
            }
            $this->options->update( $opts );

            $next = 'operational';
        } elseif ( 'operational' === $step ) {
            $next = 'done';
        }

        $this->maybe_set_generic_launch_validation_notice( $opts_before, $opts );
        $generic_preset_conflict_notice = $this->build_generic_preset_conflict_notice( $opts );
        if ( ! empty( $generic_preset_conflict_notice ) ) {
            set_transient(
                self::GENERIC_PRESET_CONFLICT_NOTICE_KEY,
                [
                    'type' => (string) ( $generic_preset_conflict_notice['type'] ?? 'error' ),
                    'message' => (string) ( $generic_preset_conflict_notice['message'] ?? '' ),
                    'action_url' => (string) ( $generic_preset_conflict_notice['action_url'] ?? '' ),
                    'action_label' => (string) ( $generic_preset_conflict_notice['action_label'] ?? '' ),
                    'actions' => is_array( $generic_preset_conflict_notice['actions'] ?? null )
                        ? $generic_preset_conflict_notice['actions']
                        : [],
                ],
                10 * MINUTE_IN_SECONDS
            );
            delete_transient( self::GENERIC_PRESET_SUMMARY_NOTICE_KEY );
            $forced_next = sanitize_key( (string) ( $generic_preset_conflict_notice['primary_step'] ?? '' ) );
            if ( in_array( $forced_next, [ 'listings', 'services' ], true ) ) {
                $next = $forced_next;
            }
        } else {
            delete_transient( self::GENERIC_PRESET_CONFLICT_NOTICE_KEY );
            $this->maybe_set_generic_preset_summary_notice( $opts, $step, $next );
        }

        return $next;
    }

    private function is_generic_advanced_setup_enabled( array $opts, array $payload = [] ): bool
    {
        if ( array_key_exists( 'generic_advanced_setup_enabled', $payload ) ) {
            return ! empty( $payload['generic_advanced_setup_enabled'] );
        }

        return ! empty( $opts['generic_advanced_setup_enabled'] );
    }

    private function get_generic_setup_preset_options(): array
    {
        return [
            'author_provider' => __( 'Provider-Owned Directory: Listing Author mapping + Provider Only services + explicit placement + required pages + launch-ready checks', 'mybookaro' ),
            'meta_key_provider' => __( 'Editorial + Meta Key Directory: Listing Meta Key mapping + Provider Only services + explicit placement + required pages + launch-ready checks', 'mybookaro' ),
            'author_admin_catalog' => __( 'Shared Catalog Directory: Listing Author mapping + Admin Catalog Only services + explicit placement + required pages + launch-ready checks', 'mybookaro' ),
        ];
    }

    private function sanitize_generic_setup_preset( $preset ): string
    {
        $preset = sanitize_key( (string) $preset );
        $options = $this->get_generic_setup_preset_options();
        if ( ! array_key_exists( $preset, $options ) ) {
            return 'author_provider';
        }

        return $preset;
    }

    private function resolve_generic_setup_preset( array $opts, array $payload = [] ): string
    {
        if ( array_key_exists( 'generic_setup_preset', $payload ) ) {
            return $this->sanitize_generic_setup_preset( $payload['generic_setup_preset'] );
        }

        $stored_preset = sanitize_key( (string) ( $opts['generic_setup_preset'] ?? '' ) );
        if ( '' !== $stored_preset ) {
            return $this->sanitize_generic_setup_preset( $stored_preset );
        }

        $provider_resolution_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? '' ) );
        $services_model = sanitize_key( (string) ( $opts['services_model'] ?? $opts['generic_services_mode'] ?? '' ) );
        if ( 'admin_catalog' === $services_model ) {
            $services_model = 'admin_only';
        }

        if ( 'meta_key' === $provider_resolution_mode ) {
            return 'meta_key_provider';
        }
        if ( 'admin_only' === $services_model ) {
            return 'author_admin_catalog';
        }

        return 'author_provider';
    }

    private function get_generic_setup_preset_defaults( string $preset, array $opts = [] ): array
    {
        $preset = $this->sanitize_generic_setup_preset( $preset );
        $existing_meta_key = sanitize_key( (string) ( $opts['provider_meta_key'] ?? $opts['listing_provider_meta_key'] ?? '' ) );
        if ( '' === $existing_meta_key ) {
            $existing_meta_key = 'provider_user_id';
        }

        if ( 'meta_key_provider' === $preset ) {
            return [
                'provider_resolution_mode' => 'meta_key',
                'provider_meta_key' => $existing_meta_key,
                'services_model' => 'provider_only',
                'provider_services_enabled' => 1,
                'allow_provider_custom_services' => 0,
                'allow_provider_override_catalog' => 0,
                'auto_insert_booking_button_enabled' => 1,
                'auto_insert_booking_button' => 'after_content',
                'auto_insert_booking_button_selector' => '',
            ];
        }

        if ( 'author_admin_catalog' === $preset ) {
            return [
                'provider_resolution_mode' => 'author',
                'provider_meta_key' => '',
                'services_model' => 'admin_only',
                'provider_services_enabled' => 0,
                'allow_provider_custom_services' => 0,
                'allow_provider_override_catalog' => 0,
                'auto_insert_booking_button_enabled' => 1,
                'auto_insert_booking_button' => 'after_content',
                'auto_insert_booking_button_selector' => '',
            ];
        }

        return [
            'provider_resolution_mode' => 'author',
            'provider_meta_key' => '',
            'services_model' => 'provider_only',
            'provider_services_enabled' => 1,
            'allow_provider_custom_services' => 0,
            'allow_provider_override_catalog' => 0,
            'auto_insert_booking_button_enabled' => 1,
            'auto_insert_booking_button' => 'after_content',
            'auto_insert_booking_button_selector' => '',
        ];
    }

    private function get_operational_defaults_map(): array
    {
        return GeneralTab::get_operational_defaults_map();
    }

    private function get_operational_summary_groups( array $opts ): array
    {
        $defaults = $this->get_operational_defaults_map();
        $active = [];
        foreach ( $defaults as $key => $default_value ) {
            $active[ $key ] = array_key_exists( $key, $opts ) ? $opts[ $key ] : $default_value;
        }

        return [
            [
                'title' => __( 'Availability and workflow', 'mybookaro' ),
                'rows' => [
                    [
                        'label' => __( 'Minimum notice before booking', 'mybookaro' ),
                        'default' => $this->format_operational_hours( absint( $defaults['booking_min_notice_hours'] ) ),
                        'active' => $this->format_operational_hours( absint( $active['booking_min_notice_hours'] ) ),
                    ],
                    [
                        'label' => __( 'Maximum booking window', 'mybookaro' ),
                        'default' => $this->format_operational_days( absint( $defaults['booking_max_window_days'] ) ),
                        'active' => $this->format_operational_days( absint( $active['booking_max_window_days'] ) ),
                    ],
                    [
                        'label' => __( 'Buffer before bookings', 'mybookaro' ),
                        'default' => $this->format_operational_minutes( absint( $defaults['booking_buffer_before_minutes'] ) ),
                        'active' => $this->format_operational_minutes( absint( $active['booking_buffer_before_minutes'] ) ),
                    ],
                    [
                        'label' => __( 'Buffer after bookings', 'mybookaro' ),
                        'default' => $this->format_operational_minutes( absint( $defaults['booking_buffer_after_minutes'] ) ),
                        'active' => $this->format_operational_minutes( absint( $active['booking_buffer_after_minutes'] ) ),
                    ],
                    [
                        'label' => __( 'Customer cancellation window', 'mybookaro' ),
                        'default' => $this->format_operational_hours( absint( $defaults['booking_cancel_window_hours'] ) ),
                        'active' => $this->format_operational_hours( absint( $active['booking_cancel_window_hours'] ) ),
                    ],
                    [
                        'label' => __( 'Customer reschedule window', 'mybookaro' ),
                        'default' => $this->format_operational_hours( absint( $defaults['booking_reschedule_window_hours'] ) ),
                        'active' => $this->format_operational_hours( absint( $active['booking_reschedule_window_hours'] ) ),
                    ],
                    [
                        'label' => __( 'Approval workflow', 'mybookaro' ),
                        'default' => $this->format_operational_workflow( ! empty( $defaults['auto_approve_bookings'] ) ),
                        'active' => $this->format_operational_workflow( ! empty( $active['auto_approve_bookings'] ) ),
                    ],
                ],
            ],
            [
                'title' => __( 'Anti-spam and duplicate protection', 'mybookaro' ),
                'rows' => [
                    [
                        'label' => __( 'Honeypot field', 'mybookaro' ),
                        'default' => $this->format_operational_toggle( ! empty( $defaults['booking_spam_honeypot_enabled'] ) ),
                        'active' => $this->format_operational_toggle( ! empty( $active['booking_spam_honeypot_enabled'] ) ),
                    ],
                    [
                        'label' => __( 'Minimum form fill time', 'mybookaro' ),
                        'default' => $this->format_operational_seconds( absint( $defaults['booking_spam_min_fill_seconds'] ) ),
                        'active' => $this->format_operational_seconds( absint( $active['booking_spam_min_fill_seconds'] ) ),
                    ],
                    [
                        'label' => __( 'Burst window length', 'mybookaro' ),
                        'default' => $this->format_operational_seconds( absint( $defaults['booking_spam_burst_window_seconds'] ) ),
                        'active' => $this->format_operational_seconds( absint( $active['booking_spam_burst_window_seconds'] ) ),
                    ],
                    [
                        'label' => __( 'Per-IP burst limit', 'mybookaro' ),
                        'default' => $this->format_operational_requests_per_window( absint( $defaults['booking_spam_burst_ip_limit'] ) ),
                        'active' => $this->format_operational_requests_per_window( absint( $active['booking_spam_burst_ip_limit'] ) ),
                    ],
                    [
                        'label' => __( 'Per-email burst limit', 'mybookaro' ),
                        'default' => $this->format_operational_requests_per_window( absint( $defaults['booking_spam_burst_email_limit'] ) ),
                        'active' => $this->format_operational_requests_per_window( absint( $active['booking_spam_burst_email_limit'] ) ),
                    ],
                    [
                        'label' => __( 'Duplicate pending booking block', 'mybookaro' ),
                        'default' => $this->format_operational_hours( absint( $defaults['booking_spam_duplicate_pending_hours'] ) ),
                        'active' => $this->format_operational_hours( absint( $active['booking_spam_duplicate_pending_hours'] ) ),
                    ],
                ],
            ],
            [
                'title' => __( 'Reminders and booking lifecycle', 'mybookaro' ),
                'rows' => [
                    [
                        'label' => __( 'Reminder emails (24h + 1h)', 'mybookaro' ),
                        'default' => $this->format_operational_toggle( ! empty( $defaults['notify_reminder'] ) ),
                        'active' => $this->format_operational_toggle( ! empty( $active['notify_reminder'] ) ),
                    ],
                    [
                        'label' => __( 'Review invite emails', 'mybookaro' ),
                        'default' => $this->format_operational_toggle( ! empty( $defaults['notify_review_invite'] ) ),
                        'active' => $this->format_operational_toggle( ! empty( $active['notify_review_invite'] ) ),
                    ],
                    [
                        'label' => __( 'Auto-complete approved bookings', 'mybookaro' ),
                        'default' => $this->format_operational_automation_rule(
                            ! empty( $defaults['auto_complete_enabled'] ),
                            absint( $defaults['auto_complete_delay_hours'] )
                        ),
                        'active' => $this->format_operational_automation_rule(
                            ! empty( $active['auto_complete_enabled'] ),
                            absint( $active['auto_complete_delay_hours'] )
                        ),
                    ],
                    [
                        'label' => __( 'Auto-expire pending bookings', 'mybookaro' ),
                        'default' => $this->format_operational_automation_rule(
                            ! empty( $defaults['auto_expire_enabled'] ),
                            absint( $defaults['auto_expire_delay_hours'] )
                        ),
                        'active' => $this->format_operational_automation_rule(
                            ! empty( $active['auto_expire_enabled'] ),
                            absint( $active['auto_expire_delay_hours'] )
                        ),
                    ],
                ],
            ],
        ];
    }

    private function format_operational_toggle( bool $enabled ): string
    {
        return $enabled ? __( 'On', 'mybookaro' ) : __( 'Off', 'mybookaro' );
    }

    private function format_operational_workflow( bool $auto_approve_enabled ): string
    {
        return $auto_approve_enabled
            ? __( 'Auto-approve bookings (manual approval bypassed)', 'mybookaro' )
            : __( 'Manual provider approval required', 'mybookaro' );
    }

    private function format_operational_hours( int $hours ): string
    {
        if ( $hours < 1 ) {
            return __( 'Off', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: hours */
            _n( '%d hour', '%d hours', $hours, 'mybookaro' ),
            $hours
        );
    }

    private function format_operational_days( int $days ): string
    {
        if ( $days < 1 ) {
            return __( 'Off', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: days */
            _n( '%d day', '%d days', $days, 'mybookaro' ),
            $days
        );
    }

    private function format_operational_minutes( int $minutes ): string
    {
        if ( $minutes < 1 ) {
            return __( 'Off', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: minutes */
            _n( '%d minute', '%d minutes', $minutes, 'mybookaro' ),
            $minutes
        );
    }

    private function format_operational_seconds( int $seconds ): string
    {
        if ( $seconds < 1 ) {
            return __( 'Off', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: seconds */
            _n( '%d second', '%d seconds', $seconds, 'mybookaro' ),
            $seconds
        );
    }

    private function format_operational_requests_per_window( int $limit ): string
    {
        if ( $limit < 1 ) {
            return __( 'Off', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: max requests in burst window */
            _n( '%d request per window', '%d requests per window', $limit, 'mybookaro' ),
            $limit
        );
    }

    private function format_operational_automation_rule( bool $enabled, int $delay_hours ): string
    {
        if ( ! $enabled ) {
            return __( 'Off', 'mybookaro' );
        }
        if ( $delay_hours < 1 ) {
            return __( 'On (no delay)', 'mybookaro' );
        }

        return sprintf(
            /* translators: %s: delay in hours */
            __( 'On (delay: %s)', 'mybookaro' ),
            $this->format_operational_hours( $delay_hours )
        );
    }

    public function render_page(): void
    {
        if ( ! $this->wizard_enabled() ) {
            wp_die(
                esc_html__( 'The setup wizard is disabled.', 'mybookaro' ),
                esc_html__( 'Not available', 'mybookaro' ),
                [ 'response' => 403 ]
            );
        }
        if ( ! $this->can_manage_admin() ) {
            wp_die( esc_html__( 'You do not have permission to access this page.', 'mybookaro' ) );
        }

        $mode = $this->wizard_mode();
        if ( 'mylisting' === $mode ) {
            $this->render_mylisting_wizard_page();
            return;
        }

        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        $support_snapshot_url = (string) ( $support_touchpoints['support_snapshot_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-snapshot' ) );
        $support_bundle_url = (string) ( $support_touchpoints['support_bundle_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-bundle' ) );
        $generic_validation_url = (string) ( $support_touchpoints['generic_validation_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' ) );
        $steps = [
            'modes'   => __( 'Lane', 'mybookaro' ),
            'listings'=> __( 'Listings', 'mybookaro' ),
            'services'=> __( 'Services', 'mybookaro' ),
            'pages'   => __( 'Pages', 'mybookaro' ),
            'operational' => __( 'Operational', 'mybookaro' ),
            'done'    => __( 'Finish', 'mybookaro' ),
        ];

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $default_step = array_key_first( $steps ) ?: 'listings';
        $step = sanitize_text_field( wp_unslash( $_GET['step'] ?? $default_step ) );
        if ( ! isset( $steps[ $step ] ) ) {
            $step = $default_step;
        }
        $step_keys = array_keys( $steps );
        $current_index = array_search( $step, $step_keys, true );
        if ( false === $current_index ) {
            $current_index = 0;
        }
        $prev_step = $current_index > 0 ? $step_keys[ $current_index - 1 ] : '';

        $opts = $this->options->get_all();
        if ( 'done' === $step ) {
            wp_safe_redirect( $this->get_wizard_completion_redirect_url( $opts ) );
            exit;
        }
        $general_settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' );
        $notifications_settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=notifications' );
        $operational_summary_groups = $this->get_operational_summary_groups( $opts );
        $site_type = $this->resolve_site_type_from_options( $opts );
        $site_type_selector = ( 'advanced_mapping' === $site_type ) ? 'directory' : $site_type;
        $site_type_options = function_exists( 'bookaro_get_site_type_options' )
            ? bookaro_get_site_type_options()
            : [
                'directory' => __( 'Directory lanes (MyListing Directory or Generic Directory)', 'mybookaro' ),
                'single_business' => __( 'Single Business', 'mybookaro' ),
            ];
        unset( $site_type_options['advanced_mapping'] );
        $is_single_business = ( 'single_business' === $site_type );
        $is_advanced_mapping = ( 'advanced_mapping' === $site_type );
        $generic_confirmation_required = $this->generic_confirmation_required( $opts );
        $generic_legacy_fallback_active = $this->is_generic_legacy_fallback_active( $opts );
        $generic_validation_prompt = $this->get_generic_validation_prompt( $opts );
        $generic_runtime_failed_count = $this->get_generic_runtime_validation_failed_count();
        $generic_validation_refresh_required = ! empty( $generic_validation_prompt['active'] ) && ! empty( $generic_validation_prompt['needs_validation'] );
        $generic_launch_blocked = ! $is_single_business && (
            $generic_confirmation_required
            || $generic_legacy_fallback_active
            || $generic_validation_refresh_required
            || $generic_runtime_failed_count > 0
        );
        $generic_launch_blocked_label = $generic_confirmation_required
            ? __( 'Generic confirmation required', 'mybookaro' )
            : ( $generic_legacy_fallback_active ? __( 'Legacy fallback review required', 'mybookaro' ) : ( $generic_runtime_failed_count > 0 ? __( 'Launch blocked', 'mybookaro' ) : __( 'Revalidation required', 'mybookaro' ) ) );
        $generic_launch_blocked_message = $generic_confirmation_required
            ? $this->get_generic_confirmation_required_notice_message()
            : (
                $generic_legacy_fallback_active
                    ? $this->get_generic_legacy_review_notice_message()
                    : (
                        $generic_runtime_failed_count > 0
                            ? $this->get_generic_runtime_validation_blocked_notice_message( $generic_runtime_failed_count, $generic_validation_refresh_required )
                            : $this->get_generic_launch_readiness_notice_message()
                    )
            );
        $generic_launch_blocked_action_url = $generic_confirmation_required
            ? $this->get_generic_confirmation_required_notice_url()
            : ( $generic_legacy_fallback_active ? $this->get_generic_confirmation_required_notice_url() : $generic_validation_url );
        $generic_launch_blocked_action_label = $generic_confirmation_required
            ? $this->get_generic_confirmation_required_notice_action_label()
            : ( $generic_legacy_fallback_active ? $this->get_generic_legacy_review_notice_action_label() : ( $generic_runtime_failed_count > 0 ? $this->get_generic_runtime_validation_blocked_notice_action_label() : $this->get_generic_launch_readiness_notice_action_label() ) );
        $generic_launch_blocked_pill_class = ( $generic_runtime_failed_count > 0 || $generic_confirmation_required ) ? 'bookaro-status-pill--error' : 'bookaro-status-pill--warn';
        $generic_launch_blocked_pill_label = ( $generic_runtime_failed_count > 0 || $generic_confirmation_required ) ? __( 'Fail', 'mybookaro' ) : __( 'Warn', 'mybookaro' );
        $support_touchpoint_actions = $this->get_support_touchpoint_actions();
        $generic_launch_blocked_support_actions = $this->get_support_handoff_notice_actions( $generic_launch_blocked_action_url );
        $integration_mode = sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) );
        if ( ! in_array( $integration_mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
            $integration_mode = 'auto';
        }
        if ( in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true ) ) {
            $integration_mode = 'generic';
        }
        $integration_mode_description = $generic_confirmation_required
            ? __( 'MyListing is not detected. Pick your lane first (Single Business or guided Generic Directory), save this step, then run validation before launch.', 'mybookaro' )
            : (
                $generic_legacy_fallback_active
                    ? __( 'MyListing is not detected. Generic Directory is using legacy saved settings. Review this lane step and save once to confirm Generic Directory, then run validation before launch.', 'mybookaro' )
                    : __( 'Only used for Directory lane. Auto-select uses MyListing when active; otherwise Bookaro uses Generic Directory.', 'mybookaro' )
            );
        if ( $is_single_business ) {
            $integration_mode_description = __( 'Not needed for Single Business. This setting only applies to Directory lanes.', 'mybookaro' );
        } elseif ( $is_advanced_mapping ) {
            $integration_mode_description = __( 'Your site is using a legacy Generic Directory state. Directory lane choice is handled automatically.', 'mybookaro' );
        }
        $ui_mode = $this->resolve_ui_mode_for_wizard( $opts, $integration_mode );
        $listing_id = (int) ( $opts['generic_setup_listing_id'] ?? 0 );
        $listing_post_type_options = $this->get_listing_post_type_options();
        $selected_listing_types = $opts['allowed_listing_post_types'] ?? [];
        if ( empty( $selected_listing_types ) && ! empty( $opts['listing_post_type'] ) ) {
            $selected_listing_types = [ $opts['listing_post_type'] ];
        }
        if ( ! is_array( $selected_listing_types ) ) {
            $selected_listing_types = [ $selected_listing_types ];
        }
        $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $selected_listing_types ) ) ) );
        if ( empty( $selected_listing_types ) && ! $is_single_business ) {
            $selected_listing_types = array_keys( $listing_post_type_options );
            $selected_listing_types = array_slice( $selected_listing_types, 0, 1 );
        }
        $selected_allowed_pages = $opts['allowed_listing_pages'] ?? [];
        if ( ! is_array( $selected_allowed_pages ) ) {
            $selected_allowed_pages = [ $selected_allowed_pages ];
        }
        $selected_allowed_pages = array_values( array_unique( array_filter( array_map( 'absint', $selected_allowed_pages ) ) ) );
        $provider_resolution_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? '' ) );
        $provider_meta_key = sanitize_key( (string) ( $opts['provider_meta_key'] ?? '' ) );
        if ( '' === $provider_meta_key && ! empty( $opts['listing_provider_meta_key'] ) ) {
            $provider_meta_key = sanitize_key( (string) $opts['listing_provider_meta_key'] );
        }
        $generic_advanced_setup_enabled = ! empty( $opts['generic_advanced_setup_enabled'] );
        if ( $is_advanced_mapping ) {
            $generic_advanced_setup_enabled = true;
        }
        $generic_setup_preset_options = $this->get_generic_setup_preset_options();
        $generic_setup_preset = $this->resolve_generic_setup_preset( $opts );
        if ( $is_single_business ) {
            $generic_setup_preset = 'author_provider';
        }
        $generic_preset_defaults = $this->get_generic_setup_preset_defaults( $generic_setup_preset, $opts );
        if ( ! in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true ) ) {
            $provider_resolution_mode = sanitize_key( (string) ( $generic_preset_defaults['provider_resolution_mode'] ?? 'author' ) );
        }
        if ( ! $generic_advanced_setup_enabled ) {
            $provider_resolution_mode = sanitize_key( (string) ( $generic_preset_defaults['provider_resolution_mode'] ?? $provider_resolution_mode ) );
            $provider_meta_key = sanitize_key( (string) ( $generic_preset_defaults['provider_meta_key'] ?? $provider_meta_key ) );
        }
        if ( $is_single_business ) {
            $provider_resolution_mode = 'author';
            $provider_meta_key = '';
        }
        $default_services_model = $generic_advanced_setup_enabled
            ? 'hybrid'
            : sanitize_key( (string) ( $generic_preset_defaults['services_model'] ?? 'provider_only' ) );
        if ( ! in_array( $default_services_model, [ 'provider_only', 'admin_only', 'hybrid' ], true ) ) {
            $default_services_model = 'provider_only';
        }
        $services_model = sanitize_key( (string) ( $opts['services_model'] ?? $opts['generic_services_mode'] ?? $default_services_model ) );
        if ( 'admin_catalog' === $services_model ) {
            $services_model = 'admin_only';
        }
        if ( ! in_array( $services_model, [ 'admin_only', 'provider_only', 'hybrid' ], true ) ) {
            $services_model = $default_services_model;
        }
        if ( $is_single_business ) {
            $services_model = 'provider_only';
        }
        $auto_insert_mode = sanitize_key( (string) ( $opts['auto_insert_booking_button'] ?? '' ) );
        if ( ! in_array( $auto_insert_mode, [ 'before_content', 'after_content', 'selector' ], true ) ) {
            $auto_insert_mode = '';
        }
        if ( array_key_exists( 'auto_insert_booking_button_enabled', $opts ) ) {
            $auto_insert_enabled = ! empty( $opts['auto_insert_booking_button_enabled'] );
        } else {
            $auto_insert_enabled = ( '' !== $auto_insert_mode );
        }
        $auto_insert_selector = sanitize_text_field( (string) ( $opts['auto_insert_booking_button_selector'] ?? '' ) );
        if ( ! array_key_exists( 'auto_insert_booking_button_enabled', $opts ) && ! array_key_exists( 'auto_insert_booking_button', $opts ) && ! $generic_advanced_setup_enabled ) {
            $auto_insert_enabled = ! empty( $generic_preset_defaults['auto_insert_booking_button_enabled'] );
            $auto_insert_mode = sanitize_key( (string) ( $generic_preset_defaults['auto_insert_booking_button'] ?? 'after_content' ) );
            if ( ! in_array( $auto_insert_mode, [ 'before_content', 'after_content', 'selector' ], true ) ) {
                $auto_insert_mode = 'after_content';
            }
            $auto_insert_selector = sanitize_text_field( (string) ( $generic_preset_defaults['auto_insert_booking_button_selector'] ?? '' ) );
        }
        $wizard_placement_strategy = function_exists( 'bookaro_get_booking_placement_strategy' )
            ? sanitize_key( (string) bookaro_get_booking_placement_strategy() )
            : sanitize_key( (string) ( $opts['booking_placement_strategy'] ?? '' ) );
        if ( ! in_array( $wizard_placement_strategy, [ 'directory_template', 'normal_page', 'shortcode_only', 'css_selector' ], true ) ) {
            $wizard_placement_strategy = $is_single_business ? 'normal_page' : 'shortcode_only';
        }
        $page_options = $this->get_page_options();
        $provider_user_options = $this->get_provider_user_options();
        $default_provider_id = absint( $opts['default_provider_id'] ?? 0 );
        if ( $default_provider_id > 0 && ! get_user_by( 'ID', $default_provider_id ) ) {
            $default_provider_id = 0;
        }
        if ( $is_single_business && $default_provider_id < 1 ) {
            $fallback_provider_id = get_current_user_id();
            if ( $fallback_provider_id > 0 && get_user_by( 'ID', $fallback_provider_id ) ) {
                $default_provider_id = $fallback_provider_id;
            }
        }
        $page_overrides = $opts['listing_post_type_pages'] ?? [];
        if ( ! is_array( $page_overrides ) ) {
            $page_overrides = [];
        }
        // Resolve booking/dashboard pages with full fallback chain: per-post-
        // type overrides -> Setup-Wizard staging keys -> canonical
        // bookaro_settings[booking_page_id] etc. Without the canonical fallback,
        // sites that assigned pages via the Settings UI (which writes the
        // canonical keys) saw "Booking page: Missing" here even though the
        // booking flow worked. bookaro_get_page_for_context() encapsulates
        // the same chain SettingsPageController and GettingStartedController
        // already use. Bug 17.
        $primary_listing_type = $selected_listing_types[0] ?? '';
        $resolve_page = function ( string $context, string $staging_key ) use (
            $page_overrides,
            $selected_listing_types,
            $primary_listing_type,
            $opts
        ): int {
            $staged = absint( $opts[ $staging_key ] ?? 0 );
            $from_overrides = $this->resolve_page_override(
                $page_overrides,
                $selected_listing_types,
                $context,
                $staged
            );
            if ( $from_overrides > 0 ) {
                return $from_overrides;
            }
            if ( $primary_listing_type === '' || ! function_exists( 'bookaro_get_page_for_context' ) ) {
                return 0;
            }
            return absint( bookaro_get_page_for_context( '', $primary_listing_type, $context ) );
        };
        $default_booking_page = $resolve_page( 'booking', 'generic_setup_booking_page_id' );
        $default_provider_page = $resolve_page( 'provider_dashboard', 'generic_setup_provider_dashboard_page_id' );
        $default_customer_page = $resolve_page( 'customer_dashboard', 'generic_setup_customer_dashboard_page_id' );
        $default_services_page = absint( $opts['generic_setup_services_page_id'] ?? 0 );
        $depends_site_type_directory = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_site_type_single_business = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'single_business' ],
            ],
        ] ) ?: '';
        $depends_allowed_pages = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'allowed_listing_post_types', 'operator' => 'contains', 'value' => 'page' ],
                [ 'field' => 'site_type', 'operator' => 'not_equals', 'value' => 'single_business' ],
            ],
        ] ) ?: '';
        $depends_provider_meta_advanced = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'truthy' ],
                [ 'field' => 'provider_resolution_mode', 'operator' => 'equals', 'value' => 'meta_key' ],
            ],
        ] ) ?: '';
        $depends_generic_advanced = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'truthy' ],
            ],
        ] ) ?: '';
        $depends_generic_standard = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'falsy' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_mode_generic = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
            ],
        ] ) ?: '';
        $depends_mode_generic_directory = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_mode_generic_standard = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'falsy' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_mode_generic_advanced = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'truthy' ],
            ],
        ] ) ?: '';
        $depends_mode_mylisting = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'mylisting' ],
            ],
        ] ) ?: '';
        $depends_preset_author_provider = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'falsy' ],
                [ 'field' => 'generic_setup_preset', 'operator' => 'equals', 'value' => 'author_provider' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_preset_meta_key = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'falsy' ],
                [ 'field' => 'generic_setup_preset', 'operator' => 'equals', 'value' => 'meta_key_provider' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_preset_admin_catalog = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'integration_mode', 'operator' => 'equals', 'value' => 'generic' ],
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'falsy' ],
                [ 'field' => 'generic_setup_preset', 'operator' => 'equals', 'value' => 'author_admin_catalog' ],
                [ 'field' => 'site_type', 'operator' => 'equals', 'value' => 'directory' ],
            ],
        ] ) ?: '';
        $depends_auto_insert_advanced = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'truthy' ],
                [ 'field' => 'auto_insert_booking_button_enabled', 'operator' => 'truthy' ],
            ],
        ] ) ?: '';
        $depends_auto_insert_selector_advanced = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'generic_advanced_setup_enabled', 'operator' => 'truthy' ],
                [ 'field' => 'auto_insert_booking_button_enabled', 'operator' => 'truthy' ],
                [ 'field' => 'auto_insert_booking_button', 'operator' => 'equals', 'value' => 'selector' ],
            ],
        ] ) ?: '';
        $depends_ui_shortcodes = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'ui_mode', 'operator' => 'equals', 'value' => 'shortcodes' ],
            ],
        ] ) ?: '';
        $depends_ui_woocommerce = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'ui_mode', 'operator' => 'equals', 'value' => 'woocommerce' ],
            ],
        ] ) ?: '';
        $preset_meta_key_example = sanitize_key( (string) ( $generic_preset_defaults['provider_meta_key'] ?? 'provider_user_id' ) );
        if ( '' === $preset_meta_key_example ) {
            $preset_meta_key_example = 'provider_user_id';
        }
        $generic_preset_profiles = [
            'author_provider' => [
                'pattern' => __( 'Provider-Owned Directory', 'mybookaro' ),
                'outcome' => __( 'Expected outcome: bookings route to each listing owner, and each provider manages their own services.', 'mybookaro' ),
                'who' => __( 'Best for: directories where each provider account authors and manages its own listings.', 'mybookaro' ),
                'decision_hint' => __( 'Use this when listing post_author already equals the provider account that should receive bookings.', 'mybookaro' ),
                'not_for' => __( 'Choose another pattern when editors/admins publish listings and provider ownership is stored in meta.', 'mybookaro' ),
                'site_shape' => __( 'Example site shape: single-provider directory entries authored directly by each provider user.', 'mybookaro' ),
                'assumptions' => __( 'Assumption check: open a sample listing in wp-admin and verify post_author matches the intended provider user ID.', 'mybookaro' ),
                'mapping_guidance' => __( 'Provider mapping guidance: keep Provider Resolution = Listing Author. MyBookaro will use listing post_author as provider owner.', 'mybookaro' ),
                'provider_example' => __( 'Mapping example: listing #123 (author user #44) resolves provider user #44.', 'mybookaro' ),
                'services_guidance' => __( 'Services guidance: use Provider Only so each provider manages only their own services.', 'mybookaro' ),
                'services_example' => __( 'Services example: provider #44 sees and edits only services owned by provider #44.', 'mybookaro' ),
                'placement_guidance' => __( 'Placement expectation: keep UI Mode = Shortcodes, assign Booking + Provider Dashboard + Customer Dashboard pages, and place Booking Button/Services Cards in your listing template or page content. Auto-Insert stays available only as a fallback.', 'mybookaro' ),
                'required_pages' => __( 'Required pages: Booking page, plus Provider Dashboard and Customer Dashboard pages when UI Mode = Shortcodes.', 'mybookaro' ),
                'ready_definition' => __( 'Ready means: provider mapping resolves on sample listings, provider services are available, required pages are assigned with dashboard embeds, Generic validation passes, and one full booking test succeeds.', 'mybookaro' ),
                'quick_setup' => __( 'Quick setup: Provider Mapping = Listing Author. Services Source = Provider Only. Placement = assign pages, then place Booking Button/Services Cards explicitly. Finish by running System Status validation and one full booking test.', 'mybookaro' ),
                'defaults' => __( 'Defaults applied: Provider Mapping = Listing Author, Services Source = Provider Only, Auto-Insert fallback = After content.', 'mybookaro' ),
            ],
            'meta_key_provider' => [
                'pattern' => __( 'Editorial + Meta Key Directory', 'mybookaro' ),
                'outcome' => __( 'Expected outcome: editors can publish listings while bookings still route to the correct provider via listing meta.', 'mybookaro' ),
                'who' => __( 'Best for: directories where listing authorship is editorial and provider ownership is stored in one meta key.', 'mybookaro' ),
                'decision_hint' => __( 'Use this when post_author is not the provider and a provider user ID field (for example, provider_user_id) is consistently populated.', 'mybookaro' ),
                'not_for' => __( 'Choose Provider-Owned Directory when listing author already matches provider ownership on all bookable listings.', 'mybookaro' ),
                'site_shape' => __( 'Example site shape: an editor authors listing #123 while provider_user_id stores provider user #44.', 'mybookaro' ),
                'assumptions' => __( 'Assumption check: confirm the same provider meta key exists and stores valid WordPress user IDs across listings.', 'mybookaro' ),
                'mapping_guidance' => __( 'Provider mapping guidance: set Provider Resolution = Listing Meta Key and use one stable key across listing post types. MyBookaro reads that user ID, then falls back to author if needed.', 'mybookaro' ),
                'provider_example' => sprintf(
                    /* translators: %s: provider meta key */
                    __( 'Mapping example: listing #123 has %s=44, so provider resolves to user #44 even when authored by another user.', 'mybookaro' ),
                    $preset_meta_key_example
                ),
                'services_guidance' => __( 'Services guidance: Provider Only is safest when providers should still manage their own services after meta-key routing.', 'mybookaro' ),
                'services_example' => __( 'Services example: provider #44 manages provider-owned services after listing meta resolves ownership.', 'mybookaro' ),
                'placement_guidance' => __( 'Placement expectation: keep UI Mode = Shortcodes, assign Booking + Provider Dashboard + Customer Dashboard pages, and place Booking Button/Services Cards on the listing/page surfaces where customers start bookings. Auto-Insert stays available only as a fallback.', 'mybookaro' ),
                'required_pages' => __( 'Required pages: Booking page, plus Provider Dashboard and Customer Dashboard pages when UI Mode = Shortcodes.', 'mybookaro' ),
                'ready_definition' => __( 'Ready means: the provider meta key is populated with valid user IDs, services source stays Provider Only, required pages are assigned with dashboard embeds, Generic validation passes, and one full booking test succeeds.', 'mybookaro' ),
                'quick_setup' => sprintf(
                    /* translators: %s: provider meta key */
                    __( 'Quick setup: Provider Mapping = Listing Meta Key, Provider Meta Key = %s, Services Source = Provider Only, then assign pages and place Booking Button/Services Cards explicitly. Finish by running System Status validation and one full booking test.', 'mybookaro' ),
                    $preset_meta_key_example
                ),
                'defaults' => __( 'Defaults applied: Provider Mapping = Listing Meta Key, Services Source = Provider Only, Auto-Insert fallback = After content.', 'mybookaro' ),
            ],
            'author_admin_catalog' => [
                'pattern' => __( 'Shared Catalog Directory', 'mybookaro' ),
                'outcome' => __( 'Expected outcome: bookings still resolve to listing owners while admins maintain one shared service catalog.', 'mybookaro' ),
                'who' => __( 'Best for: teams that want standardized services managed by admins, not by providers.', 'mybookaro' ),
                'decision_hint' => __( 'Use this when providers should fulfill bookings but should not create or edit service definitions.', 'mybookaro' ),
                'not_for' => __( 'Choose another pattern when each provider needs custom services per listing.', 'mybookaro' ),
                'site_shape' => __( 'Example site shape: admins publish one shared catalog in wp-admin while listing author remains the provider.', 'mybookaro' ),
                'assumptions' => __( 'Assumption check: listing author remains provider owner and your team can maintain one shared service catalog.', 'mybookaro' ),
                'mapping_guidance' => __( 'Provider mapping guidance: keep Provider Resolution = Listing Author so listing post_author remains provider owner, and disable provider service editing.', 'mybookaro' ),
                'provider_example' => __( 'Mapping example: listing #123 (author user #44) resolves provider user #44.', 'mybookaro' ),
                'services_guidance' => __( 'Services guidance: use Admin Catalog Only for one shared service menu maintained by admins.', 'mybookaro' ),
                'services_example' => __( 'Services example: customers book from one admin-managed catalog; providers do not create custom services.', 'mybookaro' ),
                'placement_guidance' => __( 'Placement expectation: keep UI Mode = Shortcodes, assign Booking + Provider Dashboard + Customer Dashboard pages, and place Booking Button/Services Cards wherever customers discover the shared catalog. Auto-Insert stays available only as a fallback.', 'mybookaro' ),
                'required_pages' => __( 'Required pages: Booking page, plus Provider Dashboard and Customer Dashboard pages when UI Mode = Shortcodes.', 'mybookaro' ),
                'ready_definition' => __( 'Ready means: listing-author provider mapping is intact, shared catalog services are published, required pages are assigned with dashboard embeds, Generic validation passes, and one full booking test succeeds.', 'mybookaro' ),
                'quick_setup' => __( 'Quick setup: Provider Mapping = Listing Author. Services Source = Admin Catalog Only. Placement = assign pages, then place Booking Button/Services Cards explicitly. Finish by running System Status validation and one full booking test.', 'mybookaro' ),
                'defaults' => __( 'Defaults applied: Provider Mapping = Listing Author, Services Source = Admin Catalog Only, Auto-Insert fallback = After content.', 'mybookaro' ),
            ],
        ];
        $generic_preset_profile = $generic_preset_profiles[ $generic_setup_preset ] ?? $generic_preset_profiles['author_provider'];
        $generic_preset_pattern_name = (string) ( $generic_preset_profile['pattern'] ?? '' );
        $generic_preset_outcome = (string) ( $generic_preset_profile['outcome'] ?? '' );
        $generic_preset_who_should_use = (string) ( $generic_preset_profile['who'] ?? '' );
        $generic_preset_decision_hint = (string) ( $generic_preset_profile['decision_hint'] ?? '' );
        $generic_preset_not_for = (string) ( $generic_preset_profile['not_for'] ?? '' );
        $generic_preset_site_shape = (string) ( $generic_preset_profile['site_shape'] ?? '' );
        $generic_preset_summary = (string) ( $generic_preset_profile['assumptions'] ?? '' );
        $generic_provider_mapping_guidance = (string) ( $generic_preset_profile['mapping_guidance'] ?? '' );
        $generic_provider_mapping_example = (string) ( $generic_preset_profile['provider_example'] ?? '' );
        $generic_services_mapping_guidance = (string) ( $generic_preset_profile['services_guidance'] ?? '' );
        $generic_services_mapping_example = (string) ( $generic_preset_profile['services_example'] ?? '' );
        $generic_placement_guidance = (string) ( $generic_preset_profile['placement_guidance'] ?? '' );
        $generic_required_pages_guidance = (string) ( $generic_preset_profile['required_pages'] ?? '' );
        $generic_ready_definition = (string) ( $generic_preset_profile['ready_definition'] ?? '' );
        $generic_preset_quick_setup = (string) ( $generic_preset_profile['quick_setup'] ?? '' );
        $generic_preset_defaults_summary = (string) ( $generic_preset_profile['defaults'] ?? '' );
        $single_business_provider_ready = ( $default_provider_id > 0 );
        $single_business_missing_pages = [];
        $single_business_missing_page_keys = [];
        $single_business_booking_page_ready = ( $default_booking_page > 0 );
        if ( ! $single_business_booking_page_ready ) {
            $single_business_missing_pages[] = __( 'Booking page', 'mybookaro' );
            $single_business_missing_page_keys[] = 'booking';
        }
        $single_business_dashboard_pages_ready = true;
        if ( 'shortcodes' === $ui_mode ) {
            if ( $default_provider_page < 1 ) {
                $single_business_missing_pages[] = __( 'Provider dashboard page', 'mybookaro' );
                $single_business_missing_page_keys[] = 'provider_dashboard';
                $single_business_dashboard_pages_ready = false;
            }
            if ( $default_customer_page < 1 ) {
                $single_business_missing_pages[] = __( 'Customer dashboard page', 'mybookaro' );
                $single_business_missing_page_keys[] = 'customer_dashboard';
                $single_business_dashboard_pages_ready = false;
            }
        }
        $single_business_pages_ready = empty( $single_business_missing_page_keys );
        $single_business_pages_detail = $single_business_pages_ready
            ? (
                'shortcodes' === $ui_mode
                    ? __( 'Booking page, Provider Dashboard page, and Customer Dashboard page are assigned.', 'mybookaro' )
                    : __( 'Booking page is assigned. Dashboard pages use WooCommerce My Account.', 'mybookaro' )
            )
            : sprintf(
                /* translators: %s: comma separated missing pages */
                __( 'Missing: %s.', 'mybookaro' ),
                implode( ', ', $single_business_missing_pages )
            );
        if ( ! $single_business_pages_ready ) {
            $single_business_pages_detail .= ' ' . __( 'Single Business sequence is strict: assign Booking page first, then dashboard pages (if Shortcodes mode).', 'mybookaro' );
        }
        $single_business_pages_action_label = __( 'Assign pages', 'mybookaro' );
        if ( ! $single_business_pages_ready ) {
            $missing_booking_page = in_array( 'booking', $single_business_missing_page_keys, true );
            $missing_dashboard_pages = in_array( 'provider_dashboard', $single_business_missing_page_keys, true ) || in_array( 'customer_dashboard', $single_business_missing_page_keys, true );
            if ( $missing_booking_page && $missing_dashboard_pages ) {
                $single_business_pages_action_label = __( 'Assign booking + dashboard pages', 'mybookaro' );
            } elseif ( $missing_booking_page ) {
                $single_business_pages_action_label = __( 'Assign Booking page', 'mybookaro' );
            } elseif ( $missing_dashboard_pages ) {
                $single_business_pages_action_label = __( 'Assign dashboard pages', 'mybookaro' );
            }
        }

        $single_business_services_count = $single_business_provider_ready
            ? $this->count_single_business_available_services( $default_provider_id )
            : 0;
        $single_business_services_ready = $single_business_provider_ready && $single_business_services_count > 0;
        $single_business_preview_url = $this->resolve_single_business_preview_url( $default_booking_page, $default_services_page );
        $single_business_preview_ready = $single_business_provider_ready
            && $single_business_pages_ready
            && $single_business_services_ready
            && '' !== trim( $single_business_preview_url );
        $single_business_fast_path_url = $this->get_single_business_fast_path_url();
        $single_business_fast_path_ready = $single_business_provider_ready
            && $single_business_pages_ready
            && $single_business_services_ready
            && '' !== trim( $single_business_fast_path_url );
        $single_business_provider_detail = $single_business_provider_ready
            ? __( 'Default Provider is set. Continue with pages, first service, then preview booking.', 'mybookaro' )
            : __( 'Set Default Provider first. Single Business bookings cannot resolve provider context without it.', 'mybookaro' );
        $single_business_services_detail = ! $single_business_provider_ready
            ? __( 'Cannot validate service inventory until Default Provider is set.', 'mybookaro' )
            : (
                $single_business_services_ready
                    ? sprintf(
                        /* translators: %d: available services count */
                        __( 'Available services for the Default Provider: %d. Continue to preview booking.', 'mybookaro' ),
                        $single_business_services_count
                    )
                    : __( 'No services are available for the Default Provider. Create one service before previewing bookings.', 'mybookaro' )
            );
        $single_business_ready_detail = $single_business_preview_ready
            ? __( 'Open booking/services preview and run one end-to-end booking test.', 'mybookaro' )
            : __( 'Follow this order: Default Provider -> Pages -> First service -> Preview booking.', 'mybookaro' );
        $generic_compact_context = [];
        if ( ! $is_single_business && 'generic' === $integration_mode ) {
            $generic_model_payload = $this->build_generic_compact_model_payload(
                $generic_setup_preset,
                $provider_resolution_mode,
                $provider_meta_key,
                $services_model,
                $wizard_placement_strategy,
                $auto_insert_enabled,
                $auto_insert_mode,
                $auto_insert_selector
            );
            $generic_compact_context = [
                'current_model' => (string) ( $generic_model_payload['summary'] ?? '' ),
                'model_items' => is_array( $generic_model_payload['items'] ?? null ) ? $generic_model_payload['items'] : [],
                'main_blocker' => $this->build_generic_compact_blocker_summary(
                    $generic_confirmation_required,
                    $generic_legacy_fallback_active,
                    $generic_validation_refresh_required,
                    $generic_runtime_failed_count
                ),
            ];
        }
        $generic_preset_conflict_notice = $this->build_generic_preset_conflict_notice( $opts );
        $generic_preset_conflict_actions = [];
        if ( ! empty( $generic_preset_conflict_notice ) ) {
            $generic_preset_conflict_actions = $this->normalize_notice_actions(
                (string) ( $generic_preset_conflict_notice['action_url'] ?? '' ),
                (string) ( $generic_preset_conflict_notice['action_label'] ?? '' ),
                is_array( $generic_preset_conflict_notice['actions'] ?? null )
                    ? $generic_preset_conflict_notice['actions']
                    : []
            );
        } else {
            delete_transient( self::GENERIC_PRESET_CONFLICT_NOTICE_KEY );
        }
        $lane_summary = $this->build_wizard_lane_summary_banner(
            $site_type,
            $integration_mode,
            $generic_launch_blocked,
            $generic_launch_blocked_message,
            $generic_launch_blocked_action_label,
            $generic_launch_blocked_action_url,
            $step,
            $steps,
            (int) $current_index,
            $single_business_provider_ready,
            $single_business_pages_ready,
            $single_business_services_ready,
            $single_business_fast_path_url,
            $generic_compact_context,
            [
                'provider_ready' => $single_business_provider_ready,
                'pages_ready' => $single_business_pages_ready,
                'services_ready' => $single_business_services_ready,
                'missing_page_keys' => $single_business_missing_page_keys,
                'default_provider_url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' ),
                'pages_url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=pages' ),
                'pages_action_label' => $single_business_pages_action_label,
                'create_service_url' => admin_url( 'post-new.php?post_type=' . ( defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service' ) ),
                'ready_url' => '' !== trim( $single_business_preview_url ) ? $single_business_preview_url : $single_business_fast_path_url,
                'provider_detail' => $single_business_provider_detail,
                'pages_detail' => $single_business_pages_detail,
                'services_detail' => $single_business_services_detail,
                'ready_detail' => $single_business_ready_detail,
                'services_count' => $single_business_services_count,
                'dashboard_mode' => $ui_mode,
                'booking_page_ready' => $single_business_booking_page_ready,
                'dashboard_pages_ready' => $single_business_dashboard_pages_ready,
                'preview_ready' => $single_business_preview_ready,
                'preview_url' => $single_business_preview_url,
                'fast_path_ready' => $single_business_fast_path_ready,
                'fast_path_url' => $single_business_fast_path_url,
            ]
        );
        ?>
        <div class="wrap bookaro-admin bookaro-setup-wizard">
            <div class="bookaro-card bookaro-hero bookaro-setup-hero">
                <div class="bookaro-hero__content">
                    <div class="bookaro-hero__brand">
                        <img src="<?php echo esc_url( BOOKARO_PLUGIN_URL . 'assets/img/mb-logo.svg' ); ?>" alt="<?php esc_attr_e( 'MyBookaro', 'mybookaro' ); ?>" width="120" height="36" />
                    </div>
                    <h1><?php esc_html_e( 'MyBookaro Setup Wizard', 'mybookaro' ); ?></h1>
                    <p class="description"><?php esc_html_e( 'Choose your lane first: MyListing Directory, Single Business, or guided Generic Directory. MyBookaro is compatible with MyListing, and each lane has a launch checklist.', 'mybookaro' ); ?></p>
                    <p class="description">
                        <?php
                        printf(
                            /* translators: %1$s: dynamic string, %2$s: dynamic string */
                            wp_kses_post( __( 'Support handoff: start with the <a href="%1$s">masked support snapshot</a>. Use the <a href="%2$s">Support Bundle</a> only when support asks for deeper diagnostics.', 'mybookaro' ) ),
                            esc_url( $support_snapshot_url ),
                            esc_url( $support_bundle_url )
                        );
                        ?>
                    </p>
                </div>
                <div class="bookaro-hero__actions">
                    <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' ) ); ?>">
                        <?php esc_html_e( 'Go to settings', 'mybookaro' ); ?>
                    </a>
                    <?php foreach ( $support_touchpoint_actions as $support_touchpoint_action ) : ?>
                        <a class="button button-secondary" href="<?php echo esc_url( (string) ( $support_touchpoint_action['url'] ?? '' ) ); ?>">
                            <?php echo esc_html( (string) ( $support_touchpoint_action['label'] ?? '' ) ); ?>
                        </a>
                    <?php endforeach; ?>
                    <?php if ( $generic_launch_blocked ) : ?>
                        <a class="button button-primary" href="<?php echo esc_url( $generic_launch_blocked_action_url ); ?>">
                            <?php echo esc_html( $generic_launch_blocked_action_label ); ?>
                        </a>
                    <?php endif; ?>
                </div>
            </div>
            <?php TemplateLoader::render( 'admin/components/lane-summary-banner.php', [ 'lane_summary' => $lane_summary ] ); ?>

            <div class="bookaro-card bookaro-stepper">
                <?php
                $step_index = 0;
                foreach ( $steps as $slug => $label ) :
                    $is_active = ( $slug === $step );
                    $classes = [ 'bookaro-stepper__item' ];
                    if ( $is_active ) {
                        $classes[] = 'is-active';
                    }
                    if ( $step_index < $current_index ) {
                        $classes[] = 'is-complete';
                    }
                    $step_index++;
                    ?>
                    <div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
                        <span class="bookaro-stepper__index"><?php echo esc_html( (string) $step_index ); ?></span>
                        <span class="bookaro-stepper__label"><?php echo esc_html( $label ); ?></span>
                    </div>
                <?php endforeach; ?>
            </div>

            <?php if ( $generic_launch_blocked ) : ?>
                <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                    <strong><?php echo esc_html( $generic_launch_blocked_label ); ?></strong>
                    <span class="bookaro-status-pill <?php echo esc_attr( $generic_launch_blocked_pill_class ); ?>">
                        <?php echo esc_html( $generic_launch_blocked_pill_label ); ?>
                    </span>
                    <p class="description"><?php echo esc_html( $generic_launch_blocked_message ); ?></p>
                    <p>
                        <a class="button button-primary" href="<?php echo esc_url( $generic_launch_blocked_action_url ); ?>">
                            <?php echo esc_html( $generic_launch_blocked_action_label ); ?>
                        </a>
                        <?php foreach ( $generic_launch_blocked_support_actions as $support_touchpoint_action ) : ?>
                            <a class="button button-secondary" href="<?php echo esc_url( (string) ( $support_touchpoint_action['url'] ?? '' ) ); ?>">
                                <?php echo esc_html( (string) ( $support_touchpoint_action['label'] ?? '' ) ); ?>
                            </a>
                        <?php endforeach; ?>
                    </p>
                </div>
            <?php endif; ?>

            <div class="bookaro-card bookaro-setup-panel">
            <?php if ( ! empty( $generic_preset_conflict_notice ) && '' !== trim( (string) ( $generic_preset_conflict_notice['message'] ?? '' ) ) ) : ?>
                <div class="bookaro-note bookaro-note--error bookaro-setup-note">
                    <strong><?php echo esc_html( (string) ( $generic_preset_conflict_notice['title'] ?? __( 'Generic preset mismatch', 'mybookaro' ) ) ); ?></strong>
                    <p class="description"><?php echo esc_html( (string) ( $generic_preset_conflict_notice['message'] ?? '' ) ); ?></p>
                    <?php if ( ! empty( $generic_preset_conflict_actions ) ) : ?>
                        <p>
                            <?php foreach ( $generic_preset_conflict_actions as $index => $action ) : ?>
                                <a class="button <?php echo esc_attr( 0 === $index ? 'button-primary' : 'button-secondary' ); ?>" href="<?php echo esc_url( (string) ( $action['url'] ?? '' ) ); ?>">
                                    <?php echo esc_html( (string) ( $action['label'] ?? '' ) ); ?>
                                </a>
                            <?php endforeach; ?>
                        </p>
                    <?php endif; ?>
                </div>
            <?php endif; ?>
            <?php if ( 'modes' === $step ) : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Choose your lane', 'mybookaro' ); ?></h2>
                    <p class="description"><?php esc_html_e( 'Start with lane choice: MyListing Directory, Single Business, or guided Generic Directory. Then confirm mapping, services, pages, and validation for that lane.', 'mybookaro' ); ?></p>
                </div>
                <?php if ( $generic_confirmation_required ) : ?>
                    <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                        <strong><?php esc_html_e( 'Generic setup confirmation required', 'mybookaro' ); ?></strong>
                        <p class="description"><?php echo esc_html( $this->get_generic_confirmation_required_notice_message() ); ?></p>
                    </div>
                <?php elseif ( $generic_legacy_fallback_active ) : ?>
                    <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                        <strong><?php esc_html_e( 'Legacy Generic fallback detected', 'mybookaro' ); ?></strong>
                        <p class="description"><?php echo esc_html( $this->get_generic_legacy_review_notice_message() ); ?></p>
                    </div>
                <?php endif; ?>
                <?php
                $integration_options = function_exists( 'bookaro_get_integration_mode_options' )
                    ? bookaro_get_integration_mode_options()
                    : [
                        'auto' => __( 'Auto-select Directory lane (MyListing when active)', 'mybookaro' ),
                        'mylisting' => __( 'MyListing Directory', 'mybookaro' ),
                        'generic' => __( 'Generic Directory', 'mybookaro' ),
                    ];
                if ( isset( $integration_options['auto'] ) ) {
                    $integration_options['auto'] = __( 'Auto-select Directory lane (MyListing when active)', 'mybookaro' );
                }
                ?>
                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                    <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                    <input type="hidden" name="action" value="bookaro_setup_wizard">
                    <input type="hidden" name="step" value="modes">

                    <table class="form-table" role="presentation">
                        <tr>
                            <th scope="row"><label for="bookaro-site-type"><?php esc_html_e( 'Lane', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-site-type" name="site_type" data-bookaro-setting="site_type">
                                    <?php foreach ( $site_type_options as $site_type_value => $site_type_label ) : ?>
                                        <option value="<?php echo esc_attr( $site_type_value ); ?>" <?php selected( $site_type_selector, $site_type_value ); ?>>
                                            <?php echo esc_html( $site_type_label ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Choose one lane first: MyListing Directory, Single Business, or guided Generic Directory. Generic advanced options are optional and do not create a fourth lane.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_site_type_directory ); ?>">
                            <th scope="row"><label for="bookaro-integration-mode"><?php esc_html_e( 'Directory lane choice', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-integration-mode" name="integration_mode" data-bookaro-setting="integration_mode">
                                    <?php foreach ( $integration_options as $value => $label ) : ?>
                                        <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $integration_mode, $value ); ?>>
                                            <?php echo esc_html( $label ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php echo esc_html( $integration_mode_description ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_site_type_single_business ); ?>">
                            <th scope="row"><?php esc_html_e( 'Lane status', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Single Business is a first-class provider-first lane: set Default Provider, assign pages, and run a preview booking.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_mylisting ); ?>">
                            <th scope="row"><?php esc_html_e( 'MyListing Directory lane path', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Complete the MyListing Directory lane checklist: sidebar booking entry, repeater mapping, and one end-to-end booking test.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_directory ); ?>">
                            <th scope="row"><?php esc_html_e( 'Generic Directory lane path', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Choose the Generic preset that matches your directory workflow, then confirm provider mapping, Services Source, placement path, required pages, and ready definition before launch.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_site_type_single_business ); ?>">
                            <th scope="row"><?php esc_html_e( 'Single Business launch path', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Provider-first Single Business flow: set a default provider, assign booking/dashboard pages, and run one end-to-end booking test.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_advanced ); ?>">
                            <th scope="row"><?php esc_html_e( 'Generic Directory advanced options', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Use Generic advanced options only when none of the three guided presets fit. You can override provider mapping, services source, and placement directly, then validate in System Status before launch.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_directory ); ?>">
                            <th scope="row"><?php esc_html_e( 'Generic Directory guided presets', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Use one of these three Generic presets. Each one tells you the expected ownership, services source, and placement path before you launch.', 'mybookaro' ); ?></p>
                                <table class="widefat striped">
                                    <thead>
                                        <tr>
                                            <th><?php esc_html_e( 'Preset', 'mybookaro' ); ?></th>
                                            <th><?php esc_html_e( 'Provider mapping', 'mybookaro' ); ?></th>
                                            <th><?php esc_html_e( 'Services source', 'mybookaro' ); ?></th>
                                            <th><?php esc_html_e( 'Placement + required pages + ready', 'mybookaro' ); ?></th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr>
                                            <td><?php esc_html_e( 'Provider-Owned Directory', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Listing Author (provider = listing post_author)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Provider Only (providers manage their own services)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Use Shortcodes mode, assign Booking/Provider/Customer pages, place Booking Button/Services Cards explicitly. Ready means mapping/services/pages validate and one full booking test succeeds.', 'mybookaro' ); ?></td>
                                        </tr>
                                        <tr>
                                            <td><?php esc_html_e( 'Editorial + Meta Key Directory', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Listing Meta Key (provider user ID field on the listing)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Provider Only (providers manage their own services)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Use Shortcodes mode, assign Booking/Provider/Customer pages, place Booking Button/Services Cards explicitly. Ready means meta-key mapping/services/pages validate and one full booking test succeeds.', 'mybookaro' ); ?></td>
                                        </tr>
                                        <tr>
                                            <td><?php esc_html_e( 'Shared Catalog Directory', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Listing Author (provider = listing post_author)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Admin Catalog Only (admins manage one shared catalog)', 'mybookaro' ); ?></td>
                                            <td><?php esc_html_e( 'Use Shortcodes mode, assign Booking/Provider/Customer pages, place Booking Button/Services Cards explicitly. Ready means shared catalog/services/pages validate and one full booking test succeeds.', 'mybookaro' ); ?></td>
                                        </tr>
                                    </tbody>
                                </table>
                                <p class="description"><?php esc_html_e( 'Generic advanced options (optional) let you override provider mapping, services source, or selector-based placement when none of the three presets fit your data model.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><?php esc_html_e( 'UI Mode', 'mybookaro' ); ?></th>
                            <td>
                                <label>
                                    <input type="radio" name="ui_mode" value="shortcodes" data-bookaro-setting="ui_mode" <?php checked( $ui_mode, 'shortcodes' ); ?>>
                                    <?php esc_html_e( 'Shortcodes (place dashboards and booking UI on pages you choose)', 'mybookaro' ); ?>
                                </label><br>
                                <label>
                                    <input type="radio" name="ui_mode" value="woocommerce" data-bookaro-setting="ui_mode" <?php checked( $ui_mode, 'woocommerce' ); ?>>
                                    <?php esc_html_e( 'WooCommerce My Account (dashboards in the My Account area)', 'mybookaro' ); ?>
                                </label>
                                <p class="description" data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic ); ?>">
                                    <?php esc_html_e( 'For the Generic Directory lane, keep Shortcodes as the primary path (pages + blocks/shortcodes + validation). Use WooCommerce only when you intentionally want dashboards in My Account.', 'mybookaro' ); ?>
                                </p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_standard ); ?>">
                            <th scope="row"><label for="bookaro-generic-setup-preset"><?php esc_html_e( 'Guided setup path', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-generic-setup-preset" name="generic_setup_preset" data-bookaro-setting="generic_setup_preset">
                                    <?php foreach ( $generic_setup_preset_options as $preset_value => $preset_label ) : ?>
                                        <option value="<?php echo esc_attr( $preset_value ); ?>" <?php selected( $generic_setup_preset, $preset_value ); ?>>
                                            <?php echo esc_html( $preset_label ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Choose the Generic preset that matches your directory workflow. Review the placement expectation in the preset details before continuing.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_directory ); ?>">
                            <th scope="row"><?php esc_html_e( 'Advanced Generic options (optional)', 'mybookaro' ); ?></th>
                            <td>
                                <input type="hidden" name="generic_advanced_setup_enabled" value="0">
                                <label>
                                    <input type="checkbox" name="generic_advanced_setup_enabled" value="1" data-bookaro-setting="generic_advanced_setup_enabled" <?php checked( $generic_advanced_setup_enabled ); ?>>
                                    <?php esc_html_e( 'Enable Generic advanced options', 'mybookaro' ); ?>
                                </label>
                                <p class="description"><?php esc_html_e( 'Leave this off for the three guided presets. Enable it only if you need to override provider mapping, services source, or selector-based placement directly.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_mode_generic_advanced ); ?>">
                            <th scope="row"><?php esc_html_e( 'Advanced options status', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Advanced Generic options are enabled. The Listings and Services steps will show raw Provider Mapping, Services Source, and placement fields that can override preset defaults.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_preset_author_provider ); ?>">
                            <th scope="row"><?php esc_html_e( 'Guided path details', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><strong><?php esc_html_e( 'Guided path:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['pattern'] ?? '' ) ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Expected outcome:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['outcome'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['who'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['decision_hint'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['not_for'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['site_shape'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['assumptions'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['mapping_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['provider_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['services_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['services_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['placement_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['required_pages'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['ready_definition'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['quick_setup'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_provider']['defaults'] ?? '' ) ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_preset_meta_key ); ?>">
                            <th scope="row"><?php esc_html_e( 'Guided path details', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><strong><?php esc_html_e( 'Guided path:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['pattern'] ?? '' ) ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Expected outcome:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['outcome'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['who'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['decision_hint'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['not_for'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['site_shape'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['assumptions'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['mapping_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['provider_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['services_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['services_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['placement_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['required_pages'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['ready_definition'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['quick_setup'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['meta_key_provider']['defaults'] ?? '' ) ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_preset_admin_catalog ); ?>">
                            <th scope="row"><?php esc_html_e( 'Guided path details', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><strong><?php esc_html_e( 'Guided path:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['pattern'] ?? '' ) ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Expected outcome:', 'mybookaro' ); ?></strong> <?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['outcome'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['who'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['decision_hint'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['not_for'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['site_shape'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['assumptions'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['mapping_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['provider_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['services_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['services_example'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['placement_guidance'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['required_pages'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['ready_definition'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['quick_setup'] ?? '' ) ); ?></p>
                                <p class="description"><?php echo esc_html( (string) ( $generic_preset_profiles['author_admin_catalog']['defaults'] ?? '' ) ); ?></p>
                            </td>
                        </tr>
                    </table>

                    <div class="bookaro-actions">
                        <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                            <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                        </button>
                    </div>
                </form>
            <?php elseif ( 'listings' === $step ) : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Listing settings', 'mybookaro' ); ?></h2>
                    <p class="description">
                        <?php
                        echo esc_html(
                            $is_single_business
                                ? __( 'Single Business path: listing post type selection is optional. Keep provider-centric defaults unless you need explicit listing mapping.', 'mybookaro' )
                                : __( 'Choose the listing post types that should be bookable, then keep the preset provider mapping unless advanced options are intentionally enabled.', 'mybookaro' )
                        );
                        ?>
                    </p>
                </div>
                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                    <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                    <input type="hidden" name="action" value="bookaro_setup_wizard">
                    <input type="hidden" name="step" value="listings">
                    <input type="hidden" name="site_type" value="<?php echo esc_attr( $site_type ); ?>" data-bookaro-setting="site_type">
                    <input type="hidden" name="generic_advanced_setup_enabled" value="<?php echo esc_attr( $generic_advanced_setup_enabled ? '1' : '' ); ?>" data-bookaro-setting="generic_advanced_setup_enabled">
                    <input type="hidden" name="generic_setup_preset" value="<?php echo esc_attr( $generic_setup_preset ); ?>" data-bookaro-setting="generic_setup_preset">

                    <table class="form-table" role="presentation">
                        <tr>
                            <th scope="row"><label for="bookaro-listing-types"><?php esc_html_e( 'Listing Post Types', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-listing-types" name="allowed_listing_post_types[]" multiple size="6" data-bookaro-setting="allowed_listing_post_types">
                                    <?php foreach ( $listing_post_type_options as $key => $label ) : ?>
                                        <option value="<?php echo esc_attr( $key ); ?>" <?php selected( in_array( $key, $selected_listing_types, true ) ); ?>>
                                            <?php echo esc_html( $label ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description">
                                    <?php
                                    echo esc_html(
                                        $is_single_business
                                            ? __( 'Optional in Single Business lane. Leave empty to keep provider-centric defaults, or select listing post types if you also publish provider listings.', 'mybookaro' )
                                            : __( 'Select the post types that represent your listings.', 'mybookaro' )
                                    );
                                    ?>
                                </p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_site_type_single_business ); ?>">
                            <th scope="row"><label for="bookaro-default-provider"><?php esc_html_e( 'Default Provider', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-default-provider" name="default_provider_id">
                                    <?php foreach ( $provider_user_options as $provider_user_id => $provider_label ) : ?>
                                        <option value="<?php echo esc_attr( $provider_user_id ); ?>" <?php selected( (int) $provider_user_id, $default_provider_id ); ?>>
                                            <?php echo esc_html( $provider_label ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Single Business uses this provider for booking buttons and services cards when no listing context is provided.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_allowed_pages ); ?>">
                            <th scope="row"><label for="bookaro-allowed-pages"><?php esc_html_e( 'Allowed Listing Pages', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-allowed-pages" name="allowed_listing_pages[]" multiple size="6">
                                    <?php foreach ( $this->get_page_options() as $page_id => $page_title ) : ?>
                                        <option value="<?php echo esc_attr( $page_id ); ?>" <?php selected( in_array( $page_id, $selected_allowed_pages, true ) ); ?>>
                                            <?php echo esc_html( $page_title ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Optional. If you include Pages above, restrict bookings to specific page IDs.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_generic_standard ); ?>">
                            <th scope="row"><?php esc_html_e( 'Preset provider mapping', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Advanced options are off. Provider Mapping comes from the selected Generic preset.', 'mybookaro' ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Guided path:', 'mybookaro' ); ?></strong> <?php echo esc_html( $generic_preset_pattern_name ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Expected outcome:', 'mybookaro' ); ?></strong> <?php echo esc_html( $generic_preset_outcome ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_who_should_use ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_decision_hint ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_not_for ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_site_shape ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_summary ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_provider_mapping_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_provider_mapping_example ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_placement_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_required_pages_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_ready_definition ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_quick_setup ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_defaults_summary ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_preset_meta_key ); ?>">
                            <th scope="row"><?php esc_html_e( 'Meta key recommendation', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'If your theme stores provider IDs in another field, set that key when advanced options are enabled (example: owner_user_id or agent_id).', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_generic_advanced ); ?>">
                            <th scope="row"><label for="bookaro-provider-resolution"><?php esc_html_e( 'Provider Resolution', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-provider-resolution" name="provider_resolution_mode" data-bookaro-setting="provider_resolution_mode">
                                    <option value="author" <?php selected( $provider_resolution_mode, 'author' ); ?>>
                                        <?php esc_html_e( 'Listing Author', 'mybookaro' ); ?>
                                    </option>
                                    <option value="meta_key" <?php selected( $provider_resolution_mode, 'meta_key' ); ?>>
                                        <?php esc_html_e( 'Listing Meta Key', 'mybookaro' ); ?>
                                    </option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Advanced compatibility control: change Provider Mapping only if the selected Generic preset does not match how your listings resolve providers.', 'mybookaro' ); ?></p>
                                <p class="description"><?php esc_html_e( 'Use Listing Author when providers publish their own listings. Use Listing Meta Key when editors/admins publish listings and a meta field (for example provider_user_id) stores the provider WordPress user ID.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_provider_meta_advanced ); ?>">
                            <th scope="row"><label for="bookaro-provider-meta"><?php esc_html_e( 'Provider Meta Key', 'mybookaro' ); ?></label></th>
                            <td>
                                <input type="text" id="bookaro-provider-meta" name="provider_meta_key" class="regular-text" value="<?php echo esc_attr( $provider_meta_key ); ?>">
                                <p class="description"><?php esc_html_e( 'Meta key that stores the provider user ID for a listing when using the Listing Meta Key mode (example: provider_user_id).', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                    </table>

                    <div class="bookaro-actions">
                        <?php if ( $prev_step !== '' ) : ?>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                            </a>
                        <?php endif; ?>
                        <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                            <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                        </button>
                    </div>
                </form>
            <?php elseif ( 'services' === $step ) : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Services and booking button', 'mybookaro' ); ?></h2>
                    <p class="description"><?php esc_html_e( 'Confirm the preset Services Source, then set the booking entry placement customers will actually use. Use advanced options only when the preset does not fit.', 'mybookaro' ); ?></p>
                </div>
                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                    <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                    <input type="hidden" name="action" value="bookaro_setup_wizard">
                    <input type="hidden" name="step" value="services">
                    <input type="hidden" name="generic_advanced_setup_enabled" value="<?php echo esc_attr( $generic_advanced_setup_enabled ? '1' : '' ); ?>" data-bookaro-setting="generic_advanced_setup_enabled">
                    <input type="hidden" name="generic_setup_preset" value="<?php echo esc_attr( $generic_setup_preset ); ?>" data-bookaro-setting="generic_setup_preset">

                    <table class="form-table" role="presentation">
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_generic_standard ); ?>">
                            <th scope="row"><?php esc_html_e( 'Preset services source', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Advanced options are off. Services Source comes from the selected Generic preset.', 'mybookaro' ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Guided path:', 'mybookaro' ); ?></strong> <?php echo esc_html( $generic_preset_pattern_name ); ?></p>
                                <p class="description"><strong><?php esc_html_e( 'Expected outcome:', 'mybookaro' ); ?></strong> <?php echo esc_html( $generic_preset_outcome ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_who_should_use ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_decision_hint ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_not_for ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_site_shape ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_summary ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_services_mapping_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_services_mapping_example ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_placement_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_required_pages_guidance ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_ready_definition ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_quick_setup ); ?></p>
                                <p class="description"><?php echo esc_html( $generic_preset_defaults_summary ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_preset_admin_catalog ); ?>">
                            <th scope="row"><?php esc_html_e( 'Catalog guidance', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'Keep provider service editing disabled for shared catalogs, publish/update services from wp-admin, then place Booking Button/Services Cards wherever customers should access that shared menu.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_generic_advanced ); ?>">
                            <th scope="row"><label for="bookaro-services-model"><?php esc_html_e( 'Services Model', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-services-model" name="services_model">
                                    <option value="provider_only" <?php selected( $services_model, 'provider_only' ); ?>>
                                        <?php esc_html_e( 'Provider Only', 'mybookaro' ); ?>
                                    </option>
                                    <option value="admin_only" <?php selected( $services_model, 'admin_only' ); ?>>
                                        <?php esc_html_e( 'Admin Catalog Only', 'mybookaro' ); ?>
                                    </option>
                                    <option value="hybrid" <?php selected( $services_model, 'hybrid' ); ?>>
                                        <?php esc_html_e( 'Hybrid (Catalog + Provider)', 'mybookaro' ); ?>
                                    </option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Advanced compatibility control: change Services Source only if the selected Generic preset does not match how your services should be managed.', 'mybookaro' ); ?></p>
                                <p class="description"><?php esc_html_e( 'Examples: Provider Only for marketplaces where each provider has unique offers. Admin Catalog for fixed service menus. Hybrid for shared base services plus provider-specific extras.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><label for="bookaro-booking-placement-strategy"><?php esc_html_e( 'Booking placement', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-booking-placement-strategy" name="booking_placement_strategy" data-bookaro-setting="booking_placement_strategy">
                                    <option value="normal_page" <?php selected( $wizard_placement_strategy, 'normal_page' ); ?>>
                                        <?php esc_html_e( 'Normal page (place Booking Button / Services blocks on a page you choose)', 'mybookaro' ); ?>
                                    </option>
                                    <option value="shortcode_only" <?php selected( $wizard_placement_strategy, 'shortcode_only' ); ?>>
                                        <?php esc_html_e( 'Shortcode / block only', 'mybookaro' ); ?>
                                    </option>
                                    <option value="directory_template" <?php selected( $wizard_placement_strategy, 'directory_template' ); ?>>
                                        <?php esc_html_e( 'Directory / listing template (auto-insert on listing pages)', 'mybookaro' ); ?>
                                    </option>
                                    <option value="css_selector" <?php selected( $wizard_placement_strategy, 'css_selector' ); ?>>
                                        <?php esc_html_e( 'CSS selector', 'mybookaro' ); ?>
                                    </option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Where customers start a booking. Single Business and most page-based sites should use Normal page or Shortcode / block only. Choose Directory / listing template or CSS selector only when your theme renders listing pages that should carry the Book Now button.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><?php esc_html_e( 'Auto-Insert Book Now', 'mybookaro' ); ?></th>
                            <td>
                                <label>
                                    <input type="checkbox" name="auto_insert_booking_button_enabled" value="1" data-bookaro-setting="auto_insert_booking_button_enabled" <?php checked( $auto_insert_enabled ); ?>>
                                    <?php esc_html_e( 'Automatically insert a Book Now button on listing pages', 'mybookaro' ); ?>
                                </label>
                                <p class="description"><?php esc_html_e( 'Optional fallback when you cannot place Booking Button/Services Cards blocks or shortcodes directly. The primary Generic path is assigned pages plus explicit placement.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_generic_standard ); ?>">
                            <th scope="row"><?php esc_html_e( 'Placement strategy defaults', 'mybookaro' ); ?></th>
                            <td>
                                <p class="description"><?php esc_html_e( 'The preset expects an assigned Booking page and explicit Booking Button/Services Cards placement. New installs keep Auto-Insert fallback = After content, and existing custom placement is preserved.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_auto_insert_advanced ); ?>">
                            <th scope="row"><label for="bookaro-auto-insert-placement"><?php esc_html_e( 'Auto-Insert Placement', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-auto-insert-placement" name="auto_insert_booking_button" data-bookaro-setting="auto_insert_booking_button">
                                    <option value=""><?php esc_html_e( 'Select placement', 'mybookaro' ); ?></option>
                                    <option value="before_content" <?php selected( $auto_insert_mode, 'before_content' ); ?>>
                                        <?php esc_html_e( 'Before content', 'mybookaro' ); ?>
                                    </option>
                                    <option value="after_content" <?php selected( $auto_insert_mode, 'after_content' ); ?>>
                                        <?php esc_html_e( 'After content', 'mybookaro' ); ?>
                                    </option>
                                    <option value="selector" <?php selected( $auto_insert_mode, 'selector' ); ?>>
                                        <?php esc_html_e( 'Via CSS selector (advanced)', 'mybookaro' ); ?>
                                    </option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Choose where the Book Now button should appear when auto-insert is enabled.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_auto_insert_selector_advanced ); ?>">
                            <th scope="row"><label for="bookaro-auto-insert-selector"><?php esc_html_e( 'Auto-Insert Selector', 'mybookaro' ); ?></label></th>
                            <td>
                                <input type="text" id="bookaro-auto-insert-selector" name="auto_insert_booking_button_selector" class="regular-text" value="<?php echo esc_attr( $auto_insert_selector ); ?>">
                                <p class="description"><?php esc_html_e( 'Used only when placement is set to CSS selector. Example: .listing-cta or #book-now-anchor.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                    </table>

                    <div class="bookaro-note bookaro-setup-note">
                        <strong><?php esc_html_e( 'Preview and insert blocks', 'mybookaro' ); ?></strong>
                        <p class="description">
                            <?php esc_html_e( 'Primary recommendation: place Booking Button and Services Cards blocks (or equivalent shortcodes) in your listing/page templates. Use auto-insert only as a fallback.', 'mybookaro' ); ?>
                        </p>
                    </div>

                    <div class="bookaro-actions">
                        <?php if ( $prev_step !== '' ) : ?>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                            </a>
                        <?php endif; ?>
                        <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                            <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                        </button>
                    </div>
                </form>
            <?php elseif ( 'pages' === $step ) : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Create pages', 'mybookaro' ); ?></h2>
                    <p class="description"><?php esc_html_e( 'Assign booking/dashboard pages first, then review operational defaults, place blocks/shortcodes, run Generic validation, and finish with a full test booking.', 'mybookaro' ); ?></p>
                </div>
                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                    <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                    <input type="hidden" name="action" value="bookaro_setup_wizard">
                    <input type="hidden" name="step" value="pages">
                    <input type="hidden" name="ui_mode_current" value="<?php echo esc_attr( $ui_mode ); ?>" data-bookaro-setting="ui_mode">

                    <p class="description"><?php esc_html_e( 'New pages will be pre-filled with the required blocks. You can override these pages later per listing post type in Settings > General.', 'mybookaro' ); ?></p>
                    <div class="bookaro-note bookaro-note--warning bookaro-setup-note" data-bookaro-depends="<?php echo esc_attr( $depends_ui_woocommerce ); ?>">
                        <strong><?php esc_html_e( 'UI mode is WooCommerce', 'mybookaro' ); ?></strong>
                        <p class="description"><?php esc_html_e( 'Dashboards live in My Account in this mode. For the recommended Generic path, switch to Shortcodes when you want page-assigned dashboard blocks/shortcodes.', 'mybookaro' ); ?></p>
                    </div>

                    <table class="form-table" role="presentation">
                        <tr>
                            <th scope="row"><label for="bookaro-booking-page"><?php esc_html_e( 'Booking Page', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-booking-page" name="booking_page_id">
                                    <option value=""><?php esc_html_e( 'Select a page', 'mybookaro' ); ?></option>
                                    <option value="new"><?php esc_html_e( 'Create new booking page', 'mybookaro' ); ?></option>
                                    <?php foreach ( $page_options as $page_id => $page_title ) : ?>
                                        <option value="<?php echo esc_attr( $page_id ); ?>" <?php selected( $page_id, $default_booking_page ); ?>>
                                            <?php echo esc_html( $page_title ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Use this when you want a dedicated booking page for listings.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_ui_shortcodes ); ?>">
                            <th scope="row"><label for="bookaro-provider-page"><?php esc_html_e( 'Provider Dashboard Page', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-provider-page" name="provider_dashboard_page_id">
                                    <option value=""><?php esc_html_e( 'Select a page', 'mybookaro' ); ?></option>
                                    <option value="new"><?php esc_html_e( 'Create new provider dashboard page', 'mybookaro' ); ?></option>
                                    <?php foreach ( $page_options as $page_id => $page_title ) : ?>
                                        <option value="<?php echo esc_attr( $page_id ); ?>" <?php selected( $page_id, $default_provider_page ); ?>>
                                            <?php echo esc_html( $page_title ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                            </td>
                        </tr>
                        <tr data-bookaro-depends="<?php echo esc_attr( $depends_ui_shortcodes ); ?>">
                            <th scope="row"><label for="bookaro-customer-page"><?php esc_html_e( 'Customer Dashboard Page', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-customer-page" name="customer_dashboard_page_id">
                                    <option value=""><?php esc_html_e( 'Select a page', 'mybookaro' ); ?></option>
                                    <option value="new"><?php esc_html_e( 'Create new customer dashboard page', 'mybookaro' ); ?></option>
                                    <?php foreach ( $page_options as $page_id => $page_title ) : ?>
                                        <option value="<?php echo esc_attr( $page_id ); ?>" <?php selected( $page_id, $default_customer_page ); ?>>
                                            <?php echo esc_html( $page_title ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><label for="bookaro-services-page"><?php esc_html_e( 'Services Cards Page', 'mybookaro' ); ?></label></th>
                            <td>
                                <select id="bookaro-services-page" name="services_page_id">
                                    <option value=""><?php esc_html_e( 'Select a page', 'mybookaro' ); ?></option>
                                    <option value="new"><?php esc_html_e( 'Create new services page', 'mybookaro' ); ?></option>
                                    <?php foreach ( $page_options as $page_id => $page_title ) : ?>
                                        <option value="<?php echo esc_attr( $page_id ); ?>" <?php selected( $page_id, $default_services_page ); ?>>
                                            <?php echo esc_html( $page_title ); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description">
                                    <?php
                                    echo esc_html(
                                        $is_single_business
                                            ? __( 'Single Business: create a normal page and use Services Cards with provider context (provider ID + source="provider").', 'mybookaro' )
                                            : __( 'Use this page for listing-based services cards, or add explicit IDs in your shortcode/block attributes.', 'mybookaro' )
                                    );
                                    ?>
                                </p>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><?php esc_html_e( 'Demo Content', 'mybookaro' ); ?></th>
                            <td>
                                <label>
                                    <input type="checkbox" name="create_demo_content" value="1">
                                    <?php echo esc_html( $is_single_business ? __( 'Create demo pages + sample provider services', 'mybookaro' ) : __( 'Create demo pages + sample services (admin catalog)', 'mybookaro' ) ); ?>
                                </label>
                                <p class="description"><?php esc_html_e( 'Adds removable demo content to help you test quickly. You can delete it later from Getting Started.', 'mybookaro' ); ?></p>
                            </td>
                        </tr>
                    </table>

                    <div class="bookaro-actions">
                        <?php if ( $prev_step !== '' ) : ?>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                            </a>
                        <?php endif; ?>
                        <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                            <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                        </button>
                    </div>
                </form>
            <?php elseif ( 'operational' === $step ) : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Review operational defaults', 'mybookaro' ); ?></h2>
                    <p class="description"><?php esc_html_e( 'Confirm availability, workflow, anti-spam, reminder, and lifecycle guardrails before launch. This step is read-only and does not overwrite saved settings.', 'mybookaro' ); ?></p>
                </div>

                <?php foreach ( $operational_summary_groups as $group ) : ?>
                    <h3><?php echo esc_html( (string) $group['title'] ); ?></h3>
                    <table class="widefat striped" role="presentation">
                        <thead>
                            <tr>
                                <th><?php esc_html_e( 'Setting', 'mybookaro' ); ?></th>
                                <th><?php esc_html_e( 'Shipped default', 'mybookaro' ); ?></th>
                                <th><?php esc_html_e( 'Active on this site', 'mybookaro' ); ?></th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ( $group['rows'] as $row ) : ?>
                                <tr>
                                    <th scope="row"><?php echo esc_html( (string) $row['label'] ); ?></th>
                                    <td><?php echo esc_html( (string) $row['default'] ); ?></td>
                                    <td><?php echo esc_html( (string) $row['active'] ); ?></td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                <?php endforeach; ?>

                <div class="bookaro-note bookaro-setup-note">
                    <strong><?php esc_html_e( 'Need to adjust guardrails?', 'mybookaro' ); ?></strong>
                    <p class="description"><?php esc_html_e( 'Open the settings tabs below to change these values, then return to finish setup.', 'mybookaro' ); ?></p>
                    <p>
                        <a class="button button-secondary" href="<?php echo esc_url( $general_settings_url ); ?>">
                            <?php esc_html_e( 'Open General settings', 'mybookaro' ); ?>
                        </a>
                        <a class="button button-secondary" href="<?php echo esc_url( $notifications_settings_url ); ?>">
                            <?php esc_html_e( 'Open Notification settings', 'mybookaro' ); ?>
                        </a>
                    </p>
                </div>

                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                    <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                    <input type="hidden" name="action" value="bookaro_setup_wizard">
                    <input type="hidden" name="step" value="operational">

                    <div class="bookaro-actions">
                        <?php if ( $prev_step !== '' ) : ?>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                            </a>
                        <?php endif; ?>
                        <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                            <?php esc_html_e( 'Finish Setup', 'mybookaro' ); ?>
                        </button>
                    </div>
                </form>
            <?php else : ?>
                <div class="bookaro-setup-panel__header">
                    <h2><?php esc_html_e( 'Setup complete', 'mybookaro' ); ?></h2>
                    <p class="description"><?php esc_html_e( 'MyBookaro is configured. Before launch in the Generic Directory lane: guided path, pages, operational defaults review, blocks/shortcodes, validation, and a full test booking.', 'mybookaro' ); ?></p>
                </div>
                <?php if ( $generic_launch_blocked ) : ?>
                    <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                        <strong><?php echo esc_html( $generic_confirmation_required ? __( 'Generic confirmation required before launch', 'mybookaro' ) : ( $generic_legacy_fallback_active ? __( 'Legacy Generic fallback review required', 'mybookaro' ) : ( $generic_runtime_failed_count > 0 ? __( 'Launch blocked until Generic validation passes', 'mybookaro' ) : __( 'Final pre-launch check required', 'mybookaro' ) ) ) ); ?></strong>
                        <p class="description"><?php echo esc_html( $generic_launch_blocked_message ); ?></p>
                        <p>
                            <a class="button button-primary" href="<?php echo esc_url( $generic_launch_blocked_action_url ); ?>">
                                <?php echo esc_html( $generic_launch_blocked_action_label ); ?>
                            </a>
                        </p>
                    </div>
                <?php endif; ?>
                <?php
                $default_provider_id = absint( $opts['default_provider_id'] ?? 0 );
                $example_listing_id = $listing_id > 0 ? $listing_id : 0;
                $example_provider_id = $default_provider_id > 0 ? $default_provider_id : max( 1, get_current_user_id() );
                if ( $example_provider_id < 1 ) {
                    $example_provider_id = 123;
                }
                $use_provider_context = ( 'mylisting' !== $integration_mode ) && ( $is_single_business || $example_listing_id < 1 );
                if ( $example_listing_id < 1 && ! $use_provider_context ) {
                    $example_listing_id = 123;
                }

                $booking_button_shortcode = $use_provider_context
                    ? sprintf( '[bookaro_booking_button provider_id="%d"]', $example_provider_id )
                    : sprintf( '[bookaro_booking_button listing_id="%d"]', $example_listing_id );
                $services_cards_shortcode = $use_provider_context
                    ? sprintf( '[bookaro_services_cards provider_id="%d" source="provider" columns="3"]', $example_provider_id )
                    : sprintf( '[bookaro_services_cards listing_id="%d" columns="3"]', $example_listing_id );

                $booking_button_block = $use_provider_context
                    ? sprintf( '<!-- wp:bookaro/booking-button {"providerId":%d} /-->', $example_provider_id )
                    : sprintf( '<!-- wp:bookaro/booking-button {"listingId":%d} /-->', $example_listing_id );
                $services_cards_block = $use_provider_context
                    ? sprintf( '<!-- wp:bookaro/services-cards {"providerId":%d,"columns":3,"source":"provider"} /-->', $example_provider_id )
                    : sprintf( '<!-- wp:bookaro/services-cards {"listingId":%d,"columns":3} /-->', $example_listing_id );

                $post_types_ok = $is_single_business ? true : ! empty( $selected_listing_types );
                $post_types_detail = $is_single_business
                    ? __( 'Single Business does not require listing post type selection.', 'mybookaro' )
                    : (
                        $post_types_ok
                            ? sprintf(
                                /* translators: %s: selected listing post types */
                                __( 'Selected post types: %s.', 'mybookaro' ),
                                implode( ', ', array_map( 'sanitize_key', $selected_listing_types ) )
                            )
                            : __( 'No listing post types selected yet.', 'mybookaro' )
                    );

                $provider_resolution_ok = in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true )
                    && ( 'meta_key' !== $provider_resolution_mode || '' !== $provider_meta_key );
                if ( 'meta_key' === $provider_resolution_mode ) {
                    $provider_resolution_detail = '' !== $provider_meta_key
                        ? sprintf(
                            /* translators: %s: provider meta key */
                            __( 'Provider resolution uses Listing Meta Key (%s): MyBookaro reads provider user ID from listing meta, then falls back to listing author if needed.', 'mybookaro' ),
                            $provider_meta_key
                        )
                        : __( 'Provider resolution is set to Listing Meta Key, but the meta key is empty. Open Setup Wizard > Listings and fill Provider Meta Key (for example provider_user_id).', 'mybookaro' );
                } else {
                    $provider_resolution_detail = __( 'Provider resolution uses Listing Author: MyBookaro uses listing post_author as provider owner.', 'mybookaro' );
                }

                $services_model_labels = [
                    'provider_only' => __( 'Provider Only', 'mybookaro' ),
                    'admin_only' => __( 'Admin Catalog Only', 'mybookaro' ),
                    'hybrid' => __( 'Hybrid', 'mybookaro' ),
                ];
                $services_source_ok = isset( $services_model_labels[ $services_model ] );
                $services_source_detail = $services_source_ok
                    ? sprintf(
                        /* translators: %s: services model label */
                        __( 'Services source: %s.', 'mybookaro' ),
                        $services_model_labels[ $services_model ]
                    )
                    : __( 'Services Source is not configured yet. Next step: Open Setup Wizard > Services, select the Services Source that matches your directory model, then save.', 'mybookaro' );
                $generic_preset_selected = GenericPresetProfiles::has( $generic_setup_preset );
                $generic_preset_detail = $generic_preset_selected
                    ? GenericPresetProfiles::build_selection_detail( $generic_setup_preset )
                    : __( 'No Generic preset selected yet. Next step: Open Setup Wizard > Lane, select the Generic preset that matches your directory workflow and placement expectation, then save.', 'mybookaro' );

                $missing_pages = [];
                if ( $default_booking_page < 1 ) {
                    $missing_pages[] = __( 'Booking page', 'mybookaro' );
                }
                if ( 'shortcodes' === $ui_mode ) {
                    if ( $default_provider_page < 1 ) {
                        $missing_pages[] = __( 'Provider dashboard page', 'mybookaro' );
                    }
                    if ( $default_customer_page < 1 ) {
                        $missing_pages[] = __( 'Customer dashboard page', 'mybookaro' );
                    }
                }
                $page_assignment_ok = empty( $missing_pages );
                $page_assignment_detail = $page_assignment_ok
                    ? (
                        'shortcodes' === $ui_mode
                            ? __( 'Booking page, Provider Dashboard page, and Customer Dashboard page are assigned.', 'mybookaro' )
                            : __( 'Booking page is assigned. Dashboards use WooCommerce My Account.', 'mybookaro' )
                    )
                    : sprintf(
                        /* translators: %s: missing page names */
                        __( 'Missing: %s. Open Setup Wizard > Pages and assign these pages. In Shortcodes mode, the dashboard pages must also contain the matching MyBookaro dashboard block or shortcode.', 'mybookaro' ),
                        implode( ', ', $missing_pages )
                    );

                $notify_reminder = ! empty( $opts['notify_reminder'] );
                $notify_review_invite = ! empty( $opts['notify_review_invite'] );
                $notification_automations_ok = $notify_reminder || $notify_review_invite;
                $notification_automations_detail = sprintf(
                    /* translators: 1: reminder email toggle, 2: review invite toggle */
                    __( 'Reminders: %1$s | Review invites: %2$s.', 'mybookaro' ),
                    $notify_reminder ? __( 'On', 'mybookaro' ) : __( 'Off', 'mybookaro' ),
                    $notify_review_invite ? __( 'On', 'mybookaro' ) : __( 'Off', 'mybookaro' )
                );
                if ( ! $notification_automations_ok ) {
                    $notification_automations_detail .= ' ' . __( 'Enable one or both in MyBookaro > Settings > Email.', 'mybookaro' );
                }

                $button_placement_ok = ( 'shortcodes' === $ui_mode ) && $default_booking_page > 0;
                if ( 'shortcodes' === $ui_mode && $default_booking_page > 0 ) {
                    $button_placement_detail = __( 'Shortcodes mode with Booking page is active. Next step: place Booking Button/Services Cards where customers start bookings, then update that template or page.', 'mybookaro' );
                } elseif ( $auto_insert_enabled && '' !== $auto_insert_mode ) {
                    if ( 'selector' === $auto_insert_mode ) {
                        $button_placement_detail = '' !== $auto_insert_selector
                            ? sprintf(
                                /* translators: %s: css selector */
                                __( 'Auto-insert fallback enabled via selector: %s. Recommended: place Booking Button/Services Cards block or shortcode explicitly.', 'mybookaro' ),
                                $auto_insert_selector
                            )
                            : __( 'Auto-insert selector fallback is enabled. Recommended: place Booking Button/Services Cards block or shortcode explicitly.', 'mybookaro' );
                    } else {
                        $button_placement_detail = 'before_content' === $auto_insert_mode
                            ? __( 'Auto-insert fallback placement: before content. Recommended: place Booking Button/Services Cards block or shortcode explicitly.', 'mybookaro' )
                            : __( 'Auto-insert fallback placement: after content. Recommended: place Booking Button/Services Cards block or shortcode explicitly.', 'mybookaro' );
                    }
                } elseif ( 'shortcodes' !== $ui_mode ) {
                    $button_placement_detail = __( 'Recommended for Generic: open Setup Wizard > Services, switch UI Mode to Shortcodes, save, then place Booking Button/Services Cards explicitly.', 'mybookaro' );
                } else {
                    $button_placement_detail = __( 'No booking entry is configured yet. Open Setup Wizard > Pages, assign Booking page, then place Booking Button/Services Cards or enable Auto-Insert fallback in Setup Wizard > Services.', 'mybookaro' );
                }

                $generic_path_confirmed = ! $generic_confirmation_required && ! $generic_legacy_fallback_active;
                if ( $generic_confirmation_required ) {
                    $generic_path_confirmation_detail = $this->get_generic_confirmation_required_notice_message();
                } elseif ( $generic_legacy_fallback_active ) {
                    $generic_path_confirmation_detail = $this->get_generic_legacy_review_notice_message();
                } else {
                    $generic_path_confirmation_detail = __( 'Generic path is explicitly confirmed for this site. Continue with validation and a full test booking before launch.', 'mybookaro' );
                }

                $preset_defaults_ok = $generic_preset_selected;
                $preset_defaults_detail = $generic_preset_selected
                    ? __( 'Compatibility controls are off, so ownership routing, Services Source, and placement expectations follow the selected Generic preset.', 'mybookaro' )
                    : __( 'No Generic preset selected yet. Next step: Open Setup Wizard > Lane, select the Generic preset that matches your directory workflow and placement expectation, then save.', 'mybookaro' );

                $generic_finish_checks = [
                    [
                        'label' => __( 'Confirm Generic Directory lane', 'mybookaro' ),
                        'passed' => $generic_path_confirmed,
                        'detail' => $generic_path_confirmation_detail,
                        'step' => 'modes',
                    ],
                    [
                        'label' => __( 'Runtime validation clear', 'mybookaro' ),
                        'passed' => ( 0 === (int) $generic_runtime_failed_count ),
                        'detail' => $generic_runtime_failed_count > 0
                            ? sprintf(
                                /* translators: %d: number of runtime checks needing attention */
                                _n(
                                    '%d runtime validation check still needs attention. Next step: Open System Status > Generic validation checks and resolve the first Warn/Fail item.',
                                    '%d runtime validation checks still need attention. Next step: Open System Status > Generic validation checks and resolve the first Warn/Fail item.',
                                    (int) $generic_runtime_failed_count,
                                    'mybookaro'
                                ),
                                (int) $generic_runtime_failed_count
                            )
                            : __( 'Runtime validation checks are currently clear for the selected Generic sample context.', 'mybookaro' ),
                        'step' => '',
                    ],
                    [
                        'label' => __( 'Choose guided path', 'mybookaro' ),
                        'passed' => $generic_preset_selected,
                        'detail' => $generic_preset_detail,
                        'step' => 'modes',
                    ],
                    [
                        'label' => __( 'Page assignment complete', 'mybookaro' ),
                        'passed' => $page_assignment_ok,
                        'detail' => $page_assignment_detail,
                        'step' => 'pages',
                    ],
                    [
                        'label' => __( 'Place booking blocks/shortcodes', 'mybookaro' ),
                        'passed' => $button_placement_ok,
                        'detail' => $button_placement_detail,
                        'step' => 'services',
                    ],
                ];
                if ( ! $is_single_business ) {
                    $generic_finish_checks[] = [
                        'label' => __( 'Bookable listing post types selected', 'mybookaro' ),
                        'passed' => $post_types_ok,
                        'detail' => $post_types_detail,
                        'step' => 'listings',
                    ];
                }
                if ( $generic_advanced_setup_enabled ) {
                    $generic_finish_checks[] = [
                        'label' => __( 'Provider resolution configured', 'mybookaro' ),
                        'passed' => $provider_resolution_ok,
                        'detail' => $provider_resolution_detail,
                        'step' => 'listings',
                    ];
                    $generic_finish_checks[] = [
                        'label' => __( 'Services source configured', 'mybookaro' ),
                        'passed' => $services_source_ok,
                        'detail' => $services_source_detail,
                        'step' => 'services',
                    ];
                } else {
                    $generic_finish_checks[] = [
                        'label' => __( 'Guided-path defaults active', 'mybookaro' ),
                        'passed' => $preset_defaults_ok,
                        'detail' => $preset_defaults_detail,
                        'step' => 'modes',
                    ];
                }
                $generic_finish_checks[] = [
                    'label' => __( 'Reminder and review invite automations', 'mybookaro' ),
                    'passed' => $notification_automations_ok,
                    'detail' => $notification_automations_detail,
                    'step' => '',
                ];
                $has_context_ids = $listing_id > 0 || $default_provider_id > 0;
                $runtime_validation = function_exists( 'bookaro_run_generic_admin_validation' )
                    ? bookaro_run_generic_admin_validation( [
                        'listing_id' => $listing_id,
                        'provider_id' => $default_provider_id,
                    ] )
                    : [];
                $runtime_checks = [];
                if ( is_array( $runtime_validation ) && ! empty( $runtime_validation['checks'] ) && is_array( $runtime_validation['checks'] ) ) {
                    $runtime_checks = $runtime_validation['checks'];
                }
                $runtime_failed_count = is_array( $runtime_validation )
                    ? absint( $runtime_validation['failed_count'] ?? 0 )
                    : 0;
                ?>

                <h3><?php esc_html_e( 'Generic validation checklist', 'mybookaro' ); ?></h3>
                <p class="description"><?php esc_html_e( 'Recommended launch path: 1) guided path, 2) pages, 3) operational defaults review, 4) blocks/shortcodes, 5) validation, 6) full test booking.', 'mybookaro' ); ?></p>
                <ul class="bookaro-setup-list">
                    <?php foreach ( $generic_finish_checks as $check ) : ?>
                        <?php $is_passed = ! empty( $check['passed'] ); ?>
                        <li>
                            <strong><?php echo esc_html( $check['label'] ); ?>:</strong>
                            <span class="bookaro-status-pill <?php echo esc_attr( $is_passed ? 'bookaro-status-pill--ok' : 'bookaro-status-pill--warn' ); ?>">
                                <?php echo esc_html( $is_passed ? __( 'Pass', 'mybookaro' ) : __( 'Warn', 'mybookaro' ) ); ?>
                            </span>
                            <?php echo esc_html( $check['detail'] ); ?>
                            <?php if ( ! $is_passed && ! empty( $check['step'] ) ) : ?>
                                <a href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $check['step'] ) ); ?>">
                                    <?php esc_html_e( 'Fix in wizard', 'mybookaro' ); ?>
                                </a>
                            <?php endif; ?>
                        </li>
                    <?php endforeach; ?>
                </ul>

                <h3 id="bookaro-generic-runtime-validation"><?php esc_html_e( 'Generic runtime validation', 'mybookaro' ); ?></h3>
                <p class="description">
                    <?php
                    if ( $runtime_failed_count > 0 ) {
                        echo esc_html(
                            sprintf(
                                /* translators: %d: number of failed runtime checks */
                                __( '%d runtime checks need attention before launch.', 'mybookaro' ),
                                (int) $runtime_failed_count
                            )
                        );
                    } else {
                        esc_html_e( 'Runtime checks are passing for the current Generic sample context. Next step: run one full booking request/approval flow before launch.', 'mybookaro' );
                    }
                    ?>
                </p>
                <p>
                    <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=done#bookaro-generic-runtime-validation' ) ); ?>">
                        <?php esc_html_e( 'Refresh runtime checks', 'mybookaro' ); ?>
                    </a>
                    <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' ) ); ?>">
                        <?php esc_html_e( 'Open System Status results', 'mybookaro' ); ?>
                    </a>
                </p>
                <?php if ( ! empty( $runtime_checks ) ) : ?>
                    <ul class="bookaro-setup-list">
                        <?php foreach ( $runtime_checks as $runtime_check ) : ?>
                            <?php
                            if ( ! is_array( $runtime_check ) ) {
                                continue;
                            }
                            $runtime_state = sanitize_key( (string) ( $runtime_check['state'] ?? 'info' ) );
                            $runtime_failed = in_array( $runtime_state, [ 'warn', 'error' ], true );
                            $runtime_state_label = __( 'Info', 'mybookaro' );
                            $runtime_state_class = 'bookaro-status-pill--info';
                            if ( 'ok' === $runtime_state ) {
                                $runtime_state_label = __( 'Pass', 'mybookaro' );
                                $runtime_state_class = 'bookaro-status-pill--ok';
                            } elseif ( 'warn' === $runtime_state ) {
                                $runtime_state_label = __( 'Warn', 'mybookaro' );
                                $runtime_state_class = 'bookaro-status-pill--warn';
                            } elseif ( 'error' === $runtime_state ) {
                                $runtime_state_label = __( 'Fail', 'mybookaro' );
                                $runtime_state_class = 'bookaro-status-pill--error';
                            }
                            $runtime_value = (string) ( $runtime_check['value'] ?? '' );
                            $runtime_show_value = '' !== $runtime_value && strtolower( $runtime_value ) !== strtolower( $runtime_state_label );
                            ?>
                            <li>
                                <strong><?php echo esc_html( (string) ( $runtime_check['label'] ?? '' ) ); ?>:</strong>
                                <span class="bookaro-status-pill <?php echo esc_attr( $runtime_state_class ); ?>">
                                    <?php echo esc_html( $runtime_state_label ); ?>
                                </span>
                                <?php if ( $runtime_show_value ) : ?>
                                    <span class="bookaro-status-pill bookaro-status-pill--info">
                                        <?php echo esc_html( $runtime_value ); ?>
                                    </span>
                                <?php endif; ?>
                                <?php if ( ! empty( $runtime_check['detail'] ) ) : ?>
                                    <?php echo ' '; ?>
                                    <?php echo esc_html( (string) $runtime_check['detail'] ); ?>
                                <?php endif; ?>
                                <?php if ( $runtime_failed && ! empty( $runtime_check['fix'] ) ) : ?>
                                    <?php echo ' '; ?>
                                    <?php
                                    printf(
                                        /* translators: %s: suggested fix text */
                                        esc_html__( 'Suggested fix: %s', 'mybookaro' ),
                                        esc_html( (string) $runtime_check['fix'] )
                                    );
                                    ?>
                                <?php endif; ?>
                                <?php if ( ! empty( $runtime_check['action_url'] ) && ! empty( $runtime_check['action_label'] ) ) : ?>
                                    <a href="<?php echo esc_url( (string) $runtime_check['action_url'] ); ?>">
                                        <?php echo esc_html( (string) $runtime_check['action_label'] ); ?>
                                    </a>
                                <?php endif; ?>
                            </li>
                        <?php endforeach; ?>
                    </ul>
                <?php endif; ?>

                <?php if ( ! $has_context_ids ) : ?>
                    <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                        <?php if ( $is_single_business ) : ?>
                            <strong><?php esc_html_e( 'Next action: set a default provider', 'mybookaro' ); ?></strong>
                            <p class="description"><?php esc_html_e( 'Single Business listings are optional. Go back to Listings and set a Default Provider so booking/services snippets use real provider context.', 'mybookaro' ); ?></p>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' ) ); ?>">
                                <?php esc_html_e( 'Open Listings step', 'mybookaro' ); ?>
                            </a>
                        <?php else : ?>
                            <strong><?php esc_html_e( 'Next action: set a real listing context', 'mybookaro' ); ?></strong>
                            <p class="description"><?php esc_html_e( 'Go back to Listings and select your listing post types, then create at least one listing so shortcode examples use real IDs.', 'mybookaro' ); ?></p>
                            <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' ) ); ?>">
                                <?php esc_html_e( 'Open Listings step', 'mybookaro' ); ?>
                            </a>
                        <?php endif; ?>
                    </div>
                <?php endif; ?>

                <h3><?php esc_html_e( 'Shortcodes', 'mybookaro' ); ?></h3>
                <p class="description"><?php esc_html_e( 'Paste these into any page or post.', 'mybookaro' ); ?></p>
                <div class="bookaro-setup-code-grid">
                    <div>
                        <div class="description"><?php esc_html_e( 'Booking button', 'mybookaro' ); ?></div>
                        <input type="text" class="regular-text code" readonly value="<?php echo esc_attr( $booking_button_shortcode ); ?>">
                    </div>
                    <div>
                        <div class="description"><?php esc_html_e( 'Services cards', 'mybookaro' ); ?></div>
                        <input type="text" class="regular-text code" readonly value="<?php echo esc_attr( $services_cards_shortcode ); ?>">
                    </div>
                </div>

                <h3><?php esc_html_e( 'Blocks', 'mybookaro' ); ?></h3>
                <p class="description"><?php esc_html_e( 'Use the MyBookaro blocks in the editor.', 'mybookaro' ); ?></p>
                <ul class="bookaro-setup-list">
                    <li><?php esc_html_e( 'MyBookaro Booking Button (bookaro/booking-button)', 'mybookaro' ); ?></li>
                    <li><?php esc_html_e( 'MyBookaro Booking Form (bookaro/booking-form)', 'mybookaro' ); ?></li>
                    <li><?php esc_html_e( 'MyBookaro Services Cards (bookaro/services-cards)', 'mybookaro' ); ?></li>
                    <li><?php esc_html_e( 'MyBookaro Provider Dashboard (bookaro/provider-dashboard)', 'mybookaro' ); ?></li>
                    <li><?php esc_html_e( 'MyBookaro Customer Dashboard (bookaro/customer-dashboard)', 'mybookaro' ); ?></li>
                </ul>

                <h3><?php esc_html_e( 'Services cards example', 'mybookaro' ); ?></h3>
                <p class="description"><?php esc_html_e( 'Use this snippet in the block editor or a custom page template.', 'mybookaro' ); ?></p>
                <div class="bookaro-setup-code-grid">
                    <input type="text" class="regular-text code" readonly value="<?php echo esc_attr( $services_cards_shortcode ); ?>">
                    <input type="text" class="regular-text code" readonly value="<?php echo esc_attr( $services_cards_block ); ?>">
                    <input type="text" class="regular-text code" readonly value="<?php echo esc_attr( $booking_button_block ); ?>">
                </div>
                <p>
                    <a class="button button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' ) ); ?>">
                        <?php esc_html_e( 'Go to MyBookaro Settings', 'mybookaro' ); ?>
                    </a>
                </p>
            <?php endif; ?>
            </div>
        </div>
        <?php
    }

    private function create_provider_listing( int $provider_user_id, array $data ): int
    {
        $listing_post_type = $this->get_default_listing_post_type();
        $title = sanitize_text_field( wp_unslash( $data['provider_title'] ?? '' ) );
        $description = sanitize_textarea_field( wp_unslash( $data['provider_description'] ?? '' ) );
        if ( '' === $title ) {
            $user = get_user_by( 'ID', $provider_user_id );
            $title = $user ? $user->display_name : __( 'Provider Listing', 'mybookaro' );
        }

        $listing_id = wp_insert_post( [
            'post_type'    => $listing_post_type,
            'post_title'   => $title,
            'post_content' => $description,
            'post_status'  => 'publish',
            'post_author'  => $provider_user_id,
        ] );

        if ( is_wp_error( $listing_id ) ) {
            return 0;
        }

        $email = sanitize_email( wp_unslash( $data['provider_email'] ?? '' ) );
        $phone = sanitize_text_field( wp_unslash( $data['provider_phone'] ?? '' ) );
        if ( $email ) {
            update_post_meta( $listing_id, BOOKARO_PROVIDER_EMAIL_META, $email );
        }
        if ( $phone ) {
            update_post_meta( $listing_id, BOOKARO_PROVIDER_PHONE_META, $phone );
        }

        return (int) $listing_id;
    }

    private function find_provider_listing( int $provider_user_id ): int
    {
        $listing_types = function_exists( 'bookaro_get_allowed_listing_post_types' )
            ? bookaro_get_allowed_listing_post_types()
            : [ BOOKARO_PROVIDER_POST_TYPE ];
        if ( empty( $listing_types ) ) {
            $listing_types = [ BOOKARO_PROVIDER_POST_TYPE ];
        }
        $existing = get_posts( [
            'post_type'      => $listing_types,
            'author'         => $provider_user_id,
            'posts_per_page' => 1,
            'fields'         => 'ids',
        ] );

        return ! empty( $existing ) ? (int) $existing[0] : 0;
    }

    private function create_service( int $listing_id, int $provider_user_id, array $data ): int
    {
        $title = sanitize_text_field( wp_unslash( $data['service_title'] ?? '' ) );
        if ( '' === $title ) {
            $title = __( 'Sample Service', 'mybookaro' );
        }
        $price_raw = sanitize_text_field( wp_unslash( $data['service_price'] ?? '' ) );
        $price = $price_raw === '' ? 0.0 : (float) $price_raw;
        $duration = absint( wp_unslash( $data['service_duration'] ?? 0 ) );

        // Bug 66: the catalog step recreated a service every time it ran,
        // so re-running the wizard (or hitting Back/Next through the
        // catalog step) accumulated duplicate "Sample Service" posts with
        // the same title for the same provider. Reuse an existing service
        // with the same title scoped to this provider before inserting a
        // fresh one, so the step is idempotent.
        $existing = get_posts( [
            'post_type'        => BOOKARO_SERVICE_POST_TYPE,
            'post_status'      => 'publish',
            'title'            => $title,
            'author'           => $provider_user_id > 0 ? $provider_user_id : null,
            'posts_per_page'   => 1,
            'fields'           => 'ids',
            'no_found_rows'    => true,
        ] );
        if ( ! empty( $existing ) ) {
            $service_id = (int) $existing[0];
            // Refresh the meta in case the wizard changed price/duration.
            update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
            update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, $price );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
            update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $title );
            return $service_id;
        }

        $service_id = wp_insert_post( [
            'post_type'    => BOOKARO_SERVICE_POST_TYPE,
            'post_title'   => $title,
            'post_content' => '',
            'post_status'  => 'publish',
            'post_author'  => $provider_user_id,
        ] );

        if ( is_wp_error( $service_id ) ) {
            return 0;
        }

        update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
        update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, $price );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $title );
        update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, '' );
        $owner_type = $listing_id > 0 ? 'provider' : 'admin';
        $shared = ( 'admin' === $owner_type && $listing_id < 1 ) ? 1 : 0;
        $scope = ( 'admin' === $owner_type && $shared ) ? 'global' : 'provider';
        update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, $scope );
        update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, $owner_type );
        update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, $shared );
        update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, $shared );
        update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, 'provider' === $owner_type ? $provider_user_id : 0 );

        return (int) $service_id;
    }

    private function create_page( string $slug, string $title, string $content ): int
    {
        $existing = get_page_by_path( $slug );
        if ( $existing ) {
            return (int) $existing->ID;
        }

        $page_id = wp_insert_post( [
            'post_type'    => 'page',
            'post_title'   => $title,
            'post_name'    => $slug,
            'post_content' => $content,
            'post_status'  => 'publish',
            'post_author'  => get_current_user_id(),
        ] );

        return is_wp_error( $page_id ) ? 0 : (int) $page_id;
    }

    private function resolve_page_selection( string $selection, string $slug, string $title, string $content ): int
    {
        $selection = sanitize_text_field( $selection );
        if ( '' === $selection ) {
            return 0;
        }
        if ( 'new' === $selection ) {
            return $this->create_page( $slug, $title, $content );
        }
        $page_id = absint( $selection );
        if ( $page_id < 1 || 'page' !== get_post_type( $page_id ) ) {
            return 0;
        }
        return $page_id;
    }

    private function resolve_page_override( array $overrides, array $post_types, string $context, int $fallback = 0 ): int
    {
        $context = sanitize_key( $context );
        foreach ( $post_types as $post_type ) {
            $post_type = sanitize_key( $post_type );
            if ( '' === $post_type ) {
                continue;
            }
            if ( isset( $overrides[ $post_type ] ) && is_array( $overrides[ $post_type ] ) ) {
                $page_id = absint( $overrides[ $post_type ][ $context ] ?? 0 );
                if ( $page_id > 0 && 'page' === get_post_type( $page_id ) ) {
                    return $page_id;
                }
            }
        }
        return $fallback;
    }

    private function build_booking_form_block( int $listing_id, int $provider_id = 0 ): string
    {
        $attrs = [
            'autoOpen' => true,
        ];
        if ( $listing_id > 0 ) {
            $attrs['listingId'] = $listing_id;
        } elseif ( $provider_id > 0 ) {
            $attrs['providerId'] = $provider_id;
        }
        $json = wp_json_encode( $attrs );
        if ( ! is_string( $json ) ) {
            $json = '{}';
        }
        return sprintf( '<!-- wp:bookaro/booking-form %s /-->', $json );
    }

    private function build_provider_dashboard_block(): string
    {
        return '<!-- wp:bookaro/provider-dashboard /-->';
    }

    private function build_customer_dashboard_block(): string
    {
        return '<!-- wp:bookaro/customer-dashboard /-->';
    }

    private function build_services_cards_block( int $listing_id, int $provider_id = 0 ): string
    {
        $attrs = [
            'columns'      => 3,
            'showPrice'    => true,
            'showDuration' => true,
            'source'       => 'auto',
        ];
        if ( $listing_id > 0 ) {
            $attrs['listingId'] = $listing_id;
        } elseif ( $provider_id > 0 ) {
            $attrs['providerId'] = $provider_id;
            $attrs['source'] = 'provider';
        }
        $json = wp_json_encode( $attrs );
        if ( ! is_string( $json ) ) {
            $json = '{}';
        }
        return sprintf( '<!-- wp:bookaro/services-cards %s /-->', $json );
    }

    private function create_demo_content( int $listing_id, int $provider_id = 0 ): void
    {
        $existing = get_option( 'bookaro_demo_content', [] );
        if ( ! is_array( $existing ) ) {
            $existing = [];
        }

        $pages = $existing['pages'] ?? [];
        if ( ! is_array( $pages ) ) {
            $pages = [];
        }
        $pages = $this->filter_existing_posts( $pages );

        if ( empty( $pages['demo_booking'] ) ) {
            $pages['demo_booking'] = $this->create_page(
                'bookaro-demo-booking',
                __( 'MyBookaro Demo Booking', 'mybookaro' ),
                $this->build_booking_form_block( $listing_id, $provider_id )
            );
        }
        if ( empty( $pages['demo_services'] ) ) {
            $pages['demo_services'] = $this->create_page(
                'bookaro-demo-services',
                __( 'MyBookaro Demo Services', 'mybookaro' ),
                $this->build_services_cards_block( $listing_id, $provider_id )
            );
        }

        $services = $existing['services'] ?? [];
        if ( ! is_array( $services ) ) {
            $services = [];
        }
        $services = array_values( array_filter( array_map( 'absint', $services ) ) );
        $services = $this->filter_existing_ids( $services );
        if ( empty( $services ) ) {
            $services = $this->create_demo_services( $listing_id, $provider_id );
        }

        update_option( 'bookaro_demo_content', [
            'pages' => $pages,
            'services' => $services,
            'created_at' => time(),
        ] );
    }

    private function create_demo_services( int $listing_id = 0, int $provider_id = 0 ): array
    {
        if ( ! defined( 'BOOKARO_SERVICE_POST_TYPE' ) ) {
            return [];
        }
        if ( function_exists( 'post_type_exists' ) && ! post_type_exists( BOOKARO_SERVICE_POST_TYPE ) ) {
            return [];
        }

        $listing_id = max( 0, $listing_id );
        $provider_id = max( 0, $provider_id );
        if ( $provider_id < 1 && $listing_id > 0 ) {
            $provider_id = function_exists( 'bookaro_get_listing_owner_id' )
                ? (int) bookaro_get_listing_owner_id( $listing_id )
                : 0;
            if ( $provider_id < 1 ) {
                $listing_post = get_post( $listing_id );
                if ( $listing_post ) {
                    $provider_id = (int) $listing_post->post_author;
                }
            }
        }
        $provider_owned = ( $provider_id > 0 || $listing_id > 0 );
        $owner_type = $provider_owned ? 'provider' : 'admin';
        if ( $listing_id > 0 ) {
            $scope = 'listing';
        } elseif ( $provider_id > 0 ) {
            $scope = 'provider';
        } else {
            $scope = 'global';
        }
        $shared = $provider_owned ? 0 : 1;

        $items = [
            [
                'title' => __( 'Consultation', 'mybookaro' ),
                'price' => 49,
                'duration' => 30,
            ],
            [
                'title' => __( 'Follow-up Session', 'mybookaro' ),
                'price' => 29,
                'duration' => 20,
            ],
            [
                'title' => __( 'Premium Appointment', 'mybookaro' ),
                'price' => 99,
                'duration' => 60,
            ],
        ];

        $ids = [];
        foreach ( $items as $item ) {
            $service_id = wp_insert_post( [
                'post_type'    => BOOKARO_SERVICE_POST_TYPE,
                'post_title'   => $item['title'],
                'post_status'  => 'publish',
                'post_author'  => $provider_id > 0 ? $provider_id : get_current_user_id(),
            ] );
            if ( is_wp_error( $service_id ) || $service_id < 1 ) {
                continue;
            }

            update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
            update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, (float) $item['price'] );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, (int) $item['duration'] );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, (int) $item['duration'] );
            update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $item['title'] );
            update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, '' );
            update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, $scope );
            update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, $owner_type );
            update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, $shared );
            update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, $shared );
            update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, $provider_id );
            update_post_meta( $service_id, 'bookaro_demo_content', 1 );

            $ids[] = (int) $service_id;
        }

        return $ids;
    }

    private function filter_existing_posts( array $posts ): array
    {
        $filtered = [];
        foreach ( $posts as $key => $value ) {
            $post_id = absint( $value );
            if ( $post_id < 1 ) {
                continue;
            }
            if ( get_post( $post_id ) ) {
                $filtered[ $key ] = $post_id;
            }
        }
        return $filtered;
    }

    private function filter_existing_ids( array $ids ): array
    {
        $filtered = [];
        foreach ( $ids as $id ) {
            $id = absint( $id );
            if ( $id < 1 ) {
                continue;
            }
            if ( get_post( $id ) ) {
                $filtered[] = $id;
            }
        }
        return array_values( array_unique( $filtered ) );
    }

    private function assign_role_to_user( int $user_id, string $role ): void
    {
        if ( $user_id < 1 || '' === $role ) {
            return;
        }

        $user = get_user_by( 'ID', $user_id );
        if ( ! $user instanceof \WP_User ) {
            return;
        }

        $user->add_role( $role );
    }

    private function handle_mylisting_wizard_submit( array $payload, array $opts ): string
    {
        $step = sanitize_text_field( $payload['step'] ?? 'mylisting_integration' );
        $next = 'integration';

        if ( 'mylisting_integration' === $step ) {
            $site_type = $this->resolve_site_type_from_options( $opts, $payload );
            $integration_mode = sanitize_key( $payload['integration_mode'] ?? 'auto' );
            if ( ! in_array( $integration_mode, [ 'auto', 'mylisting' ], true ) ) {
                $integration_mode = 'auto';
            }
            if ( in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true ) ) {
                $integration_mode = 'generic';
            }

            $previous_mode = $opts['integration_mode'] ?? '';
            $opts['site_type'] = $site_type;
            $opts['integration_mode'] = $integration_mode;
            $opts['frontend_enabled'] = ! empty( $payload['frontend_enabled'] ) ? 1 : 0;
            if ( 'advanced_mapping' === $site_type ) {
                $opts['generic_advanced_setup_enabled'] = 1;
            } elseif ( 'single_business' === $site_type ) {
                $opts['generic_advanced_setup_enabled'] = 0;
                $opts['generic_setup_preset'] = 'author_provider';
                $opts['provider_resolution_mode'] = 'author';
                $opts['provider_meta_key'] = '';
                $opts['services_model'] = 'provider_only';
                $opts['generic_services_mode'] = 'provider_only';
                $opts['provider_services_enabled'] = 1;
                $opts['allow_provider_custom_services'] = 0;
                $opts['allow_provider_override_catalog'] = 0;
            }
            $this->options->update( $opts );

            if ( $previous_mode !== $integration_mode && function_exists( 'flush_rewrite_rules' ) ) {
                flush_rewrite_rules();
            }

            $next = in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true )
                ? 'modes'
                : 'listings';
        } elseif ( 'mylisting_listings' === $step ) {
            $listing_options = $this->get_listing_post_type_options();
            $available_listing_types = array_keys( $listing_options );
            $default_listing_type = 'job_listing';
            if ( ! empty( $available_listing_types ) ) {
                if ( in_array( 'job_listing', $available_listing_types, true ) ) {
                    $default_listing_type = 'job_listing';
                } else {
                    $default_listing_type = (string) $available_listing_types[0];
                }
            }

            $raw_listing_types = $payload['allowed_listing_post_types'] ?? [];
            if ( ! is_array( $raw_listing_types ) ) {
                $raw_listing_types = [ $raw_listing_types ];
            }
            $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $raw_listing_types ) ) ) );
            if ( ! empty( $available_listing_types ) ) {
                $selected_listing_types = array_values( array_intersect( $selected_listing_types, $available_listing_types ) );
            }
            if ( empty( $selected_listing_types ) ) {
                $selected_listing_types = [ $default_listing_type ];
            }

            $provider_resolution_mode = sanitize_key( $payload['provider_resolution_mode'] ?? '' );
            if ( ! in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true ) ) {
                $provider_resolution_mode = '';
            }
            $provider_meta_key = sanitize_key( $payload['provider_meta_key'] ?? '' );
            if ( '' === $provider_resolution_mode ) {
                $provider_resolution_mode = $provider_meta_key !== '' ? 'meta_key' : 'author';
            }

            $opts['allowed_listing_post_types'] = $selected_listing_types;
            $opts['listing_post_type'] = $selected_listing_types[0] ?? $default_listing_type;
            $opts['provider_resolution_mode'] = $provider_resolution_mode;
            $opts['provider_meta_key'] = $provider_meta_key;
            if ( $provider_meta_key !== '' ) {
                $opts['listing_provider_meta_key'] = $provider_meta_key;
            }
            $this->options->update( $opts );

            $next = 'services';
        } elseif ( 'mylisting_services' === $step ) {
            $repeater_class = sanitize_key( $payload['mylisting_services_repeater_class'] ?? 'mybookaro_services' );
            if ( '' === $repeater_class ) {
                $repeater_class = 'mybookaro_services';
            }
            $opts['mylisting_services_repeater_class'] = $repeater_class;
            $this->options->update( $opts );
            $next = 'finish';
        } elseif ( 'mylisting_finish' === $step ) {
            $opts['mylisting_setup_completed'] = 1;
            $this->options->update( $opts );
            $next = 'finish';
        }

        return $next;
    }

    private function build_wizard_lane_summary_banner(
        string $site_type,
        string $integration_mode,
        bool $launch_blocked,
        string $blocked_message,
        string $blocked_action_label,
        string $blocked_action_url,
        string $step,
        array $steps,
        int $current_index,
        bool $single_business_provider_ready,
        bool $single_business_pages_ready,
        bool $single_business_services_ready,
        string $single_business_fast_path_url = '',
        array $generic_compact_context = [],
        array $single_business_context = []
    ): array {
        $site_type = sanitize_key( $site_type );
        $integration_mode = sanitize_key( $integration_mode );
        $step = sanitize_key( $step );
        $generic_compact_context = is_array( $generic_compact_context ) ? $generic_compact_context : [];
        $single_business_context = is_array( $single_business_context ) ? $single_business_context : [];

        $lane_label = AdminLaneSummary::resolve_lane_label( '', $integration_mode, $site_type );
        $summary = AdminLaneSummary::create_payload( $lane_label );
        $top_blocker = '';
        $next_action = $summary['next_action'];
        $state = 'ok';
        $state_label = __( 'Ready', 'mybookaro' );
        $single_business_fast_path_url = trim( $single_business_fast_path_url );
        $generic_compact_model = trim( (string) ( $generic_compact_context['current_model'] ?? '' ) );
        $generic_compact_model_items = is_array( $generic_compact_context['model_items'] ?? null ) ? $generic_compact_context['model_items'] : [];
        $generic_compact_blocker = trim( (string) ( $generic_compact_context['main_blocker'] ?? '' ) );

        if ( 'single_business' !== $site_type && 'generic' === $integration_mode ) {
            $summary['top_blocker_label'] = __( 'Main blocker', 'mybookaro' );
            $summary['next_action_label'] = __( 'Required next step', 'mybookaro' );
            $summary['model_label'] = __( 'Current lane profile', 'mybookaro' );
            if ( '' !== $generic_compact_model ) {
                $summary['model_summary'] = $generic_compact_model;
            }
            if ( ! empty( $generic_compact_model_items ) ) {
                $summary['model_items'] = $generic_compact_model_items;
            }
            $summary['summary'] = __( 'Compact Generic lane snapshot: pattern, ownership model, placement strategy, top blocker, and required next step.', 'mybookaro' );
        }

        $step_keys = array_values( array_filter( array_map( 'sanitize_key', array_keys( $steps ) ) ) );
        $next_step = '';
        if ( $current_index >= 0 && $current_index < ( count( $step_keys ) - 1 ) ) {
            $next_step = (string) ( $step_keys[ $current_index + 1 ] ?? '' );
        }
        if ( '' !== $next_step && ! empty( $steps[ $next_step ] ) ) {
            $next_action = [
                'label' => sprintf(
                    /* translators: %s: wizard step label */
                    __( 'Continue to %s', 'mybookaro' ),
                    (string) $steps[ $next_step ]
                ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $next_step ),
                'detail' => sprintf(
                    /* translators: %s: wizard step label */
                    __( 'Next step: %s', 'mybookaro' ),
                    (string) $steps[ $next_step ]
                ),
            ];
        }

        if ( 'single_business' === $site_type ) {
            $single_business_summary = __( 'Single Business first-booking order: Default Provider -> Booking/dashboard pages -> First service -> Preview booking.', 'mybookaro' );
            $summary['summary'] = $single_business_summary;
            $summary['top_blocker_label'] = __( 'Main blocker', 'mybookaro' );
            $summary['next_action_label'] = __( 'Required next step', 'mybookaro' );
            $summary['model_label'] = __( 'Single Business launch assistant', 'mybookaro' );

            $missing_page_keys = is_array( $single_business_context['missing_page_keys'] ?? null ) ? $single_business_context['missing_page_keys'] : [];
            $dashboard_mode = sanitize_key( (string) ( $single_business_context['dashboard_mode'] ?? 'shortcodes' ) );
            if ( ! in_array( $dashboard_mode, [ 'shortcodes', 'woocommerce' ], true ) ) {
                $dashboard_mode = 'shortcodes';
            }
            $booking_page_ready = array_key_exists( 'booking_page_ready', $single_business_context )
                ? ! empty( $single_business_context['booking_page_ready'] )
                : ! in_array( 'booking', $missing_page_keys, true );
            $dashboard_pages_ready = array_key_exists( 'dashboard_pages_ready', $single_business_context )
                ? ! empty( $single_business_context['dashboard_pages_ready'] )
                : (
                    'shortcodes' !== $dashboard_mode
                    || ( ! in_array( 'provider_dashboard', $missing_page_keys, true ) && ! in_array( 'customer_dashboard', $missing_page_keys, true ) )
                );
            $preview_ready = ! empty( $single_business_context['preview_ready'] );
            $fast_path_ready = ! empty( $single_business_context['fast_path_ready'] );
            $services_count = max( 0, absint( $single_business_context['services_count'] ?? 0 ) );
            $provider_ready_for_focus = array_key_exists( 'provider_ready', $single_business_context )
                ? ! empty( $single_business_context['provider_ready'] )
                : $single_business_provider_ready;
            $pages_ready_for_focus = array_key_exists( 'pages_ready', $single_business_context )
                ? ! empty( $single_business_context['pages_ready'] )
                : $single_business_pages_ready;
            $services_ready_for_focus = array_key_exists( 'services_ready', $single_business_context )
                ? ! empty( $single_business_context['services_ready'] )
                : $single_business_services_ready;
            $single_business_snapshot = AdminLaneSummary::build_single_business_readiness_snapshot( [
                'provider_ready' => $provider_ready_for_focus,
                'booking_page_ready' => $booking_page_ready,
                'services_ready' => $services_ready_for_focus,
                'services_count' => $services_count,
                'dashboard_mode' => $dashboard_mode,
                'dashboard_pages_ready' => $dashboard_pages_ready,
                'preview_ready' => $preview_ready,
                'fast_path_ready' => $fast_path_ready,
            ] );
            $summary['model_summary'] = trim( (string) ( $single_business_snapshot['summary'] ?? '' ) );
            $summary['model_items'] = is_array( $single_business_snapshot['items'] ?? null ) ? $single_business_snapshot['items'] : [];

            $single_business_focus = AdminLaneSummary::resolve_single_business_focus( [
                'provider_ready' => $provider_ready_for_focus,
                'pages_ready' => $pages_ready_for_focus,
                'services_ready' => $services_ready_for_focus,
                'missing_page_keys' => $missing_page_keys,
                'default_provider_url' => trim( (string) ( $single_business_context['default_provider_url'] ?? admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' ) ) ),
                'pages_url' => trim( (string) ( $single_business_context['pages_url'] ?? admin_url( 'admin.php?page=bookaro-setup-wizard&step=pages' ) ) ),
                'pages_action_label' => trim( (string) ( $single_business_context['pages_action_label'] ?? '' ) ),
                'create_service_url' => trim(
                    (string) ( $single_business_context['create_service_url'] ?? admin_url( 'post-new.php?post_type=' . ( defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service' ) ) )
                ),
                'ready_url' => trim( (string) ( $single_business_context['ready_url'] ?? $single_business_fast_path_url ) ),
                'provider_detail' => '' !== trim( (string) ( $single_business_context['provider_detail'] ?? '' ) )
                    ? trim( (string) $single_business_context['provider_detail'] )
                    : __( 'Set a Default Provider in Setup Wizard > Listings (or Settings > General).', 'mybookaro' ),
                'pages_detail' => trim( (string) ( $single_business_context['pages_detail'] ?? __( 'Assign booking/services/dashboard pages, then continue with validation.', 'mybookaro' ) ) ),
                'services_detail' => trim( (string) ( $single_business_context['services_detail'] ?? __( 'Create at least one provider service, then run one end-to-end booking flow test.', 'mybookaro' ) ) ),
                'ready_detail' => '' !== trim( (string) ( $single_business_context['ready_detail'] ?? '' ) )
                    ? trim( (string) $single_business_context['ready_detail'] )
                    : __( 'Follow this order: Default Provider -> Pages -> First service -> Preview booking.', 'mybookaro' ),
            ] );

            if ( 'ok' !== (string) ( $single_business_focus['state'] ?? 'ok' ) ) {
                $state = (string) $single_business_focus['state'];
                $state_label = (string) ( $single_business_focus['state_label'] ?? $state_label );
                $top_blocker = (string) ( $single_business_focus['top_blocker'] ?? '' );
                $next_action = is_array( $single_business_focus['next_action'] ?? null ) ? $single_business_focus['next_action'] : $next_action;
            } elseif ( 'operational' === $step ) {
                if ( '' === $single_business_fast_path_url ) {
                    $single_business_fast_path_url = admin_url( 'admin.php?page=bookaro-getting-started#bookaro-mode-aware-quick-start' );
                }
                $single_business_focus = AdminLaneSummary::resolve_single_business_focus( [
                    'provider_ready' => true,
                    'pages_ready' => true,
                    'services_ready' => true,
                    'ready_label' => __( 'Run Single Business fast path', 'mybookaro' ),
                    'ready_url' => $single_business_fast_path_url,
                    'ready_detail' => __( 'Create demo pages/services and seed provider availability, then open a preview booking flow without listing context.', 'mybookaro' ),
                ] );
                $state = (string) $single_business_focus['state'];
                $state_label = (string) ( $single_business_focus['state_label'] ?? $state_label );
                $top_blocker = (string) ( $single_business_focus['top_blocker'] ?? '' );
                $next_action = is_array( $single_business_focus['next_action'] ?? null ) ? $single_business_focus['next_action'] : $next_action;
            }
        }

        if ( '' === $top_blocker && $launch_blocked && 'single_business' !== $site_type ) {
            $state = 'warn';
            $state_label = __( 'Needs attention', 'mybookaro' );
            $top_blocker = '' !== $generic_compact_blocker ? $generic_compact_blocker : trim( $blocked_message );
            $next_action = [
                'label' => trim( $blocked_action_label ),
                'url' => trim( $blocked_action_url ),
                'detail' => '' !== $generic_compact_blocker ? $generic_compact_blocker : trim( $blocked_message ),
            ];
            if ( false !== strpos( strtolower( $blocked_message ), 'blocked' ) || false !== strpos( strtolower( $blocked_message ), 'required' ) ) {
                $state = 'error';
                $state_label = __( 'Blocked', 'mybookaro' );
            }
        } elseif ( '' === $top_blocker ) {
            $current_step_label = trim( (string) ( $steps[ $step ] ?? '' ) );
            if ( '' !== $current_step_label ) {
                $top_blocker = sprintf(
                    /* translators: %s: current wizard step label */
                    __( 'Current focus: %s.', 'mybookaro' ),
                    $current_step_label
                );
            }
            if ( '' === $top_blocker ) {
                $top_blocker = __( 'No blockers detected for the current lane snapshot.', 'mybookaro' );
            }
        }

        return AdminLaneSummary::normalize( array_merge( $summary, [
            'state' => $state,
            'state_label' => $state_label,
            'top_blocker' => $top_blocker,
            'next_action' => $next_action,
        ] ) );
    }

    private function build_mylisting_wizard_lane_summary_banner( array $mylisting_activation_flow, array $mylisting_next_action ): array
    {
        $summary = AdminLaneSummary::create_payload( __( 'MyListing Directory', 'mybookaro' ) );
        $summary = array_merge(
            $summary,
            AdminLaneSummary::resolve_mylisting_focus( $mylisting_activation_flow, $mylisting_next_action )
        );

        return AdminLaneSummary::normalize( array_merge( $summary, [
            'lane_label' => __( 'MyListing Directory', 'mybookaro' ),
        ] ) );
    }

    private function render_mylisting_wizard_page(): void
    {
        $steps = [
            'integration' => __( 'Lane', 'mybookaro' ),
            'listings'    => __( 'Listings', 'mybookaro' ),
            'services'    => __( 'Services', 'mybookaro' ),
            'finish'      => __( 'Finish', 'mybookaro' ),
        ];

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $default_step = array_key_first( $steps ) ?: 'integration';
        $step = sanitize_text_field( wp_unslash( $_GET['step'] ?? $default_step ) );
        if ( ! isset( $steps[ $step ] ) ) {
            $step = $default_step;
        }
        $step_keys = array_keys( $steps );
        $current_index = array_search( $step, $step_keys, true );
        if ( false === $current_index ) {
            $current_index = 0;
        }
        $prev_step = $current_index > 0 ? $step_keys[ $current_index - 1 ] : '';

        $opts = $this->options->get_all();
        $site_type = $this->resolve_site_type_from_options( $opts );
        $site_type_selector = ( 'advanced_mapping' === $site_type ) ? 'directory' : $site_type;
        $site_type_options = function_exists( 'bookaro_get_site_type_options' )
            ? bookaro_get_site_type_options()
            : [
                'directory' => __( 'Directory lanes (MyListing Directory or Generic Directory)', 'mybookaro' ),
                'single_business' => __( 'Single Business', 'mybookaro' ),
            ];
        unset( $site_type_options['advanced_mapping'] );
        $integration_mode = sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) );
        if ( ! in_array( $integration_mode, [ 'auto', 'mylisting' ], true ) ) {
            $integration_mode = 'auto';
        }
        if ( array_key_exists( 'frontend_enabled', $opts ) ) {
            $frontend_enabled = ! empty( $opts['frontend_enabled'] );
        } else {
            $frontend_enabled = true;
        }
        $listing_post_type_options = $this->get_listing_post_type_options();
        $available_listing_types = array_keys( $listing_post_type_options );
        $selected_listing_types = $opts['allowed_listing_post_types'] ?? [];
        if ( empty( $selected_listing_types ) && ! empty( $opts['listing_post_type'] ) ) {
            $selected_listing_types = [ $opts['listing_post_type'] ];
        }
        if ( ! is_array( $selected_listing_types ) ) {
            $selected_listing_types = [ $selected_listing_types ];
        }
        $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $selected_listing_types ) ) ) );
        if ( empty( $selected_listing_types ) ) {
            if ( in_array( 'job_listing', $available_listing_types, true ) ) {
                $selected_listing_types = [ 'job_listing' ];
            } elseif ( ! empty( $available_listing_types ) ) {
                $selected_listing_types = [ (string) $available_listing_types[0] ];
            }
        }
        $provider_resolution_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? '' ) );
        $provider_meta_key = sanitize_key( (string) ( $opts['provider_meta_key'] ?? '' ) );
        if ( '' === $provider_meta_key && ! empty( $opts['listing_provider_meta_key'] ) ) {
            $provider_meta_key = sanitize_key( (string) $opts['listing_provider_meta_key'] );
        }
        if ( ! in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true ) ) {
            $provider_resolution_mode = $provider_meta_key !== '' ? 'meta_key' : 'author';
        }
        $depends_provider_meta = wp_json_encode( [
            'mode' => 'all',
            'rules' => [
                [ 'field' => 'provider_resolution_mode', 'operator' => 'equals', 'value' => 'meta_key' ],
            ],
        ] );
        $repeater_class = sanitize_key( (string) ( $opts['mylisting_services_repeater_class'] ?? 'mybookaro_services' ) );
        if ( '' === $repeater_class ) {
            $repeater_class = 'mybookaro_services';
        }
        $setup_completed = ! empty( $opts['mylisting_setup_completed'] );
        $mylisting_detected = function_exists( 'bookaro_is_mylisting_active' )
            ? bookaro_is_mylisting_active()
            : $this->is_mylisting_detected();

        $settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' );
        $notifications_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=notifications' );
        $getting_started_url = admin_url( 'admin.php?page=bookaro-getting-started' );
        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        $status_url = (string) ( $support_touchpoints['system_status_url'] ?? admin_url( 'admin.php?page=bookaro-system-status' ) );
        $support_snapshot_url = (string) ( $support_touchpoints['support_snapshot_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-snapshot' ) );
        $support_bundle_url = (string) ( $support_touchpoints['support_bundle_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-bundle' ) );
        $support_touchpoint_actions = $this->get_support_touchpoint_actions();
        $default_listing_id = $this->get_default_mylisting_listing_id( $selected_listing_types );
        $mylisting_services_diagnostics = $this->get_mylisting_service_resolution_diagnostics( $default_listing_id );
        $mylisting_services_diagnostics_view = $this->build_mylisting_service_resolution_copy( $mylisting_services_diagnostics, $default_listing_id, $repeater_class );
        $mylisting_services_note_state = sanitize_key( (string) ( $mylisting_services_diagnostics_view['state'] ?? 'info' ) );
        if ( ! in_array( $mylisting_services_note_state, [ 'ok', 'warn', 'error' ], true ) ) {
            $mylisting_services_note_state = 'info';
        }
        $mylisting_services_note_class = 'info';
        if ( 'ok' === $mylisting_services_note_state ) {
            $mylisting_services_note_class = 'success';
        } elseif ( 'warn' === $mylisting_services_note_state ) {
            $mylisting_services_note_class = 'warning';
        } elseif ( 'error' === $mylisting_services_note_state ) {
            $mylisting_services_note_class = 'error';
        }
        $mylisting_activation_flow = $this->build_mylisting_activation_flow(
            $default_listing_id,
            $provider_resolution_mode,
            $provider_meta_key,
            $repeater_class
        );
        $mylisting_next_action = is_array( $mylisting_activation_flow['next_action'] ?? null )
            ? $mylisting_activation_flow['next_action']
            : [ 'label' => '', 'url' => '', 'detail' => '' ];
        $lane_summary = $this->build_mylisting_wizard_lane_summary_banner( $mylisting_activation_flow, $mylisting_next_action );
        ?>
        <div class="wrap bookaro-admin bookaro-setup-wizard">
            <div class="bookaro-card bookaro-hero bookaro-setup-hero">
                <div class="bookaro-hero__content">
                    <div class="bookaro-hero__brand">
                        <img src="<?php echo esc_url( BOOKARO_PLUGIN_URL . 'assets/img/mb-logo.svg' ); ?>" alt="<?php esc_attr_e( 'MyBookaro', 'mybookaro' ); ?>" width="120" height="36" />
                    </div>
                    <h1><?php esc_html_e( 'MyBookaro Setup Wizard', 'mybookaro' ); ?></h1>
                    <p class="description"><?php esc_html_e( 'Choose your lane first: MyListing Directory, Single Business, or guided Generic Directory. MyBookaro is compatible with MyListing, and each lane has a launch checklist.', 'mybookaro' ); ?></p>
                    <p class="description">
                        <?php
                        printf(
                            /* translators: %1$s: dynamic string, %2$s: dynamic string */
                            wp_kses_post( __( 'Support handoff: start with the <a href="%1$s">masked support snapshot</a>. Use the <a href="%2$s">Support Bundle</a> only when support asks for deeper diagnostics.', 'mybookaro' ) ),
                            esc_url( $support_snapshot_url ),
                            esc_url( $support_bundle_url )
                        );
                        ?>
                    </p>
                </div>
                <div class="bookaro-hero__actions">
                    <a class="button button-secondary" href="<?php echo esc_url( $settings_url ); ?>">
                        <?php esc_html_e( 'Go to settings', 'mybookaro' ); ?>
                    </a>
                    <?php foreach ( $support_touchpoint_actions as $support_touchpoint_action ) : ?>
                        <a class="button button-secondary" href="<?php echo esc_url( (string) ( $support_touchpoint_action['url'] ?? '' ) ); ?>">
                            <?php echo esc_html( (string) ( $support_touchpoint_action['label'] ?? '' ) ); ?>
                        </a>
                    <?php endforeach; ?>
                </div>
            </div>
            <?php TemplateLoader::render( 'admin/components/lane-summary-banner.php', [ 'lane_summary' => $lane_summary ] ); ?>

            <div class="bookaro-card bookaro-stepper">
                <?php
                $step_index = 0;
                foreach ( $steps as $slug => $label ) :
                    $is_active = ( $slug === $step );
                    $classes = [ 'bookaro-stepper__item' ];
                    if ( $is_active ) {
                        $classes[] = 'is-active';
                    }
                    if ( $step_index < $current_index ) {
                        $classes[] = 'is-complete';
                    }
                    $step_index++;
                    ?>
                    <div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
                        <span class="bookaro-stepper__index"><?php echo esc_html( (string) $step_index ); ?></span>
                        <span class="bookaro-stepper__label"><?php echo esc_html( $label ); ?></span>
                    </div>
                <?php endforeach; ?>
            </div>

            <div class="bookaro-card bookaro-setup-panel">
                <?php if ( 'integration' === $step ) : ?>
                    <div class="bookaro-setup-panel__header">
                        <h2><?php esc_html_e( 'Confirm MyListing Directory lane', 'mybookaro' ); ?></h2>
                        <p class="description"><?php esc_html_e( 'Start with lane choice, then confirm MyListing Directory lane detection and core booking behavior.', 'mybookaro' ); ?></p>
                    </div>

                    <?php if ( ! $mylisting_detected ) : ?>
                        <div class="bookaro-note bookaro-note--warning bookaro-setup-note">
                            <strong><?php esc_html_e( 'MyListing not detected', 'mybookaro' ); ?></strong>
                            <p class="description"><?php esc_html_e( 'Activate MyListing to continue with the MyListing Directory lane, or switch to Single Business or guided Generic Directory.', 'mybookaro' ); ?></p>
                        </div>
                    <?php endif; ?>

                    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                        <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                        <input type="hidden" name="action" value="bookaro_setup_wizard">
                        <input type="hidden" name="step" value="mylisting_integration">

                        <table class="form-table" role="presentation">
                              <tr>
                                  <th scope="row"><label for="bookaro-site-type"><?php esc_html_e( 'Lane', 'mybookaro' ); ?></label></th>
                                  <td>
                                      <select id="bookaro-site-type" name="site_type">
                                          <?php foreach ( $site_type_options as $site_type_value => $site_type_label ) : ?>
                                              <option value="<?php echo esc_attr( $site_type_value ); ?>" <?php selected( $site_type_selector, $site_type_value ); ?>>
                                                  <?php echo esc_html( $site_type_label ); ?>
                                              </option>
                                          <?php endforeach; ?>
                                      </select>
                                      <p class="description"><?php esc_html_e( 'Choose MyListing Directory, Single Business, or guided Generic Directory. Generic advanced options are available when you need custom mapping or placement.', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                              <tr>
                                  <th scope="row"><label for="bookaro-integration-mode"><?php esc_html_e( 'Directory lane choice', 'mybookaro' ); ?></label></th>
                                  <td>
                                      <select id="bookaro-integration-mode" name="integration_mode">
                                          <option value="auto" <?php selected( $integration_mode, 'auto' ); ?>>
                                              <?php esc_html_e( 'Auto-select Directory lane (MyListing when active)', 'mybookaro' ); ?>
                                         </option>
                                        <option value="mylisting" <?php selected( $integration_mode, 'mylisting' ); ?>>
                                            <?php esc_html_e( 'MyListing Directory', 'mybookaro' ); ?>
                                        </option>
                                      </select>
                                      <p class="description"><?php esc_html_e( 'This setting is only for the Directory lane. Auto-select uses MyListing when active; Single Business ignores this setting.', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                              <tr>
                                  <th scope="row"><?php esc_html_e( 'Frontend UI', 'mybookaro' ); ?></th>
                                  <td>
                                      <label>
                                          <input type="checkbox" name="frontend_enabled" value="1" <?php checked( $frontend_enabled ); ?>>
                                          <?php esc_html_e( 'Enable booking form and dashboards on the frontend', 'mybookaro' ); ?>
                                      </label>
                                      <p class="description"><?php esc_html_e( 'Disable while configuring. Booking UI stays hidden.', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                          </table>

                          <div class="bookaro-setup-actions">
                              <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                                  <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                              </button>
                          </div>
                      </form>
                  <?php elseif ( 'listings' === $step ) : ?>
                      <div class="bookaro-setup-panel__header">
                          <h2><?php esc_html_e( 'Listings and provider mapping', 'mybookaro' ); ?></h2>
                          <p class="description"><?php esc_html_e( 'Select MyListing post types and confirm provider ownership mapping for booking requests.', 'mybookaro' ); ?></p>
                      </div>

                      <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                          <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                          <input type="hidden" name="action" value="bookaro_setup_wizard">
                          <input type="hidden" name="step" value="mylisting_listings">

                          <table class="form-table" role="presentation">
                              <tr>
                                  <th scope="row"><label for="bookaro-listing-types"><?php esc_html_e( 'Listing Post Types', 'mybookaro' ); ?></label></th>
                                  <td>
                                      <select id="bookaro-listing-types" name="allowed_listing_post_types[]" multiple size="6" data-bookaro-setting="allowed_listing_post_types">
                                          <?php foreach ( $listing_post_type_options as $key => $label ) : ?>
                                              <option value="<?php echo esc_attr( $key ); ?>" <?php selected( in_array( $key, $selected_listing_types, true ) ); ?>>
                                                  <?php echo esc_html( $label ); ?>
                                              </option>
                                          <?php endforeach; ?>
                                      </select>
                                      <p class="description"><?php esc_html_e( 'Select the post types that represent your listings.', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                              <tr>
                                  <th scope="row"><label for="bookaro-provider-resolution"><?php esc_html_e( 'Provider Resolution', 'mybookaro' ); ?></label></th>
                                  <td>
                                      <select id="bookaro-provider-resolution" name="provider_resolution_mode" data-bookaro-setting="provider_resolution_mode">
                                          <option value="author" <?php selected( $provider_resolution_mode, 'author' ); ?>>
                                              <?php esc_html_e( 'Listing Author', 'mybookaro' ); ?>
                                          </option>
                                          <option value="meta_key" <?php selected( $provider_resolution_mode, 'meta_key' ); ?>>
                                              <?php esc_html_e( 'Listing Meta Key', 'mybookaro' ); ?>
                                          </option>
                                      </select>
                                      <p class="description"><?php esc_html_e( 'Use Listing Author when providers publish their own listings. Switch to Listing Meta Key when editors/admins publish listings and provider ownership is stored in meta.', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                              <tr data-bookaro-depends="<?php echo esc_attr( $depends_provider_meta ); ?>">
                                  <th scope="row"><label for="bookaro-provider-meta"><?php esc_html_e( 'Provider Meta Key', 'mybookaro' ); ?></label></th>
                                  <td>
                                      <input type="text" id="bookaro-provider-meta" name="provider_meta_key" class="regular-text" value="<?php echo esc_attr( $provider_meta_key ); ?>">
                                      <p class="description"><?php esc_html_e( 'Meta key that stores the provider user ID (example: provider_user_id).', 'mybookaro' ); ?></p>
                                  </td>
                              </tr>
                          </table>

                          <div class="bookaro-setup-actions">
                              <?php if ( $prev_step ) : ?>
                                  <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                      <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                                  </a>
                              <?php endif; ?>
                              <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                                  <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                              </button>
                          </div>
                      </form>
                  <?php elseif ( 'services' === $step ) : ?>
                    <div class="bookaro-setup-panel__header">
                        <h2><?php esc_html_e( 'Configure services repeater', 'mybookaro' ); ?></h2>
                        <p class="description"><?php esc_html_e( 'Set the MyListing repeater row class so MyBookaro can read provider services reliably.', 'mybookaro' ); ?></p>
                    </div>

                    <div class="bookaro-note bookaro-note--<?php echo esc_attr( $mylisting_services_note_class ); ?> bookaro-setup-note">
                        <strong><?php echo esc_html( (string) ( $mylisting_services_diagnostics_view['summary'] ?? '' ) ); ?></strong>
                        <?php if ( $default_listing_id > 0 ) : ?>
                            <p class="description">
                                <?php
                                printf(
                                    /* translators: %d: listing ID */
                                    esc_html__( 'Sample listing used for diagnostics: #%d.', 'mybookaro' ),
                                    (int) $default_listing_id
                                );
                                ?>
                            </p>
                        <?php endif; ?>
                        <?php if ( ! empty( $mylisting_services_diagnostics_view['detail'] ) ) : ?>
                            <p class="description"><?php echo esc_html( (string) $mylisting_services_diagnostics_view['detail'] ); ?></p>
                        <?php endif; ?>
                        <?php if ( ! empty( $mylisting_services_diagnostics_view['fix'] ) ) : ?>
                            <p class="description"><?php echo esc_html( (string) $mylisting_services_diagnostics_view['fix'] ); ?></p>
                        <?php endif; ?>
                    </div>

                    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                        <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                        <input type="hidden" name="action" value="bookaro_setup_wizard">
                        <input type="hidden" name="step" value="mylisting_services">

                        <table class="form-table" role="presentation">
                            <tr>
                                <th scope="row"><label for="bookaro-mylisting-repeater"><?php esc_html_e( 'Services Repeater Class', 'mybookaro' ); ?></label></th>
                                <td>
                                    <input id="bookaro-mylisting-repeater" class="regular-text" type="text" name="mylisting_services_repeater_class" value="<?php echo esc_attr( $repeater_class ); ?>">
                                    <p class="description"><?php esc_html_e( 'Set this class on the repeater row inside your MyListing Listing Type.', 'mybookaro' ); ?></p>
                                </td>
                            </tr>
                        </table>

                        <div class="bookaro-setup-actions">
                            <?php if ( $prev_step ) : ?>
                                <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                    <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                                </a>
                            <?php endif; ?>
                            <button type="submit" class="button button-primary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                                <?php esc_html_e( 'Continue', 'mybookaro' ); ?>
                            </button>
                        </div>
                    </form>
                <?php else : ?>
                    <div class="bookaro-setup-panel__header">
                        <h2><?php esc_html_e( 'Finish setup', 'mybookaro' ); ?></h2>
                        <p class="description"><?php esc_html_e( 'Use this fast path to complete one end-to-end booking test from a MyListing sidebar booking entry.', 'mybookaro' ); ?></p>
                    </div>

                    <?php if ( $setup_completed ) : ?>
                        <div class="bookaro-note bookaro-setup-note">
                            <strong><?php esc_html_e( 'Setup completed', 'mybookaro' ); ?></strong>
                            <p class="description"><?php esc_html_e( 'Keep using the action below whenever you need another end-to-end booking test.', 'mybookaro' ); ?></p>
                        </div>
                    <?php endif; ?>

                    <div class="bookaro-status-list">
                        <?php foreach ( (array) ( $mylisting_activation_flow['milestones'] ?? [] ) as $milestone ) : ?>
                            <?php
                            $milestone_passed = ! empty( $milestone['passed'] );
                            $milestone_state = $milestone_passed ? 'ok' : 'warn';
                            $milestone_label = $milestone_passed ? __( 'Ready', 'mybookaro' ) : __( 'Pending', 'mybookaro' );
                            ?>
                            <div class="bookaro-status-item">
                                <div class="bookaro-status-item__label"><?php echo esc_html( (string) ( $milestone['label'] ?? '' ) ); ?></div>
                                <div class="bookaro-status-item__value">
                                    <span class="bookaro-status-pill <?php echo esc_attr( 'bookaro-status-pill--' . $milestone_state ); ?>">
                                        <?php echo esc_html( $milestone_label ); ?>
                                    </span>
                                    <?php if ( ! empty( $milestone['detail'] ) ) : ?>
                                        <div class="bookaro-status-item__meta"><?php echo esc_html( (string) $milestone['detail'] ); ?></div>
                                    <?php endif; ?>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>

                    <?php if ( ! empty( $mylisting_next_action['detail'] ) ) : ?>
                        <p class="description"><?php echo esc_html( (string) $mylisting_next_action['detail'] ); ?></p>
                    <?php endif; ?>

                    <p>
                        <?php if ( ! empty( $mylisting_next_action['url'] ) && ! empty( $mylisting_next_action['label'] ) ) : ?>
                            <a class="button button-primary" href="<?php echo esc_url( (string) $mylisting_next_action['url'] ); ?>">
                                <?php echo esc_html( (string) $mylisting_next_action['label'] ); ?>
                            </a>
                        <?php endif; ?>
                        <a class="button button-secondary" href="<?php echo esc_url( $getting_started_url ); ?>">
                            <?php esc_html_e( 'Open Getting Started', 'mybookaro' ); ?>
                        </a>
                        <a class="button button-secondary" href="<?php echo esc_url( $notifications_url ); ?>">
                            <?php esc_html_e( 'Open Email settings', 'mybookaro' ); ?>
                        </a>
                        <a class="button button-secondary" href="<?php echo esc_url( $status_url ); ?>">
                            <?php esc_html_e( 'View System Status', 'mybookaro' ); ?>
                        </a>
                    </p>

                    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="bookaro-setup-form">
                        <?php wp_nonce_field( 'bookaro_setup_wizard' ); ?>
                        <input type="hidden" name="action" value="bookaro_setup_wizard">
                        <input type="hidden" name="step" value="mylisting_finish">

                        <div class="bookaro-setup-actions">
                            <?php if ( $prev_step ) : ?>
                                <a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $prev_step ) ); ?>">
                                    <?php esc_html_e( 'Back', 'mybookaro' ); ?>
                                </a>
                            <?php endif; ?>
                            <?php if ( ! $setup_completed ) : ?>
                                <button type="submit" class="button button-secondary bookaro-next-button" data-loading-label="<?php echo esc_attr__( 'Saving...', 'mybookaro' ); ?>">
                                    <?php esc_html_e( 'Mark Setup Complete', 'mybookaro' ); ?>
                                </button>
                            <?php else : ?>
                                <button type="submit" class="button button-secondary" disabled>
                                    <?php esc_html_e( 'Setup Complete', 'mybookaro' ); ?>
                                </button>
                            <?php endif; ?>
                        </div>
                    </form>
                <?php endif; ?>
            </div>
        </div>
        <?php
    }

    private function wizard_mode(): string
    {
        $opts = $this->options->get_all();
        $site_type = $this->resolve_site_type_from_options( $opts );
        if ( in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true ) ) {
            if ( defined( 'BOOKARO_ENABLE_GENERIC_MODE' ) && ! BOOKARO_ENABLE_GENERIC_MODE ) {
                return '';
            }
            return 'generic';
        }

        if ( ! function_exists( 'bookaro_get_integration_mode' ) ) {
            return '';
        }
        $mode = bookaro_get_integration_mode();
        if ( 'generic' === $mode ) {
            if ( defined( 'BOOKARO_ENABLE_GENERIC_MODE' ) && ! BOOKARO_ENABLE_GENERIC_MODE ) {
                return '';
            }
            return 'generic';
        }
        if ( 'mylisting' === $mode ) {
            return 'mylisting';
        }
        return '';
    }

    private function wizard_enabled(): bool
    {
        return $this->wizard_mode() !== '';
    }

    private function is_mylisting_detected(): bool
    {
        return defined( 'MYLISTING_VERSION' )
            || defined( 'MYLISTING_DIR' )
            || class_exists( '\\MyListing\\Plugin' )
            || function_exists( 'mylisting' );
    }

    private function generic_mode_enabled(): bool
    {
        if ( defined( 'BOOKARO_ENABLE_GENERIC_MODE' ) && ! BOOKARO_ENABLE_GENERIC_MODE ) {
            return false;
        }
        return function_exists( 'bookaro_get_integration_mode' )
            && 'generic' === bookaro_get_integration_mode();
    }

    private function get_listing_post_type_options(): array
    {
        $post_types = get_post_types( [ 'show_ui' => true ], 'objects' );
        $options = [];
        foreach ( $post_types as $slug => $type ) {
            if ( in_array( $slug, [ 'attachment', 'revision', 'nav_menu_item' ], true ) ) {
                continue;
            }
            if ( defined( 'BOOKARO_SERVICE_POST_TYPE' ) && $slug === BOOKARO_SERVICE_POST_TYPE ) {
                continue;
            }
            if ( defined( 'BOOKARO_BOOKING_POST_TYPE' ) && $slug === BOOKARO_BOOKING_POST_TYPE ) {
                continue;
            }
            $options[ $slug ] = $type->labels->singular_name ?? $type->label ?? $slug;
        }
        if ( empty( $options ) && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
            $options[ BOOKARO_PROVIDER_POST_TYPE ] = __( 'Provider', 'mybookaro' );
        }
        ksort( $options );
        return $options;
    }

    private function get_page_options(): array
    {
        $pages = get_pages( [
            'post_status' => [ 'publish', 'private' ],
            'sort_column' => 'post_title',
            'sort_order'  => 'ASC',
        ] );
        $options = [];
        foreach ( $pages as $page ) {
            if ( $page instanceof \WP_Post ) {
                /* translators: %d: numeric value */
                $options[ (int) $page->ID ] = $page->post_title !== '' ? $page->post_title : sprintf( __( 'Page #%d', 'mybookaro' ), $page->ID );
            }
        }
        return $options;
    }

    private function get_provider_user_options(): array
    {
        $options = [ '' => __( 'Select a provider', 'mybookaro' ) ];

        $selected_default_provider_id = absint( $this->options->get( 'default_provider_id', 0 ) );
        $provider_role = sanitize_key( (string) ( $this->options->get( 'provider_role', '' ) ) );
        $args = [
            'orderby' => 'display_name',
            'order' => 'ASC',
            'fields' => [ 'ID', 'display_name', 'user_email', 'user_login' ],
            'number' => -1,
        ];
        if ( $provider_role !== '' ) {
            $args['role__in'] = [ $provider_role ];
        }

        $users = get_users( $args );
        foreach ( $users as $user ) {
            if ( ! $user || empty( $user->ID ) ) {
                continue;
            }
            $name = $user->display_name ?: $user->user_login;
            $label = $name;
            if ( ! empty( $user->user_email ) ) {
                $label .= ' (' . $user->user_email . ')';
            }
            $options[ (string) $user->ID ] = $label;
        }

        if ( $selected_default_provider_id > 0 && ! isset( $options[ (string) $selected_default_provider_id ] ) ) {
            $selected_user = get_user_by( 'ID', $selected_default_provider_id );
            if ( $selected_user ) {
                $selected_label = $selected_user->display_name ?: $selected_user->user_login;
                if ( ! empty( $selected_user->user_email ) ) {
                    $selected_label .= ' (' . $selected_user->user_email . ')';
                }
                $options[ (string) $selected_default_provider_id ] = $selected_label;
            }
        }

        return $options;
    }

    private function get_default_listing_post_type(): string
    {
        $types = function_exists( 'bookaro_get_allowed_listing_post_types' )
            ? bookaro_get_allowed_listing_post_types()
            : [];
        if ( empty( $types ) && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
            $types = [ BOOKARO_PROVIDER_POST_TYPE ];
        }
        $type = $types[0] ?? 'page';
        return sanitize_key( (string) $type );
    }

    private function get_mylisting_finish_redirect_url(): string
    {
        return $this->get_wizard_completion_redirect_url( $this->options->get_all() );
    }

    private function get_wizard_completion_redirect_url( array $opts = [] ): string
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        $lane_id = $this->resolve_wizard_completion_lane_id( $opts );
        $url = add_query_arg(
            [
                'page' => 'bookaro-getting-started',
                'wizard_complete' => 1,
                'wizard_lane' => $lane_id,
            ],
            admin_url( 'admin.php' )
        );
        $fragment = $this->get_wizard_completion_fragment( $lane_id );
        if ( '' !== $fragment ) {
            $url .= '#' . $fragment;
        }

        return $url;
    }

    private function resolve_wizard_completion_lane_id( array $opts ): string
    {
        $site_type = $this->resolve_site_type_from_options( $opts );
        if ( 'single_business' === $site_type ) {
            return 'single_business';
        }

        return ( 'mylisting' === $this->resolve_integration_mode_from_options( $opts ) )
            ? 'mylisting_directory'
            : 'generic_directory';
    }

    private function get_wizard_completion_fragment( string $lane_id ): string
    {
        $lane_id = sanitize_key( $lane_id );
        if ( 'mylisting_directory' === $lane_id ) {
            return 'bookaro-first-booking-progress';
        }
        if ( 'single_business' === $lane_id ) {
            return 'bookaro-mode-aware-quick-start';
        }

        return 'bookaro-generic-readiness-summary';
    }

    private function get_mylisting_default_listing_post_type( array $selected_listing_types = [] ): string
    {
        if ( ! empty( $selected_listing_types ) ) {
            return sanitize_key( (string) $selected_listing_types[0] );
        }

        $opts = $this->options->get_all();
        $stored = sanitize_key( (string) ( $opts['listing_post_type'] ?? '' ) );
        if ( '' !== $stored ) {
            return $stored;
        }

        return 'job_listing';
    }

    private function get_default_mylisting_listing_id( array $selected_listing_types = [] ): int
    {
        if ( empty( $selected_listing_types ) ) {
            $selected_listing_types = [ $this->get_mylisting_default_listing_post_type() ];
        }
        $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $selected_listing_types ) ) ) );

        $posts = get_posts( [
            'post_type' => $selected_listing_types,
            'post_status' => 'publish',
            'posts_per_page' => 1,
            'orderby' => 'date',
            'order' => 'DESC',
            'fields' => 'ids',
        ] );

        if ( ! empty( $posts ) ) {
            return absint( $posts[0] );
        }

        return 0;
    }

    private function build_mylisting_create_listing_action( array $selected_listing_types = [] ): array
    {
        $post_type = $this->get_mylisting_default_listing_post_type( $selected_listing_types );
        return [
            'label' => __( 'Create listing', 'mybookaro' ),
            'url' => admin_url( 'post-new.php?post_type=' . $post_type ),
            'detail' => '',
        ];
    }

    private function build_mylisting_open_listing_action( int $listing_id, array $selected_listing_types = [] ): array
    {
        if ( $listing_id < 1 ) {
            return $this->build_mylisting_create_listing_action( $selected_listing_types );
        }

        $url = get_permalink( $listing_id );
        if ( ! $url ) {
            $url = get_edit_post_link( $listing_id, '' );
        }
        if ( ! $url ) {
            $url = admin_url( 'admin.php?page=bookaro-getting-started#bookaro-action-open-listing' );
        }

        return [
            'label' => __( 'Open listing preview', 'mybookaro' ),
            'url' => $url,
            'detail' => '',
        ];
    }

    private function get_mylisting_fast_path_url( int $listing_id ): string
    {
        $listing_id = max( 0, $listing_id );
        $url = admin_url( 'admin-post.php?action=bookaro_getting_started_fast_path_booking&listing_id=' . $listing_id );
        if ( function_exists( 'add_query_arg' ) ) {
            $url = add_query_arg(
                [
                    'action' => 'bookaro_getting_started_fast_path_booking',
                    'listing_id' => $listing_id,
                ],
                admin_url( 'admin-post.php' )
            );
        }
        if ( function_exists( 'wp_nonce_url' ) ) {
            return wp_nonce_url( $url, 'bookaro_getting_started_fast_path_booking' );
        }

        return $url;
    }

    private function resolve_single_business_preview_url( int $booking_page_id, int $services_page_id = 0 ): string
    {
        $candidates = array_values(
            array_filter(
                array_unique( [
                    absint( $booking_page_id ),
                    absint( $services_page_id ),
                ] )
            )
        );
        foreach ( $candidates as $page_id ) {
            if ( $page_id < 1 || ! get_post( $page_id ) ) {
                continue;
            }
            $view_url = get_permalink( $page_id );
            if ( $view_url ) {
                return (string) $view_url;
            }
            $edit_url = get_edit_post_link( $page_id, '' );
            if ( $edit_url ) {
                return (string) $edit_url;
            }
        }

        return '';
    }

    private function get_single_business_fast_path_url(): string
    {
        return $this->get_mylisting_fast_path_url( 0 );
    }

    private function count_single_business_available_services( int $provider_id ): int
    {
        if ( $provider_id < 1 ) {
            return 0;
        }

        if ( function_exists( 'bookaro_get_generic_provider_context_services' ) ) {
            $services = bookaro_get_generic_provider_context_services( $provider_id );
            if ( is_array( $services ) ) {
                return count( $services );
            }
        }

        return 0;
    }

    private function count_mylisting_listing_services( int $listing_id ): int
    {
        if ( $listing_id < 1 ) {
            return 0;
        }

        if ( function_exists( 'bookaro_resolve_listing_services' ) ) {
            $services = bookaro_resolve_listing_services( $listing_id, 'mylisting' );
            if ( is_array( $services ) ) {
                return count( $services );
            }
        }
        if ( function_exists( 'bookaro_get_bookaro_services_for_listing' ) ) {
            $services = bookaro_get_bookaro_services_for_listing( $listing_id );
            if ( is_array( $services ) ) {
                return count( $services );
            }
        }

        return 0;
    }

    private function get_mylisting_service_resolution_diagnostics( int $listing_id ): array
    {
        $listing_id = absint( $listing_id );
        $defaults = [
            'listing_id' => $listing_id,
            'target_repeater_class' => 'mybookaro_services',
            'reason_code' => $listing_id > 0 ? 'no_repeater_rows' : 'listing_not_selected',
            'resolution_path' => 'none',
            'status' => $listing_id > 0 ? 'warn' : 'info',
            'summary' => '',
            'detail' => '',
            'fix' => '',
            'resolved_services_count' => 0,
            'row_count_total' => 0,
            'row_count_service_like' => 0,
            'row_count_class_match' => 0,
            'row_count_prefix_fallback' => 0,
            'row_count_class_mismatch' => 0,
            'row_count_missing_label' => 0,
            'detected_prefixes' => [],
            'detected_classes' => [],
            'primary_detected_prefix' => '',
            'primary_detected_class' => '',
            'prefix_mismatch' => false,
        ];

        if ( function_exists( 'bookaro_get_mylisting_service_resolution_diagnostics' ) ) {
            $resolved = bookaro_get_mylisting_service_resolution_diagnostics( $listing_id );
            if ( is_array( $resolved ) ) {
                return array_merge( $defaults, $resolved );
            }
        }

        if ( $listing_id > 0 ) {
            $count = $this->count_mylisting_listing_services( $listing_id );
            $defaults['resolved_services_count'] = $count;
            if ( $count > 0 ) {
                $defaults['reason_code'] = 'resolved_with_class_match';
                $defaults['status'] = 'ok';
            }
        }

        return $defaults;
    }

    private function get_mylisting_resolution_path_label( string $resolution_path ): string
    {
        $resolution_path = sanitize_key( $resolution_path );
        if ( 'class_match' === $resolution_path ) {
            return __( 'Class match', 'mybookaro' );
        }
        if ( 'prefix_fallback' === $resolution_path ) {
            return __( 'Prefix fallback', 'mybookaro' );
        }
        if ( 'class_and_prefix' === $resolution_path ) {
            return __( 'Mixed class + prefix fallback', 'mybookaro' );
        }
        return __( 'No resolved path', 'mybookaro' );
    }

    private function build_mylisting_service_resolution_copy( array $diagnostics, int $listing_id, string $repeater_class = '' ): array
    {
        $listing_id = absint( $listing_id );
        $repeater_class = sanitize_key( $repeater_class );
        if ( '' === $repeater_class ) {
            $repeater_class = sanitize_key( (string) ( $diagnostics['target_repeater_class'] ?? '' ) );
        }
        if ( '' === $repeater_class ) {
            $repeater_class = 'mybookaro_services';
        }

        $reason = sanitize_key( (string) ( $diagnostics['reason_code'] ?? '' ) );
        $resolved_count = absint( $diagnostics['resolved_services_count'] ?? 0 );
        $row_count_total = absint( $diagnostics['row_count_total'] ?? 0 );
        $class_mismatch_rows = absint( $diagnostics['row_count_class_mismatch'] ?? 0 );
        $missing_labels = absint( $diagnostics['row_count_missing_label'] ?? 0 );
        $detected_prefixes = array_values( array_filter( array_map( 'sanitize_key', (array) ( $diagnostics['detected_prefixes'] ?? [] ) ) ) );
        $detected_classes = array_values( array_filter( array_map( 'sanitize_key', (array) ( $diagnostics['detected_classes'] ?? [] ) ) ) );
        $resolution_path_label = $this->get_mylisting_resolution_path_label( (string) ( $diagnostics['resolution_path'] ?? '' ) );
        $primary_prefix = sanitize_key( (string) ( $diagnostics['primary_detected_prefix'] ?? '' ) );

        $copy = [
            'state' => 'info',
            'summary' => __( 'Select a listing to run MyListing service diagnostics.', 'mybookaro' ),
            'detail' => __( 'Bookaro will inspect repeater rows and show exactly how service rows are matched.', 'mybookaro' ),
            'fix' => '',
        ];

        if ( $listing_id < 1 ) {
            return $copy;
        }

        if ( in_array( $reason, [ 'resolved_with_class_match', 'resolved_with_class_and_prefix', 'pre_resolved_services' ], true ) ) {
            $copy['state'] = 'ok';
            $copy['summary'] = sprintf(
                /* translators: %d: resolved service count */
                __( '%d service(s) detected and available for booking.', 'mybookaro' ),
                $resolved_count
            );
            $copy['detail'] = sprintf(
                /* translators: 1: resolution path label, 2: repeater class */
                __( 'Resolution path: %1$s. Configured repeater class: %2$s.', 'mybookaro' ),
                $resolution_path_label,
                $repeater_class
            );
            return $copy;
        }

        if ( 'resolved_with_prefix_fallback' === $reason ) {
            $copy['state'] = 'warn';
            $copy['summary'] = sprintf(
                /* translators: %d: resolved service count */
                __( '%d service(s) detected using prefix fallback.', 'mybookaro' ),
                $resolved_count
            );
            $copy['detail'] = sprintf(
                /* translators: 1: resolution path label, 2: detected prefix */
                __( 'Resolution path: %1$s. Rows were matched by `<prefix>-label` style fields%2$s.', 'mybookaro' ),
                $resolution_path_label,
                '' !== $primary_prefix
                    ? sprintf(
                        /* translators: %s: detected prefix */
                        __( ' (primary prefix: %s)', 'mybookaro' ),
                        $primary_prefix
                    )
                    : ''
            );
            $copy['fix'] = sprintf(
                /* translators: %s: repeater class */
                __( 'Recommended: add class `%s` to service rows so matching is explicit.', 'mybookaro' ),
                $repeater_class
            );
            return $copy;
        }

        if ( 'class_mismatch' === $reason ) {
            $copy['state'] = 'error';
            $copy['summary'] = __( 'Service rows were found, but repeater class matching failed.', 'mybookaro' );
            $copy['detail'] = sprintf(
                /* translators: 1: configured repeater class, 2: detected classes, 3: detected prefixes */
                __( 'Configured class `%1$s` did not match detected row classes (%2$s). Detected prefixes: %3$s.', 'mybookaro' ),
                $repeater_class,
                ! empty( $detected_classes ) ? implode( ', ', $detected_classes ) : __( 'none', 'mybookaro' ),
                ! empty( $detected_prefixes ) ? implode( ', ', $detected_prefixes ) : __( 'none', 'mybookaro' )
            );
            $copy['fix'] = __( 'Update Services Repeater Class to match your listing type row class, or update row classes to include the configured value.', 'mybookaro' );
            return $copy;
        }

        if ( 'no_service_like_rows' === $reason ) {
            $copy['state'] = 'error';
            $copy['summary'] = __( 'Repeater rows were found, but service fields were not detected.', 'mybookaro' );
            $copy['detail'] = sprintf(
                /* translators: %d: repeater row count */
                __( 'Bookaro found %d repeater row(s), but none include `<prefix>-label` service fields.', 'mybookaro' ),
                $row_count_total
            );
            $copy['fix'] = __( 'Ensure every service row includes a label field and optional duration/price fields using a consistent prefix.', 'mybookaro' );
            return $copy;
        }

        if ( 'missing_service_labels' === $reason ) {
            $copy['state'] = 'error';
            $copy['summary'] = __( 'Matched service rows were skipped because labels are empty.', 'mybookaro' );
            $copy['detail'] = sprintf(
                /* translators: %d: row count */
                __( '%d matched row(s) were ignored because `<prefix>-label` is empty.', 'mybookaro' ),
                $missing_labels
            );
            $copy['fix'] = __( 'Fill service labels in your MyListing repeater rows, then save and refresh this check.', 'mybookaro' );
            return $copy;
        }

        if ( 'no_repeater_rows' === $reason ) {
            $copy['state'] = 'warn';
            $copy['summary'] = __( 'No repeater rows were found for this listing.', 'mybookaro' );
            $copy['detail'] = __( 'Bookaro could not read any `_repeater` rows from the selected listing.', 'mybookaro' );
            $copy['fix'] = __( 'Add service rows in your listing type and ensure they are saved on the listing before retrying.', 'mybookaro' );
            return $copy;
        }

        if ( 'listing_not_allowed' === $reason ) {
            $copy['state'] = 'warn';
            $copy['summary'] = __( 'Selected listing is outside current listing-type rules.', 'mybookaro' );
            $copy['detail'] = __( 'Bookaro skipped MyListing service parsing because the listing is not in allowed post types.', 'mybookaro' );
            $copy['fix'] = __( 'Adjust allowed listing post types in Setup Wizard > Listings, then re-run diagnostics.', 'mybookaro' );
            return $copy;
        }

        if ( $class_mismatch_rows > 0 ) {
            $copy['state'] = 'error';
            $copy['summary'] = __( 'Service-like rows exist, but class matching still failed.', 'mybookaro' );
            $copy['detail'] = sprintf(
                /* translators: 1: configured class, 2: mismatch row count */
                __( 'Configured class `%1$s` did not match %2$d service-like row(s).', 'mybookaro' ),
                $repeater_class,
                $class_mismatch_rows
            );
            $copy['fix'] = __( 'Align Services Repeater Class with the row class used in your MyListing listing type.', 'mybookaro' );
            return $copy;
        }

        $copy['state'] = 'warn';
        $copy['summary'] = __( 'No services resolved yet.', 'mybookaro' );
        $copy['detail'] = sprintf(
            /* translators: %s: repeater class */
            __( 'Bookaro did not resolve service rows for this listing with class `%s`.', 'mybookaro' ),
            $repeater_class
        );
        $copy['fix'] = __( 'Review MyListing repeater rows, confirm class/prefix fields, then save and refresh this step.', 'mybookaro' );

        return $copy;
    }

    private function count_mylisting_listing_timeslots( int $listing_id ): int
    {
        if ( $listing_id < 1 ) {
            return 0;
        }

        $provider_id = function_exists( 'bookaro_get_listing_owner_id' )
            ? (int) bookaro_get_listing_owner_id( $listing_id )
            : 0;
        if ( $provider_id < 1 ) {
            $post = get_post( $listing_id );
            if ( $post instanceof \WP_Post ) {
                $provider_id = (int) $post->post_author;
            }
        }
        if ( $provider_id < 1 ) {
            return 0;
        }

        $schedule = new \Bookaro\Service\ScheduleService( new \Bookaro\Repository\BookingRepository() );
        $timeslots = $schedule->get_timeslots( $provider_id );
        if ( ! is_array( $timeslots ) ) {
            return 0;
        }

        return count( $timeslots );
    }

    private function count_mylisting_completed_bookings(): int
    {
        $repo = new \Bookaro\Repository\BookingRepository();
        $wpdb = $repo->get_wpdb();
        $table = esc_sql( $repo->get_table_name() );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$table} WHERE status = 'completed'" );
        return (int) $count;
    }

    private function build_mylisting_activation_flow(
        int $listing_id,
        string $provider_resolution_mode = '',
        string $provider_meta_key = '',
        string $repeater_class = ''
    ): array {
        $selected_listing_types = [];
        $opts = $this->options->get_all();
        if ( ! empty( $opts['allowed_listing_post_types'] ) && is_array( $opts['allowed_listing_post_types'] ) ) {
            $selected_listing_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $opts['allowed_listing_post_types'] ) ) ) );
        } elseif ( ! empty( $opts['listing_post_type'] ) ) {
            $selected_listing_types = [ sanitize_key( (string) $opts['listing_post_type'] ) ];
        }

        $settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' );
        $status_url = admin_url( 'admin.php?page=bookaro-system-status' );
        $create_listing_action = $this->build_mylisting_create_listing_action( $selected_listing_types );
        $open_listing_action = $this->build_mylisting_open_listing_action( $listing_id, $selected_listing_types );
        $fast_path_action = [
            'label' => __( 'Create demo setup and open test booking', 'mybookaro' ),
            'url' => $this->get_mylisting_fast_path_url( $listing_id ),
            'detail' => __( 'Creates demo booking/services pages, seeds sample services and availability, then opens your test booking flow.', 'mybookaro' ),
        ];

        $provider_resolution_mode = sanitize_key( $provider_resolution_mode );
        if ( ! in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true ) ) {
            $provider_resolution_mode = ( '' !== $provider_meta_key ) ? 'meta_key' : 'author';
        }
        $provider_meta_key = sanitize_key( $provider_meta_key );
        $provider_mapping_valid = in_array( $provider_resolution_mode, [ 'author', 'meta_key' ], true )
            && ( 'meta_key' !== $provider_resolution_mode || '' !== $provider_meta_key );

        $sidebar_hook_ok = function_exists( 'has_action' )
            ? (bool) has_action( 'mylisting/single/sidebar/actions', 'bookaro_render_mylisting_booking_button' )
            : false;
        $listing_ready = $listing_id > 0 && $provider_mapping_valid && $sidebar_hook_ok;

        if ( $listing_id < 1 ) {
            $listing_detail = __( 'Create at least one published MyListing listing, then verify the sidebar booking entry.', 'mybookaro' );
            $listing_action = $create_listing_action;
        } elseif ( ! $provider_mapping_valid ) {
            $listing_detail = __( 'Listing ownership mapping is incomplete. Use Listing Author or a valid Provider Meta Key.', 'mybookaro' );
            $listing_action = [
                'label' => __( 'Open settings', 'mybookaro' ),
                'url' => $settings_url,
                'detail' => '',
            ];
        } elseif ( ! $sidebar_hook_ok ) {
            $listing_detail = __( 'Sidebar booking entry is not active yet. Confirm the MyListing sidebar hook and run System Status checks.', 'mybookaro' );
            $listing_action = [
                'label' => __( 'Open System Status', 'mybookaro' ),
                'url' => $status_url,
                'detail' => '',
            ];
        } else {
            $listing_detail = __( 'Listing and sidebar booking entry are ready.', 'mybookaro' );
            $listing_action = $open_listing_action;
        }

        $repeater_class = sanitize_key( $repeater_class );
        if ( '' === $repeater_class ) {
            $repeater_class = 'mybookaro_services';
        }
        $wizard_services_url = admin_url( 'admin.php?page=bookaro-setup-wizard&step=services' );
        $services_diagnostics = $this->get_mylisting_service_resolution_diagnostics( $listing_id );
        $services_resolution = $this->build_mylisting_service_resolution_copy( $services_diagnostics, $listing_id, $repeater_class );
        $services_count = absint( $services_diagnostics['resolved_services_count'] ?? 0 );
        if ( $services_count < 1 ) {
            $services_count = $this->count_mylisting_listing_services( $listing_id );
        }
        $services_ready = $listing_id > 0 && $services_count > 0;

        $services_detail_parts = [];
        $services_summary = trim( (string) ( $services_resolution['summary'] ?? '' ) );
        $services_detail_meta = trim( (string) ( $services_resolution['detail'] ?? '' ) );
        $services_fix_hint = trim( (string) ( $services_resolution['fix'] ?? '' ) );
        if ( '' !== $services_summary ) {
            $services_detail_parts[] = $services_summary;
        }
        if ( '' !== $services_detail_meta ) {
            $services_detail_parts[] = $services_detail_meta;
        }
        if ( ! $services_ready && '' !== $services_fix_hint ) {
            $services_detail_parts[] = $services_fix_hint;
        }
        $services_detail = implode( ' ', array_filter( $services_detail_parts ) );
        if ( '' === $services_detail ) {
            $services_detail = $listing_id < 1
                ? __( 'Choose a listing first so Bookaro can read services from the MyListing repeater class.', 'mybookaro' )
                : __( 'No services detected yet. Add service rows or run demo setup.', 'mybookaro' );
        }
        $services_action = $listing_id > 0 ? $fast_path_action : $create_listing_action;
        $services_reason = sanitize_key( (string) ( $services_diagnostics['reason_code'] ?? '' ) );
        if ( $listing_id > 0 && in_array( $services_reason, [ 'class_mismatch', 'no_service_like_rows', 'missing_service_labels', 'no_repeater_rows', 'no_resolved_services' ], true ) ) {
            $services_action = [
                'label' => __( 'Open services step', 'mybookaro' ),
                'url' => $wizard_services_url,
                'detail' => __( 'Review the repeater class and service-row diagnostics before continuing.', 'mybookaro' ),
            ];
        }

        $timeslot_count = $this->count_mylisting_listing_timeslots( $listing_id );
        $availability_ready = $listing_id > 0 && $timeslot_count > 0;
        $availability_detail = $availability_ready
            ? sprintf(
                /* translators: %d: timeslot count */
                __( '%d provider timeslot(s) detected for booking.', 'mybookaro' ),
                $timeslot_count
            )
            : (
                $listing_id > 0
                    ? __( 'No provider timeslots detected yet. Seed demo availability, then test the booking flow.', 'mybookaro' )
                    : __( 'Choose a listing first, then add provider availability.', 'mybookaro' )
            );
        $availability_action = $listing_id > 0 ? $fast_path_action : $create_listing_action;

        $completed_bookings = $this->count_mylisting_completed_bookings();
        $booking_ready = $completed_bookings > 0;
        $booking_detail = $booking_ready
            ? sprintf(
                /* translators: %d: completed booking count */
                __( '%d completed booking(s) recorded.', 'mybookaro' ),
                $completed_bookings
            )
            : __( 'Run one end-to-end booking test from the listing sidebar booking entry.', 'mybookaro' );
        $booking_action = $listing_id > 0 ? $open_listing_action : $create_listing_action;

        $milestones = [
            [
                'key' => 'listing_ready',
                'label' => __( 'Listing ready', 'mybookaro' ),
                'passed' => $listing_ready,
                'detail' => $listing_detail,
                'action' => $listing_action,
            ],
            [
                'key' => 'services_ready',
                'label' => __( 'Services ready', 'mybookaro' ),
                'passed' => $services_ready,
                'detail' => $services_detail,
                'action' => $services_action,
            ],
            [
                'key' => 'availability_ready',
                'label' => __( 'Availability ready', 'mybookaro' ),
                'passed' => $availability_ready,
                'detail' => $availability_detail,
                'action' => $availability_action,
            ],
            [
                'key' => 'first_booking_completed',
                'label' => __( 'First booking completed', 'mybookaro' ),
                'passed' => $booking_ready,
                'detail' => $booking_detail,
                'action' => $booking_action,
            ],
        ];

        $summary = [
            'milestones' => $milestones,
            'completed' => 0,
            'total' => count( $milestones ),
            'next_action' => [
                'label' => __( 'Open listing preview', 'mybookaro' ),
                'url' => (string) ( $open_listing_action['url'] ?? '' ),
                'detail' => __( 'Run another booking request to verify notifications and availability changes.', 'mybookaro' ),
            ],
        ];

        foreach ( $milestones as $milestone ) {
            if ( ! empty( $milestone['passed'] ) ) {
                $summary['completed']++;
                continue;
            }
            $summary['next_action'] = [
                'label' => (string) ( $milestone['action']['label'] ?? __( 'Open next step', 'mybookaro' ) ),
                'url' => (string) ( $milestone['action']['url'] ?? '' ),
                'detail' => sprintf(
                    /* translators: %s: milestone label */
                    __( 'Next step: %s', 'mybookaro' ),
                    (string) ( $milestone['label'] ?? __( 'Setup step', 'mybookaro' ) )
                ),
            ];
            break;
        }

        $summary['next_action']['label'] = trim( (string) ( $summary['next_action']['label'] ?? '' ) );
        $summary['next_action']['url'] = trim( (string) ( $summary['next_action']['url'] ?? '' ) );
        $summary['next_action']['detail'] = trim( (string) ( $summary['next_action']['detail'] ?? '' ) );
        $summary['services_diagnostics'] = $services_diagnostics;
        $summary['services_ready'] = $services_ready;

        return $summary;
    }

    private function get_generic_validation_prompt( array $opts = [] ): array
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        $resolved_mode = function_exists( 'bookaro_get_integration_mode' )
            ? sanitize_key( (string) bookaro_get_integration_mode() )
            : sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) );
        $confirmation_required = $this->generic_confirmation_required( $opts );
        $active = ( 'generic' === $resolved_mode ) && ! $confirmation_required;

        $current_hash = $this->build_generic_validation_config_hash( $opts );
        $snapshot = function_exists( 'bookaro_get_generic_validation_snapshot' )
            ? bookaro_get_generic_validation_snapshot()
            : [ 'hash' => (string) ( $opts['generic_validation_review_hash'] ?? '' ), 'at' => absint( $opts['generic_validation_reviewed_at'] ?? 0 ) ];
        $reviewed_hash_raw = strtolower( (string) ( $snapshot['hash'] ?? '' ) );
        $reviewed_hash = preg_replace( '/[^a-f0-9]/', '', $reviewed_hash_raw );
        if ( ! is_string( $reviewed_hash ) ) {
            $reviewed_hash = '';
        }

        return [
            'active' => $active,
            'needs_validation' => $active && '' !== $current_hash && $reviewed_hash !== $current_hash,
            'current_hash' => $current_hash,
            'reviewed_hash' => $reviewed_hash,
            'reviewed_at' => absint( $snapshot['at'] ?? 0 ),
            'confirmation_required' => $confirmation_required,
        ];
    }

    private function build_generic_validation_config_hash( array $opts ): string
    {
        if ( function_exists( 'bookaro_build_generic_validation_config_hash' ) ) {
            return bookaro_build_generic_validation_config_hash( $opts );
        }
        $allowed_types = $opts['allowed_listing_post_types'] ?? [];
        if ( ! is_array( $allowed_types ) ) {
            $allowed_types = [ $allowed_types ];
        }
        $allowed_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $allowed_types ) ) ) );
        sort( $allowed_types );

        $allowed_pages = $opts['allowed_listing_pages'] ?? [];
        if ( ! is_array( $allowed_pages ) ) {
            $allowed_pages = [ $allowed_pages ];
        }
        $allowed_pages = array_values( array_unique( array_filter( array_map( 'absint', $allowed_pages ) ) ) );
        sort( $allowed_pages );

        $listing_page_overrides = [];
        $raw_overrides = $opts['listing_post_type_pages'] ?? [];
        if ( is_array( $raw_overrides ) ) {
            foreach ( $raw_overrides as $post_type => $contexts ) {
                $post_type = sanitize_key( (string) $post_type );
                if ( '' === $post_type || ! is_array( $contexts ) ) {
                    continue;
                }
                $row = [];
                foreach ( [ 'booking', 'provider_dashboard', 'customer_dashboard', 'services' ] as $context ) {
                    $page_id = absint( $contexts[ $context ] ?? 0 );
                    if ( $page_id > 0 ) {
                        $row[ $context ] = $page_id;
                    }
                }
                if ( ! empty( $row ) ) {
                    $listing_page_overrides[ $post_type ] = $row;
                }
            }
        }
        ksort( $listing_page_overrides );

        $payload = [
            'site_type' => $this->resolve_site_type_from_options( $opts ),
            'integration_mode_setting' => sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) ),
            'integration_mode_resolved' => function_exists( 'bookaro_get_integration_mode' )
                ? sanitize_key( (string) bookaro_get_integration_mode() )
                : sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) ),
            'ui_mode' => sanitize_key( (string) ( $opts['ui_mode'] ?? '' ) ),
            'generic_advanced_setup_enabled' => ! empty( $opts['generic_advanced_setup_enabled'] ) ? 1 : 0,
            'generic_setup_preset' => sanitize_key( (string) ( $opts['generic_setup_preset'] ?? '' ) ),
            'allowed_listing_post_types' => $allowed_types,
            'allowed_listing_pages' => $allowed_pages,
            'listing_post_type' => sanitize_key( (string) ( $opts['listing_post_type'] ?? '' ) ),
            'provider_resolution_mode' => sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? '' ) ),
            'provider_meta_key' => sanitize_key( (string) ( $opts['provider_meta_key'] ?? $opts['listing_provider_meta_key'] ?? '' ) ),
            'services_model' => sanitize_key( (string) ( $opts['services_model'] ?? '' ) ),
            'generic_services_mode' => sanitize_key( (string) ( $opts['generic_services_mode'] ?? '' ) ),
            'provider_services_enabled' => ! empty( $opts['provider_services_enabled'] ) ? 1 : 0,
            'allow_provider_custom_services' => ! empty( $opts['allow_provider_custom_services'] ) ? 1 : 0,
            'allow_provider_override_catalog' => ! empty( $opts['allow_provider_override_catalog'] ) ? 1 : 0,
            'auto_insert_booking_button_enabled' => ! empty( $opts['auto_insert_booking_button_enabled'] ) ? 1 : 0,
            'auto_insert_booking_button' => sanitize_key( (string) ( $opts['auto_insert_booking_button'] ?? '' ) ),
            'auto_insert_booking_button_selector' => sanitize_text_field( (string) ( $opts['auto_insert_booking_button_selector'] ?? '' ) ),
            'generic_setup_pages' => [
                'booking' => absint( $opts['generic_setup_booking_page_id'] ?? 0 ),
                'provider_dashboard' => absint( $opts['generic_setup_provider_dashboard_page_id'] ?? 0 ),
                'customer_dashboard' => absint( $opts['generic_setup_customer_dashboard_page_id'] ?? 0 ),
                'services' => absint( $opts['generic_setup_services_page_id'] ?? 0 ),
            ],
            'global_pages' => [
                'booking' => absint( $opts['booking_page_id'] ?? 0 ),
                'provider_dashboard' => absint( $opts['provider_dashboard_page_id'] ?? 0 ),
                'customer_dashboard' => absint( $opts['customer_dashboard_page_id'] ?? 0 ),
            ],
            'generic_setup_context' => [
                'listing_id' => absint( $opts['generic_setup_listing_id'] ?? 0 ),
                'provider_user_id' => absint( $opts['generic_setup_provider_user_id'] ?? 0 ),
                'service_id' => absint( $opts['generic_setup_service_id'] ?? 0 ),
                'default_provider_id' => absint( $opts['default_provider_id'] ?? 0 ),
            ],
            'listing_post_type_pages' => $listing_page_overrides,
        ];

        $json = wp_json_encode( $payload );
        if ( ! is_string( $json ) || '' === $json ) {
            return '';
        }

        return hash( 'sha256', $json );
    }

    private function maybe_set_generic_launch_validation_notice( array $before, array $after ): void
    {
        if ( 'generic' !== $this->resolve_integration_mode_from_options( $after ) ) {
            return;
        }

        $before_hash = $this->build_generic_validation_config_hash( $before );
        $after_hash = $this->build_generic_validation_config_hash( $after );
        if ( '' === $after_hash || $before_hash === $after_hash ) {
            return;
        }

        set_transient(
            self::GENERIC_LAUNCH_NOTICE_KEY,
            [
                'type' => 'warning',
                'message' => $this->get_generic_launch_readiness_notice_message(),
                'action_url' => $this->get_generic_validation_status_url(),
                'action_label' => $this->get_generic_launch_readiness_notice_action_label(),
            ],
            10 * MINUTE_IN_SECONDS
        );
    }

    private function maybe_set_generic_preset_summary_notice( array $opts, string $step, string $next ): void
    {
        $resolved_mode = $this->resolve_integration_mode_from_options( $opts );
        $site_type = $this->resolve_site_type_from_options( $opts );
        if ( 'generic' !== $resolved_mode || 'directory' !== $site_type ) {
            return;
        }
        if ( $this->generic_confirmation_required( $opts ) ) {
            return;
        }

        $notice = $this->build_generic_preset_summary_notice( $opts, $step, $next );
        if ( empty( $notice ) ) {
            return;
        }

        set_transient(
            self::GENERIC_PRESET_SUMMARY_NOTICE_KEY,
            $notice,
            10 * MINUTE_IN_SECONDS
        );
    }

    private function build_generic_preset_conflict_notice( array $opts ): array
    {
        $resolved_mode = $this->resolve_integration_mode_from_options( $opts );
        $site_type = $this->resolve_site_type_from_options( $opts );
        $advanced_setup_enabled = ! empty( $opts['generic_advanced_setup_enabled'] );
        if ( 'generic' !== $resolved_mode || 'directory' !== $site_type || $advanced_setup_enabled ) {
            return [];
        }

        $generic_setup_preset = sanitize_key( (string) ( $opts['generic_setup_preset'] ?? '' ) );
        if ( ! GenericPresetProfiles::has( $generic_setup_preset ) ) {
            return [];
        }

        $provider_resolution_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? '' ) );
        $provider_meta_key = sanitize_key( (string) ( $opts['provider_meta_key'] ?? $opts['listing_provider_meta_key'] ?? '' ) );
        $services_model = sanitize_key( (string) ( $opts['services_model'] ?? $opts['generic_services_mode'] ?? '' ) );
        $preset_alignment = GenericPresetProfiles::evaluate_alignment(
            $generic_setup_preset,
            $provider_resolution_mode,
            $services_model,
            $provider_meta_key
        );
        if ( empty( $preset_alignment['has_conflict'] ) ) {
            return [];
        }

        $provider_mismatch = ! empty( $preset_alignment['provider_mismatch'] );
        $services_mismatch = ! empty( $preset_alignment['services_mismatch'] );
        $preset_label = trim( (string) ( $preset_alignment['preset_label'] ?? '' ) );
        if ( '' === $preset_label ) {
            $preset_label = __( 'Selected Generic preset', 'mybookaro' );
        }
        $provider_expected_label = trim( (string) ( $preset_alignment['provider_expected_label'] ?? '' ) );
        $provider_actual_label = trim( (string) ( $preset_alignment['provider_actual_label'] ?? '' ) );
        $services_expected_label = trim( (string) ( $preset_alignment['services_expected_label'] ?? '' ) );
        $services_actual_label = trim( (string) ( $preset_alignment['services_actual_label'] ?? '' ) );

        $primary_step = $provider_mismatch ? 'listings' : 'services';
        $primary_action_label = ( 'listings' === $primary_step )
            ? __( 'Open listings step', 'mybookaro' )
            : __( 'Open services step', 'mybookaro' );
        $primary_action_url = admin_url( 'admin.php?page=bookaro-setup-wizard&step=' . $primary_step );
        $secondary_actions = [];

        if ( $provider_mismatch && $services_mismatch ) {
            $message = sprintf(
                /* translators: 1: Generic preset label, 2: expected provider mapping, 3: current provider mapping, 4: expected services source, 5: current services source */
                __( '%1$s no longer matches saved settings. Provider Mapping must be %2$s (currently %3$s), and Services Source must be %4$s (currently %5$s). Next action: open Setup Wizard > Listings and save, then open Setup Wizard > Services and save.', 'mybookaro' ),
                $preset_label,
                $provider_expected_label,
                $provider_actual_label,
                $services_expected_label,
                $services_actual_label
            );
            $secondary_actions[] = [
                'label' => __( 'Then open services step', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=services' ),
            ];
        } elseif ( $provider_mismatch ) {
            $message = sprintf(
                /* translators: 1: Generic preset label, 2: expected provider mapping, 3: current provider mapping */
                __( '%1$s expects Provider Mapping = %2$s, but this site is using %3$s. Next action: open Setup Wizard > Listings, set Provider Mapping to %2$s, and save.', 'mybookaro' ),
                $preset_label,
                $provider_expected_label,
                $provider_actual_label
            );
        } else {
            $message = sprintf(
                /* translators: 1: Generic preset label, 2: expected services source, 3: current services source */
                __( '%1$s expects Services Source = %2$s, but this site is using %3$s. Next action: open Setup Wizard > Services, set Services Source to %2$s, and save.', 'mybookaro' ),
                $preset_label,
                $services_expected_label,
                $services_actual_label
            );
        }

        return [
            'type' => 'error',
            'title' => __( 'Generic preset mismatch', 'mybookaro' ),
            'message' => $message,
            'action_url' => $primary_action_url,
            'action_label' => $primary_action_label,
            'actions' => $secondary_actions,
            'primary_step' => $primary_step,
        ];
    }

    private function build_generic_preset_summary_notice( array $opts, string $step, string $next ): array
    {
        $provider_resolution_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? 'author' ) );
        $provider_meta_key = sanitize_key( (string) ( $opts['provider_meta_key'] ?? $opts['listing_provider_meta_key'] ?? '' ) );
        $services_model = sanitize_key( (string) ( $opts['services_model'] ?? $opts['generic_services_mode'] ?? 'provider_only' ) );
        $placement_strategy = sanitize_key( (string) ( $opts['booking_placement_strategy'] ?? '' ) );
        if ( '' === $placement_strategy && function_exists( 'bookaro_get_booking_placement_strategy' ) ) {
            $placement_strategy = sanitize_key( (string) bookaro_get_booking_placement_strategy() );
        }
        if ( ! in_array( $placement_strategy, [ 'directory_template', 'normal_page', 'shortcode_only', 'css_selector' ], true ) ) {
            $placement_strategy = 'shortcode_only';
        }
        $auto_insert_enabled = ! empty( $opts['auto_insert_booking_button_enabled'] );
        $auto_insert_mode = sanitize_key( (string) ( $opts['auto_insert_booking_button'] ?? '' ) );
        $auto_insert_selector = sanitize_text_field( (string) ( $opts['auto_insert_booking_button_selector'] ?? '' ) );
        $generic_setup_preset = $this->resolve_generic_setup_preset( $opts );
        $generic_validation_prompt = $this->get_generic_validation_prompt( $opts );
        $needs_validation_refresh = ! empty( $generic_validation_prompt['active'] ) && ! empty( $generic_validation_prompt['needs_validation'] );
        $runtime_failed_count = $this->get_generic_runtime_validation_failed_count();
        $confirmation_required = $this->generic_confirmation_required( $opts );
        $legacy_fallback_active = $this->is_generic_legacy_fallback_active( $opts );
        $compact_model_payload = $this->build_generic_compact_model_payload(
            $generic_setup_preset,
            $provider_resolution_mode,
            $provider_meta_key,
            $services_model,
            $placement_strategy,
            $auto_insert_enabled,
            $auto_insert_mode,
            $auto_insert_selector
        );
        $current_model = (string) ( $compact_model_payload['summary'] ?? '' );
        $model_snapshot = is_array( $compact_model_payload['snapshot'] ?? null ) ? $compact_model_payload['snapshot'] : [];
        $top_blocker = $this->build_generic_compact_blocker_summary(
            $confirmation_required,
            $legacy_fallback_active,
            $needs_validation_refresh,
            $runtime_failed_count
        );

        $next_step = $this->get_generic_summary_next_step( $next, $legacy_fallback_active );

        $saved_step = sanitize_key( $step );
        $saved_step_label_map = [
            'modes' => __( 'Lane', 'mybookaro' ),
            'listings' => __( 'Listings', 'mybookaro' ),
            'services' => __( 'Services', 'mybookaro' ),
            'pages' => __( 'Pages', 'mybookaro' ),
            'operational' => __( 'Operational', 'mybookaro' ),
        ];
        $saved_step_label = (string) ( $saved_step_label_map[ $saved_step ] ?? __( 'Generic setup', 'mybookaro' ) );
        $preset_detail = GenericPresetProfiles::build_selection_detail( $generic_setup_preset );
        $summary_text = sprintf(
            /* translators: %s: step label */
            __( 'Saved from %s. Confirm the current model, blocker, and required next step before continuing.', 'mybookaro' ),
            $saved_step_label
        );
        if ( '' !== trim( $preset_detail ) ) {
            $summary_text .= ' ' . $preset_detail;
        }

        return [
            'title' => __( 'Generic setup summary', 'mybookaro' ),
            'summary' => $summary_text,
            'current_model' => $current_model,
            'top_blocker' => $top_blocker,
            'provider_mapping' => (string) ( $model_snapshot['provider'] ?? '' ),
            'services_model' => (string) ( $model_snapshot['services'] ?? '' ),
            'placement_strategy' => (string) ( $model_snapshot['placement'] ?? '' ),
            'next_step_label' => (string) ( $next_step['label'] ?? '' ),
            'next_step_url' => (string) ( $next_step['url'] ?? '' ),
            'next_step_detail' => (string) ( $next_step['detail'] ?? '' ),
            'legacy_note' => $legacy_fallback_active ? $this->get_generic_legacy_review_notice_message() : '',
        ];
    }

    private function build_generic_compact_model_payload(
        string $generic_setup_preset,
        string $provider_resolution_mode,
        string $provider_meta_key,
        string $services_model,
        string $placement_strategy,
        bool $auto_insert_enabled = false,
        string $auto_insert_mode = '',
        string $auto_insert_selector = ''
    ): array {
        $snapshot = GenericPresetProfiles::build_compact_lane_snapshot(
            $generic_setup_preset,
            $provider_resolution_mode,
            $provider_meta_key,
            $services_model,
            $placement_strategy,
            $auto_insert_enabled,
            $auto_insert_mode,
            $auto_insert_selector
        );
        $model = AdminLaneSummary::build_generic_model_snapshot(
            (string) ( $snapshot['pattern'] ?? '' ),
            (string) ( $snapshot['provider'] ?? '' ),
            (string) ( $snapshot['services'] ?? '' ),
            (string) ( $snapshot['placement'] ?? '' )
        );

        return [
            'summary' => (string) ( $model['summary'] ?? '' ),
            'items' => is_array( $model['items'] ?? null ) ? $model['items'] : [],
            'snapshot' => $snapshot,
        ];
    }

    private function build_generic_compact_model_summary(
        string $generic_setup_preset,
        string $provider_resolution_mode,
        string $provider_meta_key,
        string $services_model,
        string $placement_strategy,
        bool $auto_insert_enabled = false,
        string $auto_insert_mode = '',
        string $auto_insert_selector = ''
    ): string {
        $payload = $this->build_generic_compact_model_payload(
            $generic_setup_preset,
            $provider_resolution_mode,
            $provider_meta_key,
            $services_model,
            $placement_strategy,
            $auto_insert_enabled,
            $auto_insert_mode,
            $auto_insert_selector
        );

        return (string) ( $payload['summary'] ?? '' );
    }

    private function build_generic_compact_blocker_summary(
        bool $confirmation_required,
        bool $legacy_fallback_active,
        bool $needs_validation_refresh,
        int $runtime_failed_count
    ): string {
        if ( $confirmation_required ) {
            return __( 'Generic lane is not confirmed yet.', 'mybookaro' );
        }

        if ( $legacy_fallback_active ) {
            return __( 'Generic lane still uses legacy fallback metadata and needs a one-time Lane save.', 'mybookaro' );
        }

        if ( $runtime_failed_count > 0 ) {
            return sprintf(
                /* translators: %d: number of failed Generic runtime validation checks */
                _n(
                    '%d Generic validation check is currently blocking launch.',
                    '%d Generic validation checks are currently blocking launch.',
                    $runtime_failed_count,
                    'mybookaro'
                ),
                $runtime_failed_count
            );
        }

        if ( $needs_validation_refresh ) {
            return __( 'Generic validation snapshot is stale after recent settings changes.', 'mybookaro' );
        }

        return __( 'No Generic launch blocker is currently detected.', 'mybookaro' );
    }

    private function get_generic_summary_next_step( string $next, bool $legacy_fallback_active = false ): array
    {
        if ( $legacy_fallback_active ) {
            return [
                'label' => __( 'Review and save Generic confirmation', 'mybookaro' ),
                'url' => $this->get_generic_confirmation_required_notice_url(),
                'detail' => __( 'Open Setup Wizard > Lane, save once to record explicit Generic confirmation metadata, then continue.', 'mybookaro' ),
            ];
        }

        $next = sanitize_key( $next );
        $steps = [
            'listings' => [
                'label' => __( 'Open listings step', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' ),
                'detail' => __( 'Open Setup Wizard > Listings, confirm provider mapping and listing post types, then save.', 'mybookaro' ),
            ],
            'services' => [
                'label' => __( 'Open services step', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=services' ),
                'detail' => __( 'Open Setup Wizard > Services, confirm the services model and placement strategy, then save.', 'mybookaro' ),
            ],
            'pages' => [
                'label' => __( 'Open pages step', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=pages' ),
                'detail' => __( 'Open Setup Wizard > Pages, assign required pages, and save.', 'mybookaro' ),
            ],
            'operational' => [
                'label' => __( 'Open operational step', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=operational' ),
                'detail' => __( 'Open Setup Wizard > Operational, confirm automation defaults, then save.', 'mybookaro' ),
            ],
            'done' => [
                'label' => $this->get_generic_launch_readiness_notice_action_label(),
                'url' => $this->get_generic_validation_status_url(),
                'detail' => __( 'Run Generic validation in System Status and clear every warning or error before launch.', 'mybookaro' ),
            ],
        ];

        if ( isset( $steps[ $next ] ) ) {
            return $steps[ $next ];
        }

        return [
            'label' => __( 'Open Generic validation checks', 'mybookaro' ),
            'url' => $this->get_generic_validation_status_url(),
            'detail' => __( 'Run Generic validation and clear every warning or error before launch.', 'mybookaro' ),
        ];
    }

    private function get_default_ui_mode_for_integration( string $integration_mode ): string
    {
        $integration_mode = sanitize_key( $integration_mode );
        if ( ! in_array( $integration_mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
            $integration_mode = 'auto';
        }
        if ( 'auto' === $integration_mode ) {
            $integration_mode = ( function_exists( 'bookaro_is_mylisting_active' ) && bookaro_is_mylisting_active() )
                ? 'mylisting'
                : 'generic';
        }
        return ( 'generic' === $integration_mode ) ? 'shortcodes' : 'woocommerce';
    }

    private function normalize_site_type_setting( $site_type ): string
    {
        $site_type = sanitize_key( (string) $site_type );
        if ( ! in_array( $site_type, [ 'directory', 'single_business', 'advanced_mapping' ], true ) ) {
            return 'directory';
        }
        return $site_type;
    }

    private function resolve_site_type_from_options( array $opts, array $payload = [] ): string
    {
        if ( array_key_exists( 'site_type', $payload ) ) {
            return $this->normalize_site_type_setting( $payload['site_type'] );
        }
        return $this->normalize_site_type_setting( $opts['site_type'] ?? 'directory' );
    }

    private function resolve_ui_mode_for_wizard( array $opts, string $integration_mode = '' ): string
    {
        if ( '' === $integration_mode ) {
            $integration_mode = sanitize_key( (string) ( $opts['integration_mode'] ?? 'auto' ) );
        }
        $default_ui_mode = $this->get_default_ui_mode_for_integration( $integration_mode );
        $ui_mode = sanitize_key( (string) ( $opts['ui_mode'] ?? $default_ui_mode ) );
        if ( ! in_array( $ui_mode, [ 'shortcodes', 'woocommerce' ], true ) ) {
            $ui_mode = $default_ui_mode;
        }
        if ( 'woocommerce' === $ui_mode ) {
            $woocommerce_active = function_exists( 'bookaro_is_woocommerce_active' )
                ? (bool) bookaro_is_woocommerce_active()
                : ( class_exists( 'WooCommerce' ) || defined( 'WC_VERSION' ) || function_exists( 'WC' ) );
            if ( ! $woocommerce_active ) {
                $ui_mode = 'shortcodes';
            }
        }
        return $ui_mode;
    }

    private function normalize_integration_mode_setting( $mode ): string
    {
        $mode = sanitize_key( (string) $mode );
        if ( ! in_array( $mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
            return 'auto';
        }
        return $mode;
    }

    private function is_generic_setup_confirmed( array $opts = [] ): bool
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        if ( function_exists( 'bookaro_is_generic_setup_confirmed' ) ) {
            return (bool) bookaro_is_generic_setup_confirmed( $opts );
        }

        if ( ! empty( $opts['generic_setup_confirmed'] ) ) {
            return true;
        }

        $mode = $this->normalize_integration_mode_setting( $opts['integration_mode'] ?? 'auto' );
        if ( 'generic' === $mode ) {
            return true;
        }

        return ! empty( $opts['generic_setup_completed'] );
    }

    private function is_generic_setup_explicitly_confirmed( array $opts = [] ): bool
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        if ( function_exists( 'bookaro_is_generic_setup_explicitly_confirmed' ) ) {
            return (bool) bookaro_is_generic_setup_explicitly_confirmed( $opts );
        }

        if ( ! empty( $opts['generic_setup_confirmed'] ) ) {
            return true;
        }
        if ( absint( $opts['generic_setup_confirmed_at'] ?? 0 ) > 0 ) {
            return true;
        }
        if ( '' !== sanitize_key( (string) ( $opts['generic_setup_confirmation_source'] ?? '' ) ) ) {
            return true;
        }

        $mode = $this->normalize_integration_mode_setting( $opts['integration_mode'] ?? 'auto' );
        return 'generic' === $mode;
    }

    private function is_generic_legacy_fallback_active( array $opts = [] ): bool
    {
        if ( defined( 'BOOKARO_ENABLE_GENERIC_MODE' ) && ! BOOKARO_ENABLE_GENERIC_MODE ) {
            return false;
        }

        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        if ( function_exists( 'bookaro_is_generic_legacy_fallback_active' ) ) {
            return (bool) bookaro_is_generic_legacy_fallback_active();
        }

        $mode = $this->normalize_integration_mode_setting( $opts['integration_mode'] ?? 'auto' );
        if ( 'auto' !== $mode ) {
            return false;
        }

        if ( $this->is_mylisting_detected() ) {
            return false;
        }

        if ( ! $this->is_generic_setup_confirmed( $opts ) ) {
            return false;
        }

        return ! $this->is_generic_setup_explicitly_confirmed( $opts );
    }

    private function generic_confirmation_required( array $opts = [] ): bool
    {
        if ( defined( 'BOOKARO_ENABLE_GENERIC_MODE' ) && ! BOOKARO_ENABLE_GENERIC_MODE ) {
            return false;
        }

        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }

        $mode = $this->normalize_integration_mode_setting( $opts['integration_mode'] ?? 'auto' );
        if ( 'auto' !== $mode ) {
            return false;
        }

        if ( $this->is_mylisting_detected() ) {
            return false;
        }

        return ! $this->is_generic_setup_confirmed( $opts );
    }

    private function get_generic_confirmation_required_notice_message(): string
    {
        return __( 'MyListing is not detected. Generic Directory is available, but launch stays blocked until an admin opens Setup Wizard > Lane, selects Generic Directory, saves, then opens System Status > Generic validation checks.', 'mybookaro' );
    }

    private function get_generic_confirmation_required_notice_action_label(): string
    {
        return __( 'Open Setup Wizard > Lane', 'mybookaro' );
    }

    private function get_generic_confirmation_required_notice_url(): string
    {
        return admin_url( 'admin.php?page=bookaro-setup-wizard&step=modes' );
    }

    private function get_generic_legacy_review_notice_message(): string
    {
        return __( 'Generic Directory is running from legacy automatic Generic settings, but explicit lane confirmation metadata is missing. Open Setup Wizard > Lane, save once, then open System Status > Generic validation checks before launch.', 'mybookaro' );
    }

    private function get_generic_legacy_review_notice_action_label(): string
    {
        return __( 'Open Setup Wizard > Lane', 'mybookaro' );
    }

    private function get_generic_runtime_validation_failed_count(): int
    {
        if ( ! function_exists( 'bookaro_run_generic_admin_validation' ) ) {
            return 0;
        }

        $runtime_validation = bookaro_run_generic_admin_validation();
        if ( ! is_array( $runtime_validation ) ) {
            return 0;
        }

        return absint( $runtime_validation['failed_count'] ?? 0 );
    }

    private function get_generic_runtime_validation_blocked_notice_message( int $failed_count, bool $needs_validation_refresh = false ): string
    {
        $failed_count = max( 0, $failed_count );
        if ( $failed_count < 1 ) {
            return $this->get_generic_launch_readiness_notice_message();
        }

        $runtime_message = sprintf(
            /* translators: %d: number of runtime checks needing attention */
            _n(
                'Launch is blocked: %d Generic runtime validation check still needs attention.',
                'Launch is blocked: %d Generic runtime validation checks still need attention.',
                $failed_count,
                'mybookaro'
            ),
            (int) $failed_count
        );

        if ( ! $needs_validation_refresh ) {
            return $runtime_message . ' ' . __( 'Open System Status > Generic validation checks, apply the Suggested fix for each Warn/Fail item, then refresh this page.', 'mybookaro' );
        }

        return $runtime_message . ' ' . __( 'Configuration also changed since the last validation snapshot. Open System Status > Generic validation checks, resolve every Warn/Fail item, then refresh this page before launch.', 'mybookaro' );
    }

    private function get_generic_runtime_validation_blocked_notice_action_label(): string
    {
        return __( 'Open Generic validation checks', 'mybookaro' );
    }

    private function resolve_integration_mode_from_options( array $opts ): string
    {
        $site_type = $this->resolve_site_type_from_options( $opts );
        if ( in_array( $site_type, [ 'single_business', 'advanced_mapping' ], true ) ) {
            return 'generic';
        }
        $mode = $this->normalize_integration_mode_setting( $opts['integration_mode'] ?? 'auto' );
        if ( 'auto' === $mode ) {
            $mode = ( function_exists( 'bookaro_is_mylisting_active' ) && bookaro_is_mylisting_active() )
                ? 'mylisting'
                : 'generic';
        }
        return $mode;
    }

    private function get_generic_launch_readiness_notice_message(): string
    {
        return __( 'Generic Directory lane settings changed (provider mapping, services model, or page/placement assignment) since the last completed validation snapshot. Open System Status > Generic validation checks, review Suggested fix and Next step for each Warn/Fail item, then refresh this page before launch.', 'mybookaro' );
    }

    private function get_generic_launch_readiness_notice_action_label(): string
    {
        return __( 'Run System Status validation', 'mybookaro' );
    }

    private function get_generic_validation_status_url(): string
    {
        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        return (string) ( $support_touchpoints['generic_validation_url'] ?? admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' ) );
    }

    private function sanitize_css_var( string $value, string $fallback ): string
    {
        $value = trim( (string) $value );
        if ( $value === '' ) {
            return $fallback;
        }
        $value = preg_replace( '/[<>"\'\\\\]/', '', $value );
        return $value !== '' ? $value : $fallback;
    }

    private function plugin_asset_path( string $relative ): string
    {
        $relative = ltrim( $relative, '/\\' );
        if ( defined( 'BOOKARO_PLUGIN_FILE' ) ) {
            return plugin_dir_path( BOOKARO_PLUGIN_FILE ) . $relative;
        }
        if ( defined( 'BOOKARO_PLUGIN_DIR' ) ) {
            return rtrim( BOOKARO_PLUGIN_DIR, '/\\' ) . '/' . $relative;
        }
        return $relative;
    }

    private function plugin_asset_url( string $relative ): string
    {
        $relative = ltrim( $relative, '/\\' );
        if ( defined( 'BOOKARO_PLUGIN_FILE' ) ) {
            return plugins_url( $relative, BOOKARO_PLUGIN_FILE );
        }
        if ( defined( 'BOOKARO_PLUGIN_URL' ) ) {
            return rtrim( BOOKARO_PLUGIN_URL, '/' ) . '/' . $relative;
        }
        return $relative;
    }
}

