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

/**
 * Service for handling wp-admin UI modifications, list views, and top bar edits.
 */
class NEXDIRECTORY_Admin_UI_Service {

    /**
     * @var string
     */
    private $post_type;

    /**
     * @var NEXDIRECTORY_User_Capabilities
     */
    private $user_caps;

    /**
     * @var NEXDIRECTORY_Event_Meta_Service
     */
    private $event_meta;

    /**
     * @var mixed NEXDIRECTORY_Frontend_Navigation_Service (handles routing and UI labels)
     */
    private $frontend_nav;

    /**
     * Constructor.
     */
    public function __construct($post_type, $user_caps, $event_meta, $frontend_nav) {
        $this->post_type = sanitize_key($post_type);
        $this->user_caps = $user_caps;
        $this->event_meta = $event_meta;
        $this->frontend_nav = $frontend_nav;
    }

    /**
     * Builds the frontend edit URL for an event.
     */
    public function get_frontend_event_edit_url($post_id) {
        $post_id = absint((int) $post_id);
        if ($post_id <= 0) {
            return '';
        }

        $current_user_id = is_user_logged_in() ? (int) get_current_user_id() : 0;
        $locked_demo_edit = method_exists($this->user_caps, 'is_demo_event_edit_locked')
            ? (bool) $this->user_caps->is_demo_event_edit_locked($post_id, $current_user_id)
            : false;
        if ($locked_demo_edit) {
            return $this->get_admin_duplicate_event_url($post_id);
        }

        $submit_url = '';
        if (is_object($this->frontend_nav) && method_exists($this->frontend_nav, 'get_platform_page_url')) {
            $submit_url = (string) $this->frontend_nav->get_platform_page_url(
                'nexdirectory_page_submit_event_url',
                ['submit', 'add-new-event'],
                home_url('/submit/')
            );
        }
        if ($submit_url === '') {
            $submit_url = esc_url_raw((string) get_option('nexdirectory_page_submit_event_url', ''));
        }
        if ($submit_url === '') {
            $submit_url = (string) home_url('/submit/');
        }
        $submit_url = esc_url_raw($submit_url);
        if ($submit_url === '') {
            return '';
        }

        return (string) nexdirectory_add_query_arg([
            'nexdirectory_tab' => 'submit',
            'edit_event_id' => $post_id,
        ], $submit_url) . '#submit';
    }

    /**
     * Builds nonce-protected duplicate URL used as "create editable copy" fallback.
     */
    private function get_admin_duplicate_event_url($post_id) {
        $post_id = absint((int) $post_id);
        if ($post_id <= 0) {
            return '';
        }

        return (string) wp_nonce_url(
            nexdirectory_add_query_arg([
                'action' => 'nexdirectory_duplicate_event',
                'post' => $post_id,
            ], admin_url('admin.php')),
            'nexdirectory_duplicate_event_' . $post_id
        );
    }

    /**
     * Hides the admin bar for users with the 'event_submitter' role.
     */
    public function filter_show_admin_bar_for_submitter($show_admin_bar) {
        if ($this->is_event_webapp_request()) {
            return false;
        }

        if (!is_user_logged_in() || current_user_can('manage_options')) {
            return $show_admin_bar;
        }
        
        if ($this->user_caps->is_event_submitter_user(get_current_user_id())) {
            return false;
        }
        
        return $show_admin_bar;
    }

    /**
     * Detects frontend Event Web App requests so WordPress admin bar can be fully disabled.
     */
    private function is_event_webapp_request() {
        if (is_admin()) {
            return false;
        }

        $webapp_flags = ['nexdirectory_webapp_manifest', 'nexdirectory_webapp_sw', 'nexdirectory_webapp_icon'];
        foreach ($webapp_flags as $flag_key) {
            $flag_value = isset($_GET[$flag_key]) ? sanitize_key((string) wp_unslash($_GET[$flag_key])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only frontend webapp routing flag.
            if (in_array($flag_value, ['1', 'true', 'yes'], true)) {
                return true;
            }
        }

        $configured_url = (string) get_option('nexdirectory_page_event_webapp_url', '');
        if ($configured_url === '' && is_object($this->frontend_nav) && method_exists($this->frontend_nav, 'get_platform_page_url')) {
            $configured_url = (string) $this->frontend_nav->get_platform_page_url(
                'nexdirectory_page_event_webapp_url',
                ['event-app'],
                home_url('/event-app/')
            );
        }
        if ($configured_url === '') {
            $configured_url = (string) home_url('/event-app/');
        }

        $configured_path = wp_parse_url($configured_url, PHP_URL_PATH);
        $configured_path = is_string($configured_path) ? trim($configured_path) : '';
        $configured_path = $configured_path !== '' ? trailingslashit($configured_path) : '/event-app/';

        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
        $request_path = wp_parse_url($request_uri, PHP_URL_PATH);
        $request_path = is_string($request_path) ? trim($request_path) : '';
        $request_path = $request_path !== '' ? trailingslashit($request_path) : '/';
        if ($request_path === $configured_path) {
            return true;
        }

        if (function_exists('is_page') && is_page()) {
            $queried = get_queried_object();
            if ($queried instanceof WP_Post && has_shortcode((string) $queried->post_content, 'nexdirectory_event_webapp')) {
                return true;
            }
        }

        return false;
    }

    /**
     * Prevents submitters from accessing the generic wp-admin dashboard.
     */
    public function enforce_submitter_dashboard_lockout() {
        if (!is_admin() || !is_user_logged_in()) {
            return;
        }
        if (current_user_can('manage_options')) {
            return;
        }
        if ((function_exists('wp_doing_ajax') && wp_doing_ajax()) || (defined('DOING_AJAX') && DOING_AJAX)) {
            return;
        }
        if ((defined('DOING_CRON') && DOING_CRON) || (defined('REST_REQUEST') && REST_REQUEST)) {
            return;
        }
        if (!$this->user_caps->is_event_submitter_user(get_current_user_id())) {
            return;
        }

        global $pagenow;
        $pagenow_clean = is_string($pagenow) ? strtolower($pagenow) : '';
        if (in_array($pagenow_clean, ['admin-post.php', 'admin-ajax.php', 'async-upload.php'], true)) {
            return;
        }

        // Delegate to Frontend Navigation service to get the correct account URL
        $account_url = $this->frontend_nav->get_platform_page_url(
            'nexdirectory_page_account_url', 
            ['account'], 
            home_url('/account/')
        );
        
        $account_url = nexdirectory_add_query_arg([
            'nexdirectory_notice' => rawurlencode(__('Dashboard access is disabled for your account. Use My Account instead.', 'nexdirectory')),
            'nexdirectory_notice_type' => 'error',
        ], $account_url);

        $this->frontend_nav->safe_redirect_or_fallback((string) $account_url);
    }

    /**
     * Rewrites the "Edit" link in the admin list view to point to the frontend builder.
     */
    public function filter_admin_event_edit_link($url, $post_id, $context = 'display') {
        $post_id = absint((int) $post_id);
        if ($post_id <= 0 || get_post_type($post_id) !== $this->post_type) {
            return $url;
        }
        $current_user_id = is_user_logged_in() ? (int) get_current_user_id() : 0;
        $can_duplicate_locked = method_exists($this->user_caps, 'user_can_duplicate_event')
            ? (bool) $this->user_caps->user_can_duplicate_event($post_id, $current_user_id)
            : false;
        if (!current_user_can('edit_post', $post_id) && !$can_duplicate_locked) {
            return $url;
        }
        
        // Delegate to Frontend Navigation service
        $frontend_url = $this->get_frontend_event_edit_url($post_id);
            
        if ($frontend_url === '') {
            return $url;
        }
        
        return $frontend_url;
    }

    /**
     * Adds the standalone publishing status node to the WP admin bar.
     */
    public function add_demo_limit_admin_bar_node($wp_admin_bar) {
        if (!is_admin_bar_showing()) {
            return;
        }
        if (!class_exists('WP_Admin_Bar') || !($wp_admin_bar instanceof WP_Admin_Bar)) {
            return;
        }
        if (!is_user_logged_in() || !current_user_can('manage_options')) {
            return;
        }
        $wp_admin_bar->add_node([
            'id' => 'nexdirectory-publishing-status',
            'title' => esc_html__('Nex Directory Free: Unlimited', 'nexdirectory'),
            'href' => esc_url(admin_url('admin.php?page=nexdirectory-settings')),
            'meta' => [
                'class' => 'ab-item nexdirectory-core-unlimited',
                'title' => esc_attr__('Unlimited core publishing is included.', 'nexdirectory'),
            ],
        ]);
    }

    /**
     * Rewrites the WP Admin Bar "Edit Post" node to point to the frontend builder.
     */
    public function replace_admin_bar_event_edit_link($wp_admin_bar) {
        if (is_admin() || !is_admin_bar_showing() || !is_singular($this->post_type)) {
            return;
        }
        if (!class_exists('WP_Admin_Bar') || !($wp_admin_bar instanceof WP_Admin_Bar)) {
            return;
        }

        $post_id = (int) get_queried_object_id();
        $current_user_id = is_user_logged_in() ? (int) get_current_user_id() : 0;
        $can_edit_post = $post_id > 0 && current_user_can('edit_post', $post_id);
        $can_duplicate_locked = $post_id > 0 && method_exists($this->user_caps, 'user_can_duplicate_event')
            ? (bool) $this->user_caps->user_can_duplicate_event($post_id, $current_user_id)
            : false;
        if ($post_id <= 0 || (!$can_edit_post && !$can_duplicate_locked)) {
            return;
        }

        $frontend_url = $this->get_frontend_event_edit_url($post_id);
            
        if ($frontend_url === '') {
            return;
        }

        $locked_demo_edit = method_exists($this->user_caps, 'is_demo_event_edit_locked')
            ? (bool) $this->user_caps->is_demo_event_edit_locked($post_id, $current_user_id)
            : false;

        $edit_node = $wp_admin_bar->get_node('edit');
        if (!$edit_node) {
            return;
        }
        
        $edit_node->href = $frontend_url;
        $edit_node->title = $locked_demo_edit
            ? esc_html__('Create Editable Copy', 'nexdirectory')
            : esc_html__('Edit Event', 'nexdirectory');
        $wp_admin_bar->add_node($edit_node);

        // Add a second WP editor shortcut so admins can still open the native post editor directly.
        if ($can_edit_post) {
            $wp_editor_url = nexdirectory_add_query_arg([
                'post' => $post_id,
                'action' => 'edit',
                'nexdirectory_wp_editor' => '1',
            ], admin_url('post.php'));

            $wp_admin_bar->add_node([
                'id' => 'nexdirectory-edit-wp-page',
                'parent' => false,
                'title' => esc_html__('Edit Page', 'nexdirectory'),
                'href' => esc_url($wp_editor_url),
                'meta' => [
                    'class' => 'ab-item',
                ],
            ]);
        }
    }

    /**
     * Filters row actions on the post list table to replace the standard edit link.
     */
    public function filter_admin_event_row_actions($actions, $post) {
        if (!$post instanceof WP_Post || (string) $post->post_type !== $this->post_type) {
            return $actions;
        }
        $post_id = (int) $post->ID;
        $current_user_id = is_user_logged_in() ? (int) get_current_user_id() : 0;
        $can_edit_post = current_user_can('edit_post', $post_id);
        $can_duplicate_locked = method_exists($this->user_caps, 'user_can_duplicate_event')
            ? (bool) $this->user_caps->user_can_duplicate_event($post_id, $current_user_id)
            : false;
        if (!$can_edit_post && !$can_duplicate_locked) {
            return $actions;
        }
        
        $frontend_edit_url = $this->get_frontend_event_edit_url($post_id);
        $locked_demo_edit = method_exists($this->user_caps, 'is_demo_event_edit_locked')
            ? (bool) $this->user_caps->is_demo_event_edit_locked($post_id, $current_user_id)
            : false;
        if ($frontend_edit_url !== '' && (isset($actions['edit']) || $can_duplicate_locked)) {
            $actions['edit'] = '<a href="' . esc_url($frontend_edit_url) . '">' . esc_html($locked_demo_edit ? __('Create Editable Copy', 'nexdirectory') : __('Edit Event', 'nexdirectory')) . '</a>';
        }

        $wp_editor_url = nexdirectory_add_query_arg([
            'post' => (int) $post->ID,
            'action' => 'edit',
            'nexdirectory_wp_editor' => '1',
        ], admin_url('post.php'));

        $view_page_url = '';
        if ((string) get_post_status((int) $post->ID) === 'publish') {
            $view_page_url = (string) get_permalink((int) $post->ID);
        } else {
            $preview_url = get_preview_post_link($post);
            if (is_string($preview_url) && $preview_url !== '') {
                $view_page_url = $preview_url;
            } else {
                $fallback_view_url = get_permalink((int) $post->ID);
                $view_page_url = is_string($fallback_view_url) ? $fallback_view_url : '';
            }
        }
        $open_event_url = $view_page_url !== '' ? $view_page_url : $frontend_edit_url;

        $duplicate_event_url = $this->get_admin_duplicate_event_url($post_id);

        $transfer_owner_url = wp_nonce_url(nexdirectory_add_query_arg([
            'action' => 'nexdirectory_open_transfer_owner',
            'post_id' => (int) $post->ID,
        ], admin_url('admin-post.php')), 'nexdirectory_transfer_owner_' . (int) $post->ID);

        $ordered_actions = [];
        foreach ((array) $actions as $action_key => $action_markup) {
            $ordered_actions[$action_key] = $action_markup;
            if ((string) $action_key === 'edit') {
                if ($open_event_url !== '') {
                    $ordered_actions['open_event'] = '<a href="' . esc_url($open_event_url) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('Open Event', 'nexdirectory') . '</a>';
                }
                if ($can_edit_post) {
                    $ordered_actions['view_wp_page'] = '<a href="' . esc_url($wp_editor_url) . '">' . esc_html__('Edit WP Page', 'nexdirectory') . '</a>';
                }
                if ($can_edit_post || $can_duplicate_locked) {
                    $ordered_actions['duplicate_event'] = '<a href="' . esc_url($duplicate_event_url) . '">' . esc_html__('Duplicate Event', 'nexdirectory') . '</a>';
                }
                if ($can_edit_post && current_user_can('manage_options')) {
                    $ordered_actions['change_owner'] = '<a href="' . esc_url($transfer_owner_url) . '">' . esc_html__('Change Owner', 'nexdirectory') . '</a>';
                }
            }
        }

        if ($frontend_edit_url !== '' && !isset($ordered_actions['edit'])) {
            $ordered_actions['edit'] = '<a href="' . esc_url($frontend_edit_url) . '">' . esc_html($locked_demo_edit ? __('Create Editable Copy', 'nexdirectory') : __('Edit Event', 'nexdirectory')) . '</a>';
        }
        if ($open_event_url !== '' && !isset($ordered_actions['open_event'])) {
            $ordered_actions['open_event'] = '<a href="' . esc_url($open_event_url) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('Open Event', 'nexdirectory') . '</a>';
        }
        if ($can_edit_post && !isset($ordered_actions['view_wp_page'])) {
            $ordered_actions['view_wp_page'] = '<a href="' . esc_url($wp_editor_url) . '">' . esc_html__('Edit WP Page', 'nexdirectory') . '</a>';
        }
        if (($can_edit_post || $can_duplicate_locked) && !isset($ordered_actions['duplicate_event'])) {
            $ordered_actions['duplicate_event'] = '<a href="' . esc_url($duplicate_event_url) . '">' . esc_html__('Duplicate Event', 'nexdirectory') . '</a>';
        }
        if ($can_edit_post && current_user_can('manage_options') && !isset($ordered_actions['change_owner'])) {
            $ordered_actions['change_owner'] = '<a href="' . esc_url($transfer_owner_url) . '">' . esc_html__('Change Owner', 'nexdirectory') . '</a>';
        }

        if (isset($ordered_actions['inline hide-if-no-js'])) unset($ordered_actions['inline hide-if-no-js']);
        if (isset($ordered_actions['inline'])) unset($ordered_actions['inline']);

        return $ordered_actions;
    }

    /**
     * Handles row-action duplication for an event and redirects to the editor.
     */
    public function handle_admin_duplicate_event() {
        if (!is_admin() || !is_user_logged_in()) {
            wp_die(esc_html__('You are not allowed to duplicate this event.', 'nexdirectory'));
        }

        $source_post_id = isset($_GET['post']) ? absint((int) wp_unslash($_GET['post'])) : 0;
        if ($source_post_id <= 0) {
            wp_die(esc_html__('Invalid event selected for duplication.', 'nexdirectory'));
        }

        check_admin_referer('nexdirectory_duplicate_event_' . $source_post_id);

        if (get_post_type($source_post_id) !== $this->post_type) {
            wp_die(esc_html__('Invalid event selected for duplication.', 'nexdirectory'));
        }
        $current_user_id = (int) get_current_user_id();
        $can_duplicate = method_exists($this->user_caps, 'user_can_duplicate_event')
            ? (bool) $this->user_caps->user_can_duplicate_event($source_post_id, $current_user_id)
            : current_user_can('edit_post', $source_post_id);
        if (!$can_duplicate) {
            wp_die(esc_html__('You are not allowed to duplicate this event.', 'nexdirectory'));
        }

        $source_post = get_post($source_post_id);
        if (!$source_post instanceof WP_Post) {
            wp_die(esc_html__('Could not load the event to duplicate.', 'nexdirectory'));
        }

        $copy_suffix = __('(Copy)', 'nexdirectory');
        $source_title = sanitize_text_field((string) $source_post->post_title);
        $new_title = trim($source_title . ' ' . $copy_suffix);
        if ($new_title === '') {
            $new_title = __('Untitled Event (Copy)', 'nexdirectory');
        }

        $new_post_id = wp_insert_post([
            'post_type' => $this->post_type,
            'post_status' => 'draft',
            'post_title' => $new_title,
            'post_content' => (string) $source_post->post_content,
            'post_excerpt' => (string) $source_post->post_excerpt,
            'post_author' => $current_user_id,
            'post_parent' => (int) $source_post->post_parent,
            'menu_order' => (int) $source_post->menu_order,
            'comment_status' => (string) $source_post->comment_status,
            'ping_status' => (string) $source_post->ping_status,
        ], true);

        if (is_wp_error($new_post_id) || (int) $new_post_id <= 0) {
            wp_die(esc_html__('Unable to duplicate event right now. Please try again.', 'nexdirectory'));
        }

        $this->copy_event_post_data((int) $source_post_id, (int) $new_post_id, $source_post);

        $redirect_url = '';
        $redirect_url = $this->get_frontend_event_edit_url((int) $new_post_id);
        if ($redirect_url === '') {
            $redirect_url = (string) nexdirectory_add_query_arg([
                'post' => (int) $new_post_id,
                'action' => 'edit',
            ], admin_url('post.php'));
        }

        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Copies post meta and taxonomy assignments from source to duplicated event.
     */
    private function copy_event_post_data($source_post_id, $target_post_id, WP_Post $source_post) {
        $meta_blacklist = ['_edit_lock', '_edit_last', '_wp_old_slug'];
        $private_meta_allowlist = ['_thumbnail_id'];
        $source_meta = get_post_meta((int) $source_post_id);
        if (is_array($source_meta)) {
            foreach ($source_meta as $meta_key => $meta_values) {
                $meta_key = (string) $meta_key;
                if (strpos($meta_key, '_') === 0 && !in_array($meta_key, $private_meta_allowlist, true)) {
                    continue;
                }
                if ($meta_key === '' || in_array($meta_key, $meta_blacklist, true) || $this->should_skip_event_meta_on_duplicate($meta_key)) {
                    continue;
                }
                if (!is_array($meta_values)) {
                    continue;
                }
                foreach ($meta_values as $meta_value) {
                    add_post_meta((int) $target_post_id, $meta_key, maybe_unserialize($meta_value));
                }
            }
        }

        $taxonomies = get_object_taxonomies((string) $source_post->post_type);
        if (is_array($taxonomies)) {
            foreach ($taxonomies as $taxonomy) {
                $term_ids = wp_get_object_terms((int) $source_post_id, (string) $taxonomy, ['fields' => 'ids']);
                if (is_wp_error($term_ids) || !is_array($term_ids)) {
                    continue;
                }
                wp_set_object_terms((int) $target_post_id, array_map('absint', $term_ids), (string) $taxonomy, false);
            }
        }
    }

    /**
     * Prevents sensitive/runtime metadata from being cloned to duplicated events.
     */
    private function should_skip_event_meta_on_duplicate($meta_key) {
        $meta_key = (string) $meta_key;
        if ($meta_key === '') {
            return true;
        }
        $meta_key_lower = strtolower($meta_key);
        if (
            strpos($meta_key_lower, 'token') !== false
            || strpos($meta_key_lower, 'secret') !== false
            || strpos($meta_key_lower, 'password') !== false
            || strpos($meta_key_lower, 'hash') !== false
        ) {
            return true;
        }

        $exact_keys = [
            'nexdirectory_webapp_install_registry',
            'nexdirectory_webapp_chat_messages',
            'nexdirectory_webapp_qa_items',
            'nexdirectory_webapp_polls_feed',
            'nexdirectory_webapp_notifications_feed',
            'nexdirectory_webapp_user_itineraries',
            'nexdirectory_webapp_push_key',
            'nexdirectory_event_team_members',
            'nexdirectory_claimable',
            'nexdirectory_claimed_by',
            'nexdirectory_claim_reviewed_at',
            'nexdirectory_claim_reviewed_by',
            'nexdirectory_admin_pending_notified',
            'nexdirectory_reminder_sent',
            'nexdirectory_duplicate_candidate',
            'nexdirectory_demo_imported',
            'nexdirectory_demo_locked',
            'nexdirectory_demo_imported_at',
            'nexdirectory_demo_import_batch',
            'nexdirectory_demo_item_index',
        ];
        if (in_array($meta_key, $exact_keys, true)) {
            return true;
        }

        $prefixes = [
            'nexdirectory_boost_',
            'nexdirectory_import_',
            'nexdirectory_claim_',
            'nexdirectory_webapp_install_',
        ];
        foreach ($prefixes as $prefix) {
            if (strpos($meta_key, $prefix) === 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Enforces 'list' mode on the admin screen to prevent 'excerpt' layout bugs.
     */
    public function enforce_admin_event_list_mode() {
        $request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_key((string) wp_unslash($_SERVER['REQUEST_METHOD'])) : 'get';
        if (!is_admin() || wp_doing_ajax() || $request_method !== 'get') {
            return;
        }
        
        global $pagenow;
        if ((string) $pagenow !== 'edit.php') {
            return;
        }
        
        $post_type = isset($_GET['post_type']) ? sanitize_key((string) wp_unslash($_GET['post_type'])) : 'post'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen routing.
        if ($post_type !== $this->post_type) {
            return;
        }

        if (function_exists('set_user_setting')) {
            set_user_setting('posts_list_mode', 'list');
        }

        $current_mode = isset($_GET['mode']) ? sanitize_key((string) wp_unslash($_GET['mode'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen routing.
        if ($current_mode === 'list') {
            return;
        }
        
        // Don't interrupt bulk actions
        if (!empty($_GET['action']) && sanitize_key((string) wp_unslash($_GET['action'])) !== '-1') return; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen routing.
        if (!empty($_GET['action2']) && sanitize_key((string) wp_unslash($_GET['action2'])) !== '-1') return; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen routing.

        $list_url = nexdirectory_add_query_arg(['post_type' => $this->post_type, 'mode' => 'list'], admin_url('edit.php'));
        wp_safe_redirect((string) $list_url);
        exit;
    }

    /**
     * Injects CSS to hide row excerpts in wp-admin and style classification pills.
     */
    public function hide_admin_event_list_descriptions() {
        if (!is_admin()) return;
        
        global $pagenow;
        if ((string) $pagenow !== 'edit.php') return;
        
        $post_type = isset($_GET['post_type']) ? sanitize_key((string) wp_unslash($_GET['post_type'])) : 'post'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin list display context.
        if ($post_type !== $this->post_type) return;

        $post_type_class = sanitize_html_class((string) $this->post_type);
        $css = sprintf(
            'body.post-type-%1$s .wp-list-table td.column-title .excerpt{display:none!important;}body.post-type-%1$s .wp-list-table td.column-title{white-space:normal;}body.post-type-%1$s .wp-list-table .column-nexdirectory_official_classification{width:170px;}body.post-type-%1$s .nexdirectory-admin-classification-pill{display:inline-flex;align-items:center;justify-content:center;padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;line-height:1.3;border:1px solid #d0d7de;background:#f6f8fa;color:#24292f;}body.post-type-%1$s .nexdirectory-admin-classification-official{background:#ecfdf3;border-color:#b7ebd0;color:#067647;}body.post-type-%1$s .nexdirectory-admin-classification-unofficial{background:#fff1f3;border-color:#ffd5dc;color:#b42318;}',
            $post_type_class
        );
        $handle = 'nexdirectory-admin-list-no-excerpt';
        if (!wp_style_is($handle, 'registered')) {
            wp_register_style($handle, false, [], defined('NEXDIRECTORY_DB_VERSION') ? NEXDIRECTORY_DB_VERSION : null);
        }
        wp_enqueue_style($handle);
        wp_add_inline_style($handle, wp_strip_all_tags($css));
        wp_print_styles([$handle]);
    }

    /**
     * Adds the Official Classification column to the admin table.
     */
    public function add_admin_official_classification_column($columns) {
        if (!is_array($columns)) return $columns;

        $ui_labels = method_exists($this->frontend_nav, 'get_site_profile_ui_labels') ? $this->frontend_nav->get_site_profile_ui_labels() : [];
        $column_label = sanitize_text_field((string) ($ui_labels['single_classification_label'] ?? __('Classification', 'nexdirectory')));

        $updated = [];
        $inserted = false;
        foreach ($columns as $key => $label) {
            $updated[$key] = $label;
            if ($key === 'title') {
                $updated['nexdirectory_official_classification'] = $column_label;
                $inserted = true;
            }
        }
        if (!$inserted) {
            $updated['nexdirectory_official_classification'] = $column_label;
        }

        return $updated;
    }

    /**
     * Renders the Official Classification column cell.
     */
    public function render_admin_official_classification_column($column_name, $post_id) {
        if ((string) $column_name !== 'nexdirectory_official_classification') return;

        $labels = method_exists($this->frontend_nav, 'get_classification_labels') ? $this->frontend_nav->get_classification_labels() : [];
        $is_official = $this->event_meta->get_official_event_flag((int) $post_id);
        
        $label = $is_official
            ? (string) ($labels['official_short'] ?? __('Official', 'nexdirectory'))
            : (string) ($labels['unofficial_short'] ?? __('Unofficial', 'nexdirectory'));
            
        $class = $is_official ? 'nexdirectory-admin-classification-official' : 'nexdirectory-admin-classification-unofficial';

        echo '<span class="nexdirectory-admin-classification-pill ' . esc_attr($class) . '">' . esc_html($label) . '</span>';
    }

    /**
     * Injects the official classification dropdown into the Quick/Bulk Edit row.
     */
    public function render_bulk_edit_official_field($column_name, $post_type) {
        if (!is_admin() || (string) $post_type !== $this->post_type || (string) $column_name !== 'nexdirectory_official_classification') {
            return;
        }
        if (!current_user_can('edit_posts')) {
            return;
        }

        $ui_labels = method_exists($this->frontend_nav, 'get_site_profile_ui_labels') ? $this->frontend_nav->get_site_profile_ui_labels() : [];
        $is_events_profile = (string) ($ui_labels['is_events_profile'] ?? '1') === '1';
        if (!$is_events_profile) return;

        $labels = method_exists($this->frontend_nav, 'get_classification_labels') ? $this->frontend_nav->get_classification_labels() : [];
        $column_label = esc_html((string) ($ui_labels['single_classification_label'] ?? __('Official Classification', 'nexdirectory')));
        ?>
        <fieldset class="inline-edit-col-left nexdirectory-bulk-official-fieldset">
            <div class="inline-edit-col">
                <label class="alignleft">
                    <span class="title"><?php echo esc_html($column_label); ?></span>
                    <select name="nexdirectory_bulk_official_event">
                        <option value=""><?php esc_html_e('No Change', 'nexdirectory'); ?></option>
                        <option value="1"><?php echo esc_html((string) ($labels['official'] ?? __('Official', 'nexdirectory'))); ?></option>
                        <option value="0"><?php echo esc_html((string) ($labels['unofficial'] ?? __('Unofficial', 'nexdirectory'))); ?></option>
                    </select>
                </label>
            </div>
        </fieldset>
        <?php
    }

    /**
     * Saves the value from the Quick/Bulk edit dropdown.
     */
    public function handle_bulk_edit_official_field_save($post_id, $post, $update) {
        if (!$update || !$post instanceof WP_Post || (string) $post->post_type !== $this->post_type) {
            return;
        }
        if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id) || !is_admin()) {
            return;
        }
        if (!current_user_can('edit_post', $post_id)) {
            return;
        }

        $nonce = isset($_REQUEST['_inline_edit']) ? sanitize_text_field((string) wp_unslash($_REQUEST['_inline_edit'])) : '';
        if ($nonce === '' || !wp_verify_nonce($nonce, 'inlineeditnonce')) {
            return;
        }

        $action = isset($_REQUEST['action']) ? sanitize_key((string) wp_unslash($_REQUEST['action'])) : '';
        $action2 = isset($_REQUEST['action2']) ? sanitize_key((string) wp_unslash($_REQUEST['action2'])) : '';
        $bulk_edit_marker = isset($_REQUEST['bulk_edit']) ? sanitize_key((string) wp_unslash($_REQUEST['bulk_edit'])) : '';
        $bulk_ids = isset($_REQUEST['post']) ? array_map('absint', (array) wp_unslash($_REQUEST['post'])) : [];
        
        $is_bulk_context = !empty($bulk_ids) && ($bulk_edit_marker !== '' || $action === 'edit' || $action2 === 'edit');
        if (!$is_bulk_context || !isset($_REQUEST['nexdirectory_bulk_official_event'])) {
            return;
        }

        $requested_official = sanitize_text_field((string) wp_unslash($_REQUEST['nexdirectory_bulk_official_event']));
        if (!in_array($requested_official, ['0', '1'], true)) {
            return;
        }

        $this->event_meta->apply_official_flag_with_admin_gate((int) $post_id, $requested_official, get_current_user_id());
    }

    /**
     * Redirects users trying to hit /wp-admin/post.php directly if they should be using the frontend builder.
     */
    public function maybe_redirect_admin_event_editor() {
        if (!is_admin() || wp_doing_ajax()) return;
        
        global $pagenow;
        if ((string) $pagenow !== 'post.php') return;
        
        $action = isset($_GET['action']) ? sanitize_key((string) wp_unslash($_GET['action'])) : 'edit'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin editor routing.
        if ($action !== 'edit') return;
        
        $post_id = isset($_GET['post']) ? absint((int) wp_unslash($_GET['post'])) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin editor routing.
        if ($post_id <= 0 || get_post_type($post_id) !== $this->post_type) return;
        if (!current_user_can('edit_post', $post_id)) return;

        $allow_wp_editor = isset($_GET['nexdirectory_wp_editor']) ? sanitize_key((string) wp_unslash($_GET['nexdirectory_wp_editor'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin editor routing.
        $locked_demo_edit = method_exists($this->user_caps, 'is_demo_event_edit_locked')
            ? (bool) $this->user_caps->is_demo_event_edit_locked($post_id, (int) get_current_user_id())
            : false;
        if ($locked_demo_edit) {
            $duplicate_url = $this->get_admin_duplicate_event_url($post_id);
            if ($duplicate_url !== '') {
                $this->frontend_nav->safe_redirect_or_fallback($duplicate_url);
            }
            return;
        }

        if ($allow_wp_editor === '1') return;

        $frontend_url = $this->get_frontend_event_edit_url($post_id);

        if ($frontend_url !== '') {
            $this->frontend_nav->safe_redirect_or_fallback($frontend_url);
        }
    }
}
