<?php
/**
 * Custom Admin Menu Addon
 *
 * Adds custom WordPress admin sidebar menus/submenus from Menu Manager page.
 *
 * @package Polanger_Dashboard_Tools_Pro
 */

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

class PDT_Custom_Admin_Menu {

  /**
   * Option key for saved custom menus.
   */
  const OPTION_NAME = 'pdt_custom_admin_menus';

  /**
   * Runtime map for menu link behavior.
   *
   * @var array
   */
  private $runtime_link_map = array();

  /**
   * Constructor.
   */
  public function __construct() {
    add_action( 'admin_menu', array( $this, 'register_custom_menus' ), 90 );
    add_action( 'admin_menu', array( $this, 'cleanup_duplicate_parent_submenus' ), 99999 );
    add_action( 'admin_post_pdt_custom_menu_save', array( $this, 'handle_save_menu' ) );
    add_action( 'admin_post_pdt_custom_menu_delete', array( $this, 'handle_delete_menu' ) );
    add_action( 'admin_init', array( $this, 'maybe_redirect_custom_menu_target' ), 20 );
    add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
    add_action( 'pdt_menu_manager_after_header', array( $this, 'render_toolbar' ) );
    add_action( 'pdt_menu_manager_after_form', array( $this, 'render_manager_section' ) );
  }

  /**
   * Load addon assets on Menu Manager page.
   *
   * @return void
   */
  public function enqueue_assets() {
    if ( ! empty( $this->runtime_link_map ) ) {
      wp_enqueue_script(
        'pdt-custom-admin-menu-runtime',
        plugin_dir_url( __FILE__ ) . 'js/custom-admin-menu-runtime.js',
        array(),
        PDT_VERSION,
        true
      );

      wp_localize_script(
        'pdt-custom-admin-menu-runtime',
        'pdtCustomMenuRuntimeData',
        array(
          'linkMap' => $this->runtime_link_map,
        )
      );
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $current_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';

    if ( 'polanger-dashboard' !== $current_page ) {
      return;
    }

    wp_enqueue_style(
      'pdt-custom-admin-menu-style',
      plugin_dir_url( __FILE__ ) . 'css/custom-admin-menu.css',
      array(),
      '1.0.0'
    );

    wp_enqueue_script(
      'pdt-custom-admin-menu-script',
      plugin_dir_url( __FILE__ ) . 'js/custom-admin-menu.js',
      array( 'jquery' ),
      PDT_VERSION,
      true
    );

    $slug_map = array();
    $menu_items_for_js = array();
    foreach ( $this->get_saved_menus() as $menu_id => $menu ) {
      $menu_key = '';
      if ( ! empty( $menu['menu_key'] ) ) {
        $menu_key = $menu['menu_key'];
      } elseif ( ! empty( $menu['menu_slug'] ) ) {
        // Backward compatibility for old addon records.
        $menu_key = $menu['menu_slug'];
      }

      if ( ! empty( $menu_key ) ) {
        $slug_map[ $menu_key ] = $menu_id;
      }

      $menu_items_for_js[ $menu_id ] = array(
        'menu_title'  => isset( $menu['menu_title'] ) ? $menu['menu_title'] : '',
        'menu_target' => isset( $menu['menu_target'] ) ? $menu['menu_target'] : ( $menu['menu_slug'] ?? '' ),
        'menu_icon'   => isset( $menu['menu_icon'] ) ? $menu['menu_icon'] : 'dashicons-admin-generic',
        'position'    => isset( $menu['position'] ) ? (string) $menu['position'] : '',
        'new_tab'     => ! empty( $menu['new_tab'] ),
        'submenus'    => isset( $menu['submenus'] ) && is_array( $menu['submenus'] ) ? array_values( $menu['submenus'] ) : array(),
      );
    }

    wp_localize_script(
      'pdt-custom-admin-menu-script',
      'pdtCustomMenuData',
      array(
        'menuMap'         => $slug_map,
        'deleteUrl'       => admin_url( 'admin-post.php' ),
        'deleteNonce'     => wp_create_nonce( 'pdt_custom_menu_delete' ),
        'deleteAction'    => 'pdt_custom_menu_delete',
        'deleteConfirm'   => __( 'This will delete the custom menu and all related submenus. Continue?', 'polanger-admin-menu-manager' ),
        'deleteAriaLabel' => __( 'Delete custom menu', 'polanger-admin-menu-manager' ),
        'menuItems'       => $menu_items_for_js,
        'editModalTitle'  => __( 'Edit Admin Menu', 'polanger-admin-menu-manager' ),
        'addModalTitle'   => __( 'Add New Admin Menu', 'polanger-admin-menu-manager' ),
        'editSubmitLabel' => __( 'Update Menu', 'polanger-admin-menu-manager' ),
        'addSubmitLabel'  => __( 'Save Menu', 'polanger-admin-menu-manager' ),
        'submenuTitleLabel' => __( 'Submenu Title', 'polanger-admin-menu-manager' ),
        'submenuTitleDescription' => __( 'Label shown in sidebar under the main menu.', 'polanger-admin-menu-manager' ),
        'submenuTargetLabel' => __( 'Submenu Target (Slug or URL)', 'polanger-admin-menu-manager' ),
        'submenuTargetPlaceholder' => __( 'admin.php?page=my-page or https://example.com/help', 'polanger-admin-menu-manager' ),
        'submenuTargetDescription' => __( 'WordPress admin target or full external URL.', 'polanger-admin-menu-manager' ),
        'submenuSlugLabel' => __( 'Submenu Slug', 'polanger-admin-menu-manager' ),
        'submenuSlugPlaceholder' => __( 'my-submenu', 'polanger-admin-menu-manager' ),
        'submenuSlugDescription' => __( 'Unique submenu URL key. Leave empty to auto-generate.', 'polanger-admin-menu-manager' ),
        'submenuBehaviorLabel' => __( 'Submenu Link Behavior', 'polanger-admin-menu-manager' ),
        'openSameTabLabel' => __( 'Open in same tab', 'polanger-admin-menu-manager' ),
        'openNewTabLabel' => __( 'Open in new tab', 'polanger-admin-menu-manager' ),
        'submenuBehaviorDescription' => __( 'Recommended for external URLs.', 'polanger-admin-menu-manager' ),
        'removeLabel' => __( 'Remove', 'polanger-admin-menu-manager' ),
      )
    );
  }

  /**
   * Render Add New Menu action button.
   *
   * @return void
   */
  public function render_toolbar() {
    ?>
    <div class="pdt-custom-menu-toolbar">
      <button type="button" class="button button-primary pdt-open-custom-menu-modal">
        <span class="dashicons dashicons-plus-alt2"></span>
        <?php esc_html_e( 'Add New Menu', 'polanger-admin-menu-manager' ); ?>
      </button>
    </div>
    <?php
  }

  /**
   * Render management section and modal.
   *
   * @return void
   */
  public function render_manager_section() {
    $menus = $this->get_saved_menus();
    ?>
    <div class="pdt-custom-menu-manager">
      <?php
      // phpcs:ignore WordPress.Security.NonceVerification.Recommended
      if ( isset( $_GET['pdt_custom_menu_saved'] ) && '1' === sanitize_text_field( wp_unslash( $_GET['pdt_custom_menu_saved'] ) ) ) :
      ?>
        <div class="notice notice-success is-dismissible">
          <p><?php esc_html_e( 'Custom admin menu saved.', 'polanger-admin-menu-manager' ); ?></p>
        </div>
      <?php endif; ?>
      <?php
      // phpcs:ignore WordPress.Security.NonceVerification.Recommended
      if ( isset( $_GET['pdt_custom_menu_deleted'] ) && '1' === sanitize_text_field( wp_unslash( $_GET['pdt_custom_menu_deleted'] ) ) ) :
      ?>
        <div class="notice notice-success is-dismissible">
          <p><?php esc_html_e( 'Custom admin menu deleted.', 'polanger-admin-menu-manager' ); ?></p>
        </div>
      <?php endif; ?>

      <div class="pdt-custom-menu-card">
        <div class="pdt-custom-menu-card-header">
          <h3><?php esc_html_e( 'Custom Menus', 'polanger-admin-menu-manager' ); ?></h3>
          <p><?php esc_html_e( 'Manage the menus you added to the WordPress sidebar.', 'polanger-admin-menu-manager' ); ?></p>
        </div>

        <?php if ( empty( $menus ) ) : ?>
          <p class="pdt-custom-menu-empty"><?php esc_html_e( 'No custom menu added yet.', 'polanger-admin-menu-manager' ); ?></p>
        <?php else : ?>
          <table class="widefat striped pdt-custom-menu-table">
            <thead>
              <tr>
                <th><?php esc_html_e( 'Menu Title', 'polanger-admin-menu-manager' ); ?></th>
                <th><?php esc_html_e( 'Target', 'polanger-admin-menu-manager' ); ?></th>
                <th><?php esc_html_e( 'Submenus', 'polanger-admin-menu-manager' ); ?></th>
                <th><?php esc_html_e( 'Action', 'polanger-admin-menu-manager' ); ?></th>
              </tr>
            </thead>
            <tbody>
              <?php foreach ( $menus as $menu_id => $menu ) : ?>
                <tr>
                  <td><?php echo esc_html( $menu['menu_title'] ); ?></td>
                  <td><code><?php echo esc_html( isset( $menu['menu_target'] ) ? $menu['menu_target'] : ( $menu['menu_slug'] ?? '' ) ); ?></code></td>
                  <td><?php echo esc_html( isset( $menu['submenus'] ) && is_array( $menu['submenus'] ) ? count( $menu['submenus'] ) : 0 ); ?></td>
                  <td>
                    <div class="pdt-custom-menu-table-actions">
                      <button type="button" class="button button-secondary pdt-custom-menu-edit-btn" data-menu-id="<?php echo esc_attr( $menu_id ); ?>">
                        <?php esc_html_e( 'Edit', 'polanger-admin-menu-manager' ); ?>
                      </button>
                      <button type="button" class="button button-link-delete pdt-custom-menu-delete-btn" data-menu-id="<?php echo esc_attr( $menu_id ); ?>">
                        <?php esc_html_e( 'Delete', 'polanger-admin-menu-manager' ); ?>
                      </button>
                    </div>
                  </td>
                </tr>
              <?php endforeach; ?>
            </tbody>
          </table>
        <?php endif; ?>
      </div>
    </div>

    <div class="pdt-custom-menu-modal" id="pdt-custom-menu-modal" aria-hidden="true">
      <div class="pdt-custom-menu-modal__overlay pdt-close-custom-menu-modal"></div>
      <div class="pdt-custom-menu-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="pdt-custom-menu-modal-title">
        <div class="pdt-custom-menu-modal__header">
          <h2 id="pdt-custom-menu-modal-title"><?php esc_html_e( 'Add New Admin Menu', 'polanger-admin-menu-manager' ); ?></h2>
          <button type="button" class="pdt-custom-menu-modal__close pdt-close-custom-menu-modal" aria-label="<?php esc_attr_e( 'Close', 'polanger-admin-menu-manager' ); ?>">&times;</button>
        </div>
        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="pdt-custom-menu-form">
          <?php wp_nonce_field( 'pdt_custom_menu_save' ); ?>
          <input type="hidden" name="action" value="pdt_custom_menu_save" />
          <input type="hidden" name="menu_id" id="pdt_edit_menu_id" value="" />

          <div class="pdt-custom-menu-grid">
            <div class="pdt-custom-menu-field pdt-field-menu-title">
              <label for="pdt_menu_title"><?php esc_html_e( 'Menu Title', 'polanger-admin-menu-manager' ); ?></label>
              <input type="text" id="pdt_menu_title" name="menu_title" required />
              <p class="description"><?php esc_html_e( 'Sidebar menu label shown to users.', 'polanger-admin-menu-manager' ); ?></p>
            </div>
            <div class="pdt-custom-menu-field pdt-field-menu-target">
              <label for="pdt_menu_target"><?php esc_html_e( 'Menu Target (Slug or URL)', 'polanger-admin-menu-manager' ); ?></label>
              <input type="text" id="pdt_menu_target" name="menu_target" placeholder="<?php esc_attr_e( 'admin.php?page=my-plugin or https://example.com/help', 'polanger-admin-menu-manager' ); ?>" required />
              <p class="description"><?php esc_html_e( 'Enter a WordPress admin target or a full external URL.', 'polanger-admin-menu-manager' ); ?></p>
              <label class="pdt-custom-toggle">
                <input type="checkbox" name="menu_new_tab" value="1" />
                <span><?php esc_html_e( 'Open in new tab (for external links)', 'polanger-admin-menu-manager' ); ?></span>
              </label>
              <p class="description"><?php esc_html_e( 'Useful for help docs, support pages, or external dashboards.', 'polanger-admin-menu-manager' ); ?></p>
            </div>
            <div class="pdt-custom-menu-field pdt-field-menu-icon">
              <label for="pdt_menu_icon"><?php esc_html_e( 'Menu Icon', 'polanger-admin-menu-manager' ); ?></label>
              <div class="pdt-custom-icon-picker">
                <input type="hidden" id="pdt_menu_icon" name="menu_icon" value="dashicons-admin-generic" />
                <button type="button" class="button pdt-custom-icon-picker-trigger">
                  <span class="dashicons dashicons-admin-generic"></span>
                  <?php esc_html_e( 'Choose icon', 'polanger-admin-menu-manager' ); ?>
                </button>
              </div>
              <p class="description"><?php esc_html_e( 'Select an icon for this menu item.', 'polanger-admin-menu-manager' ); ?></p>
            </div>
            <div class="pdt-custom-menu-field pdt-field-menu-position">
              <label for="pdt_menu_position"><?php esc_html_e( 'Menu Position', 'polanger-admin-menu-manager' ); ?></label>
              <input type="number" id="pdt_menu_position" name="menu_position" min="1" step="1" placeholder="81" />
              <p class="description"><?php esc_html_e( 'Optional order number in sidebar. Leave empty for automatic placement.', 'polanger-admin-menu-manager' ); ?></p>
            </div>
          </div>

          <div class="pdt-custom-submenus">
            <div class="pdt-custom-submenus__header">
              <h3><?php esc_html_e( 'Submenus', 'polanger-admin-menu-manager' ); ?></h3>
              <button type="button" class="button pdt-add-submenu-row">
                <?php esc_html_e( 'Add Submenu', 'polanger-admin-menu-manager' ); ?>
              </button>
            </div>
            <p class="description"><?php esc_html_e( 'Add child pages under this main menu. You can add as many as you need.', 'polanger-admin-menu-manager' ); ?></p>
            <div class="pdt-custom-submenus__rows"></div>
          </div>

          <div class="pdt-custom-menu-modal__footer">
            <button type="button" class="button pdt-close-custom-menu-modal"><?php esc_html_e( 'Cancel', 'polanger-admin-menu-manager' ); ?></button>
            <button type="submit" class="button button-primary pdt-custom-menu-submit-btn"><?php esc_html_e( 'Save Menu', 'polanger-admin-menu-manager' ); ?></button>
          </div>
        </form>
      </div>
    </div>
    <div class="pdt-custom-icon-modal" id="pdt-custom-icon-modal" aria-hidden="true">
      <div class="pdt-custom-icon-modal__overlay pdt-close-custom-icon-modal"></div>
      <div class="pdt-custom-icon-modal__dialog" role="dialog" aria-modal="true">
        <div class="pdt-custom-icon-modal__header">
          <h3><?php esc_html_e( 'Select Menu Icon', 'polanger-admin-menu-manager' ); ?></h3>
          <button type="button" class="pdt-close-custom-icon-modal">&times;</button>
        </div>
        <div class="pdt-custom-icon-grid">
          <?php foreach ( $this->get_dashicon_options() as $icon ) : ?>
            <button type="button" class="pdt-custom-icon-option" data-icon="<?php echo esc_attr( $icon ); ?>" title="<?php echo esc_attr( $icon ); ?>">
              <span class="dashicons <?php echo esc_attr( $icon ); ?>"></span>
            </button>
          <?php endforeach; ?>
        </div>
      </div>
    </div>
    <?php
  }

  /**
   * Limited dashicon set for icon picker.
   *
   * @return array
   */
  private function get_dashicon_options() {
    return array(
      'dashicons-admin-appearance', 'dashicons-admin-collapse', 'dashicons-admin-comments',
      'dashicons-admin-customizer', 'dashicons-admin-generic', 'dashicons-admin-home',
      'dashicons-admin-links', 'dashicons-admin-media', 'dashicons-admin-multisite',
      'dashicons-admin-network', 'dashicons-admin-page', 'dashicons-admin-plugins',
      'dashicons-admin-post', 'dashicons-admin-settings', 'dashicons-admin-site',
      'dashicons-admin-tools', 'dashicons-admin-users', 'dashicons-album',
      'dashicons-analytics', 'dashicons-archive', 'dashicons-arrow-down',
      'dashicons-arrow-left', 'dashicons-arrow-right', 'dashicons-arrow-up',
      'dashicons-art', 'dashicons-awards', 'dashicons-backup',
      'dashicons-bank', 'dashicons-beer', 'dashicons-bell',
      'dashicons-block-default', 'dashicons-book', 'dashicons-book-alt',
      'dashicons-buddicons-activity', 'dashicons-buddicons-buddypress-logo', 'dashicons-buddicons-community',
      'dashicons-buddicons-forums', 'dashicons-buddicons-friends', 'dashicons-buddicons-groups',
      'dashicons-buddicons-pm', 'dashicons-buddicons-replies', 'dashicons-buddicons-topics',
      'dashicons-building', 'dashicons-businessman', 'dashicons-businessperson',
      'dashicons-businesswoman', 'dashicons-calculator', 'dashicons-calendar',
      'dashicons-calendar-alt', 'dashicons-camera', 'dashicons-camera-alt',
      'dashicons-car', 'dashicons-carrot', 'dashicons-cart',
      'dashicons-category', 'dashicons-chart-area', 'dashicons-chart-bar',
      'dashicons-chart-line', 'dashicons-chart-pie', 'dashicons-clipboard',
      'dashicons-clock', 'dashicons-cloud', 'dashicons-cloud-saved',
      'dashicons-cloud-upload', 'dashicons-coffee', 'dashicons-color-picker',
      'dashicons-columns', 'dashicons-controls-back', 'dashicons-controls-forward',
      'dashicons-controls-pause', 'dashicons-controls-play', 'dashicons-controls-repeat',
      'dashicons-controls-skipback', 'dashicons-controls-skipforward', 'dashicons-controls-volumeoff',
      'dashicons-controls-volumeon', 'dashicons-cover-image', 'dashicons-dashboard',
      'dashicons-database', 'dashicons-desktop', 'dashicons-dismiss',
      'dashicons-download', 'dashicons-drumstick', 'dashicons-edit',
      'dashicons-edit-large', 'dashicons-edit-page', 'dashicons-editor-aligncenter',
      'dashicons-editor-alignleft', 'dashicons-editor-alignright', 'dashicons-editor-bold',
      'dashicons-editor-break', 'dashicons-editor-code', 'dashicons-editor-contract',
      'dashicons-editor-customchar', 'dashicons-editor-expand', 'dashicons-editor-help',
      'dashicons-editor-indent', 'dashicons-editor-insertmore', 'dashicons-editor-italic',
      'dashicons-editor-justify', 'dashicons-editor-kitchensink', 'dashicons-editor-ltr',
      'dashicons-editor-ol', 'dashicons-editor-outdent', 'dashicons-editor-paragraph',
      'dashicons-editor-paste-text', 'dashicons-editor-paste-word', 'dashicons-editor-quote',
      'dashicons-editor-removeformatting', 'dashicons-editor-rtl', 'dashicons-editor-spellcheck',
      'dashicons-editor-strikethrough', 'dashicons-editor-table', 'dashicons-editor-textcolor',
      'dashicons-editor-ul', 'dashicons-editor-underline', 'dashicons-editor-unlink',
      'dashicons-editor-video', 'dashicons-ellipsis', 'dashicons-email',
      'dashicons-email-alt', 'dashicons-email-alt2', 'dashicons-embed-audio',
      'dashicons-embed-generic', 'dashicons-embed-photo', 'dashicons-embed-post',
      'dashicons-embed-video', 'dashicons-excerpt-view', 'dashicons-exit',
      'dashicons-external', 'dashicons-facebook', 'dashicons-facebook-alt',
      'dashicons-feedback', 'dashicons-filter', 'dashicons-flag',
      'dashicons-food', 'dashicons-format-aside', 'dashicons-format-audio',
      'dashicons-format-chat', 'dashicons-format-gallery', 'dashicons-format-image',
      'dashicons-format-quote', 'dashicons-format-status', 'dashicons-format-video',
      'dashicons-forms', 'dashicons-fullscreen-alt', 'dashicons-fullscreen-exit-alt',
      'dashicons-games', 'dashicons-google', 'dashicons-grid-view',
      'dashicons-groups', 'dashicons-hammer', 'dashicons-heading',
      'dashicons-heart', 'dashicons-hidden', 'dashicons-hourglass',
      'dashicons-html', 'dashicons-id', 'dashicons-id-alt',
      'dashicons-image-crop', 'dashicons-image-filter', 'dashicons-image-flip-horizontal',
      'dashicons-image-flip-vertical', 'dashicons-image-rotate', 'dashicons-image-rotate-left',
      'dashicons-image-rotate-right', 'dashicons-images-alt', 'dashicons-images-alt2',
      'dashicons-index-card', 'dashicons-info', 'dashicons-info-outline',
      'dashicons-insert', 'dashicons-insert-after', 'dashicons-insert-before',
      'dashicons-instagram', 'dashicons-keyboard-hide', 'dashicons-laptop',
      'dashicons-layout', 'dashicons-leftright', 'dashicons-lightbulb',
      'dashicons-linkedin', 'dashicons-list-view', 'dashicons-location',
      'dashicons-location-alt', 'dashicons-lock', 'dashicons-marker',
      'dashicons-media-archive', 'dashicons-media-audio', 'dashicons-media-code',
      'dashicons-media-default', 'dashicons-media-document', 'dashicons-media-interactive',
      'dashicons-media-spreadsheet', 'dashicons-media-text', 'dashicons-media-video',
      'dashicons-megaphone', 'dashicons-menu', 'dashicons-menu-alt',
      'dashicons-menu-alt2', 'dashicons-menu-alt3', 'dashicons-microphone',
      'dashicons-migrate', 'dashicons-minus', 'dashicons-money',
      'dashicons-money-alt', 'dashicons-move', 'dashicons-nametag',
      'dashicons-networking', 'dashicons-no', 'dashicons-no-alt',
      'dashicons-open-folder', 'dashicons-palmtree', 'dashicons-paperclip',
      'dashicons-pdf', 'dashicons-performance', 'dashicons-pets',
      'dashicons-phone', 'dashicons-pinterest', 'dashicons-playlist-audio',
      'dashicons-playlist-video', 'dashicons-plus', 'dashicons-plus-alt',
      'dashicons-plus-alt2', 'dashicons-podio', 'dashicons-portfolio',
      'dashicons-post-status', 'dashicons-pressthis', 'dashicons-printer',
      'dashicons-privacy', 'dashicons-products', 'dashicons-randomize',
      'dashicons-reddit', 'dashicons-redo', 'dashicons-remove',
      'dashicons-rest-api', 'dashicons-rss', 'dashicons-saved',
      'dashicons-schedule', 'dashicons-screenoptions', 'dashicons-search',
      'dashicons-share', 'dashicons-share-alt', 'dashicons-share-alt2',
      'dashicons-shield', 'dashicons-shield-alt', 'dashicons-shortcode',
      'dashicons-slides', 'dashicons-smartphone', 'dashicons-smiley',
      'dashicons-sort', 'dashicons-sos', 'dashicons-spotify',
      'dashicons-star-empty', 'dashicons-star-filled', 'dashicons-star-half',
      'dashicons-sticky', 'dashicons-store', 'dashicons-superhero',
      'dashicons-superhero-alt', 'dashicons-table-col-after', 'dashicons-table-col-before',
      'dashicons-table-col-delete', 'dashicons-table-row-after', 'dashicons-table-row-before',
      'dashicons-table-row-delete', 'dashicons-tablet', 'dashicons-tag',
      'dashicons-tagcloud', 'dashicons-testimonial', 'dashicons-text',
      'dashicons-text-page', 'dashicons-thumbs-down', 'dashicons-thumbs-up',
      'dashicons-tickets', 'dashicons-tickets-alt', 'dashicons-tide',
      'dashicons-translation', 'dashicons-trash', 'dashicons-twitter',
      'dashicons-twitter-alt', 'dashicons-undo', 'dashicons-universal-access',
      'dashicons-universal-access-alt', 'dashicons-unlock', 'dashicons-update',
      'dashicons-update-alt', 'dashicons-upload', 'dashicons-vault',
      'dashicons-video-alt', 'dashicons-video-alt2', 'dashicons-video-alt3',
      'dashicons-visibility', 'dashicons-warning', 'dashicons-welcome-add-page',
      'dashicons-welcome-comments', 'dashicons-welcome-learn-more', 'dashicons-welcome-view-site',
      'dashicons-welcome-widgets-menus', 'dashicons-welcome-write-blog', 'dashicons-whatsapp',
      'dashicons-wordpress', 'dashicons-wordpress-alt', 'dashicons-xing',
      'dashicons-yes', 'dashicons-yes-alt', 'dashicons-youtube',
    );
  }

  /**
   * Handle save request.
   *
   * @return void
   */
  public function handle_save_menu() {
    if ( ! current_user_can( 'manage_options' ) ) {
      wp_die( esc_html__( 'Permission denied.', 'polanger-admin-menu-manager' ) );
    }

    check_admin_referer( 'pdt_custom_menu_save' );

    $editing_menu_id = isset( $_POST['menu_id'] ) ? sanitize_text_field( wp_unslash( $_POST['menu_id'] ) ) : '';
    $menu_title = isset( $_POST['menu_title'] ) ? sanitize_text_field( wp_unslash( $_POST['menu_title'] ) ) : '';
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized by sanitize_menu_target().
    $menu_target = isset( $_POST['menu_target'] ) ? $this->sanitize_menu_target( wp_unslash( $_POST['menu_target'] ) ) : '';
    $menu_icon  = isset( $_POST['menu_icon'] ) ? sanitize_text_field( wp_unslash( $_POST['menu_icon'] ) ) : 'dashicons-admin-generic';
    $position   = isset( $_POST['menu_position'] ) ? absint( wp_unslash( $_POST['menu_position'] ) ) : 0;
    $menu_new_tab = ! empty( $_POST['menu_new_tab'] );

    if ( empty( $menu_title ) || empty( $menu_target ) ) {
      wp_safe_redirect( admin_url( 'admin.php?page=polanger-dashboard' ) );
      exit;
    }

    $menus = $this->get_saved_menus();
    $menu_key = '';
    if ( ! empty( $editing_menu_id ) && isset( $menus[ $editing_menu_id ]['menu_key'] ) ) {
      $menu_key = $menus[ $editing_menu_id ]['menu_key'];
    } else {
      $menu_key = $this->build_internal_slug( $menu_title, $menus );
    }

    $submenus = $this->sanitize_submenus( $menu_key );

    $menu_id = ! empty( $editing_menu_id ) && isset( $menus[ $editing_menu_id ] ) ? $editing_menu_id : 'menu_' . strtolower( wp_generate_password( 8, false, false ) );
    $menus[ $menu_id ] = array(
      'menu_title'  => $menu_title,
      'menu_target' => $menu_target,
      'menu_key'    => $menu_key,
      'menu_icon'   => $menu_icon,
      'position'    => $position,
      'new_tab'     => $menu_new_tab,
      'submenus'    => $submenus,
    );

    update_option( self::OPTION_NAME, $menus );

    wp_safe_redirect( admin_url( 'admin.php?page=polanger-dashboard&pdt_custom_menu_saved=1' ) );
    exit;
  }

  /**
   * Handle delete request.
   *
   * @return void
   */
  public function handle_delete_menu() {
    if ( ! current_user_can( 'manage_options' ) ) {
      wp_die( esc_html__( 'Permission denied.', 'polanger-admin-menu-manager' ) );
    }

    check_admin_referer( 'pdt_custom_menu_delete' );

    $menu_id = isset( $_POST['menu_id'] ) ? sanitize_text_field( wp_unslash( $_POST['menu_id'] ) ) : '';
    $menus   = $this->get_saved_menus();

    if ( ! empty( $menu_id ) && isset( $menus[ $menu_id ] ) ) {
      unset( $menus[ $menu_id ] );
      update_option( self::OPTION_NAME, $menus );
    }

    wp_safe_redirect( admin_url( 'admin.php?page=polanger-dashboard&pdt_custom_menu_deleted=1' ) );
    exit;
  }

  /**
   * Register saved custom menus in WordPress admin sidebar.
   *
   * @return void
   */
  public function register_custom_menus() {
    $menus = $this->get_saved_menus();

    if ( empty( $menus ) ) {
      return;
    }

    foreach ( $menus as $menu ) {
      if ( empty( $menu['menu_title'] ) ) {
        continue;
      }

      $menu_target = ! empty( $menu['menu_target'] ) ? $menu['menu_target'] : ( $menu['menu_slug'] ?? '' );
      $menu_key = ! empty( $menu['menu_key'] ) ? $menu['menu_key'] : 'pdt-custom-menu-' . sanitize_key( $menu['menu_title'] );

      if ( empty( $menu_target ) || empty( $menu_key ) ) {
        continue;
      }

      $icon       = ! empty( $menu['menu_icon'] ) ? $menu['menu_icon'] : 'dashicons-admin-generic';
      $position   = ! empty( $menu['position'] ) ? (int) $menu['position'] : null;
      $menu_slug  = $menu_key;
      $target_url = $menu_target;
      $new_tab    = ! empty( $menu['new_tab'] );

      add_menu_page(
        $menu['menu_title'],
        $menu['menu_title'],
        'manage_options',
        $menu_slug,
        '__return_null',
        $icon,
        $position
      );

      $this->runtime_link_map[ $menu_slug ] = array(
        'url'     => $target_url,
        'new_tab' => $new_tab,
      );

      if ( ! empty( $menu['submenus'] ) && is_array( $menu['submenus'] ) ) {
        foreach ( $menu['submenus'] as $submenu ) {
          if ( empty( $submenu['menu_slug'] ) || empty( $submenu['menu_title'] ) || empty( $submenu['target'] ) ) {
            continue;
          }

          add_submenu_page(
            $menu_slug,
            $submenu['menu_title'],
            $submenu['menu_title'],
            'manage_options',
            $submenu['menu_slug'],
            '__return_null'
          );

          $this->runtime_link_map[ $submenu['menu_slug'] ] = array(
            'url'     => $submenu['target'],
            'new_tab' => ! empty( $submenu['new_tab'] ),
          );
        }
      }
    }
  }

  /**
   * Remove WordPress auto-duplicated parent submenu entries.
   *
   * Runs late to ensure all menu registrations are complete.
   *
   * @return void
   */
  public function cleanup_duplicate_parent_submenus() {
    $menus = $this->get_saved_menus();
    if ( empty( $menus ) ) {
      return;
    }

    global $submenu;

    foreach ( $menus as $menu ) {
      $menu_slug = ! empty( $menu['menu_key'] ) ? $menu['menu_key'] : '';
      if ( '' === $menu_slug && ! empty( $menu['menu_title'] ) ) {
        $menu_slug = 'pdt-custom-menu-' . sanitize_key( $menu['menu_title'] );
      }

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

      remove_submenu_page( $menu_slug, $menu_slug );

      // Fallback for stubborn duplicates.
      if ( isset( $submenu[ $menu_slug ] ) && is_array( $submenu[ $menu_slug ] ) ) {
        foreach ( $submenu[ $menu_slug ] as $sub_key => $sub_item ) {
          if ( isset( $sub_item[2] ) && $sub_item[2] === $menu_slug ) {
            unset( $submenu[ $menu_slug ][ $sub_key ] );
          }
        }
      }
    }
  }

  /**
   * Get saved menus option.
   *
   * @return array
   */
  private function get_saved_menus() {
    $menus = get_option( self::OPTION_NAME, array() );
    return is_array( $menus ) ? $menus : array();
  }

  /**
   * Ensure unique main menu slug.
   *
   * @param string $slug  Candidate slug.
   * @param array  $menus Existing menus.
   * @return string
   */
  private function build_internal_slug( $menu_title, $menus ) {
    $slug = 'pdt-custom-menu-' . sanitize_key( $menu_title );
    $used = array();

    foreach ( $menus as $menu ) {
      if ( ! empty( $menu['menu_key'] ) ) {
        $used[] = $menu['menu_key'];
      }
    }

    $original = $slug;
    $i = 2;
    while ( in_array( $slug, $used, true ) ) {
      $slug = $original . '-' . $i;
      $i++;
    }

    return $slug;
  }

  /**
   * Sanitize submenu rows from request.
   *
   * @param string $parent_slug Parent menu slug.
   * @return array
   */
  private function sanitize_submenus( $parent_slug ) {
    // phpcs:disable WordPress.Security.NonceVerification.Missing
    // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    $submenu_titles = isset( $_POST['submenu_menu_title'] ) && is_array( $_POST['submenu_menu_title'] ) ? wp_unslash( $_POST['submenu_menu_title'] ) : array();
    $targets        = isset( $_POST['submenu_target'] ) && is_array( $_POST['submenu_target'] ) ? wp_unslash( $_POST['submenu_target'] ) : array();
    $sub_new_tabs   = isset( $_POST['submenu_new_tab'] ) && is_array( $_POST['submenu_new_tab'] ) ? wp_unslash( $_POST['submenu_new_tab'] ) : array();
    $sub_slugs      = isset( $_POST['submenu_slug'] ) && is_array( $_POST['submenu_slug'] ) ? wp_unslash( $_POST['submenu_slug'] ) : array();
    // phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    // phpcs:enable WordPress.Security.NonceVerification.Missing

    $submenus = array();
    $used_slugs = array();
    $row_count = max( count( $submenu_titles ), count( $targets ), count( $sub_slugs ) );

    for ( $i = 0; $i < $row_count; $i++ ) {
      $menu_title = isset( $submenu_titles[ $i ] ) ? sanitize_text_field( $submenu_titles[ $i ] ) : '';
      $target     = isset( $targets[ $i ] ) ? $this->sanitize_menu_target( $targets[ $i ] ) : '';
      $slug       = isset( $sub_slugs[ $i ] ) ? sanitize_key( $sub_slugs[ $i ] ) : '';
      $new_tab    = isset( $sub_new_tabs[ $i ] ) && '1' === (string) $sub_new_tabs[ $i ];

      if ( empty( $menu_title ) || empty( $target ) ) {
        continue;
      }

      if ( empty( $slug ) ) {
        $slug = sanitize_key( $parent_slug . '-' . $menu_title );
      }

      $slug = $this->ensure_unique_submenu_slug( $slug, $used_slugs );
      $used_slugs[] = $slug;

      $submenus[] = array(
        'menu_title' => $menu_title,
        'target'     => $target,
        'menu_slug'  => $slug,
        'new_tab'    => $new_tab,
      );
    }

    return $submenus;
  }

  /**
   * Ensure unique submenu slug inside same parent.
   *
   * @param string $slug       Candidate slug.
   * @param array  $used_slugs Already used slugs.
   * @return string
   */
  private function ensure_unique_submenu_slug( $slug, $used_slugs ) {
    $original = $slug;
    $i = 2;
    while ( in_array( $slug, $used_slugs, true ) ) {
      $slug = $original . '-' . $i;
      $i++;
    }
    return $slug;
  }

  /**
   * Sanitize menu target (internal slug/query or external URL).
   *
   * @param string $target Target input.
   * @return string
   */
  private function sanitize_menu_target( $target ) {
    $target = trim( (string) $target );
    if ( '' === $target ) {
      return '';
    }

    if ( preg_match( '#^https?://#i', $target ) ) {
      return esc_url_raw( $target );
    }

    return sanitize_text_field( $target );
  }

  /**
   * Redirect custom menu slugs to their configured targets.
   *
   * Prevents blank fallback pages like admin.php?page=pdt-custom-menu-...
   * when parent menu has submenus.
   *
   * @return void
   */
  public function maybe_redirect_custom_menu_target() {
    if ( wp_doing_ajax() ) {
      return;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $current_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
    if ( '' === $current_page ) {
      return;
    }

    $menus = $this->get_saved_menus();
    if ( empty( $menus ) ) {
      return;
    }

    $target = '';
    foreach ( $menus as $menu ) {
      $menu_key = ! empty( $menu['menu_key'] ) ? $menu['menu_key'] : '';
      if ( '' === $menu_key && ! empty( $menu['menu_title'] ) ) {
        $menu_key = 'pdt-custom-menu-' . sanitize_key( $menu['menu_title'] );
      }

      if ( $menu_key === $current_page ) {
        $target = ! empty( $menu['menu_target'] ) ? $menu['menu_target'] : ( $menu['menu_slug'] ?? '' );
        break;
      }

      if ( ! empty( $menu['submenus'] ) && is_array( $menu['submenus'] ) ) {
        foreach ( $menu['submenus'] as $submenu ) {
          if ( empty( $submenu['menu_slug'] ) || $submenu['menu_slug'] !== $current_page ) {
            continue;
          }
          $target = ! empty( $submenu['target'] ) ? $submenu['target'] : '';
          break 2;
        }
      }
    }

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

    // New-tab preferences are handled on click via JS; server redirect should still resolve target.
    $redirect_url = $this->resolve_target_url( $target );
    if ( '' === $redirect_url ) {
      return;
    }

    $http_host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
    $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
    $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $http_host . $request_uri;
    if ( $current_url === $redirect_url ) {
      return;
    }

    if ( $this->is_external_url( $redirect_url ) ) {
      $host = wp_parse_url( $redirect_url, PHP_URL_HOST );
      if ( is_string( $host ) && '' !== $host ) {
        add_filter(
          'allowed_redirect_hosts',
          function( $hosts ) use ( $host ) {
            $hosts[] = $host;
            return array_unique( $hosts );
          }
        );
      }
      wp_safe_redirect( $redirect_url );
    } else {
      wp_safe_redirect( $redirect_url );
    }
    exit;
  }

  /**
   * Convert target value into absolute admin/external URL.
   *
   * @param string $target Raw target value.
   * @return string
   */
  private function resolve_target_url( $target ) {
    $target = trim( (string) $target );
    if ( '' === $target ) {
      return '';
    }

    if ( preg_match( '#^https?://#i', $target ) ) {
      return esc_url_raw( $target );
    }

    if ( 0 === strpos( $target, 'admin.php' ) || preg_match( '#^[a-z0-9\-]+\.php(\?.*)?$#i', $target ) ) {
      return admin_url( ltrim( $target, '/' ) );
    }

    return admin_url( 'admin.php?page=' . rawurlencode( $target ) );
  }

  /**
   * Check if given URL points outside wp-admin host.
   *
   * @param string $url URL to test.
   * @return bool
   */
  private function is_external_url( $url ) {
    $url_host  = wp_parse_url( $url, PHP_URL_HOST );
    $site_host = wp_parse_url( home_url(), PHP_URL_HOST );

    if ( empty( $url_host ) || empty( $site_host ) ) {
      return false;
    }

    return strtolower( $url_host ) !== strtolower( $site_host );
  }
}
