<?php
if (!defined('ABSPATH')) exit;

/**
 * CAS Admin Wizard
 */
if (!function_exists('custausu_admin_module_icon_html')) {
  function custausu_admin_module_icon_html(string $filename, string $class = ''): string {
    $filename = trim($filename);
    $class = sanitize_html_class($class);

    if ($filename === '') {
      return '';
    }

    $rel = 'inc/assets/images/' . ltrim($filename, '/');

    if (
      defined('CUSTAUSU_PLUGIN_DIR') &&
      defined('CUSTAUSU_PLUGIN_URL') &&
      file_exists(CUSTAUSU_PLUGIN_DIR . $rel)
    ) {
      return '<span class="custausu-module-card__icon ' . esc_attr($class) . '" aria-hidden="true">'
        . '<img class="custausu-module-card__icon-img" src="' . esc_url(CUSTAUSU_PLUGIN_URL . $rel) . '" alt="">'
        . '</span>';
    }

    return '<span class="custausu-module-card__icon custausu-module-card__icon--fallback ' . esc_attr($class) . '" aria-hidden="true">'
      . '<span class="dashicons dashicons-shield-alt"></span>'
      . '</span>';
  }
}

if (!function_exists('custausu_wizard_option_name')) {
  function custausu_wizard_option_name(): string {
    return 'custausu_wizard_state';
  }
}

if (!function_exists('custausu_wizard_now_utc')) {
  function custausu_wizard_now_utc(): string {
    return gmdate('Y-m-d H:i:s');
  }
}

if (!function_exists('custausu_wizard_sanitize_datetime')) {
  function custausu_wizard_sanitize_datetime($value): string {
    $value = is_string($value) ? trim($value) : '';
    if ($value === '') return '';

    $ts = strtotime($value . ' UTC');
    if (!is_int($ts) || $ts <= 0) return '';

    return gmdate('Y-m-d H:i:s', $ts);
  }
}

if (!function_exists('custausu_wizard_get_default_state')) {
  function custausu_wizard_get_default_state(): array {
    return [
      'schema_version' => 1,
      'wizard_version' => 1,

      'started_at'   => '',
      'completed_at' => '',
      'dismissed_at' => '',
      'current_step' => 'welcome',

      'completed_steps' => [],

      'last_seen_effective_plan' => 'freemium',

      'is_completed' => 0,
      'is_dismissed' => 0,
    ];
  }
}

if (!function_exists('custausu_wizard_get_steps')) {
  function custausu_wizard_get_steps(): array {
    $steps = [
      'welcome' => [
        'title_en' => 'Welcome to Custom Auth Suite™',
        'title_it' => 'Benvenuto in Custom Auth Suite™',
      ],
      'core_setup' => [
        'title_en' => 'Core auth setup',
        'title_it' => 'Setup auth core',
      ],
      'email_setup' => [
        'title_en' => 'eMail & Assets',
        'title_it' => 'eMail e Asset',
      ],
      'integrations' => [
        'title_en' => 'Integrations',
        'title_it' => 'Integrazioni',
      ],
      'advanced_security' => [
        'title_en' => 'Advanced security',
        'title_it' => 'Sicurezza avanzata',
      ],
      'review' => [
        'title_en' => 'Review',
        'title_it' => 'Riepilogo',
      ],
    ];

    $steps = apply_filters('custausu_wizard_steps', $steps);
    return is_array($steps) ? $steps : [];
  }
}

if (!function_exists('custausu_wizard_normalize_state')) {
  function custausu_wizard_normalize_state(array $state): array {
    $defaults = custausu_wizard_get_default_state();
    $steps = custausu_wizard_get_steps();
    $step_keys = array_keys($steps);

    $current_step = sanitize_key((string)($state['current_step'] ?? $defaults['current_step']));
    if (!in_array($current_step, $step_keys, true)) {
      $current_step = $defaults['current_step'];
    }

    $completed_steps = is_array($state['completed_steps'] ?? null) ? $state['completed_steps'] : [];
    $normalized_completed = [];

    foreach ($completed_steps as $step) {
      $step = sanitize_key((string)$step);
      if ($step !== '' && in_array($step, $step_keys, true)) {
        $normalized_completed[] = $step;
      }
    }

    $normalized_completed = array_values(array_unique($normalized_completed));

    $out = [
      'schema_version' => max(1, (int)($state['schema_version'] ?? $defaults['schema_version'])),
      'wizard_version' => max(1, (int)($state['wizard_version'] ?? $defaults['wizard_version'])),

      'started_at'   => custausu_wizard_sanitize_datetime($state['started_at'] ?? ''),
      'completed_at' => custausu_wizard_sanitize_datetime($state['completed_at'] ?? ''),
      'dismissed_at' => custausu_wizard_sanitize_datetime($state['dismissed_at'] ?? ''),
      'current_step' => $current_step,

      'completed_steps' => $normalized_completed,

      'last_seen_effective_plan' => function_exists('custausu_free_package_sanitize_plan')
        ? (custausu_free_package_sanitize_plan($state['last_seen_effective_plan'] ?? 'freemium', true) ?: 'freemium')
        : 'freemium',

      'is_completed' => !empty($state['is_completed']) ? 1 : 0,
      'is_dismissed' => !empty($state['is_dismissed']) ? 1 : 0,
    ];

    // keep coherence
    if ($out['is_completed'] && $out['completed_at'] === '') {
      $out['completed_at'] = custausu_wizard_now_utc();
    }
    if ($out['is_dismissed'] && $out['dismissed_at'] === '') {
      $out['dismissed_at'] = custausu_wizard_now_utc();
    }

    return $out;
  }
}

if (!function_exists('custausu_wizard_bootstrap')) {
  function custausu_wizard_bootstrap(): void {
    $key = custausu_wizard_option_name();
    $existing = get_option($key, null);

    if ($existing === null) {
      add_option($key, custausu_wizard_get_default_state(), '', 'no');
      return;
    }

    $normalized = custausu_wizard_normalize_state(is_array($existing) ? $existing : []);
    if ($normalized !== $existing) {
      update_option($key, $normalized);
    }
  }
}

if (!function_exists('custausu_wizard_get_state')) {
  function custausu_wizard_get_state(): array {
    custausu_wizard_bootstrap();

    $raw = get_option(custausu_wizard_option_name(), []);
    $state = custausu_wizard_normalize_state(is_array($raw) ? $raw : []);

    if (function_exists('custausu_free_package_runtime_context')) {
      $license_state = custausu_free_package_runtime_context();
      $state['last_seen_effective_plan'] = (string)($license_state['effective_plan'] ?? 'freemium');
    }

    if ($state !== $raw) {
      update_option(custausu_wizard_option_name(), $state);
    }

    return $state;
  }
}

if (!function_exists('custausu_wizard_update_state')) {
  function custausu_wizard_update_state(array $state): bool {
    $state = custausu_wizard_normalize_state($state);
    return (bool) update_option(custausu_wizard_option_name(), $state);
  }
}

if (!function_exists('custausu_wizard_step_index')) {
  function custausu_wizard_step_index(string $step): int {
    $steps = array_keys(custausu_wizard_get_steps());
    $idx = array_search($step, $steps, true);
    return is_int($idx) ? $idx : 0;
  }
}

if (!function_exists('custausu_wizard_next_step')) {
  function custausu_wizard_next_step(string $step): string {
    $steps = array_keys(custausu_wizard_get_steps());
    $idx = array_search($step, $steps, true);
    if (!is_int($idx)) return $steps[0] ?? 'welcome';
    return $steps[$idx + 1] ?? $step;
  }
}

if (!function_exists('custausu_wizard_prev_step')) {
  function custausu_wizard_prev_step(string $step): string {
    $steps = array_keys(custausu_wizard_get_steps());
    $idx = array_search($step, $steps, true);
    if (!is_int($idx) || $idx <= 0) return $steps[0] ?? 'welcome';
    return $steps[$idx - 1] ?? $step;
  }
}

if (!function_exists('custausu_wizard_mark_step_complete')) {
  function custausu_wizard_mark_step_complete(array $state, string $step): array {
    $step = sanitize_key($step);
    $steps = array_keys(custausu_wizard_get_steps());
    if (!in_array($step, $steps, true)) return $state;

    $completed = is_array($state['completed_steps'] ?? null) ? $state['completed_steps'] : [];
    $completed[] = $step;
    $state['completed_steps'] = array_values(array_unique(array_map('sanitize_key', $completed)));

    if ($state['started_at'] === '') {
      $state['started_at'] = custausu_wizard_now_utc();
    }

    return custausu_wizard_normalize_state($state);
  }
}

if (!function_exists('custausu_wizard_set_current_step')) {
  function custausu_wizard_set_current_step(array $state, string $step): array {
    $step = sanitize_key($step);
    $steps = array_keys(custausu_wizard_get_steps());
    if (!in_array($step, $steps, true)) return $state;

    $state['current_step'] = $step;

    if ($state['started_at'] === '') {
      $state['started_at'] = custausu_wizard_now_utc();
    }

    return custausu_wizard_normalize_state($state);
  }
}

if (!function_exists('custausu_wizard_complete')) {
  function custausu_wizard_complete(): bool {
    /*
     * Completion is a server-side safety boundary, not only a disabled button.
     * Direct calls must not complete setup while Auth Core errors are blocking.
     */
    if (
      function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors()
    ) {
      return false;
    }

    $state = custausu_wizard_get_state();
    $state['is_completed'] = 1;
    $state['is_dismissed'] = 0;
    $state['completed_at'] = custausu_wizard_now_utc();
    $state['dismissed_at'] = '';
    $state['completed_steps'] = array_keys(custausu_wizard_get_steps());
    $state['current_step'] = 'review';

    if (function_exists('custausu_wizard_mark_setup_completed_flags')) {
      custausu_wizard_mark_setup_completed_flags((string) $state['completed_at']);
    }

    return custausu_wizard_update_state($state);
  }
}


if (!function_exists('custausu_wizard_dismiss')) {
  function custausu_wizard_dismiss(): bool {
    /*
     * A critical Auth recovery condition takes priority over the saved
     * dismissed/completed state. The administrator cannot hide the recovery UI
     * until the blocking configuration has been repaired.
     */
    if (
      function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors()
    ) {
      return false;
    }

    $state = custausu_wizard_get_state();
    $state['is_dismissed'] = 1;
    $state['dismissed_at'] = custausu_wizard_now_utc();

    return custausu_wizard_update_state($state);
  }
}


if (!function_exists('custausu_wizard_resume')) {
  function custausu_wizard_resume(): bool {
    $state = custausu_wizard_get_state();
    $state['is_dismissed'] = 0;
    $state['dismissed_at'] = '';

    if (!empty($state['is_completed'])) {
      $state['is_completed'] = 0;
      $state['completed_at'] = '';
    }

    return custausu_wizard_update_state($state);
  }
}

if (!function_exists('custausu_wizard_should_show')) {
  function custausu_wizard_should_show(): bool {
    /*
     * Blocking Auth Core errors always reopen the existing Wizard recovery UI.
     * Historical completion/dismissal flags remain stored and become effective
     * again automatically after the error is resolved.
     */
    if (
      function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors()
    ) {
      return true;
    }

    $state = custausu_wizard_get_state();

    if (!empty($state['is_dismissed'])) return false;
    if (!empty($state['is_completed'])) return false;

    return true;
  }
}


if (!function_exists('custausu_wizard_reset')) {
  function custausu_wizard_reset(): bool {
    $key = custausu_wizard_option_name();

    delete_option($key);
    add_option($key, custausu_wizard_get_default_state(), '', 'no');

    return true;
  }
}

if (!function_exists('custausu_wizard_health_counts')) {
  function custausu_wizard_health_counts(callable $T): array {
    if (!function_exists('custausu_admin_health_check_run')) {
      return [
        'ok' => 0,
        'warn' => 0,
        'err' => 0,
        'info' => 0,
        'preview' => 0,
      ];
    }

    $checks = custausu_admin_health_check_run($T);
    $counts = [
      'ok' => 0,
      'warn' => 0,
      'err' => 0,
      'info' => 0,
      'preview' => 0,
    ];

    foreach ((array)$checks as $c) {
      $sev = strtolower(trim((string)($c['sev'] ?? '')));
      if (isset($counts[$sev])) {
        $counts[$sev]++;
      }
    }

    return $counts;
  }
}

if (!function_exists('custausu_wizard_step_title')) {
  function custausu_wizard_step_title(string $step, callable $T): string {
    $steps = custausu_wizard_get_steps();
    $row = $steps[$step] ?? [];

    if (function_exists('custausu_admin_is_it') && custausu_admin_is_it() && !empty($row['title_it'])) return (string)$row['title_it'];
    if (!empty($row['title_en'])) return (string)$row['title_en'];

    return $step;
  }
}

if (!function_exists('custausu_wizard_step_number_label')) {
  function custausu_wizard_step_number_label(string $step, callable $T): string {
    $steps = array_keys(custausu_wizard_get_steps());
    $idx = array_search($step, $steps, true);
    $num = is_int($idx) ? ($idx + 1) : 1;

    return sprintf($T('Step %d', 'Passo %d'), $num);
  }
}

if (!function_exists('custausu_wizard_step_action_url')) {
  function custausu_wizard_step_action_url(string $step): string {
    return add_query_arg([
      'do'       => 'goto',
      'step'     => sanitize_key($step),
      '_wpnonce' => wp_create_nonce('custausu_wizard_action'),
    ], admin_url('admin-post.php?action=custausu_wizard_action'));
  }
}

if (!function_exists('custausu_wizard_render_badge')) {
  function custausu_wizard_render_badge(string $text, string $variant = 'muted'): string {
    $variant = sanitize_html_class($variant);
    return '<span class="custausu-badge custausu-badge--' . esc_attr($variant) . '">' . esc_html($text) . '</span>';
  }
}

if (!function_exists('custausu_wizard_plan_label')) {
  function custausu_wizard_plan_label(string $plan, callable $T): string {
    if (function_exists('custausu_free_package_sanitize_plan')) {
      $plan = custausu_free_package_sanitize_plan($plan, true);
    } else {
      $plan = sanitize_key($plan);

      if ($plan === 'base') {
        $plan = 'advanced';
      }
    }

    return match ($plan) {
      'freemium' => $T('Free', 'Free'),
      'advanced' => $T('Advanced', 'Advanced'),
      'premium'  => $T('Premium', 'Premium'),
      default    => $plan !== '' ? ucfirst($plan) : $T('Unknown', 'Sconosciuto'),
    };
  }
}

if (!function_exists('custausu_wizard_render_jump_link')) {
  function custausu_wizard_render_jump_link(string $label, string $target_id): string {
    $label = trim($label);
    $target_id = sanitize_html_class($target_id);

    if ($label === '' || $target_id === '') return '';

    return '<a href="#' . esc_attr($target_id) . '" class="button custausu-scrollto" data-target="' . esc_attr($target_id) . '">'
      . '<span class="custausu-scrollto__label">' . esc_html($label) . '</span>'
      . '<span class="custausu-scrollto__arrow" aria-hidden="true">↓</span>'
      . '</a>';
  }
}

if (!function_exists('custausu_wizard_render_jump_links')) {
  function custausu_wizard_render_jump_links(array $links): string {
    $html = '';

    foreach ($links as $row) {
      if (!is_array($row)) continue;

      $label = (string)($row['label'] ?? '');
      $target = (string)($row['target'] ?? '');

      $btn = custausu_wizard_render_jump_link($label, $target);
      if ($btn !== '') {
        $html .= $btn;
      }
    }

    if ($html === '') return '';

    return '<div class="custausu-wizard-links">' . $html . '</div>';
  }
}

if (!function_exists('custausu_wizard_render_actions')) {
  function custausu_wizard_render_actions(callable $T, array $state): string {
    $current = (string)($state['current_step'] ?? 'welcome');

    $base = admin_url('admin-post.php?action=custausu_wizard_action');
    $nonce = wp_create_nonce('custausu_wizard_action');
    $html = '<div class="custausu-wizard-actions">';

    $make_url = function(array $args) use ($base, $nonce): string {
      $args['_wpnonce'] = $nonce;
      return add_query_arg($args, $base);
    };

    if ($current !== 'welcome') {
      $html .= '<a class="button" href="' . esc_url($make_url([
        'do' => 'prev',
        'step' => $current,
      ])) . '">' . esc_html($T('Back', 'Indietro')) . '</a>';
    }

    $has_blocking_errors = (
      function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors()
    );
    $review_blocked = $current === 'review' && $has_blocking_errors;

    if ($review_blocked) {
      $html .= '<span class="button button-primary is-disabled" aria-disabled="true" title="' . esc_attr($T(
        'Resolve blocking Auth Core errors before finishing the wizard.',
        'Risolvi prima gli errori bloccanti dell’Auth Core prima di terminare il wizard.'
      )) . '">'
        . esc_html($T('Finish wizard', 'Termina wizard'))
        . '</span>';

      $html .= '<div class="custausu-wizard-blocking-note">'
        . esc_html(sprintf(
          $T(
            'Finish is disabled because %d blocking Auth Core error(s) still require attention in Routes & Templates.',
            'Finish è disabilitato perché ci sono ancora %d errore/i bloccanti di Auth Core da correggere in Percorsi e Template.'
          ),
          function_exists('custausu_wizard_blocking_errors_count')
            ? (int) custausu_wizard_blocking_errors_count()
            : 1
        ))
        . '</div>';
    } else {
      $html .= '<a class="button button-primary" href="' . esc_url($make_url([
        'do' => 'next',
        'step' => $current,
      ])) . '">' . esc_html(
        $current === 'review'
          ? $T('Finish wizard', 'Termina wizard')
          : $T('Continue', 'Continua')
      ) . '</a>';
    }

    /*
     * Do not offer or accept "Dismiss for now" while critical recovery is
     * required. The server-side dismiss handler enforces the same rule.
     */
    if (!$has_blocking_errors) {
      $html .= '<a class="button" href="' . esc_url($make_url([
        'do' => 'dismiss',
      ])) . '">' . esc_html($T('Dismiss for now', 'Chiudi per ora')) . '</a>';
    }

    $html .= '</div>';

    return $html;
  }
}


if (!function_exists('custausu_wizard_render_step_content')) {
  function custausu_wizard_render_step_content(callable $T, array $state): string {
    $current = (string)($state['current_step'] ?? 'welcome');
    $opt = get_option('custausu_global_settings', []);
    $opt = is_array($opt) ? $opt : [];

    $license_state = function_exists('custausu_free_package_runtime_context') ? custausu_free_package_runtime_context() : [];
    $effective_plan = (string)($license_state['effective_plan'] ?? 'freemium');

    $out = '';

    if ($current === 'welcome') {
      $out .= '<p class="custausu-wizard-text">'
        . esc_html($T(
          'Configure CAS step by step. Free features remain available without expiration; Advanced and Premium previews show optional upgrade paths.',
          'Configura CAS passo dopo passo. Le funzioni Free restano disponibili senza scadenza; le anteprime Advanced e Premium mostrano percorsi di upgrade opzionali.'
        ))
        . '</p>';

      $out .= '<div class="custausu-wizard-inline-badges">';
      $out .= custausu_wizard_render_badge(
      sprintf($T('Plan: %s', 'Piano: %s'), custausu_wizard_plan_label($effective_plan, $T)),
      $effective_plan === 'premium' ? 'premium' : ($effective_plan === 'advanced' ? 'advanced' : 'free')
      );

      $out .= '</div>';

      $out .= '<ul class="custausu-wizard-list">';
      $out .= '<li>' . esc_html($T(
      'Free: protected paths, registration, lost password, email verification, email templates.',
      'Free: percorsi protetti, registrazione, recupero password, verifica email, template email.'
    )) . '</li>';

    $out .= '<li>' . esc_html($T(
      'Advanced: Polylang / i18n, reCAPTCHA Enterprise, Contact Form 7 + Math Check, assets customization, settings export/import.',
      'Advanced: Polylang / i18n, reCAPTCHA Enterprise, Contact Form 7 + Math Check, personalizzazione asset, esportazione/importazione impostazioni.'
    )) . '</li>';

    $out .= '<li>' . esc_html($T(
      'Premium: WebAuthn / Passkeys, passkey prompt management, device intelligence, advanced debug tools, logs export tools.',
      'Premium: WebAuthn / Passkeys, gestione prompt Passkey, device intelligence, strumenti debug avanzati, strumenti di esportazione log.'
    )) . '</li>';
      $out .= '</ul>';
    }

    if ($current === 'core_setup') {

      $protected = trim((string)($opt['protected_paths'] ?? ''));

      $out .= '<p class="custausu-wizard-text">'
      . esc_html($T(
        'Review the core auth routes and protected paths. Before configuring routes, create the required WordPress pages and assign the correct CAS page templates to them. For each route, CAS accepts either a selected WordPress page OR a path.',
        'Controlla le route auth core e i percorsi protetti. Prima di configurare le route, crea le pagine WordPress necessarie e assegna loro i corretti template pagina CAS. Per ogni route, CAS accetta una pagina WordPress selezionata OPPURE un path.'
      ))
      . '</p>';

      $out .= '<ul class="custausu-wizard-list">';
      $out .= '<li>' . esc_html($T('Login page → Account Login template', 'Pagina login → template Account Login')) . '</li>';
      $out .= '<li>' . esc_html($T('Registration page → Account Register template', 'Pagina registrazione → template Account Register')) . '</li>';
      $out .= '<li>' . esc_html($T('Lost password page → Lost Password template', 'Pagina recupero password → template Lost Password')) . '</li>';
      $out .= '<li>' . esc_html($T('Password reset confirmation page → Lost Password Confirm template', 'Pagina conferma reset password → template Lost Password Confirm')) . '</li>';
      $out .= '</ul>';

      if (function_exists('custausu_admin_render_auth_pages_wizard_card')) {
        ob_start();
        custausu_admin_render_auth_pages_wizard_card($opt);
        $out .= (string) ob_get_clean();
      }

      $out .= '<p class="custausu-wizard-tip">'
        . '<span class="custausu-wizard-tip__label">' . esc_html($T('Important:', 'Importante:')) . ' </span>'
        . '<span class="custausu-wizard-tip__text">' . esc_html($T(
            'Page titles and slugs may be customized. What matters is the correct CAS template assignment and the correct route mapping below.',
            'Titoli e slug delle pagine possono essere personalizzati. Ciò che conta è l’assegnazione corretta del template CAS e la corretta mappatura della route qui sotto.'
          )) . '</span>'
        . '</p>';

      $step_alerts = custausu_wizard_get_step_attention_items('core_setup', $T);

      if (empty($step_alerts['error']) && empty($step_alerts['warn'])) {
      $out .= custausu_wizard_render_success_box(
      $T(
        'Core routes and protected paths appear configured.',
        'Le route core e i percorsi protetti risultano configurati.'
      ),
      $T(
        'The current Auth Core configuration appears complete and coherent.',
        'La configurazione Auth Core attuale risulta completa e coerente.'
      )
    );
    } else {
      $out .= custausu_wizard_render_step_alerts('core_setup', $T);
    }

      $out .= '<p class="custausu-wizard-tip">'
        . '<span class="custausu-wizard-tip__label">' . esc_html($T('Tip:', 'Tip:')) . ' </span>'
        . '<span class="custausu-wizard-tip__text">' . esc_html($T(
            'Routes & Templates define where CAS auth templates live; Protected Paths define what content requires login.',
            'Routes & Templates definisce dove vivono i template auth CAS; Protected Paths definisce quali contenuti richiedono login.'
          )) . '</span>'
        . '</p>';

      $out .= custausu_wizard_render_jump_links([
        ['label' => $T('Go to Routes & Templates', 'Vai a Percorsi e Template'), 'target' => 'custausu-section-routes-templates'],
        ['label' => $T('Go to Protected Paths', 'Vai a Percorsi Protetti'), 'target' => 'custausu-section-protected-paths'],
      ]);
    }
    if ($current === 'email_setup') {
      $out .= '<p class="custausu-wizard-text">'
        . esc_html($T(
          'eMail palette and templates are part of the Free core. Custom visual assets are optional branding enhancements available with Advanced.',
          'Palette e template eMail fanno parte del core Free. Gli asset visuali personalizzati sono miglioramenti opzionali di branding disponibili con Advanced.'
        ))
        . '</p>';

      $out .= custausu_wizard_render_success_box(
        $T('Free eMail customization is ready.', 'La personalizzazione eMail Free è pronta.'),
        $T(
          'CAS uses its built-in login/check visuals and the site home URL for the support token.',
          'CAS usa gli elementi visuali login/check integrati e la home del sito per il token di supporto.'
        )
      );

      $out .= '<p class="custausu-wizard-status custausu-wizard-status--preview">ℹ '
        . esc_html($T(
          'Custom image URLs and email branding assets are available with Advanced.',
          'URL immagine personalizzati e asset di branding email sono disponibili con Advanced.'
        ))
        . '</p>';

      $out .= custausu_wizard_render_jump_links([
        ['label' => $T('Go to eMail Customizer', 'Vai a Personalizzazione eMail'), 'target' => 'custausu-section-email-customizer'],
        ['label' => $T('View Advanced Assets preview', 'Vedi anteprima Assets Advanced'), 'target' => 'custausu-section-assets'],
      ]);
    }


    if ($current === 'integrations') {
      $out .= '<p class="custausu-wizard-text">'
        . esc_html($T(
          'Optional integrations are available in the separately distributed Advanced package.',
          'Le integrazioni opzionali sono disponibili nel pacchetto Advanced distribuito separatamente.'
        ))
        . '</p>';

      $out .= custausu_wizard_render_status_box(
        'warn',
        $T(
          'Advanced integration preview.',
          'Anteprima integrazioni Advanced.'
        ),
        $T(
          'Polylang / i18n, reCAPTCHA Enterprise, Contact Form 7 + Math Check',
          'Polylang / i18n, reCAPTCHA Enterprise, Contact Form 7 + Math Check'
        )
      );
    }

    if ($current === 'advanced_security') {
      $out .= '<p class="custausu-wizard-text">'
        . esc_html($T(
          'WebAuthn / Passkeys and device intelligence are implemented only in the separately distributed Premium package.',
          'WebAuthn / Passkeys e device intelligence sono implementati soltanto nel pacchetto Premium distribuito separatamente.'
        ))
        . '</p>';
      $out .= '<div class="custausu-wizard-inline-badges">'
        . custausu_wizard_render_badge(
          $T('Premium informational preview', 'Anteprima informativa Premium'),
          'preview'
        )
        . '</div>';
      $out .= custausu_wizard_render_status_box(
        'preview',
        $T('Separate Premium package', 'Pacchetto Premium separato'),
        $T(
          'No Passkey runtime, endpoint, credential store or device-intelligence implementation is included in this WordPress.org Free ZIP.',
          'In questo ZIP Free di WordPress.org non è incluso alcun runtime Passkey, endpoint, archivio credenziali o implementazione di device intelligence.'
        )
      );
    }
    if ($current === 'review') {
      $counts = custausu_wizard_health_counts($T);

      $out .= '<p class="custausu-wizard-text">'
        . esc_html($T(
          'Review the current plugin health before finishing the setup.',
          'Rivedi lo stato attuale del plugin prima di terminare la configurazione.'
        ))
        . '</p>';

      $out .= '<div class="custausu-wizard-health-badges">';
      $out .= custausu_wizard_render_badge('OK: ' . (int)$counts['ok'], 'ok');
      $out .= custausu_wizard_render_badge('Warn: ' . (int)$counts['warn'], 'warn');
      $out .= custausu_wizard_render_badge('Error: ' . (int)$counts['err'], 'error');
      $out .= custausu_wizard_render_badge('Info: ' . (int)$counts['info'], 'info');
      $out .= custausu_wizard_render_badge('Plan features: ' . (int)$counts['preview'], 'preview');
      $out .= '</div>';

    }

    return $out;
  }
}

if (!function_exists('custausu_wizard_step_attention_map')) {
  function custausu_wizard_step_attention_map(callable $T): array {
    $items = custausu_wizard_collect_attention_items($T);

    $rank = [
      'ok'     => 0,
      'info'   => 1,
      'preview' => 2,
      'warn'   => 3,
      'error'  => 4,
    ];

    $map = [];

    foreach ((array)$items as $item) {
      $step = sanitize_key((string)($item['step'] ?? ''));
      $sev  = strtolower(trim((string)($item['severity'] ?? '')));

      if ($step === '') continue;
      if (!isset($rank[$sev])) continue;

      if (!isset($map[$step]) || $rank[$sev] > $rank[$map[$step]]) {
        $map[$step] = $sev;
      }
    }

    return $map;
  }
}

if (!function_exists('custausu_wizard_render_steps_bar')) {
  function custausu_wizard_render_steps_bar(callable $T, array $state): string {
    $steps = custausu_wizard_get_steps();
    $current = (string)($state['current_step'] ?? 'welcome');
    $completed = is_array($state['completed_steps'] ?? null) ? $state['completed_steps'] : [];
    $attention = function_exists('custausu_wizard_attention_index')
      ? custausu_wizard_attention_index($T)
      : [];
    $attention_map = custausu_wizard_step_attention_map($T);

    $base = admin_url('admin-post.php?action=custausu_wizard_action');
    $nonce = wp_create_nonce('custausu_wizard_action');

    $html = '<div class="custausu-wizard-steps">';

    foreach ($steps as $key => $_meta) {
      $is_current = ($key === $current);
    $is_done = in_array($key, $completed, true);
      $step_meta = is_array($attention[$key] ?? null) ? $attention[$key] : [];
      $has_error = !empty($step_meta['error']);
      $has_warn = !$has_error && !empty($step_meta['warn']);
      $has_locked_only = !$has_error && !$has_warn && !empty($step_meta['preview']);
      $availability_plan = (string)($step_meta['availability_plan'] ?? '');
    $step_sev = (string)($attention_map[$key] ?? '');

    $classes = ['custausu-wizard-step'];
    $icon = '○';

    if ($is_done) {
      $classes[] = 'custausu-wizard-step--done';
      $icon = '✓';
    }

    if ($step_sev === 'warn') {
      $classes[] = 'custausu-wizard-step--warn';
      $icon = '!';
    } elseif ($step_sev === 'error') {
      $classes[] = 'custausu-wizard-step--error';
      $icon = '!';
    }

    if ($is_current) {
      $classes[] = 'custausu-wizard-step--current';
      if (!$is_done && $step_sev !== 'warn' && $step_sev !== 'error') {
       $icon = '•';
     }
    }

      $meta_html = '';

      if ($has_error) {
        $classes[] = 'custausu-wizard-step--error';
        $icon = '!';
      } elseif ($has_warn) {
        $classes[] = 'custausu-wizard-step--warn';
        $icon = '!';
      } elseif ($has_locked_only) {
        $classes[] = 'custausu-wizard-step--preview-muted';

        if ($key !== 'review' && in_array($availability_plan, ['advanced', 'premium'], true)) {
          $meta_html = '<div class="custausu-wizard-step__meta">'
            . custausu_wizard_render_badge(
                custausu_wizard_plan_label($availability_plan, $T),
                $availability_plan === 'premium' ? 'premium' : 'advanced'
              )
            . '</div>';
        }
      }
      $url = add_query_arg([
        'do'       => 'goto',
        'step'     => $key,
        '_wpnonce' => $nonce,
      ], $base);

      $html .= '<div class="' . esc_attr(implode(' ', $classes)) . '">';
      $html .= '<a class="custausu-wizard-step__link" href="' . esc_url($url) . '">';
      $html .= '<div class="custausu-wizard-step__key">' . esc_html($icon . ' ' . custausu_wizard_step_number_label($key, $T)) . '</div>';
      $html .= '<div class="custausu-wizard-step__title">' . esc_html(custausu_wizard_step_title($key, $T)) . '</div>';
      $html .= $meta_html;
      $html .= '</a>';
      $html .= '</div>';
    }

    $html .= '</div>';

    return $html;
  }
}

if (!function_exists('custausu_wizard_collect_blocking_items')) {
  function custausu_wizard_collect_blocking_items(): array {
    /*
     * Canonical Wizard blocking inventory.
     *
     * It combines field-level validation with the same Auth page/route
     * consistency engine used by Health Check. This keeps Finish, Dismiss,
     * the critical banner and the Health Check aligned when a selected Auth
     * page is deleted, trashed, assigned a wrong template or changes URL.
     */
    $items_by_target = [];

    $noopT = static function(string $en, string $it = ''): string {
      unset($it);
      return $en;
    };

    if (function_exists('custausu_wizard_collect_field_alerts')) {
      foreach ((array) custausu_wizard_collect_field_alerts($noopT) as $row) {
        $target   = sanitize_text_field((string)($row['target'] ?? ''));
        $severity = strtolower(trim((string)($row['severity'] ?? '')));
        $message  = sanitize_text_field((string)($row['message'] ?? ''));

        if ($severity !== 'error' || $target === '') {
          continue;
        }

        if ($target === 'protected_paths') {
          $items_by_target[$target] = [
            'target'   => $target,
            'lang'     => '',
            'key'      => 'protected_paths',
            'reason'   => 'auth_route_collision',
            'step'     => 'core_setup',
            'message'  => $message,
            'severity' => 'error',
          ];
          continue;
        }

        if (strpos($target, 'route:') !== 0) {
          continue;
        }

        $parts = explode(':', $target);
        if (count($parts) !== 3) {
          continue;
        }

        $lang = sanitize_key((string)$parts[1]);
        $key  = sanitize_key((string)$parts[2]);

        if (!in_array(
          $key,
          ['login', 'register', 'lostpassword', 'lostpassword_confirm'],
          true
        )) {
          continue;
        }

        $items_by_target[$target] = [
          'target'   => $target,
          'lang'     => $lang,
          'key'      => $key,
          'reason'   => 'missing_page_or_path',
          'step'     => 'core_setup',
          'message'  => $message,
          'severity' => 'error',
        ];
      }
    }

    if (function_exists('custausu_auth_page_route_consistency_issues')) {
      foreach ((array) custausu_auth_page_route_consistency_issues() as $issue) {
        if (!is_array($issue)) {
          continue;
        }

        $reason = sanitize_key((string)($issue['reason'] ?? ''));
        $lang   = sanitize_key((string)($issue['lang'] ?? ''));
        $key    = sanitize_key((string)($issue['route'] ?? ''));

        if (!in_array(
          $reason,
          [
            'auth_route_page_missing',
            'auth_route_template_mismatch',
            'auth_route_stale_path',
          ],
          true
        )) {
          continue;
        }

        if (!in_array(
          $key,
          ['login', 'register', 'lostpassword', 'lostpassword_confirm'],
          true
        )) {
          continue;
        }

        if ($lang === '') {
          $lang = 'en';
        }

        $target = 'route:' . $lang . ':' . $key;

        if ($reason === 'auth_route_page_missing') {
          $message = sprintf(
            'The selected Auth page no longer exists or is unavailable: %s (%s).',
            $key,
            strtoupper($lang)
          );
        } elseif ($reason === 'auth_route_template_mismatch') {
          $message = sprintf(
            'The selected Auth page no longer uses the expected CAS template: %s (%s).',
            $key,
            strtoupper($lang)
          );
        } else {
          $message = sprintf(
            'The saved Auth route path no longer matches the selected page URL: %s (%s).',
            $key,
            strtoupper($lang)
          );
        }

        /*
         * One blocking item per route is enough even if the same page has both
         * a template and URL mismatch. Page-missing has the highest priority.
         */
        $priority = [
          'missing_page_or_path' => 4,
          'auth_route_page_missing' => 3,
          'auth_route_template_mismatch' => 2,
          'auth_route_stale_path' => 1,
        ];
        $existing_reason = sanitize_key(
          (string)($items_by_target[$target]['reason'] ?? '')
        );

        if (
          isset($items_by_target[$target])
          && ($priority[$existing_reason] ?? 0) >= ($priority[$reason] ?? 0)
        ) {
          continue;
        }

        $items_by_target[$target] = [
          'target'   => $target,
          'lang'     => $lang,
          'key'      => $key,
          'reason'   => $reason,
          'step'     => 'core_setup',
          'message'  => $message,
          'severity' => 'error',
        ];
      }
    }

    ksort($items_by_target);
    return array_values($items_by_target);
  }
}


if (!function_exists('custausu_wizard_has_blocking_errors')) {
  function custausu_wizard_has_blocking_errors(): bool {
    return !empty(custausu_wizard_collect_blocking_items());
  }
}

if (!function_exists('custausu_wizard_blocking_errors_count')) {
  function custausu_wizard_blocking_errors_count(): int {
    return count(custausu_wizard_collect_blocking_items());
  }
}

if (!function_exists('custausu_wizard_collect_attention_items')) {
  function custausu_wizard_collect_attention_items(callable $T): array {
    $items = [];
    $opt = get_option('custausu_global_settings', []);
    $opt = is_array($opt) ? $opt : [];

    // Core setup: routes page/path + collisions
    $routes_missing = false;
    $routes_collision = false;
    $routes_consistency = false;

    if (function_exists('custausu_admin_health_check_run')) {
      foreach ((array) custausu_admin_health_check_run($T) as $check) {
        $reason = (string)($check['reason'] ?? '');

        if ($reason === 'missing_page_or_path') {
          $routes_missing = true;
        }

        if ($reason === 'auth_route_collision') {
          $routes_collision = true;
        }

        if (in_array($reason, ['auth_route_stale_path', 'auth_route_template_mismatch', 'auth_route_page_missing'], true)) {
          $routes_consistency = true;
        }
      }
    }

    if ($routes_missing) {
      $items[] = [
        'severity' => 'error',
        'blocking' => true,
        'step'     => 'core_setup',
        'title'    => $T(
          'One or more auth routes still need a page or a path.',
          'Una o più route auth devono ancora avere una pagina o un path.'
        ),
      ];
    }

    if ($routes_collision) {
      $items[] = [
        'severity' => 'error',
        'blocking' => true,
        'step'     => 'core_setup',
        'title'    => $T(
          'One or more protected paths collide with auth routes.',
          'Uno o più percorsi protetti collidono con le route auth.'
        ),
      ];
    }

    if ($routes_consistency) {
      $items[] = [
        'severity' => 'error',
        'blocking' => true,
        'step'     => 'core_setup',
        'title'    => $T(
          'One or more Auth route pages changed URL/slug or template.',
          'Una o più pagine Auth hanno cambiato URL/slug o template.'
        ),
      ];
    }

    if (trim((string)($opt['protected_paths'] ?? '')) === '') {
      $items[] = [
        'severity' => 'warn',
        'step'     => 'core_setup',
        'title'    => $T(
          'Protected paths are not configured yet.',
          'I percorsi protetti non sono ancora configurati.'
        ),
      ];
    }

    $logout_protected_conflicts = function_exists('custausu_wizard_collect_logout_redirect_protected_conflicts')
      ? custausu_wizard_collect_logout_redirect_protected_conflicts($opt)
      : [];

    if (!empty($logout_protected_conflicts)) {
      $first = $logout_protected_conflicts[0];

      $items[] = [
        'severity' => 'warn',
        'step'     => 'core_setup',
        'title'    => sprintf(
          $T(
            'Logout redirect points to a protected path: %s → %s.',
            'Il redirect dopo logout punta a un percorso protetto: %s → %s.'
          ),
          (string)($first['label'] ?? 'Logout'),
          (string)($first['logout_path'] ?? '')
        ),
      ];
    }

    // Custom Assets are an Advanced preview and never create Free warnings.


    // Local informational previews of separately distributed packages.
    $items[] = [
      'severity' => 'preview',
      'step' => 'integrations',
      'availability_plan' => 'advanced',
      'title' => $T(
        'Polylang, reCAPTCHA and CF7 integration implementations are available in the separate Advanced package.',
        'Le implementazioni Polylang, reCAPTCHA e integrazione CF7 sono disponibili nel pacchetto Advanced separato.'
      ),
    ];
    $items[] = [
      'severity' => 'preview',
      'step' => 'advanced_security',
      'availability_plan' => 'premium',
      'title' => $T(
        'Passkeys, device intelligence and advanced operational tools are available in the separate Premium package.',
        'Passkey, device intelligence e strumenti operativi avanzati sono disponibili nel pacchetto Premium separato.'
      ),
    ];
    $items[] = [
      'severity' => 'preview',
      'step' => 'review',
      'availability_plan' => 'advanced',
      'title' => $T(
        'Settings transfer is available in the separate Advanced package.',
        'Il trasferimento impostazioni è disponibile nel pacchetto Advanced separato.'
      ),
    ];
    return $items;
  }
}

if (!function_exists('custausu_wizard_attention_index')) {
  function custausu_wizard_attention_index(callable $T): array {
    $items = custausu_wizard_collect_attention_items($T);
    $out = [];

    foreach ((array)$items as $item) {
      $step = sanitize_key((string)($item['step'] ?? ''));
      $sev  = strtolower(trim((string)($item['severity'] ?? '')));

      if ($step === '' || !in_array($sev, ['error', 'warn', 'preview'], true)) {
        continue;
      }

      if (!isset($out[$step])) {
        $out[$step] = [
          'error'         => 0,
          'warn'          => 0,
          'preview'        => 0,
          'availability_plan' => '',
        ];
      }

      $out[$step][$sev]++;

      $availability_plan = function_exists('custausu_free_package_sanitize_plan')
        ? custausu_free_package_sanitize_plan((string)($item['availability_plan'] ?? ''), true)
        : sanitize_key((string)($item['availability_plan'] ?? ''));

      if ($availability_plan !== '') {
        $current = (string)($out[$step]['availability_plan'] ?? '');

        $rank_current = function_exists('custausu_free_package_plan_rank') ? custausu_free_package_plan_rank($current) : 0;
        $rank_new     = function_exists('custausu_free_package_plan_rank') ? custausu_free_package_plan_rank($availability_plan) : 0;

        if ($rank_new >= $rank_current) {
          $out[$step]['availability_plan'] = $availability_plan;
        }
      }
    }

    return $out;
  }
}

if (!function_exists('custausu_wizard_get_step_attention_items')) {
  function custausu_wizard_get_step_attention_items(string $step, callable $T): array {
    $step = sanitize_key($step);
    $grouped = [
      'error'  => [],
      'warn'   => [],
      'preview' => [],
    ];

    foreach ((array) custausu_wizard_collect_attention_items($T) as $item) {
      $item_step = sanitize_key((string)($item['step'] ?? ''));
      if ($item_step !== $step) continue;

      $sev   = sanitize_key((string)($item['severity'] ?? 'warn'));
      $title = trim((string)($item['title'] ?? ''));
      if ($title === '') continue;

      if (!isset($grouped[$sev])) {
        $grouped[$sev] = [];
      }

      $grouped[$sev][] = $title;
    }

    return $grouped;
  }
}

if (!function_exists('custausu_wizard_render_alert_box')) {
  function custausu_wizard_render_alert_box(string $variant, string $title, array $items): string {
    $items = array_values(array_filter(array_map('strval', $items)));
    if (empty($items)) return '';

    $variant = in_array($variant, ['error','warn','preview'], true) ? $variant : 'warn';

    $icon = match ($variant) {
      'error'  => '!',
      'preview' => '🔒',
      default  => '⚠',
    };

    $html  = '<div class="custausu-wizard-alert custausu-wizard-alert--' . esc_attr($variant) . '">';
    $html .= '<div class="custausu-wizard-alert__status-row">';
    $html .= '<span class="custausu-wizard-alert__status-icon custausu-wizard-alert__status-icon--' . esc_attr($variant) . '" aria-hidden="true">' . esc_html($icon) . '</span>';
    $html .= '<div class="custausu-wizard-alert__status-content">';
    $html .= '<div class="custausu-wizard-alert__title">' . esc_html($title) . '</div>';
    $html .= '<ul class="custausu-wizard-alert__list">';

    foreach ($items as $item) {
      $html .= '<li>' . esc_html($item) . '</li>';
    }

    $html .= '</ul>';
    $html .= '</div>';
    $html .= '</div>';
    $html .= '</div>';

    return $html;
  }
}

if (!function_exists('custausu_wizard_render_status_box')) {
  function custausu_wizard_render_status_box(string $variant, string $title, string $text = ''): string {
    $variant = in_array($variant, ['ok','warn','error'], true) ? $variant : 'ok';

    $icon = match ($variant) {
      'error' => '!',
      'warn'  => '⚠',
      default => '✓',
    };

    $html  = '<div class="custausu-wizard-alert custausu-wizard-alert--' . esc_attr($variant) . '">';
    $html .= '<div class="custausu-wizard-alert__status-row">';
    $html .= '<span class="custausu-wizard-alert__status-icon custausu-wizard-alert__status-icon--' . esc_attr($variant) . '" aria-hidden="true">' . esc_html($icon) . '</span>';
    $html .= '<div class="custausu-wizard-alert__status-content">';
    $html .= '<div class="custausu-wizard-alert__title">' . esc_html($title) . '</div>';

    if (trim($text) !== '') {
      $html .= '<div class="custausu-wizard-alert__status-text">' . esc_html($text) . '</div>';
    }

    $html .= '</div>';
    $html .= '</div>';
    $html .= '</div>';

    return $html;
  }
}

if (!function_exists('custausu_wizard_render_success_box')) {
  function custausu_wizard_render_success_box(string $title, string $text = ''): string {
    return custausu_wizard_render_status_box('ok', $title, $text);
  }
}

if (!function_exists('custausu_wizard_render_step_alerts')) {
  function custausu_wizard_render_step_alerts(string $step, callable $T): string {
    $items = custausu_wizard_get_step_attention_items($step, $T);
    $html = '';

    $html .= custausu_wizard_render_alert_box(
      'error',
      $T('Required fixes', 'Correzioni richieste'),
      $items['error'] ?? []
    );

    $html .= custausu_wizard_render_alert_box(
      'warn',
      $T('Recommended review', 'Verifiche consigliate'),
      $items['warn'] ?? []
    );

    $html .= custausu_wizard_render_alert_box(
      'preview',
      $T('Advanced/Premium previews', 'Anteprime Advanced/Premium'),
      $items['preview'] ?? []
    );

    return $html;
  }
}

if (!function_exists('custausu_wizard_normalize_path_for_compare')) {
  function custausu_wizard_normalize_path_for_compare($path): string {
    $path = trim((string)$path);
    if ($path === '') return '';

    $parsed = wp_parse_url($path, PHP_URL_PATH);
    if (is_string($parsed) && $parsed !== '') {
      $path = $parsed;
    }

    $path = trim($path);
    if ($path === '') return '';

    if ($path[0] !== '/') {
      $path = '/' . $path;
    }

    $path = preg_replace('#/+#', '/', $path);
    return rtrim($path, '/') . '/';
  }
}

if (!function_exists('custausu_wizard_collect_protected_paths_for_compare')) {
  function custausu_wizard_collect_protected_paths_for_compare(array $opt): array {
    $raw = (string)($opt['protected_paths'] ?? '');
    $tokens = preg_split('/(?:\r\n|\r|\n|[\t ,;]+)/', $raw);
    $paths = [];

    foreach ((array)$tokens as $token) {
      $p = custausu_wizard_normalize_path_for_compare($token);
      if ($p !== '') {
        $paths[] = $p;
      }
    }

    return array_values(array_unique($paths));
  }
}

if (!function_exists('custausu_wizard_collect_logout_redirect_protected_conflicts')) {
  function custausu_wizard_collect_logout_redirect_protected_conflicts(array $opt): array {
    $protected_paths = custausu_wizard_collect_protected_paths_for_compare($opt);

    if (empty($protected_paths)) {
      return [];
    }

    $logout_redirects = is_array($opt['routes_logout_redirect'] ?? null)
      ? $opt['routes_logout_redirect']
      : [];

    $conflicts = [];

    foreach ($logout_redirects as $key => $raw_path) {
      $key = sanitize_key((string)$key);
      $path = custausu_wizard_normalize_path_for_compare($raw_path);

      if ($key === '' || $path === '') {
        continue;
      }

      foreach ($protected_paths as $protected_path) {
        if ($path === $protected_path || str_starts_with($path, $protected_path)) {
          $conflicts[] = [
            'key' => $key,
            'label' => $key === 'default' ? 'Default fallback' : strtoupper($key),
            'logout_path' => $path,
            'protected_path' => $protected_path,
          ];
          break;
        }
      }
    }

    return $conflicts;
  }
}

if (!function_exists('custausu_wizard_collect_field_alerts')) {
  function custausu_wizard_collect_field_alerts(callable $T): array {
    $alerts = [];
    $opt = get_option('custausu_global_settings', []);
    $opt = is_array($opt) ? $opt : [];

    $site_locale = (string) get_option('WPLANG');
    if ($site_locale === '') $site_locale = 'en_US';

    $site_slug = sanitize_key(strtolower(explode('_', $site_locale)[0] ?? 'en'));
    if ($site_slug === '') $site_slug = 'en';

    $default_lang = sanitize_key((string)($opt['routes_default_lang'] ?? ''));
    if ($default_lang === '') $default_lang = $site_slug;
    $langs = [$default_lang];

    $routes_paths = (array)($opt['routes_paths'] ?? []);
    $routes_ids   = (array)($opt['routes_page_ids'] ?? []);

    foreach ($langs as $lng) {
      foreach (['login','register','lostpassword','lostpassword_confirm'] as $k) {
        $pid = (int)($routes_ids[$lng][$k] ?? 0);
        $pth = trim((string)($routes_paths[$lng][$k] ?? ''));

        if ($pid <= 0 && $pth === '') {
          $alerts[] = [
            'severity' => 'error',
            'target'   => 'route:' . $lng . ':' . $k,
            'step'     => 'core_setup',
            'message'  => sprintf(
              $T(
                'This route still needs a selected page or a path: %s (%s).',
                'Questa route richiede ancora una pagina selezionata o un path: %s (%s).'
              ),
              $k,
              strtoupper($lng)
            ),
          ];
        }
      }
    }

    if (function_exists('custausu_admin_health_check_detect_protected_auth_collisions')) {
      $collisions = custausu_admin_health_check_detect_protected_auth_collisions($opt);

      $protected_collision_added = false;

      foreach ((array)$collisions as $row) {
        $lang = sanitize_key((string)($row['lang'] ?? ''));
        $route_key = sanitize_key((string)($row['route_key'] ?? ''));
        $route_path = (string)($row['route_path'] ?? '');
        $protected_path = (string)($row['protected_path'] ?? '');

        if (!$protected_collision_added) {
          $alerts[] = [
            'severity' => 'error',
            'target'   => 'protected_paths',
            'step'     => 'core_setup',
            'message'  => sprintf(
              $T(
                'Protected Paths collide with one or more auth routes. Example collision: %s ↔ %s.',
                'I Percorsi Protetti collidono con una o più route auth. Esempio collisione: %s ↔ %s.'
              ),
              $protected_path,
              $route_path
            ),
          ];
          $protected_collision_added = true;
        }

        if ($lang !== '' && $route_key !== '') {
          $alerts[] = [
            'severity' => 'error',
            'target'   => 'route:' . $lang . ':' . $route_key,
            'step'     => 'core_setup',
            'message'  => sprintf(
              $T(
                'This auth route collides with Protected Paths: %s.',
                'Questa route auth collide con i Percorsi Protetti: %s.'
              ),
              $route_path
            ),
          ];
        }
      }
    }

    $logout_protected_conflicts = function_exists('custausu_wizard_collect_logout_redirect_protected_conflicts')
      ? custausu_wizard_collect_logout_redirect_protected_conflicts($opt)
      : [];

    foreach ($logout_protected_conflicts as $row) {
      $label = (string)($row['label'] ?? 'Logout');
      $logout_path = (string)($row['logout_path'] ?? '');
      $protected_path = (string)($row['protected_path'] ?? '');
      $key = sanitize_key((string)($row['key'] ?? 'default'));

      $alerts[] = [
        'severity' => 'warn',
        'target'   => 'routes_logout_redirect:' . $key,
        'step'     => 'core_setup',
        'message'  => sprintf(
          $T(
            'Logout redirect for %s points to a protected path (%s). After logout, users may be sent back to login.',
            'Il redirect dopo logout per %s punta a un percorso protetto (%s). Dopo il logout, gli utenti potrebbero essere rimandati al login.'
          ),
          $label,
          $protected_path !== '' ? $protected_path : $logout_path
        ),
      ];
    }

    if (trim((string)($opt['protected_paths'] ?? '')) === '') {
      $alerts[] = [
        'severity' => 'warn',
        'target'   => 'protected_paths',
        'step'     => 'core_setup',
        'message'  => $T(
          'Protected paths are still empty.',
          'I percorsi protetti sono ancora vuoti.'
        ),
      ];
    }



    return $alerts;
  }
}

if (!function_exists('custausu_wizard_render_attention_summary')) {
  function custausu_wizard_render_attention_summary(callable $T): string {
    $items = custausu_wizard_collect_attention_items($T);

    $blocking_items = [];
    $normal_items   = [];

    foreach ($items as $item) {
      if (!empty($item['blocking'])) {
        $blocking_items[] = $item;
      } else {
        $normal_items[] = $item;
      }
    }

    $counts = [
      'error'  => 0,
      'warn'   => 0,
      'preview' => 0,
    ];

    foreach ($items as $item) {
      $sev = (string)($item['severity'] ?? '');
      if (isset($counts[$sev])) {
        $counts[$sev]++;
      }
    }

    $step_actions = [];
    foreach ($items as $item) {
      $step = sanitize_key((string)($item['step'] ?? ''));
      $severity = strtolower(trim((string)($item['severity'] ?? '')));

      if ($step === '' || !in_array($severity, ['error', 'warn'], true)) {
        continue;
      }

      if (!isset($step_actions[$step])) {
        $step_actions[$step] = custausu_wizard_step_title($step, $T);
      }
    }

    ob_start();

    echo '<div class="custausu-wizard-summary">';

    if (empty($items)) {
      echo '<div class="custausu-wizard-summary__head">';
      echo '<div class="custausu-wizard-summary__title">' . esc_html($T('Setup summary', 'Riepilogo setup')) . '</div>';
      echo '<div class="custausu-wizard-summary__badges">';
      echo wp_kses( custausu_wizard_render_badge($T('No immediate issues', 'Nessun problema immediato'), 'ok'), custausu_admin_allowed_output_html() );
      echo '</div>';
      echo '</div>';

      echo wp_kses( custausu_wizard_render_success_box(
        $T(
          'The current setup appears complete and coherent.',
          'La configurazione attuale risulta completa e coerente.'
        ),
        $T(
          'No blocking errors or immediate review items were detected in the wizard.',
          'Nel wizard non sono stati rilevati errori bloccanti né elementi che richiedano una verifica immediata.'
        )
      ), custausu_admin_allowed_output_html() );

      echo '</div>';
      return (string) ob_get_clean();
    }

    echo '<div class="custausu-wizard-summary__head">';
    echo '<div class="custausu-wizard-summary__title">' . esc_html($T('Setup summary', 'Riepilogo setup')) . '</div>';
    echo '<div class="custausu-wizard-summary__badges">';

    if ($counts['error'] > 0) {
      echo wp_kses( custausu_wizard_render_badge(
        sprintf($T('%d required', '%d richiesti'), $counts['error']),
        'error'
      ), custausu_admin_allowed_output_html() );
    }
    if ($counts['warn'] > 0) {
      echo wp_kses( custausu_wizard_render_badge(
        sprintf($T('%d to review', '%d da rivedere'), $counts['warn']),
        'warn'
      ), custausu_admin_allowed_output_html() );
    }
    if ($counts['preview'] > 0) {
      echo wp_kses( custausu_wizard_render_badge(
        sprintf($T('%d plan feature', '%d funzioni piano'), $counts['preview']),
        'preview'
      ), custausu_admin_allowed_output_html() );
    }

    echo '</div>';
    echo '</div>';

    if (!empty($blocking_items)) {
      $blocking_titles = [];
      foreach ($blocking_items as $item) {
        $title = trim((string)($item['title'] ?? ''));
        if ($title !== '') $blocking_titles[] = $title;
      }

      echo wp_kses( custausu_wizard_render_alert_box(
        'error',
        $T('Blocking Auth Core issues', 'Problemi bloccanti Auth Core'),
        $blocking_titles
      ), custausu_admin_allowed_output_html() );
    }

    $warn_titles = [];
    $locked_titles = [];

    foreach ($normal_items as $item) {
      $sev = (string)($item['severity'] ?? 'warn');
      $title = trim((string)($item['title'] ?? ''));
      $availability_plan = (string)($item['availability_plan'] ?? '');

      if ($title === '') {
        continue;
      }

      if ($sev === 'preview' && in_array($availability_plan, ['advanced', 'premium'], true)) {
        $title .= ' — ' . custausu_wizard_plan_label($availability_plan, $T);
      }

      if ($sev === 'preview') {
        $locked_titles[] = $title;
      } elseif ($sev === 'warn') {
        $warn_titles[] = $title;
      }
    }

    echo wp_kses( custausu_wizard_render_alert_box(
      'warn',
      $T('Recommended review', 'Verifiche consigliate'),
      $warn_titles
    ), custausu_admin_allowed_output_html() );

    echo wp_kses( custausu_wizard_render_alert_box(
      'preview',
      $T('Advanced/Premium previews', 'Anteprime Advanced/Premium'),
      $locked_titles
    ), custausu_admin_allowed_output_html() );

    if (!empty($step_actions)) {
      echo '<div class="custausu-wizard-summary__actions">';
      foreach ($step_actions as $step => $label) {
        echo '<a class="button" href="' . esc_url(custausu_wizard_step_action_url($step)) . '">'
          . esc_html(sprintf($T('Open: %s', 'Apri: %s'), $label))
          . '</a>';
      }
      echo '</div>';
    }

    echo '</div>';

    return (string) ob_get_clean();
  }
}


if (!function_exists('custausu_wizard_readonly_request_param')) {
  function custausu_wizard_readonly_request_param(string $key, string $source = 'request'): string {
    $key = sanitize_key($key);

    if ($key === '') {
      return '';
    }

    $source = sanitize_key($source);
    $raw = null;

    if ($source === 'get') {
      // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin query arg used only to decide UI visibility.
      if (!isset($_GET[$key])) {
        return '';
      }

      // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only admin query arg; unslashed and sanitized immediately below.
      $raw = wp_unslash($_GET[$key]);
    } else {
      // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin request arg used only to decide UI visibility.
      if (!isset($_REQUEST[$key])) {
        return '';
      }

      // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only admin request arg; unslashed and sanitized immediately below.
      $raw = wp_unslash($_REQUEST[$key]);
    }

    if (is_array($raw)) {
      return '';
    }

    return sanitize_text_field(rawurldecode((string) $raw));
  }
}

if (!function_exists('custausu_wizard_render_panel')) {
  function custausu_wizard_render_panel(callable $T): string {
    $state = custausu_wizard_get_state();
    $current = (string)($state['current_step'] ?? 'welcome');

    ob_start();

    echo '<div class="custausu-wizard-panel custausu-module-card custausu-module-card--wizard">';

    echo '<div class="custausu-wizard-panel__head custausu-module-card__head">';
    echo '<div class="custausu-module-card__main">';

    echo wp_kses( custausu_admin_module_icon_html('custausu-wizard-icon.png', 'custausu-module-card__icon--wizard'), custausu_admin_allowed_output_html() );

    echo '<div class="custausu-module-card__text">';
    echo '<h2 class="custausu-wizard-panel__title custausu-module-card__title">'
      . esc_html($T('CAS Wizard', 'CAS Wizard'))
      . '</h2>';
    echo '<p class="custausu-wizard-panel__desc custausu-module-card__desc">'
      . esc_html($T(
        'Configure or refine Custom Auth Suite with a guided setup. You can reopen the wizard at any time.',
        'Configura o rifinisci Custom Auth Suite con una procedura guidata. Puoi riaprire il wizard in qualsiasi momento.'
      ))
      . '</p>';
    echo '</div>';

    echo '</div>';

    echo '<div class="custausu-module-card__side">';

    if (function_exists('custausu_free_package_plan')) {
      $plan = (string) custausu_free_package_plan();

      echo '<div class="custausu-wizard-panel__badges custausu-module-card__badges">';
      echo wp_kses( custausu_wizard_render_badge(
        sprintf($T('Plan: %s', 'Piano: %s'), custausu_wizard_plan_label($plan, $T)),
        $plan === 'premium' ? 'premium' : ($plan === 'advanced' ? 'advanced' : 'free')
      ), custausu_admin_allowed_output_html() );
      echo '</div>';
    }

    echo '</div>';

    echo '</div>';

    echo '<div class="custausu-module-card__inner">';
    echo wp_kses( custausu_wizard_render_steps_bar($T, $state), custausu_admin_allowed_output_html() );
    echo '</div>';

    echo '<div class="custausu-wizard-panel__body">';
    if (custausu_wizard_readonly_request_param('custausu_wizard_blocked', 'get') !== '') {
      echo '<div class="custausu-wizard-blocking-banner">';
      echo esc_html($T(
        'Finish wizard is currently disabled because blocking Auth Core errors are still present in Routes & Templates.',
        'Il termine del wizard è attualmente disabilitato perché sono ancora presenti errori bloccanti di Auth Core in Percorsi e Template.'
      ));
      echo '</div>';
    }

    if ($current === 'review') {
      echo wp_kses( custausu_wizard_render_attention_summary($T), custausu_admin_allowed_output_html() );
    }

    echo '<div>';
    echo '<div class="custausu-wizard-panel__eyebrow">'
      . esc_html($T('Current step', 'Step corrente'))
      . '</div>';
    echo '<h3 class="custausu-wizard-panel__step-title">'
      . esc_html(custausu_wizard_step_title($current, $T))
      . '</h3>';
    echo '</div>';

    echo wp_kses( custausu_wizard_render_step_content($T, $state), custausu_admin_allowed_output_html() );
    echo wp_kses( custausu_wizard_render_actions($T, $state), custausu_admin_allowed_output_html() );

    if ($current === 'review' && function_exists('custausu_admin_health_check_html')) {
      echo '<div class="custausu-wizard-section">';
      echo wp_kses( custausu_admin_health_check_html($T), custausu_admin_allowed_output_html() );
      echo '</div>';
    }

    echo '</div>';
    echo '</div>';

    return (string) ob_get_clean();
  }
}

if (!function_exists('custausu_wizard_admin_notice_should_show')) {
  function custausu_wizard_admin_notice_should_show(): bool {
    if (!is_admin() || !current_user_can('manage_options')) {
      return false;
    }

    global $pagenow;

    $pagenow = is_string($pagenow ?? '') ? $pagenow : '';

    $screen = function_exists('get_current_screen') ? get_current_screen() : null;
    $screen_id = is_object($screen) && isset($screen->id)
      ? (string)$screen->id
      : '';
    $screen_base = is_object($screen) && isset($screen->base)
      ? (string)$screen->base
      : '';

    $action  = sanitize_key(custausu_wizard_readonly_request_param('action', 'request'));
    $action2 = sanitize_key(custausu_wizard_readonly_request_param('action2', 'request'));

    /*
     * Never interrupt WordPress plugin install/update/overwrite screens.
     * On all normal admin screens, including CAS Settings, a blocking Auth
     * recovery notice must remain visible until the problem is resolved.
     */
    if (
      in_array($pagenow, ['update.php', 'plugin-install.php'], true)
      || in_array($screen_id, ['update', 'plugin-install'], true)
      || in_array($screen_base, ['update', 'plugin-install'], true)
      || in_array(
        $action,
        ['upload-plugin', 'upgrade-plugin', 'update-selected', 'install-plugin'],
        true
      )
      || in_array($action2, ['update-selected'], true)
    ) {
      return false;
    }

    return function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors();
  }
}




if (!function_exists('custausu_wizard_mark_setup_completed_flags')) {
  function custausu_wizard_mark_setup_completed_flags(string $completed_at = ''): void {
    $completed_at = custausu_wizard_sanitize_datetime($completed_at);
    if ($completed_at === '') {
      $completed_at = custausu_wizard_now_utc();
    }

    update_option('custausu_wizard_completed', 1, false);
    update_option('custausu_setup_completed', 1, false);
    update_option('custausu_wizard_completed_at', $completed_at, false);
    update_option('custausu_setup_completed_at', $completed_at, false);

    $opt = get_option('custausu_global_settings', []);
    $opt = is_array($opt) ? $opt : [];

    $opt['wizard_completed'] = 1;
    $opt['setup_completed'] = 1;
    $opt['custausu_wizard_completed'] = 1;
    $opt['wizard_completed_at'] = $completed_at;
    $opt['setup_completed_at'] = $completed_at;

    update_option('custausu_global_settings', $opt, false);
  }
}

if (!function_exists('custausu_wizard_setup_has_no_immediate_issues')) {
  function custausu_wizard_setup_has_no_immediate_issues(): bool {
    if (function_exists('custausu_auth_page_route_consistency_issues')) {
      $route_issues = (array) custausu_auth_page_route_consistency_issues();
      if (!empty($route_issues)) {
        return false;
      }
    }

    if (function_exists('custausu_wizard_has_blocking_errors') && custausu_wizard_has_blocking_errors()) {
      return false;
    }

    if (function_exists('custausu_wizard_collect_attention_items')) {
      $T = function_exists('custausu_admin_t')
        ? 'custausu_admin_t'
        : static function(string $en, string $it = ''): string {
          return $en;
        };

      $items = (array) custausu_wizard_collect_attention_items($T);

      foreach ($items as $item) {
        $severity = sanitize_key((string)($item['severity'] ?? ''));

        if (in_array($severity, ['error', 'warn'], true)) {
          return false;
        }
      }
    }

    return true;
  }
}


if (!function_exists('custausu_wizard_setup_completed')) {
  function custausu_wizard_setup_completed(): bool {
    $state = function_exists('custausu_wizard_get_state')
      ? custausu_wizard_get_state()
      : [];

    if (is_array($state)) {
      if (!empty($state['is_completed']) || !empty($state['completed_at'])) {
        return true;
      }
    }

    $opt = get_option('custausu_global_settings', []);
    $opt = is_array($opt) ? $opt : [];

    if (
      !empty($opt['wizard_completed']) ||
      !empty($opt['setup_completed']) ||
      !empty($opt['custausu_wizard_completed']) ||
      !empty($opt['wizard_completed_at']) ||
      !empty($opt['setup_completed_at'])
    ) {
      return true;
    }

    $completed_flags = [
      get_option('custausu_wizard_completed'),
      get_option('custausu_setup_completed'),
      get_option('custausu_wizard_completed_at'),
      get_option('custausu_setup_completed_at'),
    ];

    foreach ($completed_flags as $flag) {
      if (!empty($flag)) {
        return true;
      }
    }

    if (function_exists('custausu_wizard_setup_has_no_immediate_issues') && custausu_wizard_setup_has_no_immediate_issues()) {
      return true;
    }

    return false;
  }
}

if (!function_exists('custausu_wizard_is_install_update_screen')) {
  function custausu_wizard_is_install_update_screen(): bool {
    global $pagenow;

    $screen = function_exists('get_current_screen') ? get_current_screen() : null;
    $screen_id = is_object($screen) ? (string)($screen->id ?? '') : '';
    $screen_base = is_object($screen) ? (string)($screen->base ?? '') : '';

    $action  = sanitize_key(custausu_wizard_readonly_request_param('action', 'request'));
    $action2 = sanitize_key(custausu_wizard_readonly_request_param('action2', 'request'));

    return in_array((string) $pagenow, ['update.php', 'plugin-install.php'], true)
      || in_array($screen_id, ['update', 'plugin-install'], true)
      || in_array($screen_base, ['update', 'plugin-install'], true)
      || in_array($action, ['upload-plugin', 'upgrade-plugin', 'update-selected', 'install-plugin'], true)
      || in_array($action2, ['update-selected'], true);
  }
}

if (!function_exists('custausu_wizard_render_admin_welcome_notice')) {
  function custausu_wizard_render_admin_welcome_notice(): void {
    if (!is_admin() || !current_user_can('manage_options')) {
      return;
    }

    $page = sanitize_key(custausu_wizard_readonly_request_param('page', 'get'));

    /*
     * CAS Settings already contains the Wizard, Health Check and route alerts.
     * Do not duplicate the global admin notice inside the CAS settings screen.
     */
    if ($page === 'custausu-settings') {
      return;
    }

    if (function_exists('custausu_wizard_setup_completed') && custausu_wizard_setup_completed()) {
      return;
    }

    $T = static function (string $en, string $it = ''): string {
      if (function_exists('custausu_admin_t')) {
        return custausu_admin_t($en, $it !== '' ? $it : $en);
      }

      $locale = (string) get_locale();
      return (strpos($locale, 'it_') === 0 && $it !== '') ? $it : $en;
    };

    $settings_url = admin_url('admin.php?page=custausu-settings');

    $route_issues = [];

    if (function_exists('custausu_auth_page_route_consistency_issues')) {
      $route_issues = (array) custausu_auth_page_route_consistency_issues();
    }

    if (!empty($route_issues)) {
      echo '<div class="notice notice-error custausu-admin-setup-notice custausu-admin-setup-notice--error">';
      echo '<p><strong>Custom Auth Suite:</strong> ';
      echo esc_html(sprintf(
        $T(
          'CAS detected %d Auth route configuration issue(s). Check Routes & Templates.',
          'CAS ha rilevato %d problema/i di configurazione delle route Auth. Controlla Percorsi e Template.'
        ),
        count($route_issues)
      ));
      echo '</p>';
      echo '<p><a class="button button-primary" href="' . esc_url($settings_url . '#custausu-section-routes-templates') . '">';
      echo esc_html($T('Check configuration', 'Controlla configurazione'));
      echo '</a></p>';
      echo '</div>';
      return;
    }

    $completed_flags = [
      get_option('custausu_wizard_completed'),
      get_option('custausu_setup_completed'),
      get_option('custausu_wizard_completed_at'),
      get_option('custausu_setup_completed_at'),
    ];

    foreach ($completed_flags as $flag) {
      if (!empty($flag)) {
        return;
      }
    }

    echo '<div class="notice notice-info custausu-admin-setup-notice custausu-admin-setup-notice--welcome">';
    echo '<p><strong>Custom Auth Suite:</strong> ';
    echo esc_html($T(
      'Welcome to Custom Auth Suite™! Configure the plugin now; it is important to do it as soon as possible.',
      'Benvenuto in Custom Auth Suite™! Configura subito il plugin: è importante farlo il prima possibile.'
    ));
    echo '</p>';
    echo '<p><a class="button button-primary" href="' . esc_url($settings_url) . '">';
    echo esc_html($T('Configure now', 'Configura ora'));
    echo '</a></p>';
    echo '</div>';
  }
}


if (!function_exists('custausu_wizard_render_admin_blocking_notice')) {
  function custausu_wizard_render_admin_blocking_notice(): void {
    if (!current_user_can('manage_options')) {
      return;
    }

    if (
      function_exists('custausu_wizard_is_install_update_screen')
      && custausu_wizard_is_install_update_screen()
    ) {
      return;
    }

    $has_blocking_errors = (
      function_exists('custausu_wizard_has_blocking_errors')
      && custausu_wizard_has_blocking_errors()
    );

    /*
     * A critical Auth recovery condition takes priority over the normal first
     * setup welcome notice. Without blocking errors, retain the existing
     * welcome flow for installations that have not completed setup.
     */
    if (!$has_blocking_errors) {
      if (
        function_exists('custausu_wizard_setup_completed')
        && !custausu_wizard_setup_completed()
      ) {
        custausu_wizard_render_admin_welcome_notice();
      }
      return;
    }

    if (
      !function_exists('custausu_wizard_admin_notice_should_show')
      || !custausu_wizard_admin_notice_should_show()
    ) {
      return;
    }

    $T = function_exists('custausu_admin_t')
      ? 'custausu_admin_t'
      : static function(string $en, string $it = ''): string {
        unset($it);
        return $en;
      };

    $count = function_exists('custausu_wizard_blocking_errors_count')
      ? (int)custausu_wizard_blocking_errors_count()
      : 1;

    /*
     * Use goto instead of resume: the Wizard is made visible by the blocking
     * condition, while historical completed/dismissed flags remain untouched.
     * Once repaired, the previous hidden/completed state becomes effective again.
     */
    $url = wp_nonce_url(
      add_query_arg([
        'action' => 'custausu_wizard_action',
        'do'     => 'goto',
        'step'   => 'core_setup',
      ], admin_url('admin-post.php')),
      'custausu_wizard_action'
    );

    echo '<div class="notice notice-error custausu-admin-setup-notice custausu-admin-setup-notice--error">';
    echo '<p><strong>Custom Auth Suite:</strong> ';
    echo esc_html(sprintf(
      $T(
        'CAS detected %d blocking Auth Core configuration error(s). Review Routes & Templates and Protected Paths.',
        'CAS ha rilevato %d errore/i bloccanti di configurazione Auth Core. Controlla Percorsi e Template e i Percorsi Protetti.'
      ),
      $count
    ));
    echo '</p>';

    echo '<p>';
    echo '<a class="button button-primary" href="' . esc_url($url) . '">'
      . esc_html($T('Review configuration', 'Controlla configurazione'))
      . '</a>';
    echo '</p>';
    echo '</div>';
  }
}


if (!function_exists('custausu_admin_render_top_panel')) {
  function custausu_admin_render_top_panel(callable $T): string {
    if (custausu_wizard_should_show()) {
      return custausu_wizard_render_panel($T);
    }

    if (function_exists('custausu_admin_health_check_html')) {
      $html = '';

      $resume_url = wp_nonce_url(
        add_query_arg([
          'action' => 'custausu_wizard_action',
          'do'     => 'resume',
        ], admin_url('admin-post.php')),
        'custausu_wizard_action'
      );

      $html .= '<div class="custausu-module-card custausu-module-card--wizard custausu-module-card--compact">';
      $html .= '<div class="custausu-module-card__head">';
      $html .= '<div class="custausu-module-card__main">';

      $html .= custausu_admin_module_icon_html('custausu-wizard-icon.png', 'custausu-module-card__icon--wizard');

      $html .= '<div class="custausu-module-card__text">';
      $html .= '<h2 class="custausu-module-card__title">' . esc_html($T('CAS Wizard', 'CAS Wizard')) . '</h2>';
      $html .= '<p class="custausu-module-card__desc">' . esc_html($T(
        'The guided setup is currently hidden. Reopen it when you want to review or adjust the configuration.',
        'La configurazione guidata è attualmente nascosta. Riaprila quando vuoi rivedere o rifinire la configurazione.'
      )) . '</p>';
      $html .= '</div>';

      $html .= '</div>';

      $html .= '<div class="custausu-module-card__side">';
      $html .= '<span class="custausu-badge custausu-badge--ok">' . esc_html($T('Wizard hidden', 'Wizard nascosto')) . '</span>';
      $html .= '<a class="button button-primary custausu-module-card__button" href="' . esc_url($resume_url) . '">'
        . esc_html($T('Reopen wizard', 'Riapri wizard'))
        . '</a>';
      $html .= '</div>';

      $html .= '</div>';
      $html .= '</div>';

      $html .= custausu_admin_health_check_html($T);
      return $html;
    }

    return '';
  }
}

if (!function_exists('custausu_wizard_handle_admin_action')) {
  function custausu_wizard_handle_admin_action(): void {
    if (!is_admin()) return;
    $custausu_wizard_action = isset($_GET['action'])
      ? sanitize_key(wp_unslash((string) $_GET['action']))
      : '';
    if ($custausu_wizard_action !== 'custausu_wizard_action') return;
    if (!current_user_can('manage_options')) wp_die('Forbidden');

    check_admin_referer('custausu_wizard_action');

    $do = sanitize_key(wp_unslash((string)($_GET['do'] ?? '')));
    $step = sanitize_key(wp_unslash((string)($_GET['step'] ?? '')));

    $state = custausu_wizard_get_state();

    if ($do === 'dismiss') {
      if (
        function_exists('custausu_wizard_has_blocking_errors')
        && custausu_wizard_has_blocking_errors()
      ) {
        wp_safe_redirect(add_query_arg([
          'page' => 'custausu-settings',
          'custausu_wizard_blocked' => '1',
        ], admin_url('admin.php')));
        exit;
      }

      custausu_wizard_dismiss();
    }

    if ($do === 'resume') {
      custausu_wizard_resume();

      $state = custausu_wizard_get_state();

      if ($step !== '') {
        $state = custausu_wizard_set_current_step($state, $step);
      }

      custausu_wizard_update_state($state);
    }

    if ($do === 'next') {
      $current = $step !== '' ? $step : (string)($state['current_step'] ?? 'welcome');
      $state = custausu_wizard_mark_step_complete($state, $current);

      $next = custausu_wizard_next_step($current);

      if (
        $current === 'review' &&
        function_exists('custausu_wizard_has_blocking_errors') &&
        custausu_wizard_has_blocking_errors()
      ) {
        wp_safe_redirect(add_query_arg([
          'page' => 'custausu-settings',
          'custausu_wizard_blocked' => '1',
        ], admin_url('admin.php')));
        exit;
      }

      if ($current === 'review' || $next === $current) {
        custausu_wizard_complete();
      } else {
        $state = custausu_wizard_set_current_step($state, $next);
        custausu_wizard_update_state($state);
      }
    }

    if ($do === 'prev') {
      $current = $step !== '' ? $step : (string)($state['current_step'] ?? 'welcome');
      $prev = custausu_wizard_prev_step($current);
      $state = custausu_wizard_set_current_step($state, $prev);
      custausu_wizard_update_state($state);
    }

    if ($do === 'goto') {
      $target = $step !== '' ? $step : 'welcome';
      $state = custausu_wizard_set_current_step($state, $target);
      custausu_wizard_update_state($state);
    }

    wp_safe_redirect(admin_url('admin.php?page=custausu-settings'));
    exit;
  }
}

add_action('admin_init', 'custausu_wizard_bootstrap', 1);
add_action('admin_init', 'custausu_wizard_handle_admin_action', 20);
add_action('admin_notices', 'custausu_wizard_render_admin_blocking_notice');
