<?php
namespace Bookaro\Controller\Admin;

defined( 'ABSPATH' ) || exit;

// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Onboarding reads are sanitized step/nav params with no state change; the booking-count SELECTs target a custom plugin table ($wpdb->prefix) and bind values via prepare().

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

/**
 * Lane-aware onboarding checklist (MyListing Directory + Generic Directory + Single Business).
 */
class GettingStartedController
{
    private const NOTICE_KEY = 'bookaro_getting_started_notice';
    private const GENERIC_LAUNCH_NOTICE_KEY = 'bookaro_generic_launch_validation_notice';
    private const ACTION_OPTION = 'bookaro_getting_started_actions';

    private BookingRepository $db;
    private OptionRepository $options;
    private ScheduleService $schedule;

    public function __construct( BookingRepository $db, OptionRepository $options )
    {
        $this->db = $db;
        $this->options = $options;
        $this->schedule = new ScheduleService( $db );
    }

    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
    {
        $mode = function_exists( 'bookaro_get_integration_mode' ) ? bookaro_get_integration_mode() : 'mylisting';
        if ( ! in_array( $mode, [ 'mylisting', 'generic' ], true ) ) {
            return;
        }

        add_action( 'admin_menu', [ $this, 'add_submenu_page' ], 26 );
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
        add_action( 'admin_notices', [ $this, 'maybe_show_notice' ] );

        add_action( 'admin_post_bookaro_getting_started_demo_timeslots', [ $this, 'handle_demo_timeslots' ] );
        add_action( 'admin_post_bookaro_getting_started_open_listing', [ $this, 'handle_open_listing' ] );
        add_action( 'admin_post_bookaro_getting_started_test_email', [ $this, 'handle_test_email' ] );
        add_action( 'admin_post_bookaro_getting_started_demo_content_create', [ $this, 'handle_demo_content_create' ] );
        add_action( 'admin_post_bookaro_getting_started_demo_content_remove', [ $this, 'handle_demo_content_remove' ] );
        add_action( 'admin_post_bookaro_getting_started_fast_path_booking', [ $this, 'handle_fast_path_booking' ] );
    }

    public function add_submenu_page(): void
    {
        add_submenu_page(
            'bookaro-bookings',
            __( 'Getting Started', 'mybookaro' ),
            __( 'Getting Started', 'mybookaro' ),
            $this->admin_menu_capability(),
            'bookaro-getting-started',
            [ $this, 'render_page' ]
        );
    }

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

        $rel = 'assets/css/admin-settings.css';
        $path = $this->plugin_asset_path( $rel );
        $ver = file_exists( $path ) ? (string) filemtime( $path ) : BOOKARO_VERSION;
        $url = $this->plugin_asset_url( $rel );
        wp_enqueue_style( 'bookaro-admin-settings', $url, [], $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 );

        // Copy-to-clipboard behavior for shortcode snippets. Previously printed
        // as an inline script element in the template; now attached as inline JS
        // on a dedicated, src-less admin script handle scoped to this page.
        $copy_handle = 'bookaro-getting-started';
        if ( ! wp_script_is( $copy_handle, 'registered' ) ) {
            wp_register_script( $copy_handle, false, [], BOOKARO_VERSION, true );
        }
        wp_enqueue_script( $copy_handle );
        $copied_label = wp_json_encode( __( 'Copied!', 'mybookaro' ) );
        if ( ! is_string( $copied_label ) || '' === $copied_label ) {
            $copied_label = '"Copied!"';
        }
        wp_add_inline_script(
            $copy_handle,
            '(function(){'
            . "var buttons=document.querySelectorAll('.bookaro-copy-shortcode');"
            . 'if(!buttons.length){return;}'
            . 'var copiedLabel=' . $copied_label . ';'
            . 'function copyText(text){'
            . 'if(navigator.clipboard&&navigator.clipboard.writeText){return navigator.clipboard.writeText(text);}'
            . "var textarea=document.createElement('textarea');"
            . 'textarea.value=text;'
            . "textarea.style.position='fixed';"
            . "textarea.style.opacity='0';"
            . 'document.body.appendChild(textarea);'
            . 'textarea.select();'
            . "try{document.execCommand('copy');}catch(e){}"
            . 'document.body.removeChild(textarea);'
            . 'return Promise.resolve();'
            . '}'
            . 'buttons.forEach(function(button){'
            . "button.addEventListener('click',function(){"
            . "var text=button.getAttribute('data-copy')||'';"
            . 'if(!text){return;}'
            . 'copyText(text).then(function(){'
            . 'var original=button.textContent;'
            . 'button.textContent=copiedLabel;'
            . 'setTimeout(function(){button.textContent=original;},1400);'
            . '});'
            . '});'
            . '});'
            . '})();'
        );
    }

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

        $rendered_generic_launch_notice = false;
        foreach ( [ self::NOTICE_KEY, self::GENERIC_LAUNCH_NOTICE_KEY ] as $notice_key ) {
            $notice = get_transient( $notice_key );
            if ( ! is_array( $notice ) ) {
                continue;
            }
            delete_transient( $notice_key );
            $type = sanitize_html_class( (string) ( $notice['type'] ?? 'info' ) );
            $message = (string) ( $notice['message'] ?? '' );
            $action_url = isset( $notice['action_url'] ) ? (string) $notice['action_url'] : '';
            $action_label = isset( $notice['action_label'] ) ? (string) $notice['action_label'] : '';
            $actions = isset( $notice['actions'] ) && is_array( $notice['actions'] ) ? $notice['actions'] : [];
            if ( self::GENERIC_LAUNCH_NOTICE_KEY === $notice_key ) {
                $actions = array_merge( $actions, $this->get_support_handoff_notice_actions( $action_url ) );
            }
            $this->render_admin_notice( $type, $message, $action_url, $action_label, $actions );
            if ( self::GENERIC_LAUNCH_NOTICE_KEY === $notice_key && '' !== trim( $message ) ) {
                $rendered_generic_launch_notice = true;
            }
        }

        $opts = $this->options->get_all();
        $integration_mode = function_exists( 'bookaro_get_integration_mode' )
            ? (string) bookaro_get_integration_mode()
            : (string) ( $opts['integration_mode'] ?? 'auto' );
        $generic_validation_prompt = $this->get_generic_validation_prompt( $opts, $integration_mode );
        if ( ! $rendered_generic_launch_notice && ! empty( $generic_validation_prompt['active'] ) && ! empty( $generic_validation_prompt['needs_validation'] ) ) {
            $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() )
            );
        }
    }

    public function render_page(): void
    {
        if ( ! $this->can_manage_admin() ) {
            wp_die( esc_html__( 'You do not have permission to access this page.', 'mybookaro' ) );
        }

        $integration_mode = function_exists( 'bookaro_get_integration_mode' )
            ? bookaro_get_integration_mode()
            : 'mylisting';
        $site_type = $this->resolve_site_type_for_onboarding();
        $single_business = ( 'single_business' === $site_type );
        $lane_profile = $this->build_lane_profile( $integration_mode, $site_type );
        $opts = $this->options->get_all();
        $generic_validation_prompt = $this->get_generic_validation_prompt( $opts, $integration_mode );
        $listing_choices = $this->get_listing_choices();
        $default_listing_id = $this->get_default_listing_id( $listing_choices );
        $last_runs = $this->get_action_last_runs();
        $generic_validation = $this->get_generic_validation_overview();
        $quick_steps = $this->build_quick_start_steps( $integration_mode, $default_listing_id, $generic_validation, $generic_validation_prompt );
        $shortcode_snippets = $this->build_shortcode_snippets( $integration_mode, $default_listing_id );
        $mylisting_activation_flow = $this->build_mylisting_activation_flow( $integration_mode, $default_listing_id );

        $checks = $this->build_checks( $last_runs, $integration_mode, $generic_validation, $generic_validation_prompt );
        $generic_readiness_summary = $this->build_generic_readiness_summary(
            $integration_mode,
            $opts,
            $quick_steps,
            $generic_validation,
            $generic_validation_prompt
        );
        $operational_summary_items = $this->build_operational_summary_items( $opts );
        $actions = [
            'demo_timeslots' => [
                'label' => __( 'Create demo timeslots', 'mybookaro' ),
                'last_run' => $this->format_last_run( $last_runs['demo_timeslots'] ?? 0 ),
            ],
            'open_listing' => [
                'label' => ( 'generic' === $integration_mode && $single_business )
                    ? __( 'Open booking/services preview', 'mybookaro' )
                    : __( 'Open listing with booking button', 'mybookaro' ),
                'last_run' => $this->format_last_run( $last_runs['open_listing'] ?? 0 ),
            ],
            'test_email' => [
                'label' => __( 'Send test email', 'mybookaro' ),
                'last_run' => $this->format_last_run( $last_runs['test_email'] ?? 0 ),
            ],
        ];

        $demo_status = $this->get_demo_content_status();
        $actions['demo_content_create'] = [
            'label' => __( 'Create demo content', 'mybookaro' ),
            'last_run' => $this->format_last_run( $last_runs['demo_content_create'] ?? 0 ),
            'enabled' => ! $demo_status['exists'],
        ];
        $actions['demo_content_remove'] = [
            'label' => __( 'Remove demo content', 'mybookaro' ),
            'last_run' => $this->format_last_run( $last_runs['demo_content_remove'] ?? 0 ),
            'enabled' => $demo_status['exists'],
        ];

        $default_email = $this->get_default_test_email();
        $page_url = admin_url( 'admin.php?page=bookaro-getting-started' );
        $wizard_url = admin_url( 'admin.php?page=bookaro-setup-wizard' );
        $support_url = (string) apply_filters( 'bookaro_support_url', 'https://mybookaro.com/support' );
        $support_url = trim( $support_url );
        $support_docs_url = (string) apply_filters( 'bookaro_docs_url', 'https://mybookaro.com/docs' );
        $support_docs_url = rtrim( $support_docs_url, '/' );
        $support_touchpoints = SystemStatusController::get_support_touchpoint_urls();
        $system_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'] ?? ( $system_status_url . '#bookaro-support-snapshot' ) );
        $support_bundle_url = (string) ( $support_touchpoints['support_bundle_url'] ?? ( $system_status_url . '#bookaro-support-bundle' ) );
        $generic_validation_url = (string) ( $support_touchpoints['generic_validation_url'] ?? ( $system_status_url . '#bookaro-support-check-generic_validation_provider_resolution_sample' ) );
        $support_touchpoint_actions = $this->get_support_touchpoint_actions();
        $single_business_default_provider_url = admin_url( 'admin.php?page=bookaro-setup-wizard&step=listings' );
        $single_business_pages_url = admin_url( 'admin.php?page=bookaro-setup-wizard&step=pages' );
        $single_business_status = $this->build_single_business_onboarding_status( $opts, $integration_mode );
        if ( '' === trim( (string) ( $single_business_status['default_provider_url'] ?? '' ) ) ) {
            $single_business_status['default_provider_url'] = $single_business_default_provider_url;
        }
        if ( '' === trim( (string) ( $single_business_status['pages_url'] ?? '' ) ) ) {
            $single_business_status['pages_url'] = $single_business_pages_url;
        }
        $lane_summary = $this->build_lane_summary_banner(
            $lane_profile,
            $integration_mode,
            $mylisting_activation_flow,
            $generic_readiness_summary,
            $single_business_status
        );
        $wizard_completion = $this->build_wizard_completion_state(
            $opts,
            $lane_profile,
            $mylisting_activation_flow,
            $generic_readiness_summary,
            $page_url,
            $generic_validation_url,
            $single_business_default_provider_url,
            $single_business_pages_url
        );

        TemplateLoader::render( 'admin/getting-started.php', [
            'checks' => $checks,
            'actions' => $actions,
            'listing_choices' => $listing_choices,
            'default_listing_id' => $default_listing_id,
            'default_email' => $default_email,
            'page_url' => $page_url,
            'wizard_url' => $wizard_url,
            'is_pro' => $this->is_pro_active(),
            'integration_mode' => $integration_mode,
            'repeater_class' => function_exists( 'bookaro_get_mylisting_services_repeater_class' )
                ? bookaro_get_mylisting_services_repeater_class()
                : 'mybookaro_services',
            'site_type' => $site_type,
            'lane_profile' => $lane_profile,
            'demo_content' => $demo_status,
            'quick_steps' => $quick_steps,
            'shortcode_snippets' => $shortcode_snippets,
            'support_url' => $support_url,
            'support_docs_url' => $support_docs_url,
            'system_status_url' => $system_status_url,
            'support_status_url' => $support_snapshot_url,
            'support_snapshot_url' => $support_snapshot_url,
            'support_bundle_url' => $support_bundle_url,
            'support_touchpoint_actions' => $support_touchpoint_actions,
            'generic_validation' => $generic_validation,
            'generic_validation_url' => $generic_validation_url,
            'generic_readiness_summary' => $generic_readiness_summary,
            'wizard_completion' => $wizard_completion,
            'operational_summary_items' => $operational_summary_items,
            'operational_summary_url' => $page_url . '#bookaro-operational-summary',
            'operational_general_settings_url' => admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' ),
            'operational_notifications_settings_url' => admin_url( 'admin.php?page=bookaro-booking-settings&tab=notifications' ),
            'single_business_default_provider_url' => $single_business_default_provider_url,
            'single_business_pages_url' => $single_business_pages_url,
            'single_business_status' => $single_business_status,
            'mylisting_activation_flow' => $mylisting_activation_flow,
            'lane_summary' => $lane_summary,
        ] );
    }

    public function handle_demo_timeslots(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_demo_timeslots' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $listing_id = absint( $payload['listing_id'] ?? 0 );
        if ( $listing_id < 1 ) {
            $listing_id = $this->get_default_listing_id( $this->get_listing_choices() );
        }

        if ( $listing_id < 1 && ! $this->is_single_business_site_for_onboarding() ) {
            $this->set_notice( 'error', $this->empty_listing_notice() );
            $this->redirect_to_page();
        }

        $provider_id = $this->resolve_provider_id( $listing_id );
        if ( $provider_id < 1 ) {
            $this->set_notice(
                'error',
                $this->is_single_business_site_for_onboarding()
                    ? __( 'Could not resolve a Default Provider. Single Business requires no listings, but Default Provider is required. Set it in Setup Wizard > Listings (or Settings > General), then try again.', 'mybookaro' )
                    : __( 'Could not resolve a provider for the selected listing.', 'mybookaro' )
            );
            $this->redirect_to_page();
        }

        if ( ! $this->ensure_demo_timeslots_for_provider( $provider_id ) ) {
            $this->set_action_last_run( 'demo_timeslots' );
            $this->set_notice( 'success', __( 'Timeslots already exist for this provider.', 'mybookaro' ) );
            $this->redirect_to_page();
        }

        $this->set_action_last_run( 'demo_timeslots' );
        $this->set_notice( 'success', __( 'Demo timeslots created for the selected provider.', 'mybookaro' ) );
        $this->redirect_to_page();
    }

    public function handle_open_listing(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_open_listing' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $listing_id = absint( $payload['listing_id'] ?? 0 );
        if ( $listing_id < 1 ) {
            $listing_id = $this->get_default_listing_id( $this->get_listing_choices() );
        }

        if ( $listing_id < 1 && $this->is_single_business_site_for_onboarding() ) {
            $single_business_preview_url = $this->get_single_business_preview_url();
            if ( $single_business_preview_url !== '' ) {
                $this->set_action_last_run( 'open_listing' );
                wp_safe_redirect( $single_business_preview_url );
                exit;
            }
            $single_business_provider_id = $this->resolve_provider_id( 0 );
            if ( $single_business_provider_id > 0 ) {
                $this->set_action_last_run( 'open_listing' );
                wp_safe_redirect( $this->get_single_business_fast_path_url() );
                exit;
            }
            $this->set_notice( 'error', $this->empty_listing_notice( true ) );
            $this->redirect_to_page();
        }

        if ( $listing_id < 1 ) {
            $this->set_notice( 'error', $this->empty_listing_notice( true ) );
            $this->redirect_to_page();
        }

        $url = get_permalink( $listing_id );
        if ( ! $url ) {
            $url = get_edit_post_link( $listing_id, '' );
        }
        if ( ! $url ) {
            $this->set_notice( 'error', __( 'Unable to open the selected listing.', 'mybookaro' ) );
            $this->redirect_to_page();
        }

        $this->set_action_last_run( 'open_listing' );
        wp_safe_redirect( $url );
        exit;
    }

    public function handle_test_email(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_test_email' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $email = sanitize_email( $payload['bookaro_test_email'] ?? '' );
        if ( $email === '' ) {
            $email = $this->get_default_test_email();
        }

        if ( $email === '' || ! is_email( $email ) ) {
            $this->set_notice( 'error', __( 'Please enter a valid email address for the test.', 'mybookaro' ) );
            $this->redirect_to_page();
        }

        $subject = __( 'MyBookaro test email', 'mybookaro' );
        $message = __( 'This is a test email from MyBookaro. If you received it, your email settings are working.', 'mybookaro' );
        $sent = wp_mail( $email, $subject, $message );

        if ( $sent ) {
            $this->set_action_last_run( 'test_email' );
            $this->set_notice( 'success', __( 'Test email sent successfully.', 'mybookaro' ) );
        } else {
            $this->set_notice( 'error', __( 'Test email failed. Check your email configuration.', 'mybookaro' ) );
        }

        $this->redirect_to_page();
    }

    public function handle_demo_content_create(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_demo_content_create' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $listing_id = absint( $payload['listing_id'] ?? 0 );
        if ( $listing_id < 1 ) {
            $listing_id = $this->get_default_listing_id( $this->get_listing_choices() );
        }
        $provider_id = $this->resolve_provider_id( $listing_id );

        $result = $this->create_demo_content( $listing_id, $provider_id );
        if ( empty( $result['created'] ) ) {
            $this->set_notice( 'success', __( 'Demo content already exists.', 'mybookaro' ) );
        } else {
            $this->set_notice( 'success', __( 'Demo content created. You can remove it anytime.', 'mybookaro' ) );
        }
        $this->set_action_last_run( 'demo_content_create' );
        $this->redirect_to_page();
    }

    public function handle_demo_content_remove(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_demo_content_remove' );

        $removed = $this->remove_demo_content();
        if ( $removed ) {
            $this->set_notice( 'success', __( 'Demo content removed.', 'mybookaro' ) );
        } else {
            $this->set_notice( 'info', __( 'No demo content found to remove.', 'mybookaro' ) );
        }
        $this->set_action_last_run( 'demo_content_remove' );
        $this->redirect_to_page();
    }

    public function handle_fast_path_booking(): void
    {
        $this->assert_manage_options();
        check_admin_referer( 'bookaro_getting_started_fast_path_booking' );

        $payload = is_array( $_REQUEST ) ? wp_unslash( $_REQUEST ) : [];
        $listing_id = absint( $payload['listing_id'] ?? 0 );
        if ( $listing_id < 1 ) {
            $listing_id = $this->get_default_listing_id( $this->get_listing_choices() );
        }
        $single_business = $this->is_single_business_site_for_onboarding();
        if ( $listing_id < 1 && ! $single_business ) {
            $this->set_notice( 'error', $this->empty_listing_notice( true ) );
            $this->redirect_to_page();
        }

        $provider_id = $this->resolve_provider_id( $listing_id );
        if ( $provider_id < 1 && $single_business ) {
            $this->set_notice( 'error', __( 'Set a Default Provider in Settings > General before running the Single Business fast path.', 'mybookaro' ) );
            $this->redirect_to_page();
        }

        $result = $this->create_demo_content( $listing_id, $provider_id );
        $timeslots_created = $provider_id > 0
            ? $this->ensure_demo_timeslots_for_provider( $provider_id )
            : false;
        $this->set_action_last_run( 'fast_path_booking' );

        $listing_url = $listing_id > 0 ? get_permalink( $listing_id ) : '';
        if ( ! $listing_url ) {
            $listing_url = $listing_id > 0 ? get_edit_post_link( $listing_id, '' ) : '';
        }
        if ( ! $listing_url ) {
            $booking_demo_id = absint( $result['pages']['demo_booking'] ?? 0 );
            if ( $booking_demo_id > 0 ) {
                $listing_url = get_permalink( $booking_demo_id );
            }
            if ( ! $listing_url ) {
                $services_demo_id = absint( $result['pages']['demo_services'] ?? 0 );
                if ( $services_demo_id > 0 ) {
                    $listing_url = get_permalink( $services_demo_id );
                }
            }
        }
        if ( ! $listing_url && $single_business ) {
            $listing_url = $this->get_single_business_preview_url();
        }

        if ( ! $listing_url ) {
            $this->set_notice(
                'warning',
                $single_business
                    ? __( 'Demo setup is ready, but no booking/services page URL was found. Open it manually from Quick actions.', 'mybookaro' )
                    : __( 'Demo setup is ready, but no listing URL was found. Open the listing manually from Quick actions.', 'mybookaro' )
            );
            $this->redirect_to_page();
        }

        if ( ! empty( $result['created'] ) || $timeslots_created ) {
            $this->set_notice(
                'success',
                $single_business
                    ? __( 'Demo setup prepared. Continue with one end-to-end booking test from your booking/services page.', 'mybookaro' )
                    : __( 'Demo setup prepared. Continue with one end-to-end booking test from the MyListing sidebar booking entry.', 'mybookaro' )
            );
        } else {
            $this->set_notice(
                'info',
                $single_business
                    ? __( 'Demo setup was already ready. Continue with one end-to-end booking test from your booking/services page.', 'mybookaro' )
                    : __( 'Demo setup was already ready. Continue with one end-to-end booking test from the MyListing sidebar booking entry.', 'mybookaro' )
            );
        }

        wp_safe_redirect( $listing_url );
        exit;
    }

    private function build_checks( array $last_runs, string $integration_mode, array $generic_validation = [], array $generic_validation_prompt = [] ): array
    {
        $settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' );
        $shortcodes_settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=shortcodes#bookaro-settings-tabs' );
        $notifications_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=notifications' );
        $wizard_url = admin_url( 'admin.php?page=bookaro-setup-wizard' );
        $status_url = admin_url( 'admin.php?page=bookaro-system-status' );
        $generic_validation_url = $status_url . '#bookaro-support-check-generic_validation_provider_resolution_sample';
        $open_listings_url = '#bookaro-action-open-listing';
        $single_business_fast_path_url = $this->get_single_business_fast_path_url();
        $runtime_total = absint( $generic_validation['total'] ?? 0 );
        $runtime_failed = absint( $generic_validation['failed'] ?? 0 );
        $runtime_available = ! empty( $generic_validation['available'] );
        $validation_refresh_required = ! empty( $generic_validation_prompt['needs_validation'] );
        $opts = $this->options->get_all();
        $generic_confirmation_required = ! empty( $generic_validation_prompt['confirmation_required'] );
        $generic_legacy_fallback_active = ( 'generic' === $integration_mode ) && $this->is_generic_legacy_fallback_active( $opts );
        $generic_confirmation_ready = ! $generic_confirmation_required && ! $generic_legacy_fallback_active;
        $runtime_ok = ! $validation_refresh_required && $runtime_available && $runtime_total > 0 && $runtime_failed < 1;
        if ( $validation_refresh_required ) {
            $runtime_detail = $this->get_generic_launch_readiness_notice_message();
        } elseif ( ! $runtime_available || $runtime_total < 1 ) {
            $runtime_detail = __( 'Generic setup has not been checked yet. Until you run System Status, Bookaro cannot confirm lane routing, services source, booking entry placement, or required pages. Next action: open System Status and run the Generic validation checks.', 'mybookaro' );
        } elseif ( $runtime_failed > 0 ) {
            $runtime_detail = sprintf(
                /* translators: 1: failed checks, 2: total checks */
                __( '%1$d of %2$d Generic checks still need attention. That means at least one lane routing, services source, booking entry, or required page rule can still block bookings. Next action: open System Status, follow each Suggested fix, then refresh Getting Started.', 'mybookaro' ),
                $runtime_failed,
                $runtime_total
            );
        } else {
            $runtime_detail = sprintf(
                /* translators: %d: total checks */
                __( 'All %d Generic checks are passing. Bookaro can resolve lane routing, services source, booking entry placement, and required pages for the current setup. Re-run validation after lane, services, or page changes.', 'mybookaro' ),
                $runtime_total
            );
        }

        $types = $this->get_listing_post_types();
        $site_type = $this->resolve_site_type_for_onboarding();
        $single_business = ( 'single_business' === $site_type );
        $type_label = ! empty( $types ) ? implode( ', ', $types ) : __( 'Not selected', 'mybookaro' );
        if ( $single_business && empty( $types ) ) {
            $type_label = __( 'Optional in Single Business lane', 'mybookaro' );
        }
        $check_listings = $single_business ? true : ! empty( $types );
        $generic_setup_preset = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'generic_setup_preset', '' ) )
            : '';
        $generic_preset_profile = GenericPresetProfiles::get( $generic_setup_preset );
        $generic_preset_selected = ! empty( $generic_preset_profile );
        $generic_preset_detail = $generic_preset_selected
            ? GenericPresetProfiles::build_selection_detail( $generic_setup_preset )
            : __( 'No Generic preset is selected yet. Bookaro cannot confirm which ownership path, Services Source, or placement path you intended. Next action: open Setup Wizard > Lane, choose Provider-Owned Directory, Editorial + Meta Key Directory, or Shared Catalog Directory, then save.', 'mybookaro' );
        if ( $single_business ) {
            $generic_preset_selected = true;
            $generic_preset_detail = __( 'Single Business uses its own provider-first launch path.', 'mybookaro' );
        }
        $generic_advanced_setup_enabled = function_exists( 'bookaro_get_option' )
            ? ! empty( bookaro_get_option( 'generic_advanced_setup_enabled', 0 ) )
            : false;
        if ( $single_business ) {
            $generic_advanced_setup_enabled = false;
        }

        $provider_resolution = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_resolution_mode', '' )
            : '';
        $provider_resolution = sanitize_key( $provider_resolution );
        if ( '' === $provider_resolution ) {
            $provider_resolution = ( 'mylisting' === $integration_mode ) ? 'author' : '';
        }
        $provider_meta_key = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_meta_key', '' )
            : '';
        $provider_meta_key = sanitize_key( $provider_meta_key );
        $provider_resolution_valid = in_array( $provider_resolution, [ 'author', 'meta_key' ], true )
            && ( 'meta_key' !== $provider_resolution || '' !== $provider_meta_key );

        $provider_mode_label = 'meta_key' === $provider_resolution
            ? __( 'Listing Meta Key', 'mybookaro' )
            : __( 'Listing Author', 'mybookaro' );
        $provider_resolution_detail = 'meta_key' === $provider_resolution
            ? (
                '' !== $provider_meta_key
                    ? sprintf(
                        /* translators: 1: provider mode label, 2: provider meta key */
                        __( 'Provider Mapping is set to %1$s using the `%2$s` field. Bookaro will read that listing field to decide which provider should receive bookings.', 'mybookaro' ),
                        $provider_mode_label,
                        $provider_meta_key
                    )
                    : __( 'Provider Mapping is set to Listing Meta Key, but Provider Meta Key is empty. Bookaro cannot read the provider user ID from your listings until you fill that field.', 'mybookaro' )
            )
            : sprintf(
                /* translators: %s: provider mode label */
                __( 'Provider Mapping is set to %s. Bookaro will use each listing author as the provider who receives bookings.', 'mybookaro' ),
                $provider_mode_label
            );

        $services_model = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'services_model', '' )
            : '';
        if ( '' === $services_model && function_exists( 'bookaro_get_option' ) ) {
            $services_model = (string) bookaro_get_option( 'generic_services_mode', 'hybrid' );
        }
        $services_model = sanitize_key( $services_model );
        if ( 'admin_catalog' === $services_model ) {
            $services_model = 'admin_only';
        }
        $services_model_map = [
            'provider_only' => __( 'Provider Only', 'mybookaro' ),
            'admin_only' => __( 'Admin Catalog Only', 'mybookaro' ),
            'hybrid' => __( 'Hybrid', 'mybookaro' ),
        ];
        $services_model_valid = array_key_exists( $services_model, $services_model_map );
        $services_model_label = $services_model_valid
            ? (string) $services_model_map[ $services_model ]
            : __( 'Not configured', 'mybookaro' );

        $ui_mode = $this->resolve_ui_mode_for_onboarding( $integration_mode );

        $primary_type = $types[0] ?? '';
        if ( '' === $primary_type && function_exists( 'bookaro_get_option' ) ) {
            $primary_type = (string) bookaro_get_option( 'listing_post_type', '' );
        }
        $primary_type = sanitize_key( $primary_type );
        if ( '' === $primary_type ) {
            if ( $single_business && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
                $primary_type = sanitize_key( (string) BOOKARO_PROVIDER_POST_TYPE );
            } else {
                $primary_type = 'job_listing';
            }
        }

        $booking_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'booking' ) )
            : 0;
        $provider_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'provider_dashboard' ) )
            : 0;
        $customer_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'customer_dashboard' ) )
            : 0;
        $single_business_missing_booking_page = $single_business && $booking_page_id < 1;

        $missing_pages = [];
        $missing_page_keys = [];
        if ( $booking_page_id < 1 ) {
            $missing_pages[] = __( 'Booking page', 'mybookaro' );
            $missing_page_keys[] = 'booking';
        }
        if ( 'shortcodes' === $ui_mode ) {
            if ( $provider_page_id < 1 ) {
                $missing_pages[] = __( 'Provider dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'provider_dashboard';
            }
            if ( $customer_page_id < 1 ) {
                $missing_pages[] = __( 'Customer dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'customer_dashboard';
            }
        }
        $page_assignment_ok = empty( $missing_pages );
        if ( $page_assignment_ok ) {
            $page_assignment_detail = 'shortcodes' === $ui_mode
                ? __( 'Booking page, Provider Dashboard page, and Customer Dashboard page are assigned.', 'mybookaro' )
                : (
                    'generic' === $integration_mode
                        ? __( 'Booking page is assigned. WooCommerce My Account dashboards are active, but the recommended Generic path uses Shortcodes for page-assigned blocks/shortcodes.', 'mybookaro' )
                        : __( 'Booking page is assigned. Dashboard pages use WooCommerce My Account.', 'mybookaro' )
                );
        } else {
            $page_assignment_detail = sprintf(
                /* translators: %s: comma separated missing pages */
                __( 'Missing: %s.', 'mybookaro' ),
                implode( ', ', $missing_pages )
            );
            $page_assignment_detail .= ' ' . __( 'Open Setup Wizard > Pages and assign the missing pages. In Shortcodes mode, the dashboard pages must also contain the matching MyBookaro dashboard block or shortcode.', 'mybookaro' );
            if ( $single_business_missing_booking_page ) {
                $page_assignment_detail .= ' ' . __( 'Single Business listings are optional, but Booking page is required before customers can start bookings. Next action: assign Booking page first in Setup Wizard > Pages.', 'mybookaro' );
            } elseif ( $single_business ) {
                $page_assignment_detail .= ' ' . __( 'Single Business listings are optional; complete Setup Wizard > Pages to unblock launch.', 'mybookaro' );
            }
        }

        $auto_insert_mode = function_exists( 'bookaro_get_auto_insert_booking_button_mode' )
            ? (string) bookaro_get_auto_insert_booking_button_mode()
            : '';
        $auto_insert_mode = sanitize_key( $auto_insert_mode );
        $auto_insert_enabled = function_exists( 'bookaro_get_option' ) && array_key_exists( 'auto_insert_booking_button_enabled', $this->options->get_all() )
            ? (bool) bookaro_get_option( 'auto_insert_booking_button_enabled', 0 )
            : ( '' !== $auto_insert_mode );
        $auto_insert_selector = function_exists( 'bookaro_get_auto_insert_booking_button_selector' )
            ? sanitize_text_field( (string) bookaro_get_auto_insert_booking_button_selector() )
            : '';
        $booking_page_url = function_exists( 'bookaro_get_booking_page_url' )
            ? (string) bookaro_get_booking_page_url( [ 'listing_id' => 0 ] )
            : '';
        $button_placement_ok = ( $auto_insert_enabled && '' !== $auto_insert_mode ) || ( '' !== $booking_page_url );
        if ( $auto_insert_enabled && '' !== $auto_insert_mode ) {
            if ( 'selector' === $auto_insert_mode ) {
                $button_placement_detail = '' !== $auto_insert_selector
                    ? sprintf(
                        /* translators: %s: css selector */
                        __( 'Auto-insert enabled via selector: %s.', 'mybookaro' ),
                        $auto_insert_selector
                    )
                    : __( 'Auto-insert selector placement is enabled.', 'mybookaro' );
            } else {
                $placement_label = 'before_content' === $auto_insert_mode
                    ? __( 'before content', 'mybookaro' )
                    : __( 'after content', 'mybookaro' );
                $button_placement_detail = sprintf(
                    /* translators: %s: auto-insert placement */
                    __( 'Auto-insert enabled (%s).', 'mybookaro' ),
                    $placement_label
                );
            }
        } elseif ( '' !== $booking_page_url ) {
            $button_placement_detail = __( 'Booking page is configured. Next step: place Booking Button/Services Cards where customers will start bookings, then update that template or page.', 'mybookaro' );
        } else {
            $button_placement_detail = __( 'No booking entry is configured yet (Auto-Insert is off and no Booking page is assigned).', 'mybookaro' );
        }
        $block_shortcode_ready = ( 'shortcodes' === $ui_mode ) && ( '' !== $booking_page_url );
        if ( 'shortcodes' !== $ui_mode ) {
            $block_shortcode_detail = __( 'Step 3 for Generic: open Setup Wizard > Services, switch UI Mode to Shortcodes, save, then place Booking Button/Services Cards blocks or shortcodes. Auto-Insert can remain as a fallback.', 'mybookaro' );
        } elseif ( '' !== $booking_page_url ) {
            $block_shortcode_detail = __( 'Shortcodes mode is active with a Booking page. Next step: place Booking Button/Services Cards, then update the template or page where bookings start.', 'mybookaro' );
        } elseif ( $auto_insert_enabled && '' !== $auto_insert_mode ) {
            $block_shortcode_detail = __( 'Step 3 for Generic: place Booking Button/Services Cards blocks or shortcodes for explicit placement. Auto-Insert can remain enabled as a fallback.', 'mybookaro' );
        } else {
            $block_shortcode_detail = $single_business
                ? __( 'No booking page detected yet. Single Business listings are optional, but you must assign a booking page first in Setup Wizard > Pages.', 'mybookaro' )
                : __( 'No booking entry is configured yet. Assign a Booking page in Setup Wizard > Pages, then place Booking Button/Services Cards or enable Auto-Insert fallback in Setup Wizard > Services.', 'mybookaro' );
        }

        $step_three_action_url = $shortcodes_settings_url;
        $step_three_action_label = __( 'Open embed tab', 'mybookaro' );
        if ( '' === $booking_page_url ) {
            $step_three_action_url = $wizard_url . '&step=pages';
            $step_three_action_label = __( 'Assign pages first', 'mybookaro' );
        }

        $provider_resolution_check_detail = $provider_resolution_valid
            ? $provider_resolution_detail
            : __( 'Provider mapping is incomplete. Next step: Open Setup Wizard > Listings, choose Provider Mapping, fill Provider Meta Key if Meta Key mode is selected, then save.', 'mybookaro' );
        $provider_resolution_action_label = $provider_resolution_valid
            ? __( 'Open listings step', 'mybookaro' )
            : __( 'Configure provider mapping', 'mybookaro' );

        $services_source_check_detail = $services_model_valid
            ? sprintf(
                /* translators: %s: services source mode label */
                __( 'Services Source is %s. This determines which services customers can book in the Generic flow.', 'mybookaro' ),
                $services_model_label
            )
            : __( 'Services Source is not configured. Bookaro cannot tell whether customers should see provider-managed services, the shared admin catalog, or both. Next action: open Setup Wizard > Services, choose the matching Services Source, then save.', 'mybookaro' );
        $services_source_action_label = $services_model_valid
            ? __( 'Open services step', 'mybookaro' )
            : __( 'Configure services source', 'mybookaro' );

        $completed_bookings = $this->count_test_bookings();
        $email_tested = ! empty( $last_runs['test_email'] );
        $notify_status = function_exists( 'bookaro_get_option' ) ? ! empty( bookaro_get_option( 'notify_new_booking', 0 ) ) : false;
        $notify_reminder = function_exists( 'bookaro_get_option' ) ? ! empty( bookaro_get_option( 'notify_reminder', 0 ) ) : false;
        $notify_review_invite = function_exists( 'bookaro_get_option' ) ? ! empty( bookaro_get_option( 'notify_review_invite', 0 ) ) : false;
        $notification_automations_ok = $notify_reminder || $notify_review_invite;
        $flag_on = __( 'On', 'mybookaro' );
        $flag_off = __( 'Off', 'mybookaro' );
        $notification_automation_detail = sprintf(
            /* translators: 1: status emails flag, 2: reminder emails flag, 3: review invite emails flag */
            __( 'Status emails: %1$s | Reminders (24h/1h): %2$s | Review invites: %3$s.', 'mybookaro' ),
            $notify_status ? $flag_on : $flag_off,
            $notify_reminder ? $flag_on : $flag_off,
            $notify_review_invite ? $flag_on : $flag_off
        );
        if ( ! $notification_automations_ok ) {
            $notification_automation_detail .= ' ' . __( 'Enable reminders or review invites in Settings > Email to send automated follow-ups.', 'mybookaro' );
        }
        $booking_flow_detail = $completed_bookings > 0
            ? sprintf(
                /* translators: %d: completed booking count */
                __( 'Completed bookings found: %d.', 'mybookaro' ),
                $completed_bookings
            )
            : (
                $single_business
                    ? __( 'No completed booking yet. Open your booking/services page and test one booking end to end.', 'mybookaro' )
                    : __( 'No completed booking yet. Open a listing and test one booking end to end.', 'mybookaro' )
            );
        $preview_action_label = $single_business
            ? __( 'Open booking preview', 'mybookaro' )
            : __( 'Open listing preview', 'mybookaro' );

        if ( 'mylisting' === $integration_mode ) {
            $mylisting_detected = $this->is_mylisting_detected();
            $sidebar_hook_ok = function_exists( 'has_action' )
                ? (bool) has_action( 'mylisting/single/sidebar/actions', 'bookaro_render_mylisting_booking_button' )
                : false;
            $repeater_class = function_exists( 'bookaro_get_option' )
                ? sanitize_key( (string) bookaro_get_option( 'mylisting_services_repeater_class', 'mybookaro_services' ) )
                : 'mybookaro_services';
            if ( '' === $repeater_class ) {
                $repeater_class = 'mybookaro_services';
            }

            return [
                [
                    'label' => __( 'Listing ownership/provider mapping', 'mybookaro' ),
                    'passed' => $provider_resolution_valid,
                    'detail' => $provider_resolution_detail,
                    'action' => [
                        'label' => __( 'Review settings', 'mybookaro' ),
                        'url' => $settings_url,
                    ],
                ],
                [
                    'label' => __( 'Sidebar booking button hook', 'mybookaro' ),
                    'passed' => $mylisting_detected && $sidebar_hook_ok,
                    'detail' => ! $mylisting_detected
                        ? __( 'MyListing is not detected. Activate MyListing first.', 'mybookaro' )
                        : (
                            $sidebar_hook_ok
                                ? __( 'MyListing sidebar hook is active for the booking button.', 'mybookaro' )
                                : __( 'Sidebar booking button hook is missing. Re-save permalinks/settings and re-check System Status.', 'mybookaro' )
                        ),
                    'action' => [
                        'label' => __( 'Open system status', 'mybookaro' ),
                        'url' => $status_url,
                    ],
                ],
                [
                    'label' => __( 'Provider services repeater configured', 'mybookaro' ),
                    'passed' => '' !== $repeater_class,
                    'detail' => sprintf(
                        /* translators: %s: repeater row css class */
                        __( 'Current repeater class: %s.', 'mybookaro' ),
                        $repeater_class
                    ),
                    'action' => [
                        'label' => __( 'Review settings', 'mybookaro' ),
                        'url' => $settings_url,
                    ],
                ],
                [
                    'label' => __( 'Reminder and review invite automations', 'mybookaro' ),
                    'passed' => $notification_automations_ok,
                    'detail' => $notification_automation_detail,
                    'action' => [
                        'label' => __( 'Open email settings', 'mybookaro' ),
                        'url' => $notifications_url,
                    ],
                ],
                [
                    'label' => __( 'Booking flow validated', 'mybookaro' ),
                    'passed' => $completed_bookings > 0,
                    'detail' => $booking_flow_detail,
                    'action' => [
                        'label' => $preview_action_label,
                        'url' => $open_listings_url,
                    ],
                ],
            ];
        }

        $default_provider_id = $single_business
            ? $this->get_single_business_default_provider_id()
            : (
                function_exists( 'bookaro_get_option' )
                    ? absint( bookaro_get_option( 'default_provider_id', 0 ) )
                    : 0
            );
        $default_provider_ok = $default_provider_id > 0;
        $single_business_services_count = $single_business
            ? $this->count_single_business_available_services( $default_provider_id )
            : 0;
        $single_business_services_ready = $single_business && $default_provider_ok && $single_business_services_count > 0;
        $single_business_services_detail = ! $single_business
            ? ''
            : (
                ! $default_provider_ok
                    ? __( 'Cannot validate services until Default Provider is set. Next action: open Setup Wizard > Listings and set Default Provider.', 'mybookaro' )
                    : (
                        $single_business_services_ready
                            ? sprintf(
                                /* translators: %d: available services count */
                                __( 'Available services for the Default Provider: %d. Provider-first booking can render service choices.', 'mybookaro' ),
                                $single_business_services_count
                            )
                            : __( 'Booking UI cannot render service choices because no services are available for the Default Provider. Next action: create at least one service for that provider, then re-check Setup Wizard > Services if needed.', 'mybookaro' )
                    )
            );
        if ( $single_business ) {
            $service_type = defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service';
            $create_service_url = admin_url( 'post-new.php?post_type=' . $service_type );
            $single_business_preview_url = $this->get_single_business_preview_url();
            $single_business_preview_ready = $default_provider_ok
                && $page_assignment_ok
                && $single_business_services_ready
                && '' !== trim( $single_business_preview_url );
            $single_business_preview_detail = ! $default_provider_ok
                ? __( 'Step 1 is still blocked. Set Default Provider first, then continue with pages and service inventory before preview.', 'mybookaro' )
                : (
                    ! $page_assignment_ok
                        ? __( 'Step 2 is still blocked. Assign Booking page first, then required dashboard pages if you use Shortcodes mode.', 'mybookaro' )
                        : (
                            ! $single_business_services_ready
                                ? __( 'Step 3 is still blocked. Create the first service for the Default Provider before preview.', 'mybookaro' )
                                : (
                                    '' === trim( $single_business_preview_url )
                                        ? __( 'Booking/services preview URL is not available yet. Re-check page assignment, then open the booking page.', 'mybookaro' )
                                        : __( 'Open booking preview and complete one end-to-end booking test.', 'mybookaro' )
                                )
                        )
                );
            $missing_booking_page = in_array( 'booking', $missing_page_keys, true );
            $missing_dashboard_pages = in_array( 'provider_dashboard', $missing_page_keys, true ) || in_array( 'customer_dashboard', $missing_page_keys, true );
            $single_business_pages_action_label = __( 'Assign pages', 'mybookaro' );
            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_preview_action_label = ! $default_provider_ok
                ? __( 'Set Default Provider', 'mybookaro' )
                : (
                    ! $page_assignment_ok
                        ? $single_business_pages_action_label
                        : (
                            ! $single_business_services_ready
                                ? __( 'Create first service', 'mybookaro' )
                                : __( 'Open booking preview', 'mybookaro' )
                        )
                );
            $single_business_preview_action_url = ! $default_provider_ok
                ? ( $wizard_url . '&step=listings' )
                : (
                    ! $page_assignment_ok
                        ? ( $wizard_url . '&step=pages' )
                        : (
                            ! $single_business_services_ready
                                ? $create_service_url
                                : ( '' !== trim( $single_business_preview_url ) ? $single_business_preview_url : ( $wizard_url . '&step=pages' ) )
                        )
                );
            $single_business_fast_path_ready = $default_provider_ok && $page_assignment_ok && $single_business_services_ready;
            $single_business_fast_path_detail = ! $default_provider_ok
                ? __( 'Set Default Provider first. Then run the Single Business fast path to create demo pages/services, seed availability, and open a preview booking flow.', 'mybookaro' )
                : (
                    $single_business_fast_path_ready
                        ? __( 'Single Business fast path is ready. Run it once to create/update demo setup and open a preview booking flow without listing context.', 'mybookaro' )
                        : __( 'Use the Single Business fast path to create demo pages/services, seed provider availability, and open a preview booking flow without hunting through multiple screens.', 'mybookaro' )
                );

            return [
                [
                    'label' => __( 'Default provider selected', 'mybookaro' ),
                    'passed' => $default_provider_ok,
                    'detail' => $default_provider_ok
                        ? __( 'Default Provider is set. Continue with page assignment, first service, then preview booking.', 'mybookaro' )
                        : __( 'Single Business requires no listings, but Default Provider is required. Next action: open Setup Wizard > Listings, set Default Provider, save, then continue.', 'mybookaro' ),
                    'action' => [
                        'label' => __( 'Set Default Provider', 'mybookaro' ),
                        'url' => $wizard_url . '&step=listings',
                    ],
                ],
                [
                    'label' => __( 'Step 2: Assign booking/dashboard pages', 'mybookaro' ),
                    'passed' => $page_assignment_ok,
                    'detail' => $page_assignment_detail,
                    'action' => [
                        'label' => $single_business_pages_action_label,
                        'url' => $wizard_url . '&step=pages',
                    ],
                ],
                [
                    'label' => __( 'Services available for Default Provider', 'mybookaro' ),
                    'passed' => $single_business_services_ready,
                    'detail' => $single_business_services_detail,
                    'action' => [
                        'label' => ! $default_provider_ok
                            ? __( 'Set Default Provider', 'mybookaro' )
                            : ( ! $single_business_services_ready ? __( 'Create first service', 'mybookaro' ) : __( 'Open services step', 'mybookaro' ) ),
                        'url' => ! $default_provider_ok
                            ? ( $wizard_url . '&step=listings' )
                            : ( ! $single_business_services_ready ? $create_service_url : ( $wizard_url . '&step=services' ) ),
                    ],
                ],
                [
                    'label' => __( 'Step 4: Preview booking flow', 'mybookaro' ),
                    'passed' => $single_business_preview_ready || $completed_bookings > 0,
                    'detail' => $completed_bookings > 0
                        ? $booking_flow_detail
                        : $single_business_preview_detail,
                    'action' => [
                        'label' => $single_business_preview_action_label,
                        'url' => $single_business_preview_action_url,
                    ],
                ],
                [
                    'label' => __( 'Single Business first-run fast path', 'mybookaro' ),
                    'passed' => $single_business_fast_path_ready,
                    'detail' => $single_business_fast_path_detail,
                    'action' => [
                        'label' => ! $default_provider_ok ? __( 'Set Default Provider', 'mybookaro' ) : __( 'Run Single Business fast path', 'mybookaro' ),
                        'url' => ! $default_provider_ok ? ( $wizard_url . '&step=listings' ) : $single_business_fast_path_url,
                    ],
                ],
                [
                    'label' => __( 'Reminder and review invite automations', 'mybookaro' ),
                    'passed' => $notification_automations_ok,
                    'detail' => $notification_automation_detail,
                    'action' => [
                        'label' => __( 'Open email settings', 'mybookaro' ),
                        'url' => $notifications_url,
                    ],
                ],
                [
                    'label' => __( 'Email delivery test', 'mybookaro' ),
                    'passed' => $email_tested,
                    'detail' => $email_tested
                        ? __( 'Test email sent successfully.', 'mybookaro' )
                        : __( 'Send a test email to verify delivery.', 'mybookaro' ),
                    'action' => [
                        'label' => __( 'Send test email', 'mybookaro' ),
                        'url' => '#bookaro-action-test-email',
                    ],
                ],
            ];
        }
        $step_one_label = $single_business
            ? __( 'Step 1: Confirm Single Business lane defaults', 'mybookaro' )
            : __( 'Step 1: Confirm lane, guided preset, and placement path', 'mybookaro' );
        $step_one_passed = $single_business
            ? true
            : ( $generic_preset_selected && $generic_confirmation_ready );
        $step_one_detail = $single_business
            ? __( 'Single Business is a first-class provider-first lane. No listings are required.', 'mybookaro' )
            : (
                ! $generic_confirmation_ready
                    ? (
                        $generic_confirmation_required
                            ? __( 'Generic lane is not explicitly confirmed yet. Open Setup Wizard > Lane, select Generic Directory, and save before launch validation.', 'mybookaro' )
                            : __( 'Generic Directory is running from legacy automatic settings. Next step: Open Setup Wizard > Lane and save once to record explicit confirmation metadata.', 'mybookaro' )
                    )
                    : $generic_preset_detail
            );
        $step_one_action_label = $single_business
            ? __( 'Open settings', 'mybookaro' )
            : (
                ! $generic_confirmation_ready
                    ? __( 'Confirm lane in Setup Wizard', 'mybookaro' )
                    : __( 'Open lane step', 'mybookaro' )
            );
        $step_one_action_url = $single_business ? $settings_url : ( $wizard_url . '&step=modes' );

        $checks = [
            [
                'label' => $step_one_label,
                'passed' => $step_one_passed,
                'detail' => $step_one_detail,
                'action' => [
                    'label' => $step_one_action_label,
                    'url' => $step_one_action_url,
                ],
            ],
            [
                'label' => __( 'Default provider selected', 'mybookaro' ),
                'passed' => $single_business ? $default_provider_ok : true,
                'detail' => $single_business
                    ? (
                        $default_provider_ok
                            ? __( 'Default Provider is set. Single Business requires no listings, and booking can run without listing context.', 'mybookaro' )
                            : __( 'Single Business requires no listings, but Default Provider is required. Next action: open Setup Wizard > Listings, set Default Provider, save, then retry booking preview.', 'mybookaro' )
                    )
                    : __( 'Directory flow usually resolves providers from listing ownership.', 'mybookaro' ),
                'action' => [
                    'label' => $single_business ? __( 'Set Default Provider', 'mybookaro' ) : __( 'Open settings', 'mybookaro' ),
                    'url' => $single_business ? ( $wizard_url . '&step=listings' ) : $settings_url,
                ],
            ],
            [
                'label' => __( 'Step 2: Assign booking/dashboard pages', 'mybookaro' ),
                'passed' => $page_assignment_ok,
                'detail' => $page_assignment_detail,
                'action' => [
                    'label' => __( 'Open pages step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=pages',
                ],
            ],
            [
                'label' => __( 'Step 3: Place Booking Button/Services Cards blocks or shortcodes', 'mybookaro' ),
                'passed' => $block_shortcode_ready,
                'detail' => $block_shortcode_detail,
                'action' => [
                    'label' => $step_three_action_label,
                    'url' => $step_three_action_url,
                ],
            ],
            [
                'label' => __( 'Step 4: Run System Status validation', 'mybookaro' ),
                'passed' => $runtime_ok,
                'detail' => $runtime_detail,
                'action' => [
                    'label' => $validation_refresh_required
                        ? $this->get_generic_launch_readiness_notice_action_label()
                        : __( 'Open System Status validation', 'mybookaro' ),
                    'url' => $generic_validation_url,
                ],
            ],
            [
                'label' => __( 'Step 5: Test one booking', 'mybookaro' ),
                'passed' => $completed_bookings > 0,
                'detail' => $booking_flow_detail,
                'action' => [
                    'label' => $preview_action_label,
                    'url' => $open_listings_url,
                ],
            ],
        ];
        if ( $single_business ) {
            $single_business_fast_path_ready = $default_provider_ok && $page_assignment_ok && $single_business_services_ready;
            $single_business_fast_path_detail = ! $default_provider_ok
                ? __( 'Set Default Provider first. Then run the Single Business fast path to create demo pages/services, seed availability, and open a preview booking flow.', 'mybookaro' )
                : (
                    $single_business_fast_path_ready
                        ? __( 'Single Business fast path is ready. Run it once to create/update demo setup and open a preview booking flow without listing context.', 'mybookaro' )
                        : __( 'Use the Single Business fast path to create demo pages/services, seed provider availability, and open a preview booking flow without hunting through multiple screens.', 'mybookaro' )
                );
            $checks[] = [
                'label' => __( 'Single Business first-run fast path', 'mybookaro' ),
                'passed' => $single_business_fast_path_ready,
                'detail' => $single_business_fast_path_detail,
                'action' => [
                    'label' => ! $default_provider_ok ? __( 'Set Default Provider', 'mybookaro' ) : __( 'Run Single Business fast path', 'mybookaro' ),
                    'url' => ! $default_provider_ok ? ( $wizard_url . '&step=listings' ) : $single_business_fast_path_url,
                ],
            ];
        }
        if ( ! $single_business ) {
            $checks[] = [
                'label' => __( 'Bookable listing post types selected', 'mybookaro' ),
                'passed' => $check_listings,
                'detail' => sprintf(
                    /* translators: %s: listing post types */
                    __( 'Selected: %s.', 'mybookaro' ),
                    $type_label
                ),
                'action' => [
                    'label' => __( 'Open listings step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=listings',
                ],
            ];
        }
        if ( $generic_advanced_setup_enabled ) {
            $checks[] = [
                'label' => __( 'Provider resolution configured', 'mybookaro' ),
                'passed' => $provider_resolution_valid,
                'detail' => $provider_resolution_check_detail,
                'action' => [
                    'label' => $provider_resolution_action_label,
                    'url' => $wizard_url . '&step=listings',
                ],
            ];
            $checks[] = [
                'label' => __( 'Services source configured', 'mybookaro' ),
                'passed' => $services_model_valid,
                'detail' => $services_source_check_detail,
                'action' => [
                    'label' => $services_source_action_label,
                    'url' => $wizard_url . '&step=services',
                ],
            ];
        } elseif ( ! $single_business ) {
            $checks[] = [
                'label' => __( 'Guided-path defaults active', 'mybookaro' ),
                'passed' => $generic_preset_selected,
                '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' ),
                'action' => [
                    'label' => __( 'Open lane step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=modes',
                ],
            ];
        }
        $checks[] = [
            'label' => __( 'Reminder and review invite automations', 'mybookaro' ),
            'passed' => $notification_automations_ok,
            'detail' => $notification_automation_detail,
            'action' => [
                'label' => __( 'Open email settings', 'mybookaro' ),
                'url' => $notifications_url,
            ],
        ];
        $checks[] = [
            'label' => __( 'Email delivery test', 'mybookaro' ),
            'passed' => $email_tested,
            'detail' => $email_tested
                ? __( 'Test email sent successfully.', 'mybookaro' )
                : __( 'Send a test email to verify delivery.', 'mybookaro' ),
            'action' => [
                'label' => __( 'Send test email', 'mybookaro' ),
                'url' => '#bookaro-action-test-email',
            ],
        ];

        return $checks;
    }

    private function build_quick_start_steps( string $integration_mode, int $default_listing_id, array $generic_validation = [], array $generic_validation_prompt = [] ): array
    {
        $settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=general' );
        $shortcodes_settings_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=shortcodes#bookaro-settings-tabs' );
        $notifications_url = admin_url( 'admin.php?page=bookaro-booking-settings&tab=notifications' );
        $wizard_url = admin_url( 'admin.php?page=bookaro-setup-wizard' );
        $status_url = admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' );
        $support_snapshot_url = admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-snapshot' );
        $single_business_fast_path_url = $this->get_single_business_fast_path_url();
        $ui_mode = $this->resolve_ui_mode_for_onboarding( $integration_mode );
        $runtime_total = absint( $generic_validation['total'] ?? 0 );
        $runtime_failed = absint( $generic_validation['failed'] ?? 0 );
        $runtime_available = ! empty( $generic_validation['available'] );
        $validation_refresh_required = ! empty( $generic_validation_prompt['needs_validation'] );
        $opts = $this->options->get_all();
        $generic_confirmation_required = ! empty( $generic_validation_prompt['confirmation_required'] );
        $generic_legacy_fallback_active = ( 'generic' === $integration_mode ) && $this->is_generic_legacy_fallback_active( $opts );
        $generic_confirmation_ready = ! $generic_confirmation_required && ! $generic_legacy_fallback_active;
        $runtime_ok = ! $validation_refresh_required && $runtime_available && $runtime_total > 0 && $runtime_failed < 1;
        if ( $validation_refresh_required ) {
            $runtime_step_detail = $this->get_generic_launch_readiness_notice_message();
        } elseif ( ! $runtime_available || $runtime_total < 1 ) {
            $runtime_step_detail = __( 'Generic setup has not been checked yet. Run System Status validation so Bookaro can confirm lane routing, services source, booking entry placement, and required pages before launch.', 'mybookaro' );
        } elseif ( $runtime_failed > 0 ) {
            $runtime_step_detail = sprintf(
                /* translators: 1: failed checks, 2: total checks */
                __( '%1$d of %2$d Generic checks still need attention. Next action: open System Status and work through each warning or error before go-live.', 'mybookaro' ),
                $runtime_failed,
                $runtime_total
            );
        } else {
            $runtime_step_detail = sprintf(
                /* translators: %d: total checks */
                __( 'All %d Generic checks are passing. Re-run validation after mapping, services, or page changes.', 'mybookaro' ),
                $runtime_total
            );
        }

        $types = $this->get_listing_post_types();
        $site_type = $this->resolve_site_type_for_onboarding();
        $single_business = ( 'single_business' === $site_type );
        $support_handoff_detail = $single_business
            ? __( 'Before opening support requests, review the operational summary, confirm the Single Business no-listing path (Default Provider + booking/services/dashboard pages), then copy the masked support snapshot. Attach Support Bundle only when deeper diagnostics are needed.', 'mybookaro' )
            : __( 'Before opening support requests, review the operational summary, then copy the masked support snapshot. Attach Support Bundle only when deeper diagnostics are needed.', 'mybookaro' );
        $support_handoff_step = [
            'label' => __( 'Prepare support handoff tools', 'mybookaro' ),
            'passed' => true,
            'detail' => $support_handoff_detail,
            'action' => [
                'label' => __( 'Open masked snapshot', 'mybookaro' ),
                'url' => $support_snapshot_url,
            ],
        ];
        $check_listings = $single_business ? true : ! empty( $types );
        $type_label = $check_listings ? implode( ', ', $types ) : __( 'Not selected', 'mybookaro' );
        if ( $single_business && empty( $types ) ) {
            $type_label = __( 'Optional in Single Business lane', 'mybookaro' );
        }
        $generic_setup_preset = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'generic_setup_preset', '' ) )
            : '';
        $generic_preset_profile = GenericPresetProfiles::get( $generic_setup_preset );
        $generic_preset_selected = ! empty( $generic_preset_profile );
        $generic_preset_detail = $generic_preset_selected
            ? GenericPresetProfiles::build_selection_detail( $generic_setup_preset )
            : __( 'No Generic preset is selected yet. Bookaro cannot confirm which ownership path, Services Source, or placement path you intended. Next action: open Setup Wizard > Lane, choose Provider-Owned Directory, Editorial + Meta Key Directory, or Shared Catalog Directory, then save.', 'mybookaro' );
        if ( $single_business ) {
            $generic_preset_selected = true;
            $generic_preset_detail = __( 'Single Business uses its own provider-first launch path.', 'mybookaro' );
        }
        $generic_advanced_setup_enabled = function_exists( 'bookaro_get_option' )
            ? ! empty( bookaro_get_option( 'generic_advanced_setup_enabled', 0 ) )
            : false;
        if ( $single_business ) {
            $generic_advanced_setup_enabled = false;
        }

        $provider_resolution = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_resolution_mode', '' )
            : '';
        $provider_resolution = sanitize_key( $provider_resolution );
        if ( '' === $provider_resolution ) {
            $provider_resolution = ( $integration_mode === 'mylisting' ) ? 'author' : '';
        }
        $provider_meta_key = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_meta_key', '' )
            : '';
        $provider_meta_key = sanitize_key( $provider_meta_key );
        $provider_detail = $provider_resolution === 'meta_key' && $provider_meta_key !== ''
            ? sprintf(
                /* translators: %s: provider meta key */
                __( 'Provider Mapping is set to Listing Meta Key using the `%s` field. Bookaro will read that listing field to decide which provider receives bookings.', 'mybookaro' ),
                $provider_meta_key
            )
            : __( 'Provider Mapping is set to Listing Author. Bookaro will use each listing author as the provider who receives bookings.', 'mybookaro' );
        $provider_resolution_valid = in_array( $provider_resolution, [ 'author', 'meta_key' ], true )
            && ( 'meta_key' !== $provider_resolution || '' !== $provider_meta_key );

        $primary_type = $types[0] ?? '';
        if ( '' === $primary_type && function_exists( 'bookaro_get_option' ) ) {
            $primary_type = (string) bookaro_get_option( 'listing_post_type', '' );
        }
        $primary_type = sanitize_key( $primary_type );
        if ( '' === $primary_type ) {
            if ( $single_business && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
                $primary_type = sanitize_key( (string) BOOKARO_PROVIDER_POST_TYPE );
            } else {
                $primary_type = 'job_listing';
            }
        }

        $booking_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'booking' ) )
            : 0;
        $provider_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'provider_dashboard' ) )
            : 0;
        $customer_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'customer_dashboard' ) )
            : 0;
        $single_business_missing_booking_page = $single_business && $booking_page_id < 1;

        $missing_pages = [];
        $missing_page_keys = [];
        if ( $booking_page_id < 1 ) {
            $missing_pages[] = __( 'Booking page', 'mybookaro' );
            $missing_page_keys[] = 'booking';
        }
        if ( 'shortcodes' === $ui_mode ) {
            if ( $provider_page_id < 1 ) {
                $missing_pages[] = __( 'Provider dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'provider_dashboard';
            }
            if ( $customer_page_id < 1 ) {
                $missing_pages[] = __( 'Customer dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'customer_dashboard';
            }
        }

        $page_assignment_ok = empty( $missing_pages );
        if ( $page_assignment_ok ) {
            $page_assignment_detail = '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' );
        } else {
            $page_assignment_detail = sprintf(
                /* translators: %s: comma separated missing pages */
                __( 'Missing: %s.', 'mybookaro' ),
                implode( ', ', $missing_pages )
            );
            $page_assignment_detail .= ' ' . __( 'Open Setup Wizard > Pages and assign the missing pages. In Shortcodes mode, dashboard pages must also contain the matching MyBookaro dashboard block or shortcode.', 'mybookaro' );
            if ( $single_business_missing_booking_page ) {
                $page_assignment_detail .= ' ' . __( 'Single Business listings are optional, but Booking page is required before customers can start bookings. Next action: assign Booking page first in Setup Wizard > Pages.', 'mybookaro' );
            } elseif ( $single_business ) {
                $page_assignment_detail .= ' ' . __( 'Single Business listings are optional; complete Setup Wizard > Pages to unblock launch.', 'mybookaro' );
            }
        }

        $booking_page = function_exists( 'bookaro_get_booking_page_url' )
            ? bookaro_get_booking_page_url( [ 'listing_id' => $default_listing_id ] )
            : '';
        $auto_insert_mode = function_exists( 'bookaro_get_auto_insert_booking_button_mode' )
            ? bookaro_get_auto_insert_booking_button_mode()
            : '';
        $auto_insert_mode = sanitize_key( (string) $auto_insert_mode );
        $auto_insert_enabled = $auto_insert_mode !== '';
        $has_booking_page = $booking_page !== '' || ( 'generic' === $integration_mode && $auto_insert_enabled );
        $auto_insert_detail = '';
        if ( 'generic' === $integration_mode && $auto_insert_enabled ) {
            if ( 'selector' === $auto_insert_mode && function_exists( 'bookaro_get_auto_insert_booking_button_selector' ) ) {
                $selector = bookaro_get_auto_insert_booking_button_selector();
                if ( $selector !== '' ) {
                    /* translators: %s: dynamic string */
                    $auto_insert_detail = sprintf( __( 'Auto-insert enabled (selector: %s)', 'mybookaro' ), $selector );
                } else {
                    $auto_insert_detail = __( 'Auto-insert enabled (CSS selector)', 'mybookaro' );
                }
            } else {
                $label = $auto_insert_mode === 'before_content'
                    ? __( 'before content', 'mybookaro' )
                    : __( 'after content', 'mybookaro' );
                /* translators: %s: dynamic string */
                $auto_insert_detail = sprintf( __( 'Auto-insert enabled (%s).', 'mybookaro' ), $label );
            }
        }
        $missing_blocks_detail = ( 'generic' === $integration_mode )
            ? __( 'Assign a booking page in Setup Wizard > Pages, then add the MyBookaro Booking Button or Services Cards block (search "MyBookaro" in the block inserter).', 'mybookaro' )
            : __( 'Verify the MyBookaro booking button appears in the MyListing sidebar actions area.', 'mybookaro' );
        $found_blocks_detail = $auto_insert_detail !== ''
            ? $auto_insert_detail
            : __( 'Booking page detected. Preview a listing to confirm.', 'mybookaro' );
        $block_shortcode_ready = ( 'shortcodes' === $ui_mode ) && ( '' !== $booking_page );
        if ( 'shortcodes' !== $ui_mode ) {
            $block_shortcode_detail = __( 'Step 3 for Generic: open Setup Wizard > Services, switch UI Mode to Shortcodes, save, then place Booking Button/Services Cards blocks or shortcodes. Auto-Insert can remain as a fallback.', 'mybookaro' );
        } elseif ( '' !== $booking_page ) {
            $block_shortcode_detail = __( 'Shortcodes mode is active with a Booking page. Next step: place Booking Button/Services Cards, then update the template or page where bookings start.', 'mybookaro' );
        } elseif ( $auto_insert_enabled ) {
            $block_shortcode_detail = __( 'Step 3 for Generic: place Booking Button/Services Cards blocks or shortcodes for explicit placement. Auto-Insert can remain enabled as a fallback.', 'mybookaro' );
        } else {
            $block_shortcode_detail = $single_business
                ? __( 'No booking page detected yet. Single Business listings are optional, but you must assign a booking page first in Setup Wizard > Pages.', 'mybookaro' )
                : $missing_blocks_detail;
        }

        $step_three_action_url = ( '' === $booking_page )
            ? ( $wizard_url . '&step=pages' )
            : $shortcodes_settings_url;
        $step_three_action_label = ( '' === $booking_page )
            ? __( 'Assign pages first', 'mybookaro' )
            : __( 'Open embed tab', 'mybookaro' );
        $single_business_pages_action_label = __( 'Open pages step', 'mybookaro' );
        if ( $single_business && ! $page_assignment_ok ) {
            $missing_booking_page = in_array( 'booking', $missing_page_keys, true );
            $missing_dashboard_pages = in_array( 'provider_dashboard', $missing_page_keys, true ) || in_array( 'customer_dashboard', $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' );
            }
        }

        $completed_bookings = $this->count_test_bookings();
        $booking_flow_ok = $completed_bookings > 0;
        $booking_flow_detail = $booking_flow_ok
            ? sprintf(
                /* translators: %d: completed bookings */
                __( 'Completed bookings: %d.', 'mybookaro' ),
                $completed_bookings
            )
            : (
                $single_business
                    ? __( 'No completed booking yet. Run one end-to-end test booking from your booking/services page.', 'mybookaro' )
                    : __( 'No completed booking yet. Run one end-to-end test booking.', 'mybookaro' )
            );
        $preview_action_label = $single_business
            ? __( 'Open booking preview', 'mybookaro' )
            : __( 'Open listing preview', 'mybookaro' );
        $notify_reminder = function_exists( 'bookaro_get_option' ) ? ! empty( bookaro_get_option( 'notify_reminder', 0 ) ) : false;
        $notify_review_invite = function_exists( 'bookaro_get_option' ) ? ! empty( bookaro_get_option( 'notify_review_invite', 0 ) ) : false;
        $notification_automations_ok = $notify_reminder || $notify_review_invite;
        $notification_automation_detail = sprintf(
            /* translators: 1: reminder emails flag, 2: review invite emails flag */
            __( '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_automation_detail .= ' ' . __( 'Enable one or both in Settings > Email.', 'mybookaro' );
        }

        if ( 'mylisting' === $integration_mode ) {
            $sidebar_hook_ok = function_exists( 'has_action' )
                ? (bool) has_action( 'mylisting/single/sidebar/actions', 'bookaro_render_mylisting_booking_button' )
                : false;
            $repeater_class = function_exists( 'bookaro_get_option' )
                ? sanitize_key( (string) bookaro_get_option( 'mylisting_services_repeater_class', 'mybookaro_services' ) )
                : 'mybookaro_services';
            if ( '' === $repeater_class ) {
                $repeater_class = 'mybookaro_services';
            }

            return [
                [
                    'label' => __( 'Confirm listing ownership mapping', 'mybookaro' ),
                    'passed' => $provider_resolution_valid,
                    'detail' => $provider_detail,
                    'action' => [
                        'label' => __( 'Open settings', 'mybookaro' ),
                        'url' => $settings_url,
                    ],
                ],
                [
                    'label' => __( 'Verify sidebar booking button', 'mybookaro' ),
                    'passed' => $sidebar_hook_ok,
                    'detail' => $sidebar_hook_ok
                        ? __( 'Sidebar booking button hook is active.', 'mybookaro' )
                        : __( 'Booking button hook is not active yet.', 'mybookaro' ),
                    'action' => [
                        'label' => __( 'Open system status', 'mybookaro' ),
                        'url' => admin_url( 'admin.php?page=bookaro-system-status' ),
                    ],
                ],
                [
                    'label' => __( 'Set provider services repeater class', 'mybookaro' ),
                    'passed' => '' !== $repeater_class,
                    'detail' => sprintf(
                        /* translators: %s: repeater class */
                        __( 'Current class: %s', 'mybookaro' ),
                        $repeater_class
                    ),
                    'action' => [
                        'label' => __( 'Open settings', 'mybookaro' ),
                        'url' => $settings_url,
                    ],
                ],
                [
                    'label' => __( 'Enable reminders or review invites', 'mybookaro' ),
                    'passed' => $notification_automations_ok,
                    'detail' => $notification_automation_detail,
                    'action' => [
                        'label' => __( 'Open email settings', 'mybookaro' ),
                        'url' => $notifications_url,
                    ],
                ],
                [
                    'label' => __( 'Run booking flow test', 'mybookaro' ),
                    'passed' => $booking_flow_ok,
                    'detail' => $booking_flow_detail,
                    'action' => [
                        'label' => $preview_action_label,
                        'url' => '#bookaro-action-open-listing',
                    ],
                ],
                $support_handoff_step,
            ];
        }

        $service_type = defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service';
        $create_service_url = admin_url( 'post-new.php?post_type=' . $service_type );
        $default_provider_id = $single_business
            ? $this->get_single_business_default_provider_id()
            : (
                function_exists( 'bookaro_get_option' )
                    ? absint( bookaro_get_option( 'default_provider_id', 0 ) )
                    : 0
            );
        $default_provider_ok = $default_provider_id > 0;
        $single_business_services_count = $single_business
            ? $this->count_single_business_available_services( $default_provider_id )
            : 0;
        $single_business_services_ready = $single_business && $default_provider_ok && $single_business_services_count > 0;
        $single_business_services_detail = ! $single_business
            ? ''
            : (
                ! $default_provider_ok
                    ? __( 'Cannot validate services until Default Provider is set. Next action: open Setup Wizard > Listings and set Default Provider.', 'mybookaro' )
                    : (
                        $single_business_services_ready
                            ? sprintf(
                                /* translators: %d: available services count */
                                __( 'Available services for the Default Provider: %d. Provider-first booking can render service choices.', 'mybookaro' ),
                                $single_business_services_count
                            )
                            : __( 'Booking UI cannot render service choices because no services are available for the Default Provider. Next action: create at least one service for that provider.', 'mybookaro' )
                    )
            );
        $step_one_label = $single_business
            ? __( 'Step 1: Confirm Single Business lane defaults', 'mybookaro' )
            : __( 'Step 1: Confirm lane, guided preset, and placement path', 'mybookaro' );
        $step_one_passed = $single_business
            ? true
            : ( $generic_preset_selected && $generic_confirmation_ready );
        $step_one_detail = $single_business
            ? __( 'Single Business is a first-class provider-first lane. No listings are required.', 'mybookaro' )
            : (
                ! $generic_confirmation_ready
                    ? (
                        $generic_confirmation_required
                            ? __( 'Generic lane is not explicitly confirmed yet. Open Setup Wizard > Lane, select Generic Directory, and save before launch validation.', 'mybookaro' )
                            : __( 'Generic Directory is running from legacy automatic settings. Next step: Open Setup Wizard > Lane and save once to record explicit confirmation metadata.', 'mybookaro' )
                    )
                    : $generic_preset_detail
            );
        $step_one_action_label = $single_business
            ? __( 'Open settings', 'mybookaro' )
            : (
                ! $generic_confirmation_ready
                    ? __( 'Confirm lane in Setup Wizard', 'mybookaro' )
                    : __( 'Open lane step', 'mybookaro' )
            );
        $step_one_action_url = $single_business ? $settings_url : ( $wizard_url . '&step=modes' );

        if ( $single_business ) {
            $single_business_preview_url = $this->get_single_business_preview_url();
            $single_business_preview_ready = $default_provider_ok
                && $page_assignment_ok
                && $single_business_services_ready
                && '' !== trim( $single_business_preview_url );
            $single_business_preview_detail = ! $default_provider_ok
                ? __( 'Step 1 is still blocked. Set Default Provider first, then continue with pages and service inventory before preview.', 'mybookaro' )
                : (
                    ! $page_assignment_ok
                        ? __( 'Step 2 is still blocked. Assign required pages before opening booking preview.', 'mybookaro' )
                        : (
                            ! $single_business_services_ready
                                ? __( 'Step 3 is still blocked. Create the first service for the Default Provider before preview.', 'mybookaro' )
                                : (
                                    '' === trim( $single_business_preview_url )
                                        ? __( 'Booking/services preview URL is not available yet. Re-check page assignment, then open the booking page.', 'mybookaro' )
                                        : __( 'Open booking preview and complete one end-to-end booking test.', 'mybookaro' )
                                )
                        )
                );
            $single_business_preview_action_label = ! $default_provider_ok
                ? __( 'Set Default Provider', 'mybookaro' )
                : (
                    ! $page_assignment_ok
                        ? $single_business_pages_action_label
                        : (
                            ! $single_business_services_ready
                                ? __( 'Create first service', 'mybookaro' )
                                : __( 'Open booking preview', 'mybookaro' )
                        )
                );
            $single_business_preview_action_url = ! $default_provider_ok
                ? ( $wizard_url . '&step=listings' )
                : (
                    ! $page_assignment_ok
                        ? ( $wizard_url . '&step=pages' )
                        : (
                            ! $single_business_services_ready
                                ? $create_service_url
                                : ( '' !== trim( $single_business_preview_url ) ? $single_business_preview_url : ( $wizard_url . '&step=pages' ) )
                        )
                );
            $single_business_fast_path_ready = $default_provider_ok && $page_assignment_ok && $single_business_services_ready;
            $single_business_fast_path_detail = ! $default_provider_ok
                ? __( 'Set Default Provider first. Then run the Single Business fast path to create demo pages/services, seed availability, and open a preview booking flow.', 'mybookaro' )
                : (
                    $single_business_fast_path_ready
                        ? __( 'Single Business fast path is ready. Run it once to create/update demo setup and open a preview booking flow without listing context.', 'mybookaro' )
                        : __( 'Use the Single Business fast path to create demo pages/services, seed provider availability, and open a preview booking flow without hunting through multiple screens.', 'mybookaro' )
                );

            return [
                [
                    'label' => __( 'Default provider selected', 'mybookaro' ),
                    'passed' => $default_provider_ok,
                    'detail' => $default_provider_ok
                        ? __( 'Default Provider is set. Single Business requires no listings, and booking can run without listing context.', 'mybookaro' )
                        : __( 'Single Business requires no listings, but Default Provider is required. Next action: open Setup Wizard > Listings, set Default Provider, save, then retry booking preview.', 'mybookaro' ),
                    'action' => [
                        'label' => __( 'Set Default Provider', 'mybookaro' ),
                        'url' => $wizard_url . '&step=listings',
                    ],
                ],
                [
                    'label' => __( 'Step 2: Assign booking/dashboard pages', 'mybookaro' ),
                    'passed' => $page_assignment_ok,
                    'detail' => $page_assignment_detail,
                    'action' => [
                        'label' => $single_business_pages_action_label,
                        'url' => $wizard_url . '&step=pages',
                    ],
                ],
                [
                    'label' => __( 'Services available for Default Provider', 'mybookaro' ),
                    'passed' => $single_business_services_ready,
                    'detail' => $single_business_services_detail,
                    'action' => [
                        'label' => ! $default_provider_ok
                            ? __( 'Set Default Provider', 'mybookaro' )
                            : ( ! $single_business_services_ready ? __( 'Create first service', 'mybookaro' ) : __( 'Open services step', 'mybookaro' ) ),
                        'url' => ! $default_provider_ok
                            ? ( $wizard_url . '&step=listings' )
                            : ( ! $single_business_services_ready ? $create_service_url : ( $wizard_url . '&step=services' ) ),
                    ],
                ],
                [
                    'label' => __( 'Step 4: Preview booking flow', 'mybookaro' ),
                    'passed' => $single_business_preview_ready || $booking_flow_ok,
                    'detail' => $booking_flow_ok
                        ? $booking_flow_detail
                        : $single_business_preview_detail,
                    'action' => [
                        'label' => $single_business_preview_action_label,
                        'url' => $single_business_preview_action_url,
                    ],
                ],
                [
                    'label' => __( 'Single Business first-run fast path', 'mybookaro' ),
                    'passed' => $single_business_fast_path_ready,
                    'detail' => $single_business_fast_path_detail,
                    'action' => [
                        'label' => ! $default_provider_ok ? __( 'Set Default Provider', 'mybookaro' ) : __( 'Run Single Business fast path', 'mybookaro' ),
                        'url' => ! $default_provider_ok ? ( $wizard_url . '&step=listings' ) : $single_business_fast_path_url,
                    ],
                ],
                $support_handoff_step,
            ];
        }

        $steps = [
            [
                'label' => $step_one_label,
                'passed' => $step_one_passed,
                'detail' => $step_one_detail,
                'action' => [
                    'label' => $step_one_action_label,
                    'url' => $step_one_action_url,
                ],
            ],
            [
                'label' => __( 'Default provider selected', 'mybookaro' ),
                'passed' => $single_business ? $default_provider_ok : true,
                'detail' => $single_business
                    ? (
                        $default_provider_ok
                            ? __( 'Default Provider is set. Single Business requires no listings, and booking can run without listing context.', 'mybookaro' )
                            : __( 'Single Business requires no listings, but Default Provider is required. Next action: open Setup Wizard > Listings, set Default Provider, save, then retry booking preview.', 'mybookaro' )
                    )
                    : __( 'Directory flow usually resolves providers from listing ownership.', 'mybookaro' ),
                'action' => [
                    'label' => $single_business ? __( 'Set Default Provider', 'mybookaro' ) : __( 'Open settings', 'mybookaro' ),
                    'url' => $single_business ? ( $wizard_url . '&step=listings' ) : $settings_url,
                ],
            ],
        ];
        $steps[] = [
            'label' => __( 'Step 2: Assign booking/dashboard pages', 'mybookaro' ),
            'passed' => $page_assignment_ok,
            'detail' => $page_assignment_detail,
            'action' => [
                'label' => __( 'Open pages step', 'mybookaro' ),
                'url' => $wizard_url . '&step=pages',
            ],
        ];
        $steps[] = [
            'label' => __( 'Step 3: Place Booking Button/Services Cards blocks or shortcodes', 'mybookaro' ),
            'passed' => $block_shortcode_ready,
            'detail' => $block_shortcode_detail,
            'action' => [
                'label' => $step_three_action_label,
                'url' => $step_three_action_url,
            ],
        ];
        $steps[] = [
            'label' => __( 'Step 4: Run System Status validation', 'mybookaro' ),
            'passed' => $runtime_ok,
            'detail' => $runtime_step_detail,
            'action' => [
                'label' => $validation_refresh_required
                    ? $this->get_generic_launch_readiness_notice_action_label()
                    : __( 'Open System Status validation', 'mybookaro' ),
                'url' => $status_url,
            ],
        ];
        $steps[] = [
            'label' => __( 'Step 5: Test one booking', 'mybookaro' ),
            'passed' => $booking_flow_ok,
            'detail' => $booking_flow_detail . ' ' . __( 'After this test, re-open Generic validation in System Status.', 'mybookaro' ),
            'action' => [
                'label' => $preview_action_label,
                'url' => '#bookaro-action-open-listing',
            ],
        ];
        if ( ! $single_business ) {
            $steps[] = [
                'label' => __( 'Select bookable listing post types', 'mybookaro' ),
                'passed' => $check_listings,
                'detail' => sprintf(
                    /* translators: %s: listing post types */
                    __( 'Selected: %s', 'mybookaro' ),
                    $type_label
                ),
                'action' => [
                    'label' => __( 'Open listings step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=listings',
                ],
            ];
        }
        if ( $generic_advanced_setup_enabled ) {
            $steps[] = [
                'label' => __( 'Choose provider routing path (Listing Author vs Listing Meta Key)', 'mybookaro' ),
                'passed' => $provider_resolution_valid,
                'detail' => $provider_detail,
                'action' => [
                    'label' => __( 'Open listings step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=listings',
                ],
            ];
            $steps[] = [
                'label' => __( 'Set services source and booking entry rules', 'mybookaro' ),
                'passed' => $has_booking_page,
                'detail' => $has_booking_page ? $found_blocks_detail : $missing_blocks_detail,
                'action' => [
                    'label' => __( 'Open services step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=services',
                ],
            ];
        } elseif ( ! $single_business ) {
            $steps[] = [
                'label' => __( 'Keep guided-path defaults active', 'mybookaro' ),
                'passed' => $generic_preset_selected,
                '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' ),
                'action' => [
                    'label' => __( 'Open lane step', 'mybookaro' ),
                    'url' => $wizard_url . '&step=modes',
                ],
            ];
        }
        $steps[] = [
            'label' => __( 'Enable reminders or review invites', 'mybookaro' ),
            'passed' => $notification_automations_ok,
            'detail' => $notification_automation_detail,
            'action' => [
                'label' => __( 'Open email settings', 'mybookaro' ),
                'url' => $notifications_url,
            ],
        ];
        $steps[] = $support_handoff_step;

        return $steps;
    }

    private function build_mylisting_activation_flow( string $integration_mode, int $listing_id ): array
    {
        $summary = [
            'active' => false,
            'milestones' => [],
            'completed' => 0,
            'total' => 0,
            'next_action' => [
                'label' => '',
                'url' => '',
                'detail' => '',
            ],
        ];

        if ( 'mylisting' !== sanitize_key( $integration_mode ) ) {
            return $summary;
        }

        $summary['active'] = true;

        $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();
        $open_listing_action = $this->build_mylisting_open_listing_action( $listing_id );
        $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 = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'provider_resolution_mode', '' ) )
            : '';
        $provider_meta_key = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'provider_meta_key', '' ) )
            : '';
        if ( '' === $provider_meta_key && function_exists( 'bookaro_get_option' ) ) {
            $provider_meta_key = sanitize_key( (string) bookaro_get_option( 'listing_provider_meta_key', '' ) );
        }
        if ( ! in_array( $provider_resolution, [ 'author', 'meta_key' ], true ) ) {
            $provider_resolution = ( '' !== $provider_meta_key ) ? 'meta_key' : 'author';
        }
        $provider_mapping_valid = in_array( $provider_resolution, [ 'author', 'meta_key' ], true )
            && ( 'meta_key' !== $provider_resolution || '' !== $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 = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'mylisting_services_repeater_class', 'mybookaro_services' ) )
            : 'mybookaro_services';
        if ( '' === $repeater_class ) {
            $repeater_class = 'mybookaro_services';
        }
        $services_count = $listing_id > 0
            ? $this->count_listing_services( $listing_id, 'mylisting' )
            : 0;
        $services_ready = $listing_id > 0 && $services_count > 0 && '' !== $repeater_class;
        if ( $services_ready ) {
            $services_detail = sprintf(
                /* translators: 1: services count, 2: repeater css class */
                __( '%1$d service(s) detected. Repeater row class: %2$s.', 'mybookaro' ),
                $services_count,
                $repeater_class
            );
        } elseif ( $listing_id < 1 ) {
            $services_detail = __( 'Choose a listing first so Bookaro can read services from the MyListing repeater class.', 'mybookaro' );
        } else {
            $services_detail = sprintf(
                /* translators: %s: repeater css class */
                __( 'No services detected yet. Add service rows using repeater class %s, or run demo setup.', 'mybookaro' ),
                $repeater_class
            );
        }
        $services_action = $listing_id > 0
            ? $fast_path_action
            : $create_listing_action;

        $timeslot_count = $listing_id > 0
            ? $this->count_listing_timeslots( $listing_id )
            : 0;
        $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_test_bookings();
        $booking_ready = $completed_bookings > 0;
        $booking_detail = $booking_ready
            ? sprintf(
                /* translators: %d: completed bookings */
                __( '%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;
        $summary['total'] = count( $milestones );
        foreach ( $milestones as $milestone ) {
            if ( ! empty( $milestone['passed'] ) ) {
                $summary['completed']++;
            }
        }

        $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'] ) ) {
                $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;
            }
        }
        $next_action['label'] = trim( (string) ( $next_action['label'] ?? '' ) );
        $next_action['url'] = trim( (string) ( $next_action['url'] ?? '' ) );
        $next_action['detail'] = trim( (string) ( $next_action['detail'] ?? '' ) );
        $summary['next_action'] = $next_action;

        return $summary;
    }

    private function build_generic_readiness_summary(
        string $integration_mode,
        array $opts,
        array $quick_steps = [],
        array $generic_validation = [],
        array $generic_validation_prompt = []
    ): array {
        $summary = [
            'active' => false,
            'state' => 'info',
            'state_label' => __( 'Info', 'mybookaro' ),
            'current_pattern' => '',
            'validation_state' => __( 'Not required', 'mybookaro' ),
            'validation_state_level' => 'info',
            'validation_detail' => '',
            'last_validation_timestamp' => 0,
            'last_validation_run' => __( 'Never', 'mybookaro' ),
            'top_next_action' => [
                'label' => '',
                'url' => '',
                'detail' => '',
            ],
        ];

        if ( 'generic' !== sanitize_key( $integration_mode ) ) {
            return $summary;
        }

        $summary['active'] = true;
        $summary['current_pattern'] = $this->get_generic_pattern_label( $opts );
        $generic_setup_preset = sanitize_key( (string) ( $opts['generic_setup_preset'] ?? '' ) );
        $preset_launch_detail = GenericPresetProfiles::build_launch_readiness_detail( $generic_setup_preset );

        $confirmation_required = $this->generic_confirmation_required( $opts );
        $legacy_fallback_active = $this->is_generic_legacy_fallback_active( $opts );
        $needs_validation_refresh = ! empty( $generic_validation_prompt['needs_validation'] );
        $runtime_total = absint( $generic_validation['total'] ?? 0 );
        $runtime_failed = absint( $generic_validation['failed'] ?? 0 );
        $reviewed_at = absint( $generic_validation_prompt['reviewed_at'] ?? 0 );
        $status_url = admin_url( 'admin.php?page=bookaro-system-status#bookaro-support-check-generic_validation_provider_resolution_sample' );

        $summary['last_validation_timestamp'] = $reviewed_at;
        $summary['last_validation_run'] = $this->format_last_run( $reviewed_at );

        $validation_level = 'ok';
        $validation_state = __( 'Passing', 'mybookaro' );
        $validation_detail = __( 'Generic validation is current. Bookaro can resolve lane routing, services source, booking entry placement, and required pages for the current setup.', 'mybookaro' );

        if ( $confirmation_required ) {
            $validation_level = 'error';
            $validation_state = __( 'Confirmation required', 'mybookaro' );
            $validation_detail = __( 'Generic Directory is not confirmed yet. Until you save the Lane step, Bookaro cannot treat this as the intended Generic path. Next action: open Setup Wizard > Lane, select Generic Directory, save, then run System Status validation.', 'mybookaro' );
        } elseif ( $legacy_fallback_active ) {
            $validation_level = 'warn';
            $validation_state = __( 'Review confirmation', 'mybookaro' );
            $validation_detail = __( 'Generic Directory is running from older automatic settings. Save the Lane step once so Bookaro records the intended Generic path, then review the Generic validation checks.', 'mybookaro' );
        } elseif ( $needs_validation_refresh ) {
            $validation_level = 'warn';
            $validation_state = __( 'Re-run required', 'mybookaro' );
            $validation_detail = __( 'Settings changed after the last validation run. Until you re-run System Status, Bookaro cannot confirm that lane routing, services source, placement, and pages still match. Next action: open System Status, work through each Suggested fix, then refresh Getting Started.', 'mybookaro' );
        } elseif ( $runtime_total < 1 ) {
            $validation_level = 'warn';
            $validation_state = __( 'Not run yet', 'mybookaro' );
            $validation_detail = __( 'Generic validation has not run yet. Bookaro still needs to confirm lane routing, services source, booking entry placement, and required pages before launch. Next action: open System Status and run the Generic validation checks.', 'mybookaro' );
        } elseif ( $runtime_failed > 0 ) {
            $validation_level = 'error';
            $validation_state = __( 'Blocked', 'mybookaro' );
            $validation_detail = sprintf(
                /* translators: 1: failed checks, 2: total checks */
                __( '%1$d of %2$d Generic checks still need attention. That means at least one lane routing, services source, booking entry, or page requirement can still block bookings.', 'mybookaro' ),
                $runtime_failed,
                $runtime_total
            );
            $validation_detail .= ' ' . __( 'Next action: open System Status, resolve every warning or error, then refresh Getting Started.', 'mybookaro' );
        } else {
            $validation_detail = sprintf(
                /* translators: %d: number of passing checks */
                __( 'All %d Generic checks are passing. Bookaro can resolve providers, services, booking entry placement, and required pages for the current setup.', 'mybookaro' ),
                $runtime_total
            );
        }

        $summary['validation_state'] = $validation_state;
        $summary['validation_state_level'] = $validation_level;
        if ( '' !== trim( $preset_launch_detail ) ) {
            $validation_detail .= ' ' . $preset_launch_detail;
        }
        $summary['validation_detail'] = $validation_detail;

        $core_steps = array_slice( $quick_steps, 0, 5 );
        $core_steps_complete = count( $core_steps ) >= 5;
        foreach ( $core_steps as $step ) {
            if ( ! is_array( $step ) || empty( $step['passed'] ) ) {
                $core_steps_complete = false;
                break;
            }
        }

        $state = 'ok';
        $state_label = __( 'Ready', 'mybookaro' );
        if ( $confirmation_required || $runtime_failed > 0 ) {
            $state = 'error';
            $state_label = __( 'Blocked', 'mybookaro' );
        } elseif ( $legacy_fallback_active || $needs_validation_refresh || $runtime_total < 1 || ! $core_steps_complete ) {
            $state = 'warn';
            $state_label = __( 'Review needed', 'mybookaro' );
        }

        $summary['state'] = $state;
        $summary['state_label'] = $state_label;

        $top_action = [
            'label' => __( 'Open Generic validation checks', 'mybookaro' ),
            'url' => $status_url,
            'detail' => __( 'Use System Status after mapping, services, or page changes so Bookaro can confirm the current Generic setup.', 'mybookaro' ),
        ];

        if ( $confirmation_required ) {
            $top_action = [
                'label' => __( 'Confirm Generic in Setup Wizard', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=modes' ),
                'detail' => __( 'Confirm the Generic path first, then continue with validation.', 'mybookaro' ),
            ];
        } elseif ( $legacy_fallback_active ) {
            $top_action = [
                'label' => __( 'Review and save Generic confirmation', 'mybookaro' ),
                'url' => admin_url( 'admin.php?page=bookaro-setup-wizard&step=modes' ),
                'detail' => __( 'Save the Lane step once to record explicit confirmation metadata.', 'mybookaro' ),
            ];
        } elseif ( $needs_validation_refresh || $runtime_total < 1 || $runtime_failed > 0 ) {
            $top_action = [
                'label' => __( 'Run System Status validation', 'mybookaro' ),
                'url' => $status_url,
                'detail' => __( 'Resolve every warning or error before launch.', 'mybookaro' ),
            ];
        } else {
            $first_incomplete_step = null;
            foreach ( $core_steps as $step ) {
                if ( is_array( $step ) && empty( $step['passed'] ) ) {
                    $first_incomplete_step = $step;
                    break;
                }
            }
            if ( null === $first_incomplete_step ) {
                foreach ( $quick_steps as $step ) {
                    if ( is_array( $step ) && empty( $step['passed'] ) ) {
                        $first_incomplete_step = $step;
                        break;
                    }
                }
            }
            if ( is_array( $first_incomplete_step ) ) {
                $top_action = [
                    'label' => (string) ( $first_incomplete_step['action']['label'] ?? __( 'Open next setup step', 'mybookaro' ) ),
                    'url' => (string) ( $first_incomplete_step['action']['url'] ?? '' ),
                    'detail' => sprintf(
                        /* translators: %s: next incomplete checklist step label */
                        __( 'Focus next on: %s', 'mybookaro' ),
                        (string) ( $first_incomplete_step['label'] ?? __( 'Generic launch checklist step', 'mybookaro' ) )
                    ),
                ];
            } elseif ( 'ok' === $state ) {
                $top_action = [
                    'label' => __( 'Re-run validation after config changes', 'mybookaro' ),
                    'url' => $status_url,
                    'detail' => __( 'Generic launch checklist is clear. Re-run validation whenever mapping or pages change.', 'mybookaro' ),
                ];
            }
        }

        $top_action['label'] = trim( (string) ( $top_action['label'] ?? '' ) );
        $top_action['url'] = trim( (string) ( $top_action['url'] ?? '' ) );
        $top_action['detail'] = trim( (string) ( $top_action['detail'] ?? '' ) );
        $summary['top_next_action'] = $top_action;

        return $summary;
    }

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

    private function build_operational_summary_items( 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 [
            [
                'label' => __( 'Booking approval workflow', 'mybookaro' ),
                'default' => $this->format_operational_workflow( ! empty( $defaults['auto_approve_bookings'] ) ),
                'active' => $this->format_operational_workflow( ! empty( $active['auto_approve_bookings'] ) ),
            ],
            [
                'label' => __( 'Anti-spam request protection', 'mybookaro' ),
                'default' => $this->format_operational_anti_spam(
                    ! empty( $defaults['booking_spam_honeypot_enabled'] ),
                    absint( $defaults['booking_spam_min_fill_seconds'] ),
                    absint( $defaults['booking_spam_burst_window_seconds'] ),
                    absint( $defaults['booking_spam_burst_ip_limit'] ),
                    absint( $defaults['booking_spam_burst_email_limit'] )
                ),
                'active' => $this->format_operational_anti_spam(
                    ! empty( $active['booking_spam_honeypot_enabled'] ),
                    absint( $active['booking_spam_min_fill_seconds'] ),
                    absint( $active['booking_spam_burst_window_seconds'] ),
                    absint( $active['booking_spam_burst_ip_limit'] ),
                    absint( $active['booking_spam_burst_email_limit'] )
                ),
            ],
            [
                'label' => __( 'Duplicate pending request blocking', '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'] ) ),
            ],
            [
                'label' => __( 'Booking buffers', 'mybookaro' ),
                'default' => $this->format_operational_buffer_pair(
                    absint( $defaults['booking_buffer_before_minutes'] ),
                    absint( $defaults['booking_buffer_after_minutes'] )
                ),
                'active' => $this->format_operational_buffer_pair(
                    absint( $active['booking_buffer_before_minutes'] ),
                    absint( $active['booking_buffer_after_minutes'] )
                ),
            ],
            [
                'label' => __( 'Cancel and reschedule windows', 'mybookaro' ),
                'default' => $this->format_operational_window_pair(
                    absint( $defaults['booking_cancel_window_hours'] ),
                    absint( $defaults['booking_reschedule_window_hours'] )
                ),
                'active' => $this->format_operational_window_pair(
                    absint( $active['booking_cancel_window_hours'] ),
                    absint( $active['booking_reschedule_window_hours'] )
                ),
            ],
            [
                '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_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 )
        );
    }

    private function format_operational_anti_spam(
        bool $honeypot_enabled,
        int $min_fill_seconds,
        int $burst_window_seconds,
        int $burst_ip_limit,
        int $burst_email_limit
    ): string {
        return sprintf(
            /* translators: 1: honeypot on/off, 2: minimum fill time, 3: burst window duration, 4: per-IP burst limit, 5: per-email burst limit */
            __( 'Honeypot %1$s; min fill %2$s; burst %3$s; IP %4$s; email %5$s.', 'mybookaro' ),
            $this->format_operational_toggle( $honeypot_enabled ),
            $this->format_operational_seconds( $min_fill_seconds ),
            $this->format_operational_seconds( $burst_window_seconds ),
            $this->format_operational_requests_per_window( $burst_ip_limit ),
            $this->format_operational_requests_per_window( $burst_email_limit )
        );
    }

    private function format_operational_buffer_pair( int $before_minutes, int $after_minutes ): string
    {
        return sprintf(
            /* translators: 1: before buffer duration, 2: after buffer duration */
            __( 'Before: %1$s; after: %2$s.', 'mybookaro' ),
            $this->format_operational_minutes( $before_minutes ),
            $this->format_operational_minutes( $after_minutes )
        );
    }

    private function format_operational_window_pair( int $cancel_hours, int $reschedule_hours ): string
    {
        return sprintf(
            /* translators: 1: cancellation window, 2: reschedule window */
            __( 'Cancel: %1$s; reschedule: %2$s.', 'mybookaro' ),
            $this->format_operational_hours( $cancel_hours ),
            $this->format_operational_hours( $reschedule_hours )
        );
    }

    private function get_generic_pattern_label( array $opts ): string
    {
        $preset = sanitize_key( (string) ( $opts['generic_setup_preset'] ?? '' ) );
        $preset_label = GenericPresetProfiles::get_label( $preset );
        if ( '' !== $preset_label ) {
            return $preset_label;
        }

        $provider_mode = sanitize_key( (string) ( $opts['provider_resolution_mode'] ?? 'author' ) );
        if ( ! in_array( $provider_mode, [ 'author', 'meta_key' ], true ) ) {
            $provider_mode = 'author';
        }
        $provider_label = ( 'meta_key' === $provider_mode )
            ? __( 'Listing Meta Key mapping', 'mybookaro' )
            : __( 'Listing Author mapping', 'mybookaro' );

        $services_mode = sanitize_key( (string) ( $opts['services_model'] ?? $opts['generic_services_mode'] ?? 'hybrid' ) );
        if ( 'admin_catalog' === $services_mode ) {
            $services_mode = 'admin_only';
        }
        $services_label_map = [
            'provider_only' => __( 'Provider-managed services', 'mybookaro' ),
            'admin_only' => __( 'Admin-managed services', 'mybookaro' ),
            'hybrid' => __( 'Hybrid services', 'mybookaro' ),
        ];
        if ( ! isset( $services_label_map[ $services_mode ] ) ) {
            $services_mode = 'hybrid';
        }

        // Use the resolver so the displayed label matches the effective strategy
        // (e.g. Single Business coerces directory_template -> normal_page) instead of
        // hardcoding a directory default that never applies to a listing-less lane.
        $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( $placement_strategy, [ 'directory_template', 'normal_page', 'shortcode_only', 'css_selector' ], true ) ) {
            $placement_strategy = 'directory_template';
        }
        $placement_label_map = [
            'directory_template' => __( 'Directory template placement', 'mybookaro' ),
            'normal_page' => __( 'Normal page placement', 'mybookaro' ),
            'shortcode_only' => __( 'Shortcode/block-only placement', 'mybookaro' ),
            'css_selector' => __( 'CSS selector placement', 'mybookaro' ),
        ];
        $placement_label = (string) ( $placement_label_map[ $placement_strategy ] ?? $placement_strategy );

        return GenericPresetProfiles::build_custom_setup_label(
            $provider_label,
            (string) $services_label_map[ $services_mode ],
            $placement_label
        );
    }

    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();
        }

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

        $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_validation_overview(): array
    {
        $overview = [
            'available' => false,
            'mode' => '',
            'total' => 0,
            'failed' => 0,
            'ok' => 0,
            'warn' => 0,
            'error' => 0,
            'info' => 0,
        ];

        if ( ! function_exists( 'bookaro_run_generic_admin_validation' ) ) {
            return $overview;
        }

        $validation = bookaro_run_generic_admin_validation();
        if ( ! is_array( $validation ) ) {
            return $overview;
        }

        $checks = [];
        if ( ! empty( $validation['checks'] ) && is_array( $validation['checks'] ) ) {
            $checks = $validation['checks'];
        }

        $overview['available'] = true;
        $overview['mode'] = sanitize_key( (string) ( $validation['mode'] ?? '' ) );
        $overview['total'] = count( $checks );
        $overview['failed'] = absint( $validation['failed_count'] ?? 0 );

        foreach ( $checks as $check ) {
            if ( ! is_array( $check ) ) {
                continue;
            }
            $state = sanitize_key( (string) ( $check['state'] ?? 'info' ) );
            if ( ! in_array( $state, [ 'ok', 'warn', 'error', 'info' ], true ) ) {
                $state = 'info';
            }
            $overview[ $state ] = absint( $overview[ $state ] ?? 0 ) + 1;
        }

        return $overview;
    }

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

        if ( '' === $integration_mode ) {
            $integration_mode = function_exists( 'bookaro_get_integration_mode' )
                ? (string) bookaro_get_integration_mode()
                : (string) ( $opts['integration_mode'] ?? 'auto' );
        }
        $integration_mode = sanitize_key( $integration_mode );
        $active = ( 'generic' === $integration_mode );

        $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 ),
        ];
    }

    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_for_onboarding(),
            '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 build_shortcode_snippets( string $integration_mode, int $default_listing_id ): array
    {
        $single_business = $this->is_single_business_site_for_onboarding();
        $default_provider_id = function_exists( 'bookaro_get_option' )
            ? absint( bookaro_get_option( 'default_provider_id', 0 ) )
            : 0;

        if ( 'generic' === $integration_mode && $single_business ) {
            $provider_id = $default_provider_id > 0 ? $default_provider_id : 45;
            return [
                [
                    'label' => __( 'Booking button (single business)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_booking_button provider_id="%d"]', $provider_id ),
                ],
                [
                    'label' => __( 'Services cards (single business)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_services_cards provider_id="%d" source="provider" columns="3"]', $provider_id ),
                ],
            ];
        }

        if ( 'mylisting' === $integration_mode ) {
            $listing_id = $default_listing_id > 0 ? $default_listing_id : 123;
            return [
                [
                    'label' => __( 'Booking button (listing)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_booking_button listing_id="%d"]', $listing_id ),
                ],
                [
                    'label' => __( 'Services cards (listing)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_services_cards listing_id="%d" columns="3"]', $listing_id ),
                ],
            ];
        }

        if ( $default_listing_id > 0 ) {
            return [
                [
                    'label' => __( 'Booking button (listing)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_booking_button listing_id="%d"]', $default_listing_id ),
                ],
                [
                    'label' => __( 'Services cards (listing)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_services_cards listing_id="%d" columns="3"]', $default_listing_id ),
                ],
            ];
        }

        if ( $default_provider_id > 0 ) {
            return [
                [
                    'label' => __( 'Booking button (single business)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_booking_button provider_id="%d"]', $default_provider_id ),
                ],
                [
                    'label' => __( 'Services cards (single business)', 'mybookaro' ),
                    'code' => sprintf( '[bookaro_services_cards provider_id="%d" source="provider" columns="3"]', $default_provider_id ),
                ],
            ];
        }

        return [
            [
                'label' => __( 'Booking button (listing)', 'mybookaro' ),
                'code' => '[bookaro_booking_button listing_id="123"]',
            ],
            [
                'label' => __( 'Services cards (listing)', 'mybookaro' ),
                'code' => '[bookaro_services_cards listing_id="123" columns="3"]',
            ],
        ];
    }

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

    private function get_mylisting_default_listing_post_type(): string
    {
        $types = $this->get_listing_post_types();
        if ( ! empty( $types ) ) {
            return sanitize_key( (string) $types[0] );
        }

        if ( function_exists( 'bookaro_get_option' ) ) {
            $stored = sanitize_key( (string) bookaro_get_option( 'listing_post_type', '' ) );
            if ( '' !== $stored ) {
                return $stored;
            }
        }

        return 'job_listing';
    }

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

        $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 get_single_business_fast_path_url(): string
    {
        return $this->get_mylisting_fast_path_url( 0 );
    }

    private function count_listing_services( int $listing_id, string $integration_mode = '' ): int
    {
        if ( $listing_id < 1 ) {
            return 0;
        }

        $integration_mode = sanitize_key( $integration_mode );
        if ( '' === $integration_mode && function_exists( 'bookaro_get_integration_mode' ) ) {
            $integration_mode = sanitize_key( (string) bookaro_get_integration_mode() );
        }
        if ( '' === $integration_mode ) {
            $integration_mode = 'mylisting';
        }

        if ( function_exists( 'bookaro_resolve_listing_services' ) ) {
            $services = bookaro_resolve_listing_services( $listing_id, $integration_mode );
            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 count_single_business_available_services( int $provider_id ): int
    {
        if ( $provider_id < 1 || ! function_exists( 'bookaro_get_generic_provider_context_services' ) ) {
            return 0;
        }

        $services = bookaro_get_generic_provider_context_services( $provider_id );
        return is_array( $services ) ? count( $services ) : 0;
    }

    private function count_listing_timeslots( int $listing_id ): int
    {
        $provider_id = $this->resolve_provider_id( $listing_id );
        if ( $provider_id < 1 ) {
            return 0;
        }

        $timeslots = $this->schedule->get_timeslots( $provider_id );
        if ( ! is_array( $timeslots ) ) {
            return 0;
        }

        return count( $timeslots );
    }

    private function ensure_demo_timeslots_for_listing( int $listing_id ): bool
    {
        $provider_id = $this->resolve_provider_id( $listing_id );
        return $this->ensure_demo_timeslots_for_provider( $provider_id );
    }

    private function ensure_demo_timeslots_for_provider( int $provider_id ): bool
    {
        if ( $provider_id < 1 ) {
            return false;
        }

        $existing = $this->schedule->get_timeslots( $provider_id );
        if ( ! empty( $existing ) ) {
            return false;
        }

        $weekly = [
            0 => 0,
            1 => 1,
            2 => 1,
            3 => 1,
            4 => 1,
            5 => 1,
            6 => 0,
        ];
        $slots = [];
        foreach ( [ 1, 2, 3, 4, 5 ] as $weekday ) {
            $slots[] = [
                'weekday' => $weekday,
                'start_time' => '09:00',
                'end_time' => '17:00',
                'interval_m' => 30,
            ];
        }

        $this->schedule->set_weekly_availability( $provider_id, $weekly );
        $this->schedule->set_timeslots( $provider_id, $slots );
        return true;
    }

    private function count_timeslots(): int
    {
        $wpdb = $this->db->get_wpdb();
        $table = esc_sql( $this->db->get_timeslot_table() );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" );
        return (int) $count;
    }

    private function count_test_bookings(): int
    {
        $wpdb = $this->db->get_wpdb();
        $table = esc_sql( $this->db->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 get_listing_post_types(): array
    {
        if ( function_exists( 'bookaro_get_allowed_listing_post_types' ) ) {
            $types = bookaro_get_allowed_listing_post_types();
            if ( is_array( $types ) && ! empty( $types ) ) {
                return array_values( array_unique( array_filter( $types ) ) );
            }
        }
        return [];
    }

    private function get_listing_choices(): array
    {
        $types = $this->get_listing_post_types();
        if ( empty( $types ) ) {
            if ( $this->is_single_business_site_for_onboarding() ) {
                return [];
            }
            $types = [ 'job_listing' ];
        }
        $posts = get_posts( [
            'post_type' => $types,
            'post_status' => 'publish',
            'posts_per_page' => 20,
            'orderby' => 'date',
            'order' => 'DESC',
        ] );

        $choices = [];
        foreach ( $posts as $post ) {
            $choices[] = [
                'id' => (int) $post->ID,
                'title' => (string) $post->post_title,
            ];
        }

        return $choices;
    }

    private function get_default_listing_id( array $choices ): int
    {
        if ( empty( $choices ) ) {
            return 0;
        }
        return (int) $choices[0]['id'];
    }

    private function resolve_provider_id( int $listing_id ): int
    {
        if ( $listing_id < 1 ) {
            return $this->is_single_business_site_for_onboarding()
                ? $this->get_single_business_default_provider_id()
                : 0;
        }
        if ( function_exists( 'bookaro_get_listing_owner_id' ) ) {
            return (int) bookaro_get_listing_owner_id( $listing_id );
        }
        $post = get_post( $listing_id );
        return $post ? (int) $post->post_author : 0;
    }

    private function get_single_business_default_provider_id(): int
    {
        $provider_id = function_exists( 'bookaro_get_option' )
            ? absint( bookaro_get_option( 'default_provider_id', 0 ) )
            : 0;
        if ( $provider_id < 1 ) {
            return 0;
        }
        return get_user_by( 'ID', $provider_id ) ? $provider_id : 0;
    }

    private function get_single_business_page_assignment_status( array $opts = [], string $integration_mode = 'generic' ): array
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }
        if ( ! is_array( $opts ) ) {
            $opts = [];
        }

        $integration_mode = sanitize_key( $integration_mode );
        if ( ! in_array( $integration_mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
            $integration_mode = 'generic';
        }
        if ( 'auto' === $integration_mode ) {
            $integration_mode = function_exists( 'bookaro_get_integration_mode' )
                ? sanitize_key( (string) bookaro_get_integration_mode() )
                : 'generic';
        }
        if ( ! in_array( $integration_mode, [ 'mylisting', 'generic' ], true ) ) {
            $integration_mode = 'generic';
        }

        $ui_mode = $this->resolve_ui_mode_for_onboarding( $integration_mode );
        $primary_type = '';
        if ( function_exists( 'bookaro_get_option' ) ) {
            $primary_type = sanitize_key( (string) bookaro_get_option( 'listing_post_type', '' ) );
        }
        if ( '' === $primary_type && defined( 'BOOKARO_PROVIDER_POST_TYPE' ) ) {
            $primary_type = sanitize_key( (string) BOOKARO_PROVIDER_POST_TYPE );
        }
        if ( '' === $primary_type ) {
            $primary_type = 'job_listing';
        }

        $booking_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'booking' ) )
            : 0;
        if ( $booking_page_id < 1 ) {
            $booking_page_id = absint( $opts['generic_setup_booking_page_id'] ?? 0 );
        }
        if ( $booking_page_id < 1 ) {
            $booking_page_id = absint( $opts['booking_page_id'] ?? 0 );
        }

        $provider_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'provider_dashboard' ) )
            : 0;
        if ( $provider_page_id < 1 ) {
            $provider_page_id = absint( $opts['generic_setup_provider_dashboard_page_id'] ?? 0 );
        }
        if ( $provider_page_id < 1 ) {
            $provider_page_id = absint( $opts['provider_dashboard_page_id'] ?? 0 );
        }

        $customer_page_id = function_exists( 'bookaro_get_page_for_context' )
            ? absint( bookaro_get_page_for_context( $integration_mode, $primary_type, 'customer_dashboard' ) )
            : 0;
        if ( $customer_page_id < 1 ) {
            $customer_page_id = absint( $opts['generic_setup_customer_dashboard_page_id'] ?? 0 );
        }
        if ( $customer_page_id < 1 ) {
            $customer_page_id = absint( $opts['customer_dashboard_page_id'] ?? 0 );
        }

        $missing_pages = [];
        $missing_page_keys = [];
        if ( $booking_page_id < 1 ) {
            $missing_pages[] = __( 'Booking page', 'mybookaro' );
            $missing_page_keys[] = 'booking';
        }
        if ( 'shortcodes' === $ui_mode ) {
            if ( $provider_page_id < 1 ) {
                $missing_pages[] = __( 'Provider dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'provider_dashboard';
            }
            if ( $customer_page_id < 1 ) {
                $missing_pages[] = __( 'Customer dashboard page', 'mybookaro' );
                $missing_page_keys[] = 'customer_dashboard';
            }
        }

        $pages_ready = empty( $missing_pages );
        $pages_detail = $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( ', ', $missing_pages )
            );
        if ( ! $pages_ready ) {
            $pages_detail .= ' ' . __( 'Single Business sequence is strict: assign Booking page first, then Provider/Customer dashboard pages when Shortcodes mode is active.', 'mybookaro' );
        }
        $pages_action_label = __( 'Assign pages', 'mybookaro' );
        if ( ! $pages_ready ) {
            $missing_booking_page = in_array( 'booking', $missing_page_keys, true );
            $missing_dashboard_pages = in_array( 'provider_dashboard', $missing_page_keys, true ) || in_array( 'customer_dashboard', $missing_page_keys, true );
            if ( $missing_booking_page && $missing_dashboard_pages ) {
                $pages_action_label = __( 'Assign booking + dashboard pages', 'mybookaro' );
            } elseif ( $missing_booking_page ) {
                $pages_action_label = __( 'Assign Booking page', 'mybookaro' );
            } elseif ( $missing_dashboard_pages ) {
                $pages_action_label = __( 'Assign dashboard pages', 'mybookaro' );
            }
        }

        return [
            'ui_mode' => $ui_mode,
            'booking_page_id' => $booking_page_id,
            'provider_page_id' => $provider_page_id,
            'customer_page_id' => $customer_page_id,
            'missing_pages' => $missing_pages,
            'missing_page_keys' => $missing_page_keys,
            'pages_action_label' => $pages_action_label,
            'pages_ready' => $pages_ready,
            'pages_detail' => $pages_detail,
        ];
    }

    private function build_single_business_onboarding_status( array $opts = [], string $integration_mode = 'generic' ): array
    {
        if ( empty( $opts ) ) {
            $opts = $this->options->get_all();
        }
        if ( ! is_array( $opts ) ) {
            $opts = [];
        }

        $provider_id = $this->get_single_business_default_provider_id();
        $provider_ready = $provider_id > 0;
        $page_status = $this->get_single_business_page_assignment_status( $opts, $integration_mode );
        $pages_ready = ! empty( $page_status['pages_ready'] );
        $services_count = $provider_ready ? $this->count_single_business_available_services( $provider_id ) : 0;
        $services_ready = $provider_ready && $services_count > 0;
        $preview_url = $this->get_single_business_preview_url();
        $preview_ready = $provider_ready && $pages_ready && $services_ready && '' !== trim( $preview_url );
        $ui_mode = sanitize_key( (string) ( $page_status['ui_mode'] ?? 'shortcodes' ) );
        if ( ! in_array( $ui_mode, [ 'shortcodes', 'woocommerce' ], true ) ) {
            $ui_mode = 'shortcodes';
        }
        $missing_page_keys = (array) ( $page_status['missing_page_keys'] ?? [] );
        $booking_page_ready = ! in_array( 'booking', $missing_page_keys, true );
        $dashboard_pages_ready = ( 'shortcodes' !== $ui_mode )
            || ( ! in_array( 'provider_dashboard', $missing_page_keys, true ) && ! in_array( 'customer_dashboard', $missing_page_keys, true ) );
        $fast_path_url = $this->get_single_business_fast_path_url();
        $fast_path_ready = $provider_ready && $pages_ready && $services_ready && '' !== trim( $fast_path_url );

        $service_type = defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service';
        $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' );
        $services_url = admin_url( 'admin.php?page=bookaro-setup-wizard&step=services' );
        $create_service_url = admin_url( 'post-new.php?post_type=' . $service_type );

        $provider_detail = $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' );
        $pages_detail = trim( (string) ( $page_status['pages_detail'] ?? '' ) );
        $services_detail = ! $provider_ready
            ? __( 'Cannot validate service inventory until Default Provider is set.', 'mybookaro' )
            : (
                $services_ready
                    ? sprintf(
                        /* translators: %d: available services count */
                        __( 'Available services for the Default Provider: %d. Continue to preview booking.', 'mybookaro' ),
                        $services_count
                    )
                    : __( 'No services are available for the Default Provider. Create one service before previewing bookings.', 'mybookaro' )
            );
        $ready_detail = $preview_ready
            ? __( 'Open preview booking and complete one end-to-end test booking.', 'mybookaro' )
            : __( 'Follow this order: Default Provider -> Pages -> First service -> Preview booking.', 'mybookaro' );

        return [
            'provider_id' => $provider_id,
            'provider_ready' => $provider_ready,
            'provider_detail' => $provider_detail,
            'pages_ready' => $pages_ready,
            'pages_detail' => $pages_detail,
            'missing_pages' => (array) ( $page_status['missing_pages'] ?? [] ),
            'missing_page_keys' => $missing_page_keys,
            'pages_action_label' => (string) ( $page_status['pages_action_label'] ?? __( 'Assign pages', 'mybookaro' ) ),
            'services_count' => $services_count,
            'services_ready' => $services_ready,
            'services_detail' => $services_detail,
            'ui_mode' => $ui_mode,
            'booking_page_ready' => $booking_page_ready,
            'dashboard_pages_ready' => $dashboard_pages_ready,
            'preview_ready' => $preview_ready,
            'fast_path_ready' => $fast_path_ready,
            'ready_detail' => $ready_detail,
            'default_provider_url' => $default_provider_url,
            'pages_url' => $pages_url,
            'services_url' => $services_url,
            'create_service_url' => $create_service_url,
            'preview_url' => $preview_url,
            'fast_path_url' => $fast_path_url,
        ];
    }

    private function get_single_business_preview_url(): string
    {
        $opts = $this->options->get_all();
        $candidates = [
            absint( $opts['generic_setup_booking_page_id'] ?? 0 ),
            absint( $opts['booking_page_id'] ?? 0 ),
            absint( $opts['generic_setup_services_page_id'] ?? 0 ),
        ];
        foreach ( $candidates as $page_id ) {
            if ( $page_id < 1 || ! get_post( $page_id ) ) {
                continue;
            }
            $view_url = get_permalink( $page_id );
            if ( $view_url ) {
                return $view_url;
            }
            $edit_url = get_edit_post_link( $page_id, '' );
            if ( $edit_url ) {
                return $edit_url;
            }
        }

        return '';
    }

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

    private function is_pro_active(): bool
    {
        return function_exists( 'bookaro_is_pro_active' ) && bookaro_is_pro_active();
    }

    private function get_action_last_runs(): array
    {
        $actions = get_option( self::ACTION_OPTION, [] );
        return is_array( $actions ) ? $actions : [];
    }

    private function set_action_last_run( string $key ): void
    {
        $actions = $this->get_action_last_runs();
        $actions[ $key ] = time();
        update_option( self::ACTION_OPTION, $actions );
    }

    private function format_last_run( int $timestamp ): string
    {
        if ( $timestamp < 1 ) {
            return __( 'Never', 'mybookaro' );
        }
        $date = date_i18n(
            get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
            $timestamp
        );
        $diff = human_time_diff( $timestamp, time() );
        return sprintf(
            /* translators: 1: formatted date, 2: time ago */
            __( '%1$s (%2$s ago)', 'mybookaro' ),
            $date,
            $diff
        );
    }

    private function get_default_test_email(): string
    {
        $opts = $this->options->get_all();
        $fallback = sanitize_email( $opts['log_email'] ?? '' );
        if ( $fallback === '' ) {
            $fallback = sanitize_email( get_option( 'admin_email' ) );
        }
        return $fallback;
    }

    private function resolve_ui_mode_for_onboarding( string $integration_mode = '' ): string
    {
        if ( function_exists( 'bookaro_get_ui_mode' ) ) {
            $resolved = sanitize_key( (string) bookaro_get_ui_mode() );
            if ( in_array( $resolved, [ 'shortcodes', 'woocommerce' ], true ) ) {
                return $resolved;
            }
        }

        $integration_mode = sanitize_key( $integration_mode );
        if ( ! in_array( $integration_mode, [ 'auto', 'mylisting', 'generic' ], true ) ) {
            $integration_mode = function_exists( 'bookaro_get_integration_mode' )
                ? sanitize_key( (string) bookaro_get_integration_mode() )
                : 'auto';
        }
        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';
        }

        $default_ui_mode = ( 'generic' === $integration_mode ) ? 'shortcodes' : 'woocommerce';
        $ui_mode = function_exists( 'bookaro_get_option' )
            ? sanitize_key( (string) bookaro_get_option( 'ui_mode', $default_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 resolve_site_type_for_onboarding(): string
    {
        if ( function_exists( 'bookaro_get_site_type' ) ) {
            $site_type = sanitize_key( (string) bookaro_get_site_type() );
        } else {
            $opts = $this->options->get_all();
            $site_type = sanitize_key( (string) ( $opts['site_type'] ?? 'directory' ) );
        }
        if ( ! in_array( $site_type, [ 'directory', 'single_business', 'advanced_mapping' ], true ) ) {
            $site_type = 'directory';
        }
        return $site_type;
    }

    private function is_single_business_site_for_onboarding(): bool
    {
        return 'single_business' === $this->resolve_site_type_for_onboarding();
    }

    private function resolve_lane_id( string $integration_mode, string $site_type ): string
    {
        $integration_mode = sanitize_key( $integration_mode );
        $site_type = sanitize_key( $site_type );
        if ( 'single_business' === $site_type ) {
            return 'single_business';
        }
        if ( 'directory' === $site_type && 'mylisting' === $integration_mode ) {
            return 'mylisting_directory';
        }
        return 'generic_directory';
    }

    private function build_lane_profile( string $integration_mode, string $site_type ): array
    {
        $lane_id = $this->resolve_lane_id( $integration_mode, $site_type );
        $site_type_labels = [
            'directory' => __( 'Directory', 'mybookaro' ),
            'single_business' => __( 'Single Business', 'mybookaro' ),
            'advanced_mapping' => __( 'Generic Directory (legacy compatibility state active)', 'mybookaro' ),
        ];
        $lane_labels = [
            'mylisting_directory' => __( 'MyListing Directory', 'mybookaro' ),
            'generic_directory' => __( 'Generic Directory', 'mybookaro' ),
            'single_business' => __( 'Single Business', 'mybookaro' ),
        ];
        switch ( $lane_id ) {
            case 'mylisting_directory':
                $profile = [
                    'provider_mapping' => __( 'Listing owner/provider from MyListing listing context', 'mybookaro' ),
                    'services_model' => __( 'MyListing repeater services', 'mybookaro' ),
                    'placement_model' => __( 'Directory listing template (sidebar booking entry)', 'mybookaro' ),
                    'pages_required' => __( 'Provider and customer dashboards (or WooCommerce My Account mode)', 'mybookaro' ),
                ];
                break;
            case 'single_business':
                $profile = [
                    'provider_mapping' => __( 'Default Provider (provider-first, no listing required)', 'mybookaro' ),
                    'services_model' => __( 'Provider Only by default (Admin Only/Hybrid optional)', 'mybookaro' ),
                    'placement_model' => __( 'Normal pages or shortcode/block placement', 'mybookaro' ),
                    'pages_required' => __( 'Booking page, provider dashboard page, customer dashboard page (services page recommended)', 'mybookaro' ),
                ];
                break;
            case 'generic_directory':
            default:
                $profile = [
                    'provider_mapping' => ( 'advanced_mapping' === $site_type )
                        ? __( 'Listing Author or Listing Meta Key (legacy compatibility state active)', 'mybookaro' )
                        : __( 'Listing Author or Listing Meta Key', 'mybookaro' ),
                    'services_model' => __( 'Provider Only, Admin Catalog Only, or Hybrid', 'mybookaro' ),
                    'placement_model' => __( 'Directory templates, normal pages, shortcode/block only, or CSS selector insertion', 'mybookaro' ),
                    'pages_required' => __( 'Booking page and dashboard pages when using shortcode dashboard mode', 'mybookaro' ),
                ];
                break;
        }

        return [
            'id' => $lane_id,
            'label' => $lane_labels[ $lane_id ] ?? __( 'Generic Directory', 'mybookaro' ),
            'site_type' => $site_type,
            'site_type_label' => $site_type_labels[ $site_type ] ?? __( 'Directory', 'mybookaro' ),
            'provider_mapping' => $profile['provider_mapping'],
            'services_model' => $profile['services_model'],
            'placement_model' => $profile['placement_model'],
            'pages_required' => $profile['pages_required'],
        ];
    }

    private function build_wizard_completion_state(
        array $opts,
        array $lane_profile,
        array $mylisting_activation_flow,
        array $generic_readiness_summary,
        string $page_url,
        string $generic_validation_url,
        string $single_business_default_provider_url,
        string $single_business_pages_url
    ): array {
        $summary = [
            'active' => false,
            'lane_id' => '',
            'title' => '',
            'state' => 'info',
            'state_label' => __( 'Info', 'mybookaro' ),
            'summary' => '',
            'next_steps' => [],
            'actions' => [],
        ];

        $wizard_complete = absint( wp_unslash( $_GET['wizard_complete'] ?? 0 ) );
        if ( $wizard_complete < 1 ) {
            return $summary;
        }

        $summary['active'] = true;
        $allowed_lane_ids = [ 'mylisting_directory', 'generic_directory', 'single_business' ];
        $fallback_lane_id = sanitize_key( (string) ( $lane_profile['id'] ?? '' ) );
        if ( ! in_array( $fallback_lane_id, $allowed_lane_ids, true ) ) {
            $fallback_lane_id = 'generic_directory';
        }

        $requested_lane_id = sanitize_key( wp_unslash( $_GET['wizard_lane'] ?? '' ) );
        $lane_id = in_array( $requested_lane_id, $allowed_lane_ids, true ) ? $requested_lane_id : $fallback_lane_id;
        $summary['lane_id'] = $lane_id;

        $actions = [];
        $next_steps = [];

        if ( 'mylisting_directory' === $lane_id ) {
            $completed = absint( $mylisting_activation_flow['completed'] ?? 0 );
            $total = absint( $mylisting_activation_flow['total'] ?? 0 );
            $milestone_total = $total > 0 ? $total : 4;
            $next_action = ( isset( $mylisting_activation_flow['next_action'] ) && is_array( $mylisting_activation_flow['next_action'] ) )
                ? $mylisting_activation_flow['next_action']
                : [];

            $summary['title'] = __( 'MyListing Directory setup complete', 'mybookaro' );
            $summary['state'] = ( $completed >= $milestone_total ) ? 'ok' : 'warn';
            $summary['state_label'] = ( 'ok' === $summary['state'] )
                ? __( 'Ready', 'mybookaro' )
                : __( 'Next step required', 'mybookaro' );
            $summary['summary'] = sprintf(
                /* translators: 1: completed milestones, 2: total milestones */
                __( 'Wizard setup is saved for MyListing Directory. %1$d of %2$d first-booking milestones are complete.', 'mybookaro' ),
                $completed,
                $milestone_total
            );

            $next_steps[] = '' !== trim( (string) ( $next_action['detail'] ?? '' ) )
                ? (string) $next_action['detail']
                : __( 'Continue in First booking progress to clear the remaining milestones.', 'mybookaro' );
            $next_steps[] = __( 'Run one end-to-end booking test from the MyListing sidebar booking entry.', 'mybookaro' );

            if ( '' !== trim( (string) ( $next_action['url'] ?? '' ) ) && '' !== trim( (string) ( $next_action['label'] ?? '' ) ) ) {
                $actions[] = [
                    'label' => (string) $next_action['label'],
                    'url' => (string) $next_action['url'],
                ];
            }
            $actions[] = [
                'label' => __( 'Open first booking progress', 'mybookaro' ),
                'url' => $this->with_url_fragment( $page_url, 'bookaro-first-booking-progress' ),
            ];
            $actions[] = [
                'label' => __( 'Open booking test action', 'mybookaro' ),
                'url' => $this->with_url_fragment( $page_url, 'bookaro-action-open-listing' ),
            ];
        } elseif ( 'single_business' === $lane_id ) {
            $single_business_status = $this->build_single_business_onboarding_status( $opts, 'generic' );
            $provider_ready = ! empty( $single_business_status['provider_ready'] );
            $pages_ready = ! empty( $single_business_status['pages_ready'] );
            $services_ready = ! empty( $single_business_status['services_ready'] );
            $preview_ready = ! empty( $single_business_status['preview_ready'] );

            $summary['title'] = __( 'Single Business setup complete', 'mybookaro' );
            $summary['state'] = ( $provider_ready && $pages_ready && $services_ready && $preview_ready ) ? 'ok' : 'warn';
            $summary['state_label'] = ( 'ok' === $summary['state'] )
                ? __( 'Ready', 'mybookaro' )
                : __( 'Needs attention', 'mybookaro' );
            $summary['summary'] = ( 'ok' === $summary['state'] )
                ? __( 'Wizard setup is saved for Single Business. The first-booking path is ready: Default Provider, pages, service inventory, and preview booking.', 'mybookaro' )
                : __( 'Wizard setup is saved for Single Business. Complete the first-booking path in this order: Default Provider -> Pages -> First service -> Preview booking.', 'mybookaro' );

            if ( ! $provider_ready ) {
                $next_steps[] = trim( (string) ( $single_business_status['provider_detail'] ?? '' ) );
            }
            if ( ! $pages_ready ) {
                $next_steps[] = trim( (string) ( $single_business_status['pages_detail'] ?? '' ) );
            }
            if ( ! $services_ready ) {
                $next_steps[] = trim( (string) ( $single_business_status['services_detail'] ?? '' ) );
            }
            if ( ! $preview_ready ) {
                $next_steps[] = trim( (string) ( $single_business_status['ready_detail'] ?? '' ) );
            } else {
                $next_steps[] = __( 'Run one end-to-end booking from your booking/services page to confirm customer and provider flow.', 'mybookaro' );
            }

            $preview_url = trim( (string) ( $single_business_status['preview_url'] ?? '' ) );
            if ( '' === trim( $preview_url ) ) {
                $preview_url = $this->with_url_fragment( $page_url, 'bookaro-action-open-listing' );
            }

            $actions[] = [
                'label' => __( 'Review Default Provider', 'mybookaro' ),
                'url' => trim( (string) ( $single_business_status['default_provider_url'] ?? $single_business_default_provider_url ) ),
            ];
            $actions[] = [
                'label' => trim( (string) ( $single_business_status['pages_action_label'] ?? __( 'Assign pages', 'mybookaro' ) ) ),
                'url' => trim( (string) ( $single_business_status['pages_url'] ?? $single_business_pages_url ) ),
            ];
            if ( $provider_ready && ! $services_ready ) {
                $service_type = defined( 'BOOKARO_SERVICE_POST_TYPE' ) ? BOOKARO_SERVICE_POST_TYPE : 'bookaro_service';
                $actions[] = [
                    'label' => __( 'Create first service', 'mybookaro' ),
                    'url' => trim( (string) ( $single_business_status['create_service_url'] ?? admin_url( 'post-new.php?post_type=' . $service_type ) ) ),
                ];
            }
            $actions[] = [
                'label' => __( 'Open booking/services preview', 'mybookaro' ),
                'url' => $preview_url,
            ];
        } else {
            $generic_state = sanitize_key( (string) ( $generic_readiness_summary['state'] ?? 'info' ) );
            if ( ! in_array( $generic_state, [ 'ok', 'warn', 'error', 'info' ], true ) ) {
                $generic_state = 'info';
            }

            $summary['title'] = __( 'Generic Directory setup complete', 'mybookaro' );
            $summary['state'] = $generic_state;
            $summary['state_label'] = trim( (string) ( $generic_readiness_summary['state_label'] ?? '' ) );
            if ( '' === $summary['state_label'] ) {
                $state_labels = [
                    'ok' => __( 'Ready', 'mybookaro' ),
                    'warn' => __( 'Review needed', 'mybookaro' ),
                    'error' => __( 'Blocked', 'mybookaro' ),
                    'info' => __( 'Info', 'mybookaro' ),
                ];
                $summary['state_label'] = (string) ( $state_labels[ $generic_state ] ?? __( 'Info', 'mybookaro' ) );
            }

            if ( 'ok' === $generic_state ) {
                $summary['summary'] = __( 'Wizard setup is saved for Generic Directory and validation is currently passing.', 'mybookaro' );
            } elseif ( 'error' === $generic_state ) {
                $summary['summary'] = __( 'Wizard setup is saved for Generic Directory, but launch is blocked until validation issues are resolved.', 'mybookaro' );
            } else {
                $summary['summary'] = __( 'Wizard setup is saved for Generic Directory. Complete the remaining readiness checks before launch.', 'mybookaro' );
            }

            $top_action = ( isset( $generic_readiness_summary['top_next_action'] ) && is_array( $generic_readiness_summary['top_next_action'] ) )
                ? $generic_readiness_summary['top_next_action']
                : [];
            $top_action_detail = trim( (string) ( $top_action['detail'] ?? '' ) );
            $next_steps[] = '' !== $top_action_detail
                ? $top_action_detail
                : __( 'Review Generic readiness and clear pending checklist items before launch.', 'mybookaro' );
            $next_steps[] = __( 'After changes, re-run System Status validation and complete one full booking flow test.', 'mybookaro' );

            if ( '' !== trim( (string) ( $top_action['url'] ?? '' ) ) && '' !== trim( (string) ( $top_action['label'] ?? '' ) ) ) {
                $actions[] = [
                    'label' => (string) $top_action['label'],
                    'url' => (string) $top_action['url'],
                ];
            }
            $actions[] = [
                'label' => __( 'Open Generic readiness summary', 'mybookaro' ),
                'url' => $this->with_url_fragment( $page_url, 'bookaro-generic-readiness-summary' ),
            ];
            $actions[] = [
                'label' => __( 'Run System Status validation', 'mybookaro' ),
                'url' => $generic_validation_url,
            ];
        }

        $summary['title'] = trim( (string) $summary['title'] );
        $summary['state'] = sanitize_key( (string) $summary['state'] );
        if ( ! in_array( $summary['state'], [ 'ok', 'warn', 'error', 'info' ], true ) ) {
            $summary['state'] = 'info';
        }
        $summary['state_label'] = trim( (string) $summary['state_label'] );
        if ( '' === $summary['state_label'] ) {
            $summary['state_label'] = __( 'Info', 'mybookaro' );
        }
        $summary['summary'] = trim( (string) $summary['summary'] );
        $summary['next_steps'] = array_values(
            array_filter(
                array_map(
                    static function ( $step ): string {
                        return trim( (string) $step );
                    },
                    $next_steps
                ),
                static function ( $step ): bool {
                    return '' !== $step;
                }
            )
        );
        $summary['actions'] = $this->normalize_notice_actions( '', '', $actions );

        return $summary;
    }

    private function build_lane_summary_banner(
        array $lane_profile,
        string $integration_mode,
        array $mylisting_activation_flow,
        array $generic_readiness_summary,
        array $single_business_status = []
    ): array {
        $lane_id = sanitize_key( (string) ( $lane_profile['id'] ?? '' ) );
        $integration_mode = sanitize_key( $integration_mode );
        $site_type = sanitize_key( (string) ( $lane_profile['site_type'] ?? '' ) );

        $lane_label = trim( (string) ( $lane_profile['label'] ?? '' ) );
        if ( '' === $lane_label ) {
            $lane_label = AdminLaneSummary::resolve_lane_label( $lane_id, $integration_mode, $site_type );
        }

        $summary = AdminLaneSummary::create_payload( $lane_label );

        if ( 'single_business' === $lane_id || 'single_business' === $site_type ) {
            $provider_ready = ! empty( $single_business_status['provider_ready'] );
            $pages_ready = ! empty( $single_business_status['pages_ready'] );
            $services_ready = ! empty( $single_business_status['services_ready'] );
            $missing_page_keys = is_array( $single_business_status['missing_page_keys'] ?? null ) ? $single_business_status['missing_page_keys'] : [];
            $ui_mode = sanitize_key( (string) ( $single_business_status['ui_mode'] ?? 'shortcodes' ) );
            if ( ! in_array( $ui_mode, [ 'shortcodes', 'woocommerce' ], true ) ) {
                $ui_mode = 'shortcodes';
            }
            $booking_page_ready = array_key_exists( 'booking_page_ready', $single_business_status )
                ? ! empty( $single_business_status['booking_page_ready'] )
                : ! in_array( 'booking', $missing_page_keys, true );
            $dashboard_pages_ready = array_key_exists( 'dashboard_pages_ready', $single_business_status )
                ? ! empty( $single_business_status['dashboard_pages_ready'] )
                : (
                    'shortcodes' !== $ui_mode
                    || ( ! in_array( 'provider_dashboard', $missing_page_keys, true ) && ! in_array( 'customer_dashboard', $missing_page_keys, true ) )
                );
            $preview_ready = ! empty( $single_business_status['preview_ready'] );
            $fast_path_ready = ! empty( $single_business_status['fast_path_ready'] );
            $services_count = max( 0, absint( $single_business_status['services_count'] ?? 0 ) );
            $provider_detail = trim( (string) ( $single_business_status['provider_detail'] ?? '' ) );
            $pages_detail = trim( (string) ( $single_business_status['pages_detail'] ?? '' ) );
            $services_detail = trim( (string) ( $single_business_status['services_detail'] ?? '' ) );
            $ready_detail = trim( (string) ( $single_business_status['ready_detail'] ?? '' ) );
            $single_business_snapshot = AdminLaneSummary::build_single_business_readiness_snapshot( [
                'provider_ready' => $provider_ready,
                'booking_page_ready' => $booking_page_ready,
                'services_ready' => $services_ready,
                'services_count' => $services_count,
                'dashboard_mode' => $ui_mode,
                'dashboard_pages_ready' => $dashboard_pages_ready,
                'preview_ready' => $preview_ready,
                'fast_path_ready' => $fast_path_ready,
            ] );
            $summary['summary'] = __( 'Single Business first-booking order: Default Provider -> Booking/dashboard pages -> First service -> Preview booking.', 'mybookaro' );
            $summary['top_blocker_label'] = __( 'Main blocker', 'mybookaro' );
            $summary['next_action_label'] = __( 'Required next step', 'mybookaro' );
            $summary['model_label'] = __( 'Single Business launch assistant', 'mybookaro' );
            $summary['model_summary'] = trim( (string) ( $single_business_snapshot['summary'] ?? '' ) );
            $summary['model_items'] = is_array( $single_business_snapshot['items'] ?? null ) ? $single_business_snapshot['items'] : [];
            $summary = array_merge(
                $summary,
                AdminLaneSummary::resolve_single_business_focus( [
                    'provider_ready' => $provider_ready,
                    'pages_ready' => $pages_ready,
                    'services_ready' => $services_ready,
                    'missing_page_keys' => $missing_page_keys,
                    'default_provider_url' => trim( (string) ( $single_business_status['default_provider_url'] ?? '' ) ),
                    'pages_url' => trim( (string) ( $single_business_status['pages_url'] ?? '' ) ),
                    'pages_action_label' => trim( (string) ( $single_business_status['pages_action_label'] ?? '' ) ),
                    'create_service_url' => trim( (string) ( $single_business_status['create_service_url'] ?? '' ) ),
                    'ready_url' => trim( (string) ( $single_business_status['preview_url'] ?? '' ) ),
                    'provider_detail' => '' !== $provider_detail
                        ? $provider_detail
                        : __( 'Set a Default Provider in Setup Wizard > Listings (or Settings > General).', 'mybookaro' ),
                    'pages_detail' => '' !== $pages_detail
                        ? $pages_detail
                        : __( 'Assign Booking page first, then dashboard pages (if Shortcodes mode) in Setup Wizard > Pages.', 'mybookaro' ),
                    'services_detail' => '' !== $services_detail
                        ? $services_detail
                        : __( 'Create at least one provider service, then run a full booking flow test.', 'mybookaro' ),
                    'ready_detail' => '' !== $ready_detail
                        ? $ready_detail
                        : __( 'Follow this order: Default Provider -> Pages -> First service -> Preview booking.', 'mybookaro' ),
                ] )
            );

            return AdminLaneSummary::normalize( $summary );
        }

        if ( 'mylisting_directory' === $lane_id || 'mylisting' === $integration_mode ) {
            $summary = array_merge(
                $summary,
                AdminLaneSummary::resolve_mylisting_focus(
                    $mylisting_activation_flow,
                    is_array( $mylisting_activation_flow['next_action'] ?? null ) ? $mylisting_activation_flow['next_action'] : $summary['next_action']
                )
            );

            return AdminLaneSummary::normalize( $summary );
        }

        $generic_state = sanitize_key( (string) ( $generic_readiness_summary['state'] ?? 'info' ) );
        if ( ! in_array( $generic_state, [ 'ok', 'warn', 'error', 'info' ], true ) ) {
            $generic_state = 'info';
        }

        $summary['state'] = $generic_state;
        $summary['state_label'] = trim( (string) ( $generic_readiness_summary['state_label'] ?? '' ) );
        $summary['next_action'] = is_array( $generic_readiness_summary['top_next_action'] ?? null )
            ? $generic_readiness_summary['top_next_action']
            : $summary['next_action'];

        if ( in_array( $generic_state, [ 'warn', 'error' ], true ) ) {
            $summary['top_blocker'] = trim( (string) ( $generic_readiness_summary['validation_detail'] ?? '' ) );
            if ( '' === $summary['top_blocker'] ) {
                $summary['top_blocker'] = trim( (string) ( $generic_readiness_summary['summary'] ?? '' ) );
            }
            if ( '' === $summary['top_blocker'] ) {
                $summary['top_blocker'] = __( 'Generic validation still reports setup items that need attention before launch.', 'mybookaro' );
            }
        } else {
            $summary['top_blocker'] = __( 'No blockers detected for the current Generic lane snapshot.', 'mybookaro' );
            if ( '' === trim( (string) ( $summary['next_action']['detail'] ?? '' ) ) ) {
                $summary['next_action']['detail'] = __( 'Re-run validation after mapping, services, or page changes.', 'mybookaro' );
            }
        }

        return AdminLaneSummary::normalize( $summary );
    }

    private function with_url_fragment( string $url, string $fragment ): string
    {
        $url = trim( $url );
        $fragment = ltrim( trim( $fragment ), '#' );
        if ( '' === $fragment ) {
            return $url;
        }
        if ( '' === $url ) {
            return '#' . $fragment;
        }

        $hash_pos = strpos( $url, '#' );
        if ( false !== $hash_pos ) {
            $url = substr( $url, 0, $hash_pos );
        }

        return $url . '#' . $fragment;
    }

    private function empty_listing_notice( bool $for_open_action = false ): string
    {
        $integration_mode = function_exists( 'bookaro_get_integration_mode' )
            ? bookaro_get_integration_mode()
            : 'mylisting';

        if ( 'generic' === $integration_mode && $this->is_single_business_site_for_onboarding() ) {
            return $for_open_action
                ? __( 'No listing preview is available yet. Single Business listings are optional. Set a Default Provider, assign a booking page in Setup Wizard > Pages, then open that booking/services page. Create a listing only if your theme template requires listing context.', 'mybookaro' )
                : __( 'No listings found. Single Business listings are optional and listing post type selection is not required. Set a Default Provider and test from your booking/services page, or create a listing only if your template needs one.', 'mybookaro' );
        }

        if ( 'generic' === $integration_mode ) {
            return $for_open_action
                ? __( 'No listings found for selected post types. Open Settings > General, select listing post types, create a listing, then open it here.', 'mybookaro' )
                : __( 'No listings found for selected post types. Open Settings > General, select listing post types, create a listing, then try again.', 'mybookaro' );
        }

        return $for_open_action
            ? __( 'No MyListing listings found yet. Create a listing in MyListing, then open it here.', 'mybookaro' )
            : __( 'No MyListing listings found yet. Create a listing in MyListing, then try again.', 'mybookaro' );
    }

    private function set_notice( string $type, string $message ): void
    {
        set_transient( self::NOTICE_KEY, [
            'type' => $type,
            'message' => $message,
        ], 30 );
    }

    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 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 get_generic_launch_readiness_notice_message(): string
    {
        return __( 'Generic settings changed since the last System Status run. Until you re-run validation, Bookaro cannot confirm that lane routing, services source, booking entry placement, and required pages still match. Next action: open System Status, apply each Suggested fix and Next step, then refresh Getting Started 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 redirect_to_page(): void
    {
        wp_safe_redirect( admin_url( 'admin.php?page=bookaro-getting-started' ) );
        exit;
    }

    private function assert_manage_options(): void
    {
        if ( ! $this->can_manage_admin() ) {
            wp_die( esc_html__( 'You do not have permission to perform this action.', 'mybookaro' ) );
        }
    }

    private function is_current_page(): bool
    {
        $page = sanitize_key( wp_unslash( $_GET['page'] ?? '' ) );
        return ( 'bookaro-getting-started' === $page );
    }

    private function get_demo_content_status(): array
    {
        $data = get_option( 'bookaro_demo_content', [] );
        if ( ! is_array( $data ) ) {
            $data = [];
        }

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

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

        $exists = ! empty( $pages ) || ! empty( $services );

        return [
            'exists' => $exists,
            'pages' => $pages,
            'services' => $services,
        ];
    }

    private function create_demo_content( int $listing_id, int $provider_id = 0 ): array
    {
        $status = $this->get_demo_content_status();
        $pages = $status['pages'];
        $services = $status['services'];
        $created = false;

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

        $integration_mode = function_exists( 'bookaro_get_integration_mode' )
            ? bookaro_get_integration_mode()
            : 'mylisting';
        $integration_mode = sanitize_key( $integration_mode );

        if ( 'generic' === $integration_mode ) {
            if ( empty( $services ) ) {
                $services = $this->create_demo_services( $listing_id, $provider_id );
                $created = $created || ! empty( $services );
            }
        } elseif ( 'mylisting' === $integration_mode ) {
            $listing_has_services = $listing_id > 0
                ? ( $this->count_listing_services( $listing_id, 'mylisting' ) > 0 )
                : false;
            if ( ! $listing_has_services && $listing_id > 0 ) {
                $new_services = $this->create_demo_services( $listing_id, $provider_id );
                if ( ! empty( $new_services ) ) {
                    $services = array_values( array_unique( array_merge( $services, $new_services ) ) );
                    $created = true;
                }
            }
        }

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

        return [
            'created' => $created,
            'pages' => $pages,
            'services' => $services,
        ];
    }

    private function remove_demo_content(): bool
    {
        $status = $this->get_demo_content_status();
        $removed = false;

        foreach ( $status['pages'] as $page_id ) {
            $page_id = absint( $page_id );
            if ( $page_id > 0 && get_post( $page_id ) ) {
                wp_delete_post( $page_id, true );
                $removed = true;
            }
        }
        foreach ( $status['services'] as $service_id ) {
            $service_id = absint( $service_id );
            if ( $service_id > 0 && get_post( $service_id ) ) {
                wp_delete_post( $service_id, true );
                $removed = true;
            }
        }

        delete_option( 'bookaro_demo_content' );
        return $removed;
    }

    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 = $this->resolve_provider_id( $listing_id );
        }
        $provider_owned = ( $provider_id > 0 || $listing_id > 0 );
        if ( $listing_id > 0 ) {
            $scope = 'listing';
        } elseif ( $provider_id > 0 ) {
            $scope = 'provider';
        } else {
            $scope = 'global';
        }
        $is_shared = $provider_owned ? 0 : 1;
        $owner_type = $provider_owned ? 'provider' : 'admin';

        $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, $is_shared );
            update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, $is_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 create_demo_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(),
        ] );

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

        update_post_meta( $page_id, 'bookaro_demo_content', 1 );
        return (int) $page_id;
    }

    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 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_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 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;
    }
}
