<?php

/**
 * LinkCentral Links Overview Class
 *
 * This class extends WP_List_Table to create a custom table for displaying and managing LinkCentral links.
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
if ( !class_exists( 'WP_List_Table' ) ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class LinkCentral_Links_Overview extends WP_List_Table {
    /**
     * URL prefix for links
     */
    private $url_prefix;

    /**
     * Search term storage for filters
     */
    private $search_term = '';

    /**
     * Per-page options
     */
    private $per_page_options = [
        20,
        50,
        100,
        200
    ];

    /**
     * Get preserved URL parameters (excluding status-specific ones)
     */
    private static function get_preserved_params( $exclude = [] ) {
        $allowed_keys = array(
            'page',
            'post_status',
            'filter_broken',
            'linkcentral_category',
            'orderby',
            'order',
            's',
            'per_page',
            'paged'
        );
        $params = array();
        foreach ( $allowed_keys as $key ) {
            $val = filter_input( INPUT_GET, $key, FILTER_UNSAFE_RAW );
            if ( $val !== null && $val !== '' ) {
                $params[$key] = sanitize_text_field( wp_unslash( $val ) );
            }
        }
        $default_exclude = ['post_status', 'filter_broken'];
        $exclude = array_merge( $default_exclude, $exclude );
        foreach ( $exclude as $param ) {
            unset($params[$param]);
        }
        return $params;
    }

    /**
     * Constructor
     */
    public function __construct() {
        parent::__construct( [
            'singular' => __( 'Link', 'linkcentral' ),
            'plural'   => __( 'Links', 'linkcentral' ),
            'ajax'     => false,
        ] );
        $this->url_prefix = get_option( 'linkcentral_url_prefix', 'go' );
    }

    /**
     * Define the columns for the links table
     */
    public function get_columns() {
        return [
            'cb'              => '<input type="checkbox" />',
            'title'           => __( 'Name', 'linkcentral' ),
            'slug'            => __( 'Short URL', 'linkcentral' ),
            'destination_url' => __( 'Destination', 'linkcentral' ),
            'category'        => __( 'Category', 'linkcentral' ),
            'clicks'          => __( 'Clicks', 'linkcentral' ),
            'date'            => __( 'Date Created', 'linkcentral' ),
        ];
    }

    /**
     * Define sortable columns for the table
     */
    public function get_sortable_columns() {
        return [
            'title'  => ['title', false],
            'date'   => 'date',
            'clicks' => 'clicks',
        ];
    }

    /**
     * Prepare the items for the table to process
     */
    public function prepare_items() {
        // Verify user capability
        if ( !current_user_can( 'linkcentral_view_links' ) ) {
            wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'linkcentral' ) );
        }
        $per_page = $this->per_page_options[0];
        // Default to first option in array
        // Allow per_page to be overridden via URL parameter for quick changes
        $per_page_raw = filter_input( INPUT_GET, 'per_page', FILTER_VALIDATE_INT );
        if ( $per_page_raw !== null && $per_page_raw !== false && in_array( $per_page_raw, $this->per_page_options, true ) ) {
            $per_page = $per_page_raw;
        }
        $current_page = $this->get_pagenum();
        $post_status_raw = filter_input( INPUT_GET, 'post_status', FILTER_UNSAFE_RAW );
        $post_status = ( $post_status_raw !== null && $post_status_raw !== '' ? sanitize_key( wp_unslash( $post_status_raw ) ) : 'any' );
        // Check for broken links filter
        $filter_broken_raw = filter_input( INPUT_GET, 'filter_broken', FILTER_UNSAFE_RAW );
        $filter_broken = ( $filter_broken_raw !== null && $filter_broken_raw !== '' ? sanitize_key( wp_unslash( $filter_broken_raw ) ) : '' );
        // Check for category filter
        $filter_category_raw = filter_input( INPUT_GET, 'linkcentral_category', FILTER_VALIDATE_INT );
        $filter_category = ( $filter_category_raw !== null && $filter_category_raw !== false ? $filter_category_raw : 0 );
        // Handle search
        $search_term = '';
        $search_get = filter_input( INPUT_GET, 's', FILTER_UNSAFE_RAW );
        if ( $search_get !== null ) {
            $search_term = sanitize_text_field( wp_unslash( $search_get ) );
        }
        // Set up the query arguments
        $args = [
            'post_type'      => 'linkcentral_link',
            'posts_per_page' => $per_page,
            'paged'          => $current_page,
            'post_status'    => $post_status,
        ];
        // Add search functionality
        if ( !empty( $search_term ) ) {
            // Use custom search to search only in linkcentral_link posts
            add_filter(
                'posts_where',
                array($this, 'extend_search_where'),
                10,
                2
            );
            add_filter(
                'posts_join',
                array($this, 'extend_search_join'),
                10,
                2
            );
            add_filter(
                'posts_groupby',
                array($this, 'extend_search_groupby'),
                10,
                2
            );
            // Store search term for use in filters
            $this->search_term = $search_term;
        }
        // Handle category filtering
        if ( $filter_category > 0 ) {
            $args['tax_query'] = array(array(
                'taxonomy' => 'linkcentral_category',
                'field'    => 'term_id',
                'terms'    => $filter_category,
            ));
        }
        // Handle sorting - default to title ASC
        $orderby_raw = filter_input( INPUT_GET, 'orderby', FILTER_UNSAFE_RAW );
        $orderby = ( $orderby_raw !== null && $orderby_raw !== '' ? sanitize_key( wp_unslash( $orderby_raw ) ) : 'title' );
        $order_raw = filter_input( INPUT_GET, 'order', FILTER_UNSAFE_RAW );
        $order = ( $order_raw !== null && $order_raw !== '' ? sanitize_key( wp_unslash( $order_raw ) ) : 'ASC' );
        // Map WordPress parameters
        $orderby = ( $orderby === 't' ? 'title' : (( $orderby === 'c' ? 'clicks' : $orderby )) );
        $order = strtoupper( $order );
        // Handle special cases
        if ( $orderby === 'clicks' ) {
            $args['meta_key'] = '_linkcentral_click_count';
            $args['orderby'] = 'meta_value_num';
            // Use WordPress's built-in numeric sorting
            $args['order'] = $order;
        } else {
            $args['orderby'] = $orderby;
            $args['order'] = $order;
        }
        $query = new WP_Query($args);
        // Remove filters after query
        if ( !empty( $search_term ) ) {
            remove_filter( 'posts_where', array($this, 'extend_search_where'), 10 );
            remove_filter( 'posts_join', array($this, 'extend_search_join'), 10 );
            remove_filter( 'posts_groupby', array($this, 'extend_search_groupby'), 10 );
        }
        $this->items = $query->posts;
        $total_items = $query->found_posts;
        // Sync click counts to post meta for this page of results (used for sorting by clicks)
        foreach ( $this->items as $post ) {
            $count = $this->get_click_count( $post->ID );
            update_post_meta( $post->ID, '_linkcentral_click_count', $count );
        }
        // Set up pagination
        $this->set_pagination_args( [
            'total_items' => $total_items,
            'per_page'    => $per_page,
            'total_pages' => ceil( $total_items / $per_page ),
        ] );
        $this->_column_headers = [$this->get_columns(), [], $this->get_sortable_columns()];
    }

    /**
     * Extend search WHERE clause to include title, slug, and destination URL
     *
     * @param string $where The WHERE clause
     * @param WP_Query $query The WP_Query object
     * @return string Modified WHERE clause
     */
    public function extend_search_where( $where, $query ) {
        global $wpdb;
        if ( !empty( $this->search_term ) && $query->get( 'post_type' ) === 'linkcentral_link' ) {
            $search_term = '%' . $wpdb->esc_like( $this->search_term ) . '%';
            $where .= $wpdb->prepare(
                " AND (\n                ({$wpdb->posts}.post_title LIKE %s) OR \n                ({$wpdb->posts}.post_name LIKE %s) OR \n                (pm.meta_value LIKE %s)\n            )",
                $search_term,
                $search_term,
                $search_term
            );
        }
        return $where;
    }

    /**
     * Extend search JOIN clause to include postmeta table
     *
     * @param string $join The JOIN clause
     * @param WP_Query $query The WP_Query object
     * @return string Modified JOIN clause
     */
    public function extend_search_join( $join, $query ) {
        global $wpdb;
        // Only join postmeta table when we have a search term and we're querying links
        if ( !empty( $this->search_term ) && $query->get( 'post_type' ) === 'linkcentral_link' ) {
            $join .= " LEFT JOIN {$wpdb->postmeta} pm ON ({$wpdb->posts}.ID = pm.post_id AND pm.meta_key = '_linkcentral_destination_url')";
        }
        return $join;
    }

    /**
     * Extend search GROUP BY clause to avoid duplicate results
     *
     * @param string $groupby The GROUP BY clause
     * @param WP_Query $query The WP_Query object
     * @return string Modified GROUP BY clause
     */
    public function extend_search_groupby( $groupby, $query ) {
        global $wpdb;
        if ( !empty( $this->search_term ) && $query->get( 'post_type' ) === 'linkcentral_link' ) {
            $groupby = "{$wpdb->posts}.ID";
        }
        return $groupby;
    }

    /**
     * Default column rendering
     *
     * @param object $item Current item
     * @param string $column_name Name of the column
     * @return string
     */
    public function column_default( $item, $column_name ) {
        switch ( $column_name ) {
            case 'destination_url':
                $destination_url = get_post_meta( $item->ID, '_linkcentral_destination_url', true );
                $dynamic_rules = get_post_meta( $item->ID, '_linkcentral_dynamic_rules', true );
                $output = linkcentral_truncate_url( $destination_url );
                return $output;
            case 'category':
                $terms = get_the_terms( $item->ID, 'linkcentral_category' );
                if ( empty( $terms ) || is_wp_error( $terms ) ) {
                    return '&mdash;';
                }
                // Preserve current filters but reset category + pagination
                $base_params = self::get_preserved_params( ['linkcentral_category', 'paged'] );
                // Always ensure we're linking back to the LinkCentral overview page
                $base_params['page'] = 'linkcentral';
                $links = [];
                foreach ( $terms as $term ) {
                    $params = $base_params;
                    $params['linkcentral_category'] = $term->term_id;
                    $url = add_query_arg( $params, admin_url( 'admin.php' ) );
                    $name = esc_html( $term->name );
                    $links[] = sprintf( '<a href="%s">%s</a>', esc_url( $url ), $name );
                }
                return implode( ', ', $links );
            case 'date':
                return get_the_date( 'd F Y', $item->ID );
            default:
                return __( 'Unavailable', 'linkcentral' );
        }
    }

    /**
     * Render the checkbox column
     *
     * @param object $item Current item
     * @return string
     */
    public function column_cb( $item ) {
        return sprintf( '<input type="checkbox" name="link[]" value="%d" />', absint( $item->ID ) );
    }

    /**
     * Render the title column
     *
     * @param object $item Current item
     * @return string
     */
    public function column_title( $item ) {
        $edit_link = get_edit_post_link( $item->ID );
        $title = '<strong>';
        // Only add edit link if user has edit capability and we have a valid edit URL
        if ( current_user_can( 'linkcentral_create_edit_links' ) && $edit_link ) {
            $title .= '<a class="row-title" href="' . esc_url( $edit_link ) . '">' . esc_html( $item->post_title ) . '</a>';
        } else {
            $title .= esc_html( $item->post_title );
        }
        $status = get_post_status( $item->ID );
        $status_object = get_post_status_object( $status );
        if ( $status !== 'publish' ) {
            if ( $status === 'draft' ) {
                $status_label = __( 'Draft (inactive)', 'linkcentral' );
            } elseif ( $status_object && isset( $status_object->label ) ) {
                $status_label = $status_object->label;
            } else {
                $status_label = $status;
            }
            $title .= ' &mdash; <span class="linkcentral-post-state">' . esc_html( $status_label ) . '</span>';
        }
        if ( $item->post_password ) {
            $title .= ' <span class="dashicons dashicons-lock" title="' . esc_attr__( 'Password protected', 'linkcentral' ) . '"></span>';
        }
        $title .= '</strong>';
        $actions = [
            'id' => sprintf( '<span class="linkcentral-post-id">ID: %d</span>', $item->ID ),
        ];
        if ( $status === 'trash' ) {
            if ( current_user_can( 'linkcentral_create_edit_links' ) ) {
                $actions['untrash'] = sprintf( '<a href="%s">%s</a>', esc_url( wp_nonce_url( admin_url( 'admin.php?page=linkcentral&action=untrash&link=' . absint( $item->ID ) ), 'untrash-link_' . $item->ID ) ), esc_html__( 'Untrash', 'linkcentral' ) );
                $actions['delete'] = sprintf(
                    '<a href="%s" class="submitdelete" onclick="return confirm(\'%s\');">%s</a>',
                    esc_url( get_delete_post_link( $item->ID, '', true ) ),
                    esc_js( __( 'You are about to permanently delete this link. This action cannot be undone. Are you sure?', 'linkcentral' ) ),
                    esc_html__( 'Delete Permanently', 'linkcentral' )
                );
            }
        } else {
            if ( current_user_can( 'linkcentral_create_edit_links' ) && $edit_link ) {
                $actions['edit'] = sprintf( '<a href="%s">%s</a>', esc_url( $edit_link ), esc_html__( 'Edit', 'linkcentral' ) );
                $actions['trash'] = sprintf( '<a href="%s">%s</a>', esc_url( get_delete_post_link( $item->ID ) ), esc_html__( 'Trash', 'linkcentral' ) );
            }
        }
        return $title . $this->row_actions( $actions );
    }

    /**
     * Render the slug column
     *
     * @param object $item Current item
     * @return string
     */
    public function column_slug( $item ) {
        $short_url = linkcentral_get_link_url( $item->ID, $item->post_name );
        $copy_label = esc_attr__( 'Copy URL', 'linkcentral' );
        return sprintf(
            '<span class="linkcentral-overview-slug">%s<button type="button" class="linkcentral-copy-url" data-url="%s" aria-label="%s" title="%s"><span class="dashicons dashicons-admin-page" aria-hidden="true"></span></button></span>',
            esc_html( $short_url ),
            esc_attr( $short_url ),
            $copy_label,
            $copy_label
        );
    }

    /**
     * Render the clicks column
     *
     * @param object $item Current item
     * @return string
     */
    public function column_clicks( $item ) {
        $click_count = $this->get_click_count( $item->ID );
        return sprintf( '<span class="linkcentral-click-count" data-link-id="%d">%d</span>', absint( $item->ID ), $click_count );
    }

    /**
     * Get the click count for a specific link
     *
     * @param int $link_id Link ID
     * @return int
     */
    private function get_click_count( $link_id ) {
        global $wpdb;
        return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `{$wpdb->prefix}linkcentral_stats` WHERE link_id = %d", $link_id ) );
    }

    /**
     * Define bulk actions
     *
     * @return array
     */
    public function get_bulk_actions() {
        $actions = array();
        $post_status_raw = filter_input( INPUT_GET, 'post_status', FILTER_UNSAFE_RAW );
        $post_status = ( $post_status_raw !== null && $post_status_raw !== '' ? sanitize_key( wp_unslash( $post_status_raw ) ) : 'any' );
        if ( $post_status === 'trash' ) {
            $actions['untrash'] = __( 'Untrash', 'linkcentral' );
            $actions['delete'] = __( 'Delete Permanently', 'linkcentral' );
        } else {
            $actions['trash'] = __( 'Move to Trash', 'linkcentral' );
        }
        return $actions;
    }

    /**
     * Generate views for different post statuses
     *
     * @return array
     */
    protected function get_views() {
        $current_params = self::get_preserved_params();
        $status_links = array();
        $num_posts = wp_count_posts( 'linkcentral_link', 'readable' );
        $class = '';
        $allposts = '';
        // Calculate total posts excluding 'trash' and 'auto-draft'
        $total_posts = array_sum( (array) $num_posts ) - $num_posts->trash - $num_posts->{'auto-draft'};
        $get_post_status_raw = filter_input( INPUT_GET, 'post_status', FILTER_UNSAFE_RAW );
        $get_post_status = ( $get_post_status_raw !== null && $get_post_status_raw !== '' ? sanitize_key( wp_unslash( $get_post_status_raw ) ) : '' );
        $get_filter_broken_raw = filter_input( INPUT_GET, 'filter_broken', FILTER_UNSAFE_RAW );
        $get_filter_broken = ( $get_filter_broken_raw !== null && $get_filter_broken_raw !== '' ? sanitize_key( wp_unslash( $get_filter_broken_raw ) ) : '' );
        $class = ( empty( $class ) && empty( $get_post_status ) && empty( $get_filter_broken ) ? ' class="current"' : '' );
        $all_text = __( 'All', 'linkcentral' );
        $all_url = add_query_arg( $current_params, admin_url( 'admin.php?page=linkcentral' ) );
        $status_links['all'] = sprintf(
            '<a href="%s"%s>%s <span class="count">(%s)</span></a>',
            esc_url( $all_url ),
            $class,
            $all_text,
            number_format_i18n( $total_posts )
        );
        $statuses = get_post_stati( array(
            'show_in_admin_status_list' => true,
        ), 'objects' );
        if ( $statuses ) {
            foreach ( $statuses as $status ) {
                $class = '';
                $status_name = $status->name;
                if ( !in_array( $status_name, array(
                    'publish',
                    'draft',
                    'pending',
                    'trash',
                    'future',
                    'private',
                    'auto-draft'
                ) ) ) {
                    continue;
                }
                if ( empty( $num_posts->{$status_name} ) ) {
                    continue;
                }
                $current_post_status_raw = filter_input( INPUT_GET, 'post_status', FILTER_UNSAFE_RAW );
                $current_post_status = ( $current_post_status_raw !== null && $current_post_status_raw !== '' ? sanitize_key( wp_unslash( $current_post_status_raw ) ) : '' );
                if ( $status_name === $current_post_status ) {
                    $class = ' class="current"';
                }
                $status_params = array_merge( $current_params, [
                    'post_status' => $status_name,
                ] );
                $url = add_query_arg( $status_params, admin_url( 'admin.php?page=linkcentral' ) );
                $count = number_format_i18n( $num_posts->{$status_name} );
                // Use WordPress core's translate_nooped_plural function for proper translation
                $status_label = sprintf( translate_nooped_plural( $status->label_count, $num_posts->{$status_name} ), $count );
                $status_links[$status_name] = sprintf(
                    '<a href="%s"%s>%s</a>',
                    esc_url( $url ),
                    $class,
                    $status_label
                );
            }
        }
        return $status_links;
    }

    /**
     * Get current per-page value with validation
     */
    private function get_current_per_page() {
        $per_page_raw = filter_input( INPUT_GET, 'per_page', FILTER_VALIDATE_INT );
        $per_page = ( $per_page_raw !== null && $per_page_raw !== false ? $per_page_raw : $this->per_page_options[0] );
        // Validate against allowed options for security
        return ( in_array( $per_page, $this->per_page_options, true ) ? $per_page : $this->per_page_options[0] );
    }

    /**
     * Display the search box (override so it is always shown).
     *
     * Core hides it when there are no items and no search term; we always show it
     * so users can search or change filters (e.g. category with no results).
     *
     * @param string $text     The 'submit' button label.
     * @param string $input_id ID attribute value for the search input field.
     */
    public function search_box( $text, $input_id ) {
        $input_id = $input_id . '-search-input';
        $orderby = filter_input( INPUT_GET, 'orderby', FILTER_UNSAFE_RAW );
        if ( $orderby !== null && $orderby !== '' ) {
            $orderby = wp_unslash( $orderby );
            if ( is_array( $orderby ) ) {
                foreach ( $orderby as $key => $value ) {
                    echo '<input type="hidden" name="orderby[' . esc_attr( sanitize_key( $key ) ) . ']" value="' . esc_attr( sanitize_key( $value ) ) . '" />';
                }
            } else {
                echo '<input type="hidden" name="orderby" value="' . esc_attr( sanitize_key( $orderby ) ) . '" />';
            }
        }
        $order_param = filter_input( INPUT_GET, 'order', FILTER_UNSAFE_RAW );
        if ( $order_param !== null && $order_param !== '' ) {
            $order_sanitized = sanitize_key( wp_unslash( $order_param ) );
            if ( in_array( $order_sanitized, array('asc', 'desc'), true ) ) {
                echo '<input type="hidden" name="order" value="' . esc_attr( $order_sanitized ) . '" />';
            }
        }
        ?>
        <p class="search-box">
            <label class="screen-reader-text" for="<?php 
        echo esc_attr( $input_id );
        ?>"><?php 
        echo esc_html( $text );
        ?>:</label>
            <input type="search" id="<?php 
        echo esc_attr( $input_id );
        ?>" name="s" value="<?php 
        _admin_search_query();
        ?>" />
        <?php 
        submit_button(
            $text,
            '',
            '',
            false,
            array(
                'id' => 'search-submit',
            )
        );
        ?>
        </p>
        <?php 
    }

    /**
     * Add per-page selector to bottom navigation
     */
    protected function extra_tablenav( $which ) {
        if ( $which === 'bottom' ) {
            $current_per_page = $this->get_current_per_page();
            ?>
            <div class="alignright">
                <select class="linkcentral-per-page-selector" onchange="linkcentralChangePerPage(this.value)">
                    <?php 
            foreach ( $this->per_page_options as $option ) {
                ?>
                        <option value="<?php 
                echo esc_attr( $option );
                ?>" <?php 
                selected( $current_per_page, $option );
                ?>>
                            <?php 
                echo esc_html( $option );
                ?> <?php 
                esc_html_e( 'per page', 'linkcentral' );
                ?>
                        </option>
                    <?php 
            }
            ?>
                </select>
            </div>
            <?php 
        }
        parent::extra_tablenav( $which );
    }

    /**
     * Render the main links overview page
     */
    public static function render_all_links_page() {
        $list_table = new self();
        $list_table->prepare_items();
        $post_status_raw = filter_input( INPUT_GET, 'post_status', FILTER_UNSAFE_RAW );
        $post_status = ( $post_status_raw !== null && $post_status_raw !== '' ? sanitize_key( wp_unslash( $post_status_raw ) ) : 'any' );
        $current_params = self::get_preserved_params();
        $trash_url = add_query_arg( array_merge( $current_params, [
            'post_status' => 'trash',
        ] ), admin_url( 'admin.php?page=linkcentral' ) );
        $all_url = add_query_arg( $current_params, admin_url( 'admin.php?page=linkcentral' ) );
        // Display admin notices
        self::display_admin_notices();
        include LINKCENTRAL_PLUGIN_DIR . 'views/links-overview-page.php';
    }

    /**
     * Initialize the class
     */
    public static function init() {
        add_action( 'admin_init', array(__CLASS__, 'process_bulk_action') );
    }

    /**
     * Process bulk actions
     */
    public static function process_bulk_action() {
        if ( !isset( $_REQUEST['page'] ) || sanitize_key( wp_unslash( $_REQUEST['page'] ) ) !== 'linkcentral' ) {
            return;
        }
        $list_table = new self();
        $action = $list_table->current_action();
        if ( empty( $action ) ) {
            return;
        }
        // Check nonce for all actions
        $nonce = ( isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '' );
        if ( !wp_verify_nonce( $nonce, 'bulk-' . $list_table->_args['plural'] ) && !wp_verify_nonce( $nonce, 'untrash-link_' . (( isset( $_REQUEST['link'] ) ? absint( $_REQUEST['link'] ) : '' )) ) ) {
            wp_die( esc_html__( 'Security check failed', 'linkcentral' ) );
        }
        $post_ids = [];
        if ( isset( $_REQUEST['link'] ) && wp_verify_nonce( $nonce, 'bulk-' . $list_table->_args['plural'] ) ) {
            $post_ids = ( is_array( $_REQUEST['link'] ) ? array_map( 'intval', $_REQUEST['link'] ) : [intval( $_REQUEST['link'] )] );
        }
        // Handle individual untrash action
        if ( $action === 'untrash' && isset( $_REQUEST['link'] ) && wp_verify_nonce( $nonce, 'untrash-link_' . absint( $_REQUEST['link'] ) ) ) {
            $post_ids = [intval( $_REQUEST['link'] )];
        }
        if ( empty( $post_ids ) ) {
            return;
        }
        $current_url = add_query_arg( array() );
        // Get current URL with all parameters
        $redirect_url = remove_query_arg( ['action', 'link', '_wpnonce'], $current_url );
        // Remove action-related parameters
        $processed_count = 0;
        switch ( $action ) {
            case 'trash':
                foreach ( $post_ids as $post_id ) {
                    if ( wp_trash_post( $post_id ) ) {
                        $processed_count++;
                    }
                }
                $redirect_url = add_query_arg( 'trashed', $processed_count, $redirect_url );
                break;
            case 'untrash':
                foreach ( $post_ids as $post_id ) {
                    if ( wp_untrash_post( $post_id ) ) {
                        $processed_count++;
                    }
                }
                $redirect_url = add_query_arg( 'untrashed', $processed_count, $redirect_url );
                break;
            case 'delete':
                foreach ( $post_ids as $post_id ) {
                    if ( wp_delete_post( $post_id, true ) ) {
                        $processed_count++;
                    }
                }
                $redirect_url = add_query_arg( 'deleted', $processed_count, $redirect_url );
                break;
        }
        // Perform the redirect
        wp_safe_redirect( $redirect_url );
        exit;
    }

    /**
     * Display admin notices for bulk actions
     */
    private static function display_admin_notices() {
        $messages = array(
            'trashed'   => array(
                'singular' => __( '%s link moved to the Trash.', 'linkcentral' ),
                'plural'   => __( '%s links moved to the Trash.', 'linkcentral' ),
                'type'     => 'updated',
            ),
            'untrashed' => array(
                'singular' => __( '%s link restored from the Trash.', 'linkcentral' ),
                'plural'   => __( '%s links restored from the Trash.', 'linkcentral' ),
                'type'     => 'updated',
            ),
            'deleted'   => array(
                'singular' => __( '%s link permanently deleted.', 'linkcentral' ),
                'plural'   => __( '%s links permanently deleted.', 'linkcentral' ),
                'type'     => 'updated',
            ),
        );
        foreach ( $messages as $key => $message ) {
            $count_val = filter_input( INPUT_GET, $key, FILTER_VALIDATE_INT );
            if ( $count_val !== null && $count_val !== false && $count_val > 0 ) {
                $count = (int) $count_val;
                $text = ( $count === 1 ? $message['singular'] : $message['plural'] );
                $notice = sprintf( $text, number_format_i18n( $count ) );
                echo "<div class='notice " . esc_attr( $message['type'] ) . " is-dismissible'><p>" . esc_html( $notice ) . "</p></div>";
            }
        }
    }

}
