<?php
/**
 * Name: Custom Post Order
 * Description: Drag-and-drop custom ordering for posts, pages, and custom post types limited to 100 items for performance to manually control content display order
 * Category: Content
 * Icon: -
 * UseCases: [
 *   {
 *     "title": "Portfolio Display Order",
 *     "description": "Drag-and-drop reorder portfolio projects to show best work first instead of sorting by date."
 *   },
 *   {
 *     "title": "Product Showcase",
 *     "description": "Manually arrange featured products on shop page by dragging to highlight bestsellers or high-margin items."
 *   },
 *   {
 *     "title": "Service Prioritization",
 *     "description": "Reorder service pages to display primary offerings before secondary services regardless of creation date."
 *   }
 * ]
 * Added: 2025-08-24
 * Tags: order, sort, drag-drop, posts, pages, custom-post-types
 * WhereToFind: {
 *   "location": "Posts/Pages List",
 *   "url": "edit.php",
 *   "instructions": "Drag and drop to reorder posts - order reflects on frontend",
 *   "newTab": false
 * }
 */

// Prevent direct access
if (!defined('ABSPATH')) exit;

class SwitchboardCustomPostOrder {
    
    public function __construct() {
        add_action('wp_ajax_update_post_order', [$this, 'update_post_order']);
        add_action('wp_ajax_get_post_order_html', [$this, 'get_post_order_html']);
        add_action('wp_ajax_get_posts_for_ordering', [$this, 'ajax_get_posts_for_ordering']);
        add_action('wp_ajax_switchboard_save_post_order', [$this, 'ajax_save_post_order']);
        add_filter('pre_get_posts', [$this, 'apply_custom_order']);

        // Add Order submenu under custom post types for Editors
        add_action('admin_menu', [$this, 'add_post_type_order_submenus'], 99);

        // Data registry registration is handled at the bottom of this file via auto_register()
    }

    /**
     * Add Order submenu page under each enabled custom post type
     * This allows Editors to reorder posts without Switchboard admin access
     */
    public function add_post_type_order_submenus() {
        $settings = get_option('switchboard_custom-post-order_settings', []);

        // Get enabled post types
        $post_types_setting = isset($settings['post_types']) ? $settings['post_types'] : '';
        if (empty($post_types_setting)) {
            return;
        }

        if (is_string($post_types_setting)) {
            $enabled_post_types = array_map('trim', explode(',', $post_types_setting));
        } elseif (is_array($post_types_setting)) {
            $enabled_post_types = $post_types_setting;
        } else {
            return;
        }

        $enabled_post_types = array_filter($enabled_post_types);
        if (empty($enabled_post_types)) {
            return;
        }

        foreach ($enabled_post_types as $post_type) {
            $pt_obj = get_post_type_object($post_type);
            if (!$pt_obj) {
                continue;
            }

            // Determine parent menu slug
            if ($post_type === 'post') {
                $parent_slug = 'edit.php';
            } elseif ($post_type === 'page') {
                $parent_slug = 'edit.php?post_type=page';
            } else {
                $parent_slug = 'edit.php?post_type=' . $post_type;
            }

            // Use edit_posts capability for posts, edit_pages for pages, or the post type's edit cap
            $capability = isset($pt_obj->cap->edit_posts) ? $pt_obj->cap->edit_posts : 'edit_posts';

            add_submenu_page(
                $parent_slug,
                sprintf(__('%s Order', 'wpswitchboard'), $pt_obj->labels->name),
                __('Order', 'wpswitchboard'),
                $capability,
                'switchboard-' . $post_type . '-order',
                function() use ($post_type, $pt_obj) {
                    $this->render_post_type_order_page($post_type, $pt_obj);
                }
            );
        }
    }

    /**
     * Check if a post type has been explicitly ordered by user via our interface
     */
    private function has_explicit_order($post_type) {
        // Check in module settings (more reliable)
        $settings = get_option('switchboard_custom-post-order_settings', []);

        $ordered_types = isset($settings['ordered_post_types']) ? $settings['ordered_post_types'] : [];

        if (is_array($ordered_types) && in_array($post_type, $ordered_types)) {
            return true;
        }

        // Fallback to separate option
        $ordered_post_types = get_option('switchboard_ordered_post_types', []);

        if (is_array($ordered_post_types) && in_array($post_type, $ordered_post_types)) {
            return true;
        }

        return false;
    }

    /**
     * Mark a post type as explicitly ordered
     */
    private function mark_as_ordered($post_type) {
        if (empty($post_type)) {
            return;
        }

        // Store in module settings for reliability
        $settings = get_option('switchboard_custom-post-order_settings', []);

        if (!is_array($settings)) {
            $settings = [];
        }
        $ordered_types = isset($settings['ordered_post_types']) ? $settings['ordered_post_types'] : [];
        if (!is_array($ordered_types)) {
            $ordered_types = [];
        }

        if (!in_array($post_type, $ordered_types)) {
            $ordered_types[] = $post_type;
            $settings['ordered_post_types'] = $ordered_types;
            update_option('switchboard_custom-post-order_settings', $settings);
        }
    }

    /**
     * Render the Order page for a specific post type
     */
    public function render_post_type_order_page($post_type, $pt_obj) {
        // Enqueue jQuery UI Sortable
        wp_enqueue_script('jquery-ui-sortable');

        // Check if user has explicitly ordered this post type via our interface
        $has_custom_order = $this->has_explicit_order($post_type);

        // Get posts - use menu_order only if explicitly ordered, otherwise use WordPress default (date DESC)
        if ($has_custom_order) {
            $posts = get_posts([
                'post_type' => $post_type,
                'posts_per_page' => 100,
                'orderby' => 'menu_order',
                'order' => 'ASC',
                'post_status' => ['publish', 'draft', 'pending', 'private']
            ]);
        } else {
            $posts = get_posts([
                'post_type' => $post_type,
                'posts_per_page' => 100,
                'orderby' => 'date',
                'order' => 'DESC',
                'post_status' => ['publish', 'draft', 'pending', 'private']
            ]);
        }

        ?>
        <div class="wrap">
            <h1><?php echo esc_html(sprintf(__('%s Order', 'wpswitchboard'), $pt_obj->labels->name)); ?></h1>
            <p><?php esc_html_e('Drag and drop to reorder. Changes save automatically.', 'wpswitchboard'); ?></p>

            <?php if (count($posts) >= 100): ?>
            <div class="notice notice-warning">
                <p><?php esc_html_e('Showing first 100 items only for performance.', 'wpswitchboard'); ?></p>
            </div>
            <?php endif; ?>

            <div id="post-order-list" style="max-width: 800px; margin-top: 20px;">
                <?php if (empty($posts)): ?>
                    <p style="color: #666;"><?php esc_html_e('No posts found.', 'wpswitchboard'); ?></p>
                <?php else: ?>
                    <?php foreach ($posts as $index => $post):
                        $status = get_post_status_object($post->post_status);
                        $status_label = $status ? $status->label : $post->post_status;
                    ?>
                    <div class="sortable-post-item" data-id="<?php echo esc_attr($post->ID); ?>" style="display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: #fff; border: 1px solid #ddd; margin-bottom: 4px; cursor: move; transition: all 0.15s ease;">
                        <span style="color: #9ca3af; cursor: grab; user-select: none; font-size: 16px;">&#9776;</span>
                        <span style="flex: 1; font-weight: 500;"><?php echo esc_html($post->post_title ?: '(no title)'); ?></span>
                        <?php if ($post->post_status !== 'publish'): ?>
                        <span style="font-size: 12px; color: #666; background: #f0f0f0; padding: 2px 8px; border-radius: 3px;"><?php echo esc_html($status_label); ?></span>
                        <?php endif; ?>
                    </div>
                    <?php endforeach; ?>
                <?php endif; ?>
            </div>

            <div id="save-indicator" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #2271b1; color: white; padding: 12px 24px; border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 999999; font-weight: 500;">
                <?php esc_html_e('Order saved', 'wpswitchboard'); ?>
            </div>
        </div>

        <script>
        jQuery(document).ready(function($) {
            var postType = '<?php echo esc_js($post_type); ?>';

            $("#post-order-list").sortable({
                items: ".sortable-post-item",
                placeholder: "sortable-placeholder",
                tolerance: "pointer",
                cursor: "grabbing",
                opacity: 0.8,
                start: function(e, ui) {
                    ui.placeholder.height(ui.item.height());
                    ui.placeholder.css({
                        "background": "#f0f7ff",
                        "border": "2px dashed #2271b1",
                        "margin-bottom": "4px"
                    });
                    ui.item.css("box-shadow", "0 4px 12px rgba(0,0,0,0.15)");
                },
                stop: function(e, ui) {
                    ui.item.css("box-shadow", "");
                    saveOrder();
                }
            });

            function saveOrder() {
                var order = [];
                $("#post-order-list .sortable-post-item").each(function() {
                    order.push($(this).data("id"));
                });

                $.ajax({
                    url: ajaxurl,
                    type: "POST",
                    data: {
                        action: "switchboard_save_post_order",
                        post_type: postType,
                        order: order,
                        nonce: "<?php echo wp_create_nonce('post_ordering'); ?>"
                    },
                    success: function(response) {
                        if (response.success) {
                            $("#save-indicator").fadeIn(200);
                            setTimeout(function() {
                                $("#save-indicator").fadeOut(200);
                            }, 1500);
                        }
                    }
                });
            }
        });
        </script>

        <style>
        .sortable-post-item:hover {
            background: #f9f9f9 !important;
        }
        .sortable-placeholder {
            visibility: visible !important;
        }
        </style>
        <?php
    }
    
    public function register_data_locations() {
        return [
            'options' => [
                'switchboard_custom-post-order_settings'
            ],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [
                '_switchboard_menu_order'  // Custom field used for ordering
            ],
            'user_meta' => [],
            'transients' => []
        ];
    }
    
    public function ajax_get_posts_for_ordering() {
        check_ajax_referer('post_ordering', 'nonce');

        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => esc_html__('Permission denied', 'wpswitchboard')]);
        }

        $post_type = isset($_POST['post_type']) ? sanitize_key($_POST['post_type']) : 'post';

        // Check if user has explicitly ordered this post type via our interface
        $has_custom_order = $this->has_explicit_order($post_type);

        // Use menu_order only if explicitly ordered, otherwise use WordPress default (date DESC)
        if ($has_custom_order) {
            $args = [
                'post_type' => $post_type,
                'posts_per_page' => 100,
                'orderby' => 'menu_order',
                'order' => 'ASC',
                'post_status' => 'publish'
            ];
        } else {
            $args = [
                'post_type' => $post_type,
                'posts_per_page' => 100,
                'orderby' => 'date',
                'order' => 'DESC',
                'post_status' => 'publish'
            ];
        }

        $posts = get_posts($args);
        $posts_data = [];
        $is_hierarchical = is_post_type_hierarchical($post_type);

        foreach ($posts as $post) {
            $posts_data[] = [
                'ID' => $post->ID,
                'post_title' => $post->post_title,
                'post_date' => date('M j, Y', strtotime($post->post_date)),
                'post_parent' => $post->post_parent
            ];
        }

        wp_send_json_success(['posts' => $posts_data, 'is_hierarchical' => $is_hierarchical]);
    }
    
    public function ajax_save_post_order() {
        check_ajax_referer('post_ordering', 'nonce');

        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => esc_html__('Permission denied', 'wpswitchboard')]);
        }

        $post_type = isset($_POST['post_type']) ? sanitize_key($_POST['post_type']) : '';
        $order = isset($_POST['order']) ? array_map('intval', $_POST['order']) : [];

        if (empty($order)) {
            wp_send_json_error(['message' => esc_html__('No order data', 'wpswitchboard')]);
        }

        foreach ($order as $index => $post_id) {
            wp_update_post([
                'ID' => $post_id,
                'menu_order' => $index
            ]);
        }

        // Mark that this post type has been explicitly ordered by user
        $this->mark_as_ordered($post_type);

        wp_send_json_success(['message' => esc_html__('Order saved', 'wpswitchboard')]);
    }
    
    public function render_settings($settings = []) {
        // Handle both comma-separated string and array formats
        $post_types_setting = isset($settings['post_types']) ? $settings['post_types'] : 'post';
        if (is_string($post_types_setting) && !empty($post_types_setting)) {
            $selected_post_types = array_map('trim', explode(',', $post_types_setting));
        } elseif (is_array($post_types_setting)) {
            $selected_post_types = $post_types_setting;
        } else {
            $selected_post_types = ['post'];
        }
        
        // Exclude media and system post types
        $all_post_types = get_post_types(['public' => true], 'objects');
        $exclude_types = ['attachment', 'wp_block', 'wp_template', 'wp_template_part', 'wp_navigation'];
        $all_post_types = array_diff_key($all_post_types, array_flip($exclude_types));
        ?>
        <input type="hidden" name="module" value="custom-post-order">
        <input type="hidden" name="setting_post_types" id="setting_post_types" value="<?php echo esc_attr(implode(',', $selected_post_types)); ?>">
        <input type="hidden" name="setting_post_order" id="setting_post_order" value="">

        <div class="sb-sp-group">
            <label class="sb-sp-label"><?php esc_html_e('Select Post Types', 'wpswitchboard'); ?></label>
            <div class="switchboard-tag-selector" data-input-id="setting_post_types">
                <div class="switchboard-selected-tags" id="selected-post-types">
                    <?php foreach ($selected_post_types as $pt_slug):
                        if (isset($all_post_types[$pt_slug])): ?>
                            <span class="switchboard-tag" data-value="<?php echo esc_attr($pt_slug); ?>">
                                <?php echo esc_html($all_post_types[$pt_slug]->label); ?>
                                <span class="remove-tag">×</span>
                            </span>
                        <?php endif;
                    endforeach; ?>
                </div>
                <div class="switchboard-available-tags">
                    <?php foreach ($all_post_types as $pt_slug => $pt_obj):
                        $is_selected = in_array($pt_slug, $selected_post_types) ? 'selected' : ''; ?>
                        <span class="switchboard-tag-option <?php echo $is_selected; ?>" data-value="<?php echo esc_attr($pt_slug); ?>">
                            <?php echo esc_html($pt_obj->label); ?>
                        </span>
                    <?php endforeach; ?>
                </div>
            </div>
            <p class="sb-sp-description"><?php esc_html_e('Select which post types should have custom ordering enabled. Then choose a post type below to reorder its posts.', 'wpswitchboard'); ?></p>
        </div>

        <div class="sb-sp-group">
            <label class="sb-sp-label"><?php esc_html_e('Reorder Posts', 'wpswitchboard'); ?></label>
            <p class="sb-sp-text-sm sb-sp-m-0"><?php esc_html_e('Click a post type to reorder its published posts (up to 100 shown)', 'wpswitchboard'); ?></p>
        </div>

        <div class="sb-sp-flex sb-sp-gap-2 sb-sp-flex-wrap sb-sp-mb-4">
            <?php foreach ($selected_post_types as $pt_slug):
                if (isset($all_post_types[$pt_slug])): ?>
                    <button type="button" class="post-type-badge sb-sp-badge" data-post-type="<?php echo esc_attr($pt_slug); ?>">
                        <?php echo esc_html($all_post_types[$pt_slug]->label); ?>
                    </button>
                <?php endif;
            endforeach; ?>
        </div>

        <div id="post-order-container" class="sb-sp-hidden" style="margin-bottom: 24px;">
            <div class="sb-sp-group">
                <p class="sb-sp-m-0">
                    <strong class="sb-sp-text-semibold"><?php esc_html_e('Drag to reorder:', 'wpswitchboard'); ?></strong> <?php esc_html_e('Click and drag items to your desired order. Changes save automatically.', 'wpswitchboard'); ?>
                </p>
            </div>
            <div id="post-order-list" class="sb-sp-flex" style="flex-direction: column; gap: 8px; margin-top: 16px;">
                <div class="sb-sp-text-center sb-sp-text-gray">
                    <?php esc_html_e('Select a post type above', 'wpswitchboard'); ?>
                </div>
            </div>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            var postOrderSortable;
            var currentPostType = null;
            var allPostTypes = <?php echo json_encode(array_map(function($pt) { return ['slug' => $pt->name, 'label' => $pt->label]; }, array_values($all_post_types))); ?>;
            
            // Update badge buttons when tags change
            function updateBadgeButtons() {
                var selectedTypes = [];
                $('.switchboard-selected-tags .switchboard-tag').each(function() {
                    selectedTypes.push($(this).data('value'));
                });
                
                var badgeContainer = $('.sb-sp-flex.sb-sp-gap-2.sb-sp-flex-wrap.sb-sp-mb-4');
                badgeContainer.empty();
                
                selectedTypes.forEach(function(slug) {
                    var pt = allPostTypes.find(function(p) { return p.slug === slug; });
                    if (pt) {
                        var badge = $('<button type="button" class="post-type-badge sb-sp-badge" data-post-type="' + slug + '">' + pt.label + '</button>');
                        badgeContainer.append(badge);
                    }
                });
                
                // Re-attach click handler to new badges
                $(".post-type-badge").off("click").on("click", handleBadgeClick);
                
                // Hide container if no badges
                if (selectedTypes.length === 0) {
                    $("#post-order-container").addClass("sb-sp-hidden");
                }
            }
            
            // Handle badge click
            function handleBadgeClick() {
                var $badge = $(this);
                var postType = $badge.data("post-type");
                
                // Don't reload if already active
                if (currentPostType === postType) {
                    return;
                }
                
                currentPostType = postType;
                
                // Update badge styles
                $(".post-type-badge").removeClass("sb-sp-badge-active");
                $badge.addClass("sb-sp-badge-active");
                
                loadPostsForPostType(postType);
            }
            
            // Load posts for a post type
            function loadPostsForPostType(postType) {
                $("#post-order-container").removeClass("sb-sp-hidden");
                $("#post-order-list").html('<div class="sb-sp-text-center">Loading posts...</div>');

                // Destroy existing sortable if it exists
                if (postOrderSortable) {
                    try { $("#post-order-list").sortable("destroy"); } catch(e) {}
                    try { $("#post-order-list .post-children-group").sortable("destroy"); } catch(e) {}
                    postOrderSortable = null;
                }

                $.ajax({
                    url: ajaxurl,
                    type: "POST",
                    data: {
                        action: "get_posts_for_ordering",
                        post_type: postType,
                        nonce: "<?php echo wp_create_nonce('post_ordering'); ?>"
                    },
                    success: function(response) {
                        if (response.success && response.data.posts) {
                            var posts = response.data.posts;
                            var isHierarchical = response.data.is_hierarchical;
                            var html = "";

                            if (isHierarchical) {
                                html = buildHierarchicalPostsHtml(posts);
                            } else {
                                $.each(posts, function(i, post) {
                                    html += buildPostItemHtml(post, i);
                                });
                            }

                            $("#post-order-list").html(html);
                            updatePostNumbers();

                            if (isHierarchical) {
                                initHierarchicalPostSortable(postType);
                            } else {
                                initFlatPostSortable(postType);
                            }
                        } else {
                            $("#post-order-list").html('<div class="sb-sp-text-center">No posts found for this post type.</div>');
                        }
                    },
                    error: function() {
                        $("#post-order-list").html('<div class="sb-sp-text-center" style="padding: 12px 16px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 6px; color: #dc2626; font-size: 14px;">Error loading posts. Please try again.</div>');
                    }
                });
            }
            
            // Initial badge click handler
            $(".post-type-badge").on("click", handleBadgeClick);

            // Auto-click first post type badge on load
            if ($(".post-type-badge").length > 0) {
                $(".post-type-badge").first().click();
            }
            
            // Update badges when tag selector changes
            $(document).on('change', '#setting_post_types', function() {
                updateBadgeButtons();
            });
            
            // Also update when tags are added/removed (using a small delay to ensure DOM is updated)
            $(document).on('click', '.switchboard-tag-option, .remove-tag', function() {
                setTimeout(function() {
                    updateBadgeButtons();
                }, 100);
            });
            
            function buildPostItemHtml(post, index, hasChildren) {
                var html = '<div class="sortable-post-item sb-sp-card sb-sp-flex sb-sp-items-center sb-sp-gap-3 sb-sp-p-3" data-id="' + post.ID + '" style="cursor: move; transition: all 0.15s ease;">';
                html += '<span style="color: #9ca3af; cursor: grab; user-select: none; font-size: 18px; line-height: 1;">⋮⋮</span>';
                html += '<span class="sb-sp-badge-number" style="display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: var(--primary-100); color: var(--primary-700); font-size: 12px; font-weight: 600; flex-shrink: 0;">' + (index + 1) + '</span>';
                html += '<span class="sb-sp-flex-1">' + $('<span>').text(post.post_title).html() + '</span>';
                if (hasChildren) {
                    html += '<span style="font-size: 11px; color: #666; background: #f0f0f0; padding: 2px 8px; border-radius: 3px;">parent</span>';
                }
                html += '<span class="sb-sp-text-xs sb-sp-text-gray">' + $('<span>').text(post.post_date).html() + '</span>';
                html += '</div>';
                return html;
            }

            function buildHierarchicalPostsHtml(posts) {
                var byParent = {};
                $.each(posts, function(i, post) {
                    var pid = post.post_parent || 0;
                    if (!byParent[pid]) byParent[pid] = [];
                    byParent[pid].push(post);
                });

                function renderLevel(parentId) {
                    var children = byParent[parentId] || [];
                    var html = "";
                    var counter = {n: 0};
                    $.each(children, function(i, post) {
                        var hasChildren = !!byParent[post.ID];
                        if (hasChildren) {
                            html += '<div class="post-parent-wrapper">';
                            html += buildPostItemHtml(post, counter.n++, true);
                            html += '<div class="post-children-group" data-parent="' + post.ID + '" style="margin-left: 24px; border-left: 2px solid #e5e7eb; padding-left: 12px; margin-top: 4px; margin-bottom: 8px;">';
                            html += renderLevel(post.ID);
                            html += '</div></div>';
                        } else {
                            html += buildPostItemHtml(post, counter.n++, false);
                        }
                    });
                    return html;
                }

                // Start with top-level posts (parent=0), but also include
                // orphans whose parent wasn't fetched in the 100-post limit
                var topLevel = byParent[0] || [];
                var fetchedIds = {};
                $.each(posts, function(i, p) { fetchedIds[p.ID] = true; });

                $.each(posts, function(i, post) {
                    if (post.post_parent && !fetchedIds[post.post_parent]) {
                        // Orphan — parent not in results, show at top level
                        if (!byParent[0]) byParent[0] = [];
                        byParent[0].push(post);
                        // Remove from the original parent bucket
                        var idx = (byParent[post.post_parent] || []).indexOf(post);
                        if (idx > -1) byParent[post.post_parent].splice(idx, 1);
                    }
                });

                return renderLevel(0);
            }

            function initFlatPostSortable(postType) {
                postOrderSortable = $("#post-order-list").sortable({
                    items: "> .sortable-post-item",
                    placeholder: "sortable-placeholder",
                    tolerance: "pointer",
                    cursor: "grabbing",
                    opacity: 0.8,
                    start: function(e, ui) {
                        ui.placeholder.height(ui.item.height());
                        ui.placeholder.css({
                            "background": "var(--primary-100)",
                            "border": "2px dashed var(--primary-500)",
                            "border-radius": "4px",
                            "margin-bottom": "8px"
                        });
                        ui.item.css("box-shadow", "0 4px 12px rgba(0,0,0,0.15)");
                    },
                    stop: function(e, ui) {
                        ui.item.css("box-shadow", "");
                        updatePostNumbers();
                        savePostOrder(postType);
                    }
                });
            }

            function initHierarchicalPostSortable(postType) {
                var sortableOpts = {
                    items: "> .sortable-post-item, > .post-parent-wrapper",
                    placeholder: "sortable-placeholder",
                    tolerance: "pointer",
                    cursor: "grabbing",
                    opacity: 0.8,
                    connectWith: false,
                    start: function(e, ui) {
                        ui.placeholder.height(ui.item.height());
                        ui.placeholder.css({
                            "background": "var(--primary-100)",
                            "border": "2px dashed var(--primary-500)",
                            "border-radius": "4px",
                            "margin-bottom": "8px"
                        });
                        ui.item.css("box-shadow", "0 4px 12px rgba(0,0,0,0.15)");
                    },
                    stop: function(e, ui) {
                        ui.item.css("box-shadow", "");
                        updatePostNumbers();
                        savePostOrder(postType);
                    }
                };

                // Top-level sortable
                postOrderSortable = $("#post-order-list").sortable(sortableOpts);

                // Each children group is independently sortable
                $("#post-order-list .post-children-group").each(function() {
                    $(this).sortable({
                        items: "> .sortable-post-item",
                        placeholder: "sortable-placeholder",
                        tolerance: "pointer",
                        cursor: "grabbing",
                        opacity: 0.8,
                        connectWith: false,
                        start: function(e, ui) {
                            ui.placeholder.height(ui.item.height());
                            ui.placeholder.css({
                                "background": "var(--primary-100)",
                                "border": "2px dashed var(--primary-500)",
                                "border-radius": "4px",
                                "margin-bottom": "8px"
                            });
                            ui.item.css("box-shadow", "0 4px 12px rgba(0,0,0,0.15)");
                        },
                        stop: function(e, ui) {
                            ui.item.css("box-shadow", "");
                            updatePostNumbers();
                            savePostOrder(postType);
                        }
                    });
                });
            }

            function updatePostNumbers() {
                var n = 1;
                $("#post-order-list .sortable-post-item").each(function() {
                    $(this).find(".sb-sp-badge-number").text(n++);
                });
            }
            
            function savePostOrder(postType) {
                var order = [];
                $("#post-order-list .sortable-post-item").each(function(i) {
                    order.push($(this).data("id"));
                });

                $("#setting_post_order").val(JSON.stringify({
                    post_type: postType,
                    order: order
                }));

                // Auto-save via AJAX
                $.ajax({
                    url: ajaxurl,
                    type: "POST",
                    data: {
                        action: "switchboard_save_post_order",
                        post_type: postType,
                        order: order,
                        nonce: "<?php echo wp_create_nonce('post_ordering'); ?>"
                    },
                    success: function(response) {
                        if (response.success) {
                            // Show brief success indicator
                            var indicator = $('<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--primary-500); color: white; padding: 12px 24px; border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 999999; font-weight: 500;">Order saved</div>');
                            $('body').append(indicator);
                            setTimeout(function() {
                                indicator.fadeOut(function() { $(this).remove(); });
                            }, 1500);
                        }
                    }
                });
            }
        });
        </script>

        <div class="sb-module-option-item sb-module-toggle-item">
            <div class="sb-module-option-content">
                <div class="sb-module-toggle-header">
                    <strong class="sb-module-option-title"><?php esc_html_e('Apply on Frontend', 'wpswitchboard'); ?></strong>
                    <label class="sb-module-toggle">
                        <input type="checkbox"
                               name="setting_apply_frontend"
                               value="yes"
                               <?php checked(isset($settings['apply_frontend']) && $settings['apply_frontend'] === 'yes', true); ?>>
                        <span class="sb-module-toggle-slider"></span>
                    </label>
                </div>
                <p class="sb-module-option-text"><?php esc_html_e('Apply custom order to frontend queries (blog page, archives, etc.)', 'wpswitchboard'); ?></p>
            </div>
        </div>
        <?php
    }
    
    public function get_post_order_html() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => esc_html__('Permission denied', 'wpswitchboard')]);
        }

        $post_type = isset($_POST['post_type']) ? sanitize_key($_POST['post_type']) : 'post';

        // Check if user has explicitly ordered this post type via our interface
        $has_custom_order = $this->has_explicit_order($post_type);

        // Use menu_order only if explicitly ordered, otherwise use WordPress default (date DESC)
        if ($has_custom_order) {
            $args = [
                'post_type' => $post_type,
                'posts_per_page' => 100, // Performance limit
                'orderby' => 'menu_order',
                'order' => 'ASC',
                'post_status' => 'publish'
            ];
        } else {
            $args = [
                'post_type' => $post_type,
                'posts_per_page' => 100, // Performance limit
                'orderby' => 'date',
                'order' => 'DESC',
                'post_status' => 'publish'
            ];
        }

        $posts = get_posts($args);
        
        ob_start();
        if (empty($posts)) {
            echo '<p style="color:#666;">No items found for this post type.</p>';
        } else {
            echo '<ul class="sortable-post-list" data-post-type="' . esc_attr($post_type) . '" style="list-style:none; padding:0; margin:10px 0;">';
            foreach ($posts as $post) {
                $status_label = get_post_status_object($post->post_status)->label ?? $post->post_status;
                echo '<li class="sortable-post-item sb-sp-bg-white" data-id="' . esc_attr($post->ID) . '">';
                echo '<span style="color:#8c8f94;">☰</span>';
                echo '<span class="sb-sp-label">' . esc_html($post->post_title ?: '(no title)') . '</span>';
                                echo '<span class="sb-sp-text-xs">' . esc_html($status_label) . '</span>';
                echo '</li>';
            }
            echo '</ul>';
            
            if (count($posts) >= 100) {
                echo '<p style="color: #dc2626;">Showing first 100 items only for performance. Consider using categories or filters to organize large content sets.</p>';
            }
        }
        
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html]);
    }
    
    public function update_post_order() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => esc_html__('Permission denied', 'wpswitchboard')]);
        }

        $order = isset($_POST['order']) ? array_map('intval', wp_unslash($_POST['order'])) : [];
        $post_type = '';

        foreach ($order as $index => $post_id) {
            wp_update_post([
                'ID' => $post_id,
                'menu_order' => $index
            ]);
            // Get post type from first post
            if (empty($post_type) && $post_id > 0) {
                $post_type = get_post_type($post_id);
            }
        }

        // Mark that this post type has been explicitly ordered by user
        $this->mark_as_ordered($post_type);

        wp_send_json_success();
    }

    public function apply_custom_order($query) {
        $settings = get_option('switchboard_custom-post-order_settings', []);

        // Handle both comma-separated string and array formats
        $post_types_setting = isset($settings['post_types']) ? $settings['post_types'] : 'post';
        if (is_string($post_types_setting) && !empty($post_types_setting)) {
            $post_types = array_map('trim', explode(',', $post_types_setting));
        } elseif (is_array($post_types_setting)) {
            $post_types = $post_types_setting;
        } else {
            $post_types = ['post'];
        }

        $current_post_type = $query->get('post_type');

        // Admin posts list table — always apply custom order if this post type has been ordered
        if (is_admin() && $query->is_main_query() && !empty($current_post_type) && in_array($current_post_type, $post_types) && $this->has_explicit_order($current_post_type)) {
            // Only override when user hasn't explicitly clicked a column sort header
            if (empty($_GET['orderby'])) {
                $query->set('orderby', 'menu_order');
                $query->set('order', 'ASC');
            }
            return $query;
        }

        // Frontend — only apply if the setting is enabled
        if (!isset($settings['apply_frontend']) || $settings['apply_frontend'] !== 'yes') {
            return $query;
        }

        // Fix: On main blog page, post_type is empty, so check is_home() or if post_type is 'post'
        if (empty($current_post_type) && (is_home() || is_front_page() || is_archive())) {
            $current_post_type = 'post';
        }

        // Apply custom order only to the main query on frontend
        if (!is_admin() && $query->is_main_query() && in_array($current_post_type, $post_types) && $this->has_explicit_order($current_post_type)) {
            $query->set('orderby', 'menu_order');
            $query->set('order', 'ASC');
        }

        return $query;
    }
}

// Initialize and register with data system
$switchboard_instance = new SwitchboardCustomPostOrder();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);
