<?php
/**
 * Settings UI page renderer for the Comment Security Layer addon.
 *
 * Renders the "Comments" tab inside the core Settings page using the
 * existing Polanger styles. Sub-tabs (General, Bot Protection, Rate
 * Limiting, Content Rules, Silent Mode, Logs, Presets) are rendered
 * inside a single form so a single save handler covers the entire tab.
 *
 * @package Polanger_Dashboard_Tools
 */

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

/**
 * Comment Security Layer settings UI controller.
 */
class PDT_Comment_Security_Page {

  /**
   * Settings service.
   *
   * @var PDT_Comment_Security_Settings
   */
  private $settings;

  /**
   * Logger service.
   *
   * @var PDT_Comment_Security_Logger
   */
  private $logger;

  /**
   * Last saved notice flag for current request.
   *
   * @var string
   */
  private $save_notice = '';

  /**
   * Constructor.
   *
   * @param PDT_Comment_Security_Settings $settings Settings service.
   * @param PDT_Comment_Security_Logger   $logger   Logger service.
   */
  public function __construct( $settings, $logger ) {
    $this->settings = $settings;
    $this->logger   = $logger;
  }

  /**
   * Add the "Comments" tab to the Settings page tabs map.
   *
   * @param array $tabs Existing tabs.
   * @return array
   */
  public function register_tab( $tabs ) {
    if ( ! is_array( $tabs ) ) {
      $tabs = array();
    }

    $new = array();
    foreach ( $tabs as $tab_id => $label ) {
      $new[ $tab_id ] = $label;
      // Insert comment protection tab right after security if present.
      if ( 'security' === $tab_id && ! isset( $tabs['comments'] ) ) {
        $new['comments'] = __( 'Comment Guard', 'polanger-admin-menu-manager' );
      }
    }

    if ( ! isset( $new['comments'] ) ) {
      $new['comments'] = __( 'Comment Guard', 'polanger-admin-menu-manager' );
    }
    return $new;
  }

  /**
   * Register the icon for the Comments tab.
   *
   * @param array $icons Icon map.
   * @return array
   */
  public function register_tab_icon( $icons ) {
    if ( ! is_array( $icons ) ) {
      $icons = array();
    }
    $icons['comments'] = 'dashicons-admin-comments';
    return $icons;
  }

  /**
   * Enqueue CSS / JS for the Comments tab on the Settings page only.
   *
   * @param string $hook Current admin page hook (unused; we self-detect the tab).
   * @return void
   */
  public function enqueue_assets( $hook ) {
    unset( $hook );
    if ( ! $this->is_on_comments_tab() ) {
      return;
    }

    $base_url = plugin_dir_url( dirname( __FILE__ ) ) . 'assets/';
    $version  = defined( 'PDT_VERSION' ) ? PDT_VERSION : '1.0.0';

    wp_enqueue_style(
      'pdt-comment-security',
      $base_url . 'comment-security.css',
      array(),
      $version
    );

    wp_enqueue_script(
      'pdt-comment-security',
      $base_url . 'comment-security.js',
      array( 'jquery' ),
      $version,
      true
    );

    wp_localize_script(
      'pdt-comment-security',
      'pdtCommentSecurityI18n',
      array(
        'confirmClear' => __( 'Are you sure you want to clear all logs? This cannot be undone.', 'polanger-admin-menu-manager' ),
        'confirmReset' => __( 'Reset all Comment Security settings to default?', 'polanger-admin-menu-manager' ),
      )
    );
  }

  /**
   * Determine if the current admin request targets the Comments tab.
   *
   * @return bool
   */
  private function is_on_comments_tab() {
    if ( ! is_admin() ) {
      return false;
    }
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check
    $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
    if ( 'polanger-settings' !== $page ) {
      return false;
    }
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check
    $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
    return 'comments' === $tab;
  }

  /**
   * Handle form save before render so notices show correctly.
   *
   * Implements POST/Redirect/GET so a browser refresh does not re-submit
   * the form (which previously could re-apply a preset accidentally).
   *
   * @return void
   */
  public function maybe_handle_save() {
    if ( ! $this->is_on_comments_tab() ) {
      return;
    }

    if ( ! current_user_can( 'manage_options' ) ) {
      return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $has_save_action = ! empty( $_POST['pdt_cs_save'] ) || ! empty( $_POST['pdt_cs_apply_preset'] );
    if ( ! $has_save_action ) {
      $this->maybe_handle_log_actions();
      $this->capture_redirect_notice();
      return;
    }

    if ( ! check_admin_referer( 'pdt_cs_save', '_pdt_cs_nonce' ) ) {
      return;
    }

    $raw = isset( $_POST['pdt_cs'] ) ? wp_unslash( $_POST['pdt_cs'] ) : array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above.
    $sub = isset( $_POST['sub'] ) ? sanitize_key( wp_unslash( $_POST['sub'] ) ) : 'general';

    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above.
    $apply_preset = isset( $_POST['pdt_cs_apply_preset'] ) ? sanitize_key( $_POST['pdt_cs_apply_preset'] ) : '';
    if ( '' !== $apply_preset ) {
      $this->settings->apply_preset( $apply_preset );
      $this->redirect_to_sub( $sub, 'preset' );
      return;
    }

    $this->settings->save_partial_settings( is_array( $raw ) ? $raw : array(), $this->get_submitted_setting_keys() );
    $this->redirect_to_sub( $sub, 'updated' );
  }

  /**
   * Translate a `?cs_notice=` query arg from a previous redirect into a notice
   * banner shown on the next page render.
   *
   * @return void
   */
  private function capture_redirect_notice() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check.
    $notice = isset( $_GET['cs_notice'] ) ? sanitize_key( wp_unslash( $_GET['cs_notice'] ) ) : '';
    if ( '' === $notice ) {
      return;
    }
    switch ( $notice ) {
      case 'updated':
        $this->save_notice = __( 'Comment Security settings saved.', 'polanger-admin-menu-manager' );
        break;
      case 'preset':
        $this->save_notice = __( 'Preset applied.', 'polanger-admin-menu-manager' );
        break;
      case 'cleared':
        $this->save_notice = __( 'Comment Security logs cleared.', 'polanger-admin-menu-manager' );
        break;
    }
  }

  /**
   * Redirect to a sub-tab with a status notice flag, then exit.
   *
   * @param string $sub          Sub-tab slug.
   * @param string $notice_token Notice token captured on next render.
   * @return void
   */
  private function redirect_to_sub( $sub, $notice_token ) {
    $allowed_subs = array( 'general', 'bot', 'rate', 'content', 'silent', 'logs' );
    if ( ! in_array( $sub, $allowed_subs, true ) ) {
      $sub = 'general';
    }
    $url = add_query_arg(
      array(
        'page'      => 'polanger-settings',
        'tab'       => 'comments',
        'sub'       => $sub,
        'cs_notice' => sanitize_key( $notice_token ),
      ),
      admin_url( 'admin.php' )
    );
    wp_safe_redirect( $url );
    exit;
  }

  /**
   * Get the setting keys owned by the currently submitted sub-tab.
   *
   * @return array
   */
  private function get_submitted_setting_keys() {
    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $sub = isset( $_POST['sub'] ) ? sanitize_key( wp_unslash( $_POST['sub'] ) ) : 'general';

    $map = array(
      'general' => array(
        'enabled',
        'protect_logged_in',
        'logging_enabled',
        'log_allowed',
        'log_retention_days',
      ),
      'bot' => array(
        'honeypot_enabled',
        'honeypot_field_name',
        'timing_enabled',
        'timing_min_seconds',
        'timing_max_seconds',
      ),
      'rate' => array(
        'flood_enabled',
        'flood_per_minute',
        'flood_per_hour',
      ),
      'content' => array(
        'max_links',
        'block_non_latin_only',
        'keyword_match_mode',
        'keyword_blocklist',
        'url_blocklist',
      ),
      'silent' => array(
        'score_enabled',
        'score_threshold_spam',
        'score_threshold_drop',
        'silent_mode',
        'show_human_message',
      ),
    );

    return isset( $map[ $sub ] ) ? $map[ $sub ] : array();
  }

  /**
   * Handle log maintenance actions (clear / purge).
   *
   * @return void
   */
  private function maybe_handle_log_actions() {
    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    if ( ! empty( $_POST['pdt_cs_clear_logs'] ) ) {
      if ( ! check_admin_referer( 'pdt_cs_logs', '_pdt_cs_logs_nonce' ) ) {
        return;
      }
      $this->logger->clear_all();
      $this->redirect_to_sub( 'logs', 'cleared' );
    }
  }

  /**
   * Render the Comments tab body.
   *
   * @param bool $is_readonly Read-only flag.
   * @return void
   */
  public function render_tab( $is_readonly = false ) {
    $settings = $this->settings->get_settings();
    $active_preset_id = $this->settings->get_active_preset_id( $settings );
    $active_preset_label = $this->settings->get_active_preset_label( $settings );

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check
    $sub = isset( $_GET['sub'] ) ? sanitize_key( wp_unslash( $_GET['sub'] ) ) : 'general';
    $allowed_subs = array( 'general', 'bot', 'rate', 'content', 'silent', 'logs' );
    if ( ! in_array( $sub, $allowed_subs, true ) ) {
      $sub = 'general';
    }

    $sub_tabs = array(
      'general'  => array( __( 'General', 'polanger-admin-menu-manager' ), 'dashicons-admin-settings' ),
      'bot'      => array( __( 'Bot Protection', 'polanger-admin-menu-manager' ), 'dashicons-shield-alt' ),
      'rate'     => array( __( 'Rate Limiting', 'polanger-admin-menu-manager' ), 'dashicons-controls-pause' ),
      'content'  => array( __( 'Content Rules', 'polanger-admin-menu-manager' ), 'dashicons-filter' ),
      'silent'   => array( __( 'Silent Mode', 'polanger-admin-menu-manager' ), 'dashicons-hidden' ),
      'logs'     => array( __( 'Logs & Statistics', 'polanger-admin-menu-manager' ), 'dashicons-list-view' ),
    );
    ?>
    <?php if ( '' !== $this->save_notice ) : ?>
      <div class="notice notice-success is-dismissible pdt-cs-notice">
        <p><?php echo esc_html( $this->save_notice ); ?></p>
      </div>
    <?php endif; ?>

    <div class="pdt-cs-section">
      <div class="pdt-cs-intro">
        <span class="dashicons dashicons-admin-comments"></span>
        <div>
          <h2><?php esc_html_e( 'Comment Security Layer', 'polanger-admin-menu-manager' ); ?></h2>
          <p class="description">
            <?php esc_html_e( 'A defense-in-depth comment protection layer with honeypot, timing, link/keyword rules, flood control, behavior score, and silent mode.', 'polanger-admin-menu-manager' ); ?>
          </p>
        </div>
        <span class="pdt-cs-mode-badge pdt-cs-mode-badge-<?php echo esc_attr( $active_preset_id ); ?>">
          <?php
          printf(
            /* translators: %s: preset label */
            esc_html__( 'Mode: %s', 'polanger-admin-menu-manager' ),
            esc_html( $active_preset_label )
          );
          ?>
        </span>
        <span class="pdt-cs-state <?php echo esc_attr( $settings['enabled'] ? 'is-on' : 'is-off' ); ?>">
          <?php echo $settings['enabled'] ? esc_html__( 'Active', 'polanger-admin-menu-manager' ) : esc_html__( 'Disabled', 'polanger-admin-menu-manager' ); ?>
        </span>
      </div>

      <nav class="pdt-cs-subtabs">
        <?php
        foreach ( $sub_tabs as $key => $meta ) :
          $url = add_query_arg(
            array(
              'page' => 'polanger-settings',
              'tab'  => 'comments',
              'sub'  => $key,
            ),
            admin_url( 'admin.php' )
          );
          $active = ( $sub === $key ) ? 'is-active' : '';
          ?>
          <a href="<?php echo esc_url( $url ); ?>" class="pdt-cs-subtab <?php echo esc_attr( $active ); ?>">
            <span class="dashicons <?php echo esc_attr( $meta[1] ); ?>"></span>
            <?php echo esc_html( $meta[0] ); ?>
          </a>
        <?php endforeach; ?>
      </nav>

      <?php if ( $is_readonly ) : ?>
        <div class="pdt-info-notice">
          <span class="dashicons dashicons-visibility"></span>
          <div>
            <strong><?php esc_html_e( 'Read-only Mode', 'polanger-admin-menu-manager' ); ?></strong>
            <p><?php esc_html_e( 'You can view Comment Security settings but cannot save changes.', 'polanger-admin-menu-manager' ); ?></p>
          </div>
        </div>
      <?php endif; ?>

      <?php if ( 'logs' === $sub ) : ?>
        <?php $this->render_logs_panel( $is_readonly ); ?>
      <?php else : ?>
        <form method="post" class="pdt-settings-form pdt-cs-form">
          <?php wp_nonce_field( 'pdt_cs_save', '_pdt_cs_nonce' ); ?>
          <input type="hidden" name="sub" value="<?php echo esc_attr( $sub ); ?>" />

          <?php
          switch ( $sub ) {
            case 'general':
              $this->render_general_panel( $settings, $is_readonly );
              break;
            case 'bot':
              $this->render_bot_panel( $settings, $is_readonly );
              break;
            case 'rate':
              $this->render_rate_panel( $settings, $is_readonly );
              break;
            case 'content':
              $this->render_content_panel( $settings, $is_readonly );
              break;
            case 'silent':
              $this->render_silent_panel( $settings, $is_readonly );
              break;
          }
          ?>

          <?php if ( ! $is_readonly ) : ?>
            <p class="pdt-cs-actions">
              <button type="submit" name="pdt_cs_save" value="1" class="button button-primary">
                <?php esc_html_e( 'Save Changes', 'polanger-admin-menu-manager' ); ?>
              </button>
            </p>
          <?php endif; ?>
        </form>
      <?php endif; ?>
    </div>
    <?php
  }

  /**
   * Render: General sub-panel.
   *
   * @param array $s           Settings.
   * @param bool  $is_readonly Read-only flag.
   * @return void
   */
  private function render_general_panel( $s, $is_readonly ) {
    $disabled = $is_readonly ? 'disabled' : '';
    $current_preset = $this->settings->get_active_preset_id( $s );
    $current_label  = $this->settings->get_active_preset_label( $s );
    $presets        = $this->settings->get_presets();
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'General', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'Master switches for the Comment Security Layer.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[enabled]" value="1" <?php checked( $s['enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Enable Comment Security Layer', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'When disabled, all protection modes and advanced rules are effectively inactive.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-cs-tip-notice">
        <span class="dashicons dashicons-lightbulb"></span>
        <div>
          <strong><?php esc_html_e( 'Recommended setup', 'polanger-admin-menu-manager' ); ?></strong>
          <p><?php esc_html_e( 'If you are not sure which settings to use, choose one of the preset modes and let the system configure protection automatically.', 'polanger-admin-menu-manager' ); ?></p>
        </div>
      </div>

      <div class="pdt-cs-quick-modes">
        <div class="pdt-cs-quick-modes__header">
          <div>
            <h3><?php esc_html_e( 'Quick Protection Modes', 'polanger-admin-menu-manager' ); ?></h3>
            <p class="description"><?php esc_html_e( 'For most sites, selecting a mode is enough. Advanced tabs are only needed for custom tuning.', 'polanger-admin-menu-manager' ); ?></p>
          </div>
          <span class="pdt-cs-quick-modes__active">
            <?php
            printf(
              /* translators: %s: active preset label */
              esc_html__( 'Current mode: %s', 'polanger-admin-menu-manager' ),
              esc_html( $current_label )
            );
            ?>
          </span>
        </div>

        <div class="pdt-cs-presets pdt-cs-presets-compact">
          <?php foreach ( $presets as $key => $preset ) : ?>
            <div class="pdt-cs-preset-card <?php echo $current_preset === $key ? 'is-active' : ''; ?>">
              <h3><?php echo esc_html( $preset['label'] ); ?></h3>
              <p class="description"><?php echo esc_html( $preset['description'] ); ?></p>
              <?php if ( ! $is_readonly ) : ?>
                <button
                  type="submit"
                  name="pdt_cs_apply_preset"
                  value="<?php echo esc_attr( $key ); ?>"
                  class="button <?php echo $current_preset === $key ? 'button-secondary' : 'button-primary'; ?>"
                >
                  <?php echo $current_preset === $key ? esc_html__( 'Current mode', 'polanger-admin-menu-manager' ) : esc_html__( 'Use this mode', 'polanger-admin-menu-manager' ); ?>
                </button>
              <?php endif; ?>
            </div>
          <?php endforeach; ?>
        </div>
      </div>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[protect_logged_in]" value="1" <?php checked( $s['protect_logged_in'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Also apply to logged-in users', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'By default, only anonymous visitors are inspected. Enable this to also screen logged-in user comments.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[logging_enabled]" value="1" <?php checked( $s['logging_enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Enable protection logs', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Records every blocked or screened decision (spam / trash / drop) for the Logs & Statistics screen.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[log_allowed]" value="1" <?php checked( $s['log_allowed'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Also log allowed comments', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Off by default. Enable to log clean (allowed) comments too — useful for tuning thresholds, but may significantly increase log volume on busy sites.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label for="pdt_cs_log_retention_days"><?php esc_html_e( 'Log retention (days)', 'polanger-admin-menu-manager' ); ?></label>
        <input type="number" id="pdt_cs_log_retention_days" name="pdt_cs[log_retention_days]" min="0" max="365"
               value="<?php echo esc_attr( $s['log_retention_days'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        <p class="description"><?php esc_html_e( 'Older log rows are purged daily. Set to 0 to keep forever.', 'polanger-admin-menu-manager' ); ?></p>
      </div>
    </div>
    <?php
  }

  /**
   * Render: Bot Protection sub-panel.
   *
   * @param array $s           Settings.
   * @param bool  $is_readonly Read-only flag.
   * @return void
   */
  private function render_bot_panel( $s, $is_readonly ) {
    $disabled = $is_readonly ? 'disabled' : '';
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Bot Protection', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'Lightweight, no-JavaScript-required defenses against automated submissions.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[honeypot_enabled]" value="1" <?php checked( $s['honeypot_enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Honeypot field', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Adds a hidden form field that humans never see. Bots that auto-fill all inputs, strip unknown fields, or post manipulated payloads are caught quickly.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label for="pdt_cs_honeypot_field_name"><?php esc_html_e( 'Honeypot field name', 'polanger-admin-menu-manager' ); ?></label>
        <input type="text" id="pdt_cs_honeypot_field_name" name="pdt_cs[honeypot_field_name]"
               value="<?php echo esc_attr( $s['honeypot_field_name'] ); ?>" maxlength="60" <?php echo esc_attr( $disabled ); ?> />
        <p class="description"><?php esc_html_e( 'Use a plausible-looking name (e.g. "url2", "homepage_alt"). Avoid names like "honeypot". Legacy default names are automatically hardened with a site-specific fallback.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <hr />

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[timing_enabled]" value="1" <?php checked( $s['timing_enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Submission timing check', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Comments submitted faster than humans can read are likely automated. Missing, tampered, or replayed timing tokens are treated as hard bot signals.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row pdt-cs-inline-fields">
        <div>
          <label for="pdt_cs_timing_min_seconds"><?php esc_html_e( 'Minimum seconds before submit', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_timing_min_seconds" name="pdt_cs[timing_min_seconds]" min="1" max="600"
                 value="<?php echo esc_attr( $s['timing_min_seconds'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
        <div>
          <label for="pdt_cs_timing_max_seconds"><?php esc_html_e( 'Maximum seconds (token expiry)', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_timing_max_seconds" name="pdt_cs[timing_max_seconds]" min="60" max="86400"
                 value="<?php echo esc_attr( $s['timing_max_seconds'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
      </div>
        <p class="description"><?php esc_html_e( 'Tokens are signed with the WordPress salt, bound to the current post, tied to the browser fingerprint, and consumed after a single successful check.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-cs-tip-notice is-subtle">
        <span class="dashicons dashicons-info-outline"></span>
        <div>
          <strong><?php esc_html_e( 'Custom comment forms', 'polanger-admin-menu-manager' ); ?></strong>
          <p><?php esc_html_e( 'By default, missing our hidden marker field is treated as a hard bot signal to prevent marker-stripping bypasses. If your custom comment form cannot include pdt_cs_present, you can opt out with the pdt_comment_security_require_form_marker filter. The other layers — rate limiting, content rules, scoring — keep working in all cases.', 'polanger-admin-menu-manager' ); ?></p>
        </div>
      </div>

      <div class="pdt-cs-tip-notice is-subtle">
        <span class="dashicons dashicons-warning"></span>
        <div>
          <strong><?php esc_html_e( 'Page caching compatibility', 'polanger-admin-menu-manager' ); ?></strong>
          <p>
            <?php esc_html_e( 'If your site uses a full-page cache (WP Super Cache, W3 Total Cache, LiteSpeed Cache, etc.), the timing token baked into the cached HTML is shared between every visitor who loads that page. The first visitor\'s submission consumes the server-side state; all subsequent visitors from the same cached page receive a timing_invalid error.', 'polanger-admin-menu-manager' ); ?>
          </p>
          <p>
            <?php esc_html_e( 'To fix this, add the following line to your theme\'s functions.php or a site-specific plugin:', 'polanger-admin-menu-manager' ); ?>
            <br />
            <code>add_filter( 'pdt_comment_security_timing_stateless', '__return_true' );</code>
            <br />
            <?php esc_html_e( 'Stateless mode verifies tokens by HMAC and age only — authenticity is preserved, one-time-use enforcement is relaxed. Honeypot, flood control, and content rules are unaffected.', 'polanger-admin-menu-manager' ); ?>
          </p>
        </div>
      </div>
    </div>
    <?php
  }

  /**
   * Render: Rate Limiting sub-panel.
   *
   * @param array $s           Settings.
   * @param bool  $is_readonly Read-only flag.
   * @return void
   */
  private function render_rate_panel( $s, $is_readonly ) {
    $disabled = $is_readonly ? 'disabled' : '';
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Rate Limiting', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'Cap how many comments a single IP can submit in a given time window.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[flood_enabled]" value="1" <?php checked( $s['flood_enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Enable flood control', 'polanger-admin-menu-manager' ); ?></span>
        </label>
      </div>

      <div class="pdt-form-row pdt-cs-inline-fields">
        <div>
          <label for="pdt_cs_flood_per_minute"><?php esc_html_e( 'Max comments per minute', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_flood_per_minute" name="pdt_cs[flood_per_minute]" min="1" max="60"
                 value="<?php echo esc_attr( $s['flood_per_minute'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
        <div>
          <label for="pdt_cs_flood_per_hour"><?php esc_html_e( 'Max comments per hour', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_flood_per_hour" name="pdt_cs[flood_per_hour]" min="1" max="1000"
                 value="<?php echo esc_attr( $s['flood_per_hour'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
      </div>
      <p class="description"><?php esc_html_e( 'Counters use WordPress transients per IP. If you sit behind a CDN/proxy, configure trusted proxies via the pdt_comment_security_trusted_proxies filter.', 'polanger-admin-menu-manager' ); ?></p>
    </div>
    <?php
  }

  /**
   * Render: Content Rules sub-panel.
   *
   * @param array $s           Settings.
   * @param bool  $is_readonly Read-only flag.
   * @return void
   */
  private function render_content_panel( $s, $is_readonly ) {
    $disabled = $is_readonly ? 'disabled' : '';
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Content Rules', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'Apply context-free heuristics on comment text and URLs.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <label for="pdt_cs_max_links"><?php esc_html_e( 'Maximum links per comment', 'polanger-admin-menu-manager' ); ?></label>
        <input type="number" id="pdt_cs_max_links" name="pdt_cs[max_links]" min="0" max="50"
               value="<?php echo esc_attr( $s['max_links'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        <p class="description"><?php esc_html_e( 'Counts http/https URLs found in the comment body, plus the author website if filled. Set 0 to disable.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[block_non_latin_only]" value="1" <?php checked( $s['block_non_latin_only'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Penalize comments dominated by non-Latin characters', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Only enable on Latin-script-only sites. Adds a low score signal, not a hard block.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label for="pdt_cs_keyword_match_mode"><?php esc_html_e( 'Keyword match mode', 'polanger-admin-menu-manager' ); ?></label>
        <select id="pdt_cs_keyword_match_mode" name="pdt_cs[keyword_match_mode]" <?php echo esc_attr( $disabled ); ?>>
          <option value="word" <?php selected( $s['keyword_match_mode'], 'word' ); ?>>
            <?php esc_html_e( 'Whole word / repeated word (recommended)', 'polanger-admin-menu-manager' ); ?>
          </option>
          <option value="substring" <?php selected( $s['keyword_match_mode'], 'substring' ); ?>>
            <?php esc_html_e( 'Substring (looser)', 'polanger-admin-menu-manager' ); ?>
          </option>
        </select>
      </div>

      <div class="pdt-form-row">
        <label for="pdt_cs_keyword_blocklist"><?php esc_html_e( 'Keyword blocklist', 'polanger-admin-menu-manager' ); ?></label>
        <textarea id="pdt_cs_keyword_blocklist" name="pdt_cs[keyword_blocklist]" rows="6"
                  <?php echo esc_attr( $disabled ); ?>><?php echo esc_textarea( $this->settings->list_to_textarea( $s['keyword_blocklist'] ) ); ?></textarea>
        <p class="description"><?php esc_html_e( 'One entry per line (or comma-separated). Matched against author name, comment body, and author URL. Whole word mode also catches repeated forms such as the same blocked word typed back-to-back.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row">
        <label for="pdt_cs_url_blocklist"><?php esc_html_e( 'URL host blocklist', 'polanger-admin-menu-manager' ); ?></label>
        <textarea id="pdt_cs_url_blocklist" name="pdt_cs[url_blocklist]" rows="6"
                  <?php echo esc_attr( $disabled ); ?>><?php echo esc_textarea( $this->settings->list_to_textarea( $s['url_blocklist'] ) ); ?></textarea>
        <p class="description"><?php esc_html_e( 'Hostnames only (e.g. "spamdomain.com"). Full URLs are normalized to host. www. is stripped.', 'polanger-admin-menu-manager' ); ?></p>
      </div>
    </div>
    <?php
  }

  /**
   * Render: Silent Mode + Behavior Score sub-panel.
   *
   * @param array $s           Settings.
   * @param bool  $is_readonly Read-only flag.
   * @return void
   */
  private function render_silent_panel( $s, $is_readonly ) {
    $disabled = $is_readonly ? 'disabled' : '';
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Behavior Score', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'Each violation contributes a weighted score. Two thresholds decide what happens to the comment.', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[score_enabled]" value="1" <?php checked( $s['score_enabled'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Enable behavior scoring', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'When disabled, any single violation goes to the silent mode action.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-form-row pdt-cs-inline-fields">
        <div>
          <label for="pdt_cs_score_threshold_spam"><?php esc_html_e( 'Spam threshold (0-100)', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_score_threshold_spam" name="pdt_cs[score_threshold_spam]" min="0" max="100"
                 value="<?php echo esc_attr( $s['score_threshold_spam'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
        <div>
          <label for="pdt_cs_score_threshold_drop"><?php esc_html_e( 'Drop threshold (0-100)', 'polanger-admin-menu-manager' ); ?></label>
          <input type="number" id="pdt_cs_score_threshold_drop" name="pdt_cs[score_threshold_drop]" min="0" max="100"
                 value="<?php echo esc_attr( $s['score_threshold_drop'] ); ?>" <?php echo esc_attr( $disabled ); ?> />
        </div>
      </div>
      <?php if ( 'spam' === $s['silent_mode'] ) : ?>
        <div class="pdt-cs-tip-notice is-subtle" style="margin-top:8px;">
          <span class="dashicons dashicons-info-outline"></span>
          <div>
            <strong><?php esc_html_e( 'Drop threshold has no extra effect', 'polanger-admin-menu-manager' ); ?></strong>
            <p>
              <?php esc_html_e( 'Silent mode is set to "Mark as spam", so both the spam threshold and the drop threshold route comments to the spam queue. To make the drop threshold meaningful, switch silent mode to "Move to trash" or "Silently drop".', 'polanger-admin-menu-manager' ); ?>
            </p>
          </div>
        </div>
      <?php endif; ?>
    </div>

    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Silent Mode', 'polanger-admin-menu-manager' ); ?></h2>
      <p class="description"><?php esc_html_e( 'What to do with a comment that crosses the threshold or trips a hard signal (honeypot / timing).', 'polanger-admin-menu-manager' ); ?></p>

      <div class="pdt-form-row">
        <div class="pdt-radio-group">
          <label class="pdt-radio-option">
            <input type="radio" name="pdt_cs[silent_mode]" value="spam" <?php checked( $s['silent_mode'], 'spam' ); ?> <?php echo esc_attr( $disabled ); ?> />
            <span class="pdt-radio-label">
              <strong><?php esc_html_e( 'Mark as spam', 'polanger-admin-menu-manager' ); ?></strong>
              <small><?php esc_html_e( 'Routed to the WordPress Spam queue. Visible to admins.', 'polanger-admin-menu-manager' ); ?></small>
            </span>
          </label>
          <label class="pdt-radio-option">
            <input type="radio" name="pdt_cs[silent_mode]" value="trash" <?php checked( $s['silent_mode'], 'trash' ); ?> <?php echo esc_attr( $disabled ); ?> />
            <span class="pdt-radio-label">
              <strong><?php esc_html_e( 'Move to trash', 'polanger-admin-menu-manager' ); ?></strong>
              <small><?php esc_html_e( 'Stored as trash for short-term review then auto-purged by WordPress.', 'polanger-admin-menu-manager' ); ?></small>
            </span>
          </label>
          <label class="pdt-radio-option">
            <input type="radio" name="pdt_cs[silent_mode]" value="drop" <?php checked( $s['silent_mode'], 'drop' ); ?> <?php echo esc_attr( $disabled ); ?> />
            <span class="pdt-radio-label">
              <strong><?php esc_html_e( 'Silently drop', 'polanger-admin-menu-manager' ); ?></strong>
              <small><?php esc_html_e( 'Comment is never written. Visitor is redirected back to the post.', 'polanger-admin-menu-manager' ); ?></small>
            </span>
          </label>
        </div>
      </div>

      <div class="pdt-form-row">
        <label class="pdt-toggle-switch">
          <input type="checkbox" name="pdt_cs[show_human_message]" value="1" <?php checked( $s['show_human_message'] ); ?> <?php echo esc_attr( $disabled ); ?> />
          <span class="pdt-toggle-slider"></span>
          <span class="pdt-toggle-label"><?php esc_html_e( 'Show a human-readable rejection page on hard drops', 'polanger-admin-menu-manager' ); ?></span>
        </label>
        <p class="description"><?php esc_html_e( 'Useful for debugging false positives. Disable on production for true silent mode.', 'polanger-admin-menu-manager' ); ?></p>
      </div>

      <div class="pdt-cs-tip-notice is-subtle">
        <span class="dashicons dashicons-warning"></span>
        <div>
          <strong><?php esc_html_e( 'Hard signals bypass scoring', 'polanger-admin-menu-manager' ); ?></strong>
          <p>
            <?php esc_html_e( 'The following violations always trigger the silent mode action above, regardless of the spam / drop thresholds: honeypot trip or missing field, timing token tampering, timing too fast, blocked keyword match, and blocked URL host match.', 'polanger-admin-menu-manager' ); ?>
            <br />
            <?php esc_html_e( 'You can customize this list with the pdt_comment_security_hard_block_reasons filter.', 'polanger-admin-menu-manager' ); ?>
          </p>
        </div>
      </div>
    </div>
    <?php
  }

  /**
   * Render: Logs & Statistics panel (read-only screen, separate form).
   *
   * @param bool $is_readonly Read-only flag.
   * @return void
   */
  private function render_logs_panel( $is_readonly ) {
    $stats = $this->logger->get_stats( 30 );

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check
    $page = isset( $_GET['paged'] ) ? max( 1, (int) $_GET['paged'] ) : 1;
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only nav check
    $decision_filter = isset( $_GET['decision'] ) ? sanitize_key( wp_unslash( $_GET['decision'] ) ) : '';

    $logs = $this->logger->get_logs(
      array(
        'page'     => $page,
        'per_page' => 25,
        'decision' => $decision_filter,
      )
    );

    $total_pages = max( 1, (int) ceil( $logs['total'] / max( 1, $logs['per_page'] ) ) );

    $base_url = add_query_arg(
      array(
        'page' => 'polanger-settings',
        'tab'  => 'comments',
        'sub'  => 'logs',
      ),
      admin_url( 'admin.php' )
    );
    ?>
    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Statistics (last 30 days)', 'polanger-admin-menu-manager' ); ?></h2>
      <div class="pdt-cs-stat-grid">
        <?php
        $labels = array(
          'allow' => array( __( 'Allowed', 'polanger-admin-menu-manager' ), 'is-allow' ),
          'spam'  => array( __( 'Spam', 'polanger-admin-menu-manager' ), 'is-spam' ),
          'trash' => array( __( 'Trash', 'polanger-admin-menu-manager' ), 'is-trash' ),
          'drop'  => array( __( 'Dropped', 'polanger-admin-menu-manager' ), 'is-drop' ),
        );
        foreach ( $labels as $key => $meta ) : ?>
          <div class="pdt-cs-stat-card <?php echo esc_attr( $meta[1] ); ?>">
            <span class="pdt-cs-stat-value"><?php echo esc_html( number_format_i18n( $stats[ $key ] ) ); ?></span>
            <span class="pdt-cs-stat-label"><?php echo esc_html( $meta[0] ); ?></span>
          </div>
        <?php endforeach; ?>
      </div>
    </div>

    <div class="pdt-settings-section">
      <h2><?php esc_html_e( 'Recent Events', 'polanger-admin-menu-manager' ); ?></h2>
      <div class="pdt-cs-log-toolbar">
        <form method="get" class="pdt-cs-log-filter">
          <input type="hidden" name="page" value="polanger-settings" />
          <input type="hidden" name="tab" value="comments" />
          <input type="hidden" name="sub" value="logs" />
          <label for="pdt_cs_log_decision"><?php esc_html_e( 'Filter:', 'polanger-admin-menu-manager' ); ?></label>
          <select id="pdt_cs_log_decision" name="decision" onchange="this.form.submit();">
            <option value=""><?php esc_html_e( 'All decisions', 'polanger-admin-menu-manager' ); ?></option>
            <?php foreach ( $labels as $k => $meta ) : ?>
              <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $decision_filter, $k ); ?>><?php echo esc_html( $meta[0] ); ?></option>
            <?php endforeach; ?>
          </select>
        </form>
        <?php if ( ! $is_readonly ) : ?>
          <form method="post" class="pdt-cs-log-clear">
            <?php wp_nonce_field( 'pdt_cs_logs', '_pdt_cs_logs_nonce' ); ?>
            <button type="submit" name="pdt_cs_clear_logs" value="1" class="button" data-confirm-action="clear">
              <span class="dashicons dashicons-trash"></span>
              <?php esc_html_e( 'Clear logs', 'polanger-admin-menu-manager' ); ?>
            </button>
          </form>
        <?php endif; ?>
      </div>

      <table class="widefat striped pdt-cs-log-table">
        <thead>
          <tr>
            <th><?php esc_html_e( 'When', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'Decision', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'Score', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'Reason', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'IP', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'Author', 'polanger-admin-menu-manager' ); ?></th>
            <th><?php esc_html_e( 'Post', 'polanger-admin-menu-manager' ); ?></th>
          </tr>
        </thead>
        <tbody>
          <?php if ( empty( $logs['items'] ) ) : ?>
            <tr><td colspan="7"><?php esc_html_e( 'No log entries yet.', 'polanger-admin-menu-manager' ); ?></td></tr>
          <?php else : ?>
            <?php foreach ( $logs['items'] as $row ) : ?>
              <?php
              $decision_label = isset( $labels[ $row->decision ][0] )
                ? $labels[ $row->decision ][0]
                : ucfirst( (string) $row->decision );
              ?>
              <tr>
                <td><?php echo esc_html( mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $row->created_at ) ); ?></td>
                <td><span class="pdt-cs-decision pdt-cs-decision-<?php echo esc_attr( $row->decision ); ?>"><?php echo esc_html( $decision_label ); ?></span></td>
                <td><?php echo esc_html( $row->score ); ?></td>
                <td>
                  <code title="<?php echo esc_attr( $row->reason ); ?>">
                    <?php echo esc_html( $this->format_reason_label( (string) $row->reason ) ); ?>
                  </code>
                </td>
                <td><?php echo esc_html( $row->ip ); ?></td>
                <td>
                  <?php echo esc_html( $row->author ); ?>
                  <?php if ( $row->author_email ) : ?>
                    <br /><small><?php echo esc_html( $row->author_email ); ?></small>
                  <?php endif; ?>
                </td>
                <td>
                  <?php
                  if ( $row->post_id ) {
                    $title = get_the_title( $row->post_id );
                    if ( $title ) {
                      printf(
                        '<a href="%s">%s</a>',
                        esc_url( get_edit_post_link( $row->post_id ) ),
                        esc_html( $title )
                      );
                    } else {
                      echo esc_html( '#' . $row->post_id );
                    }
                  } else {
                    echo '&mdash;';
                  }
                  ?>
                </td>
              </tr>
            <?php endforeach; ?>
          <?php endif; ?>
        </tbody>
      </table>

      <?php if ( $total_pages > 1 ) : ?>
        <div class="tablenav">
          <div class="tablenav-pages">
            <span class="displaying-num">
              <?php
              printf(
                /* translators: 1: total log rows */
                esc_html( _n( '%s item', '%s items', $logs['total'], 'polanger-admin-menu-manager' ) ),
                esc_html( number_format_i18n( $logs['total'] ) )
              );
              ?>
            </span>
            <span class="pagination-links">
              <?php
              $prev_disabled = $page <= 1 ? 'disabled' : '';
              $next_disabled = $page >= $total_pages ? 'disabled' : '';
              $prev_args     = array_filter(
                array( 'paged' => max( 1, $page - 1 ), 'decision' => $decision_filter ),
                static function ( $v ) {
                  return '' !== $v && null !== $v;
                }
              );
              $next_args     = array_filter(
                array( 'paged' => min( $total_pages, $page + 1 ), 'decision' => $decision_filter ),
                static function ( $v ) {
                  return '' !== $v && null !== $v;
                }
              );
              $prev_url      = add_query_arg( $prev_args, $base_url );
              $next_url      = add_query_arg( $next_args, $base_url );
              ?>
              <a class="button <?php echo esc_attr( $prev_disabled ); ?>" href="<?php echo esc_url( $prev_url ); ?>">&laquo;</a>
              <span class="paging-input"><?php echo (int) $page; ?> / <?php echo (int) $total_pages; ?></span>
              <a class="button <?php echo esc_attr( $next_disabled ); ?>" href="<?php echo esc_url( $next_url ); ?>">&raquo;</a>
            </span>
          </div>
        </div>
      <?php endif; ?>
    </div>
    <?php
  }

  /**
   * Convert machine reason codes into readable labels for logs.
   *
   * Supports comma-separated reason lists.
   *
   * @param string $reason_csv Stored reason value.
   * @return string
   */
  private function format_reason_label( $reason_csv ) {
    $reason_csv = trim( (string) $reason_csv );
    if ( '' === $reason_csv ) {
      return '—';
    }

    $map = array(
      'clean'               => __( 'Clean (allowed)', 'polanger-admin-menu-manager' ),
      'form_marker_missing' => __( 'Form marker missing', 'polanger-admin-menu-manager' ),
      'honeypot'            => __( 'Honeypot filled', 'polanger-admin-menu-manager' ),
      'honeypot_missing'    => __( 'Honeypot field missing', 'polanger-admin-menu-manager' ),
      'timing_min'          => __( 'Submitted too quickly', 'polanger-admin-menu-manager' ),
      'timing_invalid'      => __( 'Timing token invalid', 'polanger-admin-menu-manager' ),
      'timing_max'          => __( 'Timing token expired', 'polanger-admin-menu-manager' ),
      'flood_minute'        => __( 'Minute rate exceeded', 'polanger-admin-menu-manager' ),
      'flood_hour'          => __( 'Hourly rate exceeded', 'polanger-admin-menu-manager' ),
      'too_many_links'      => __( 'Too many links', 'polanger-admin-menu-manager' ),
      'non_latin'           => __( 'Non-Latin dominant text', 'polanger-admin-menu-manager' ),
      'keyword'             => __( 'Blocked keyword match', 'polanger-admin-menu-manager' ),
      'url_blocklist'       => __( 'Blocked URL host match', 'polanger-admin-menu-manager' ),
    );

    $codes  = array_filter( array_map( 'trim', explode( ',', $reason_csv ) ) );
    $labels = array();
    foreach ( $codes as $code ) {
      $code = sanitize_key( $code );
      if ( '' === $code ) {
        continue;
      }

      if ( isset( $map[ $code ] ) ) {
        $labels[] = $map[ $code ];
      } else {
        $labels[] = ucfirst( str_replace( '_', ' ', $code ) );
      }
    }

    if ( empty( $labels ) ) {
      return $reason_csv;
    }

    return implode( ', ', $labels );
  }
}
