<?php
/**
 * Post Types Order Module
 *
 * Reorder any post type or taxonomy with drag and drop.
 *
 * @package BlaminhorEssentials
 */

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

/**
 * Post Types Order module class
 */
class Blaminhor_Essentials_Module_Post_Types_Order extends Blaminhor_Essentials_Module {

	/**
	 * Module ID
	 *
	 * @var string
	 */
	protected $id = 'post-types-order';

	/**
	 * Module name
	 *
	 * @var string
	 */
	protected $name = 'Post Types Order';

	/**
	 * Initialize module
	 */
	protected function init() {
		$this->name        = __( 'Post Types Order', 'blaminhor-essentials' );
		$this->description = __( 'Reorder any post type or taxonomy with drag and drop.', 'blaminhor-essentials' );
	}

	/**
	 * Get default settings
	 *
	 * @return array
	 */
	protected function get_default_settings() {
		$all_post_types     = blaminhor_essentials_get_post_types();
		$default_post_types = ! empty( $all_post_types ) ? array_keys( $all_post_types ) : array( 'post', 'page' );

		$all_taxonomies     = blaminhor_essentials_get_taxonomies();
		$default_taxonomies = ! empty( $all_taxonomies ) ? array_keys( $all_taxonomies ) : array( 'category', 'post_tag' );

		return array(
			'auto_sort'  => true,
			'post_types' => $default_post_types,
			'taxonomies' => $default_taxonomies,
			'capability' => 'manage_options',
		);
	}

	/**
	 * Register hooks
	 */
	protected function register_hooks() {
		add_action( 'admin_init', array( $this, 'handle_settings_submission' ) );

		// AJAX handlers.
		add_action( 'wp_ajax_ap_pto_get_items', array( $this, 'ajax_get_items' ) );
		add_action( 'wp_ajax_ap_pto_save_order', array( $this, 'ajax_save_order' ) );
		add_action( 'wp_ajax_ap_pto_reset_order', array( $this, 'ajax_reset_order' ) );

		// Enqueue sortable assets on admin list screens (edit.php / edit-tags.php).
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_list_sortable' ) );

		// Auto-sort on frontend and admin list screens.
		if ( $this->get_setting( 'auto_sort', true ) ) {
			add_filter( 'posts_clauses', array( $this, 'auto_sort_posts_clauses' ), 99, 2 );
			add_filter( 'terms_clauses', array( $this, 'auto_sort_terms_clauses' ), 10, 3 );
		}
	}

	/**
	 * Enqueue module-specific assets
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_assets( $hook ) {
		// Module settings page only.
		if ( 'blaminhor-essentials_page_blaminhor-essentials-post-types-order' !== $hook ) {
			return;
		}

		wp_enqueue_script( 'jquery-ui-sortable' );
	}

	/**
	 * Enqueue sortable assets on admin list screens (edit.php / edit-tags.php)
	 *
	 * Registered directly via admin_enqueue_scripts to bypass the plugin page filter.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_list_sortable( $hook ) {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;

		if ( ! $screen ) {
			return;
		}

		$capability = $this->get_setting( 'capability', 'manage_options' );

		if ( ! current_user_can( $capability ) ) {
			return;
		}

		$defaults = $this->get_default_settings();
		$config   = null;

		// Admin edit.php list screens for enabled post types.
		if ( 'edit' === $screen->base ) {
			$enabled = $this->get_setting( 'post_types', $defaults['post_types'] );

			if ( ! in_array( $screen->post_type, $enabled, true ) ) {
				return;
			}

			$config = array(
				'nonce'      => wp_create_nonce( 'blaminhor_essentials_admin' ),
				'ajaxurl'    => admin_url( 'admin-ajax.php' ),
				'type'       => $screen->post_type,
				'isTaxonomy' => false,
				'strings'    => array(
					'saved'     => __( 'Order saved.', 'blaminhor-essentials' ),
					'ajaxError' => __( 'An error occurred. Please try again.', 'blaminhor-essentials' ),
				),
			);
		}

		// Admin edit-tags.php list screens for enabled taxonomies.
		if ( 'edit-tags' === $screen->base ) {
			$enabled = $this->get_setting( 'taxonomies', $defaults['taxonomies'] );

			if ( ! in_array( $screen->taxonomy, $enabled, true ) ) {
				return;
			}

			$config = array(
				'nonce'      => wp_create_nonce( 'blaminhor_essentials_admin' ),
				'ajaxurl'    => admin_url( 'admin-ajax.php' ),
				'type'       => $screen->taxonomy,
				'isTaxonomy' => true,
				'strings'    => array(
					'saved'     => __( 'Order saved.', 'blaminhor-essentials' ),
					'ajaxError' => __( 'An error occurred. Please try again.', 'blaminhor-essentials' ),
				),
			);
		}

		if ( ! $config ) {
			return;
		}

		wp_enqueue_script( 'jquery-ui-sortable' );
		wp_enqueue_style(
			'blaminhor-essentials-modules',
			BLAMINHOR_ESSENTIALS_PLUGIN_URL . 'assets/css/modules.css',
			array(),
			BLAMINHOR_ESSENTIALS_VERSION
		);
		wp_enqueue_script(
			'blaminhor-essentials-modules',
			BLAMINHOR_ESSENTIALS_PLUGIN_URL . 'assets/js/modules.js',
			array( 'jquery', 'jquery-ui-sortable' ),
			BLAMINHOR_ESSENTIALS_VERSION,
			true
		);
		wp_add_inline_script(
			'blaminhor-essentials-modules',
			'jQuery(document).ready(function($) { if (typeof BlaminhorEssentialsPTOListSort !== "undefined") { BlaminhorEssentialsPTOListSort.init(' . wp_json_encode( $config ) . '); } });'
		);
	}

	// =========================================================================
	// AUTO-SORT HOOKS
	// =========================================================================

	/**
	 * Modify SQL clauses to sort by menu_order (frontend and admin edit.php)
	 *
	 * Uses posts_clauses filter at priority 99 to override the ORDER BY clause
	 * directly at the SQL level. This ensures the custom order is respected even
	 * when page builders (Elementor, JetEngine) modify the query via their own
	 * posts_clauses or posts_orderby filters at lower priorities.
	 *
	 * @param array    $clauses SQL clauses (fields, join, where, groupby, orderby, distinct, limits).
	 * @param WP_Query $query   The query object.
	 * @return array
	 */
	public function auto_sort_posts_clauses( $clauses, $query ) {
		// In admin, only apply on edit.php list screens and only for the main query.
		if ( is_admin() ) {
			if ( ! $query->is_main_query() ) {
				return $clauses;
			}
			$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
			if ( ! $screen || 'edit' !== $screen->base ) {
				return $clauses;
			}
			// In admin, don't override explicit column sorting (user clicked a column header).
			if ( '' !== $query->get( 'orderby' ) ) {
				return $clauses;
			}
		}

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

		if ( empty( $post_type ) ) {
			$post_type = 'post';
		}

		if ( is_array( $post_type ) ) {
			if ( 1 === count( $post_type ) ) {
				$post_type = reset( $post_type );
			} else {
				return $clauses;
			}
		}

		$defaults = $this->get_default_settings();
		$enabled  = $this->get_setting( 'post_types', $defaults['post_types'] );

		if ( ! in_array( $post_type, $enabled, true ) ) {
			return $clauses;
		}

		global $wpdb;

		$clauses['orderby'] = "{$wpdb->posts}.menu_order ASC, {$wpdb->posts}.post_date DESC";
		$clauses['order']   = '';

		return $clauses;
	}

	/**
	 * Modify term query clauses to sort by blaminhor_menu_order via LEFT JOIN
	 *
	 * Uses terms_clauses filter to add an explicit LEFT JOIN on termmeta.
	 * This ensures all terms are returned (LEFT JOIN keeps rows without meta)
	 * while sorting by custom order when available.
	 *
	 * @param array  $clauses    SQL clauses (fields, join, where, distinct, orderby, order, limits).
	 * @param array  $taxonomies Taxonomy names.
	 * @param array  $args       Term query arguments.
	 * @return array
	 */
	public function auto_sort_terms_clauses( $clauses, $taxonomies, $args ) {
		// In admin, only apply on edit-tags.php list screens.
		if ( is_admin() ) {
			$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
			if ( ! $screen || 'edit-tags' !== $screen->base ) {
				return $clauses;
			}
		}

		$defaults = $this->get_default_settings();
		$enabled  = $this->get_setting( 'taxonomies', $defaults['taxonomies'] );
		$match    = false;

		foreach ( $taxonomies as $tax ) {
			if ( in_array( $tax, $enabled, true ) ) {
				$match = true;
				break;
			}
		}

		if ( ! $match ) {
			return $clauses;
		}

		// Only override default ordering (by name).
		if ( isset( $args['orderby'] ) && 'name' !== $args['orderby'] ) {
			return $clauses;
		}

		global $wpdb;

		$clauses['join']    .= " LEFT JOIN {$wpdb->termmeta} AS blaminhor_tm ON ( t.term_id = blaminhor_tm.term_id AND blaminhor_tm.meta_key = 'blaminhor_menu_order' )";
		$clauses['orderby']  = "ORDER BY COALESCE( CAST( blaminhor_tm.meta_value AS SIGNED ), 999999 ) ASC, t.name ASC";
		$clauses['order']    = '';

		return $clauses;
	}

	// =========================================================================
	// AJAX HANDLERS
	// =========================================================================

	/**
	 * AJAX: Get items for a given type
	 */
	public function ajax_get_items() {
		$this->verify_ajax_request( $this->get_setting( 'capability', 'manage_options' ) );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$type     = isset( $_POST['type'] ) ? sanitize_key( wp_unslash( $_POST['type'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$is_tax   = isset( $_POST['is_taxonomy'] ) && 'true' === sanitize_text_field( wp_unslash( $_POST['is_taxonomy'] ) );

		if ( empty( $type ) ) {
			wp_send_json_error( __( 'No type specified.', 'blaminhor-essentials' ) );
		}

		if ( $is_tax ) {
			$items = $this->get_taxonomy_items( $type );
		} else {
			$items = $this->get_post_type_items( $type );
		}

		wp_send_json_success( $items );
	}

	/**
	 * AJAX: Save order
	 */
	public function ajax_save_order() {
		$this->verify_ajax_request( $this->get_setting( 'capability', 'manage_options' ) );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$type   = isset( $_POST['type'] ) ? sanitize_key( wp_unslash( $_POST['type'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$is_tax = isset( $_POST['is_taxonomy'] ) && 'true' === sanitize_text_field( wp_unslash( $_POST['is_taxonomy'] ) );
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified above.
		$order  = isset( $_POST['order'] ) && is_array( $_POST['order'] ) ? array_map( 'absint', wp_unslash( $_POST['order'] ) ) : array();

		if ( empty( $type ) || ! is_array( $order ) ) {
			wp_send_json_error( __( 'Invalid data.', 'blaminhor-essentials' ) );
		}

		$order = array_map( 'absint', $order );

		if ( $is_tax ) {
			$this->save_taxonomy_order( $order );
		} else {
			$this->save_post_type_order( $order );
		}

		wp_send_json_success( __( 'Order saved.', 'blaminhor-essentials' ) );
	}

	/**
	 * AJAX: Reset order
	 */
	public function ajax_reset_order() {
		$this->verify_ajax_request( $this->get_setting( 'capability', 'manage_options' ) );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$type   = isset( $_POST['type'] ) ? sanitize_key( wp_unslash( $_POST['type'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_ajax_request() above.
		$is_tax = isset( $_POST['is_taxonomy'] ) && 'true' === sanitize_text_field( wp_unslash( $_POST['is_taxonomy'] ) );

		if ( empty( $type ) ) {
			wp_send_json_error( __( 'No type specified.', 'blaminhor-essentials' ) );
		}

		if ( $is_tax ) {
			$this->reset_taxonomy_order( $type );
		} else {
			$this->reset_post_type_order( $type );
		}

		wp_send_json_success( __( 'Order reset.', 'blaminhor-essentials' ) );
	}

	// =========================================================================
	// DATA HELPERS
	// =========================================================================

	/**
	 * Get post type items ordered by menu_order
	 *
	 * @param string $post_type Post type slug.
	 * @return array
	 */
	private function get_post_type_items( $post_type ) {
		$args = array(
			'post_type'      => $post_type,
			'posts_per_page' => 500,
			'orderby'        => 'menu_order date',
			'order'          => 'ASC',
			'post_status'    => array( 'publish', 'draft', 'pending', 'private' ),
		);

		$query = new WP_Query( $args );
		$items = array();
		$total = $query->found_posts;

		foreach ( $query->posts as $index => $post ) {
			$items[] = array(
				'id'     => $post->ID,
				'title'  => $post->post_title ? $post->post_title : __( '(no title)', 'blaminhor-essentials' ),
				'status' => $post->post_status,
				'date'   => get_the_date( get_option( 'date_format' ), $post ),
				'order'  => $index + 1,
			);
		}

		return array(
			'items'    => $items,
			'total'    => $total,
			'limited'  => $total > 500,
		);
	}

	/**
	 * Get taxonomy items ordered by blaminhor_menu_order meta
	 *
	 * @param string $taxonomy Taxonomy slug.
	 * @return array
	 */
	private function get_taxonomy_items( $taxonomy ) {
		$terms = get_terms( array(
			'taxonomy'   => $taxonomy,
			'hide_empty' => false,
			'number'     => 500,
			'orderby'    => 'name',
			'order'      => 'ASC',
		) );

		$total_terms = wp_count_terms( array(
			'taxonomy'   => $taxonomy,
			'hide_empty' => false,
		) );

		if ( is_wp_error( $terms ) ) {
			$terms = array();
		}

		// Sort by blaminhor_menu_order meta (terms without it go last, then by name).
		usort( $terms, function ( $a, $b ) {
			$order_a = get_term_meta( $a->term_id, 'blaminhor_menu_order', true );
			$order_b = get_term_meta( $b->term_id, 'blaminhor_menu_order', true );
			$order_a = '' !== $order_a ? (int) $order_a : 999999;
			$order_b = '' !== $order_b ? (int) $order_b : 999999;

			if ( $order_a === $order_b ) {
				return strcmp( $a->name, $b->name );
			}
			return $order_a - $order_b;
		} );

		$items = array();

		foreach ( $terms as $index => $term ) {
			$items[] = array(
				'id'    => $term->term_id,
				'title' => $term->name,
				'count' => $term->count,
				'order' => $index + 1,
			);
		}

		return array(
			'items'   => $items,
			'total'   => (int) $total_terms,
			'limited' => (int) $total_terms > 500,
		);
	}

	/**
	 * Save post type order using menu_order field
	 *
	 * @param array $order Array of post IDs in desired order.
	 */
	private function save_post_type_order( $order ) {
		global $wpdb;

		foreach ( $order as $position => $post_id ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk update for performance.
			$wpdb->update(
				$wpdb->posts,
				array( 'menu_order' => $position ),
				array( 'ID' => $post_id ),
				array( '%d' ),
				array( '%d' )
			);
		}

		clean_post_cache( 0 );
	}

	/**
	 * Save taxonomy order using term_meta
	 *
	 * @param array $order Array of term IDs in desired order.
	 */
	private function save_taxonomy_order( $order ) {
		foreach ( $order as $position => $term_id ) {
			update_term_meta( $term_id, 'blaminhor_menu_order', $position );
		}
	}

	/**
	 * Reset post type order (set all menu_order to 0)
	 *
	 * @param string $post_type Post type slug.
	 */
	private function reset_post_type_order( $post_type ) {
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk reset for performance.
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE {$wpdb->posts} SET menu_order = 0 WHERE post_type = %s",
				$post_type
			)
		);

		clean_post_cache( 0 );
	}

	/**
	 * Reset taxonomy order (delete all blaminhor_menu_order meta for a taxonomy)
	 *
	 * @param string $taxonomy Taxonomy slug.
	 */
	private function reset_taxonomy_order( $taxonomy ) {
		$terms = get_terms( array(
			'taxonomy'   => $taxonomy,
			'hide_empty' => false,
			'fields'     => 'ids',
		) );

		if ( is_wp_error( $terms ) ) {
			return;
		}

		foreach ( $terms as $term_id ) {
			delete_term_meta( $term_id, 'blaminhor_menu_order' );
		}
	}

	// =========================================================================
	// SETTINGS
	// =========================================================================

	/**
	 * Process settings
	 *
	 * @param array $data Form data.
	 */
	protected function process_settings( $data ) {
		$settings = array();

		$settings['auto_sort'] = isset( $data['auto_sort'] );

		$settings['post_types'] = array();
		if ( isset( $data['post_types'] ) && is_array( $data['post_types'] ) ) {
			$settings['post_types'] = array_map( 'sanitize_key', $data['post_types'] );
		}

		$settings['taxonomies'] = array();
		if ( isset( $data['taxonomies'] ) && is_array( $data['taxonomies'] ) ) {
			$settings['taxonomies'] = array_map( 'sanitize_key', $data['taxonomies'] );
		}

		$allowed_caps = array( 'manage_options', 'edit_others_posts', 'edit_posts' );
		$capability   = isset( $data['capability'] ) ? sanitize_key( $data['capability'] ) : 'manage_options';
		$settings['capability'] = in_array( $capability, $allowed_caps, true ) ? $capability : 'manage_options';

		$this->save_settings( $settings );

		add_action( 'admin_notices', function () {
			blaminhor_essentials_admin_notice( __( 'Settings saved.', 'blaminhor-essentials' ), 'success' );
		} );
	}

	// =========================================================================
	// SETTINGS PAGE
	// =========================================================================

	/**
	 * Render settings page
	 */
	public function render_settings_page() {
		$this->handle_settings_submission();

		$post_types  = blaminhor_essentials_get_post_types();
		$taxonomies  = blaminhor_essentials_get_taxonomies();
		$defaults    = $this->get_default_settings();
		$enabled_pts = $this->get_setting( 'post_types', $defaults['post_types'] );
		$enabled_tax = $this->get_setting( 'taxonomies', $defaults['taxonomies'] );
		$auto_sort   = $this->get_setting( 'auto_sort', true );
		$capability  = $this->get_setting( 'capability', 'manage_options' );
		?>
		<div class="wrap blaminhor-essentials-wrap">
			<div class="blaminhor-essentials-header">
				<h1><?php echo esc_html( $this->name ); ?></h1>
				<p class="blaminhor-essentials-tagline"><?php echo esc_html( $this->description ); ?></p>
			</div>

			<div class="blaminhor-essentials-tabs-wrapper">
				<div class="blaminhor-essentials-tabs">
					<button class="blaminhor-essentials-tab active" data-tab="reorder"><?php esc_html_e( 'Reorder', 'blaminhor-essentials' ); ?></button>
					<button class="blaminhor-essentials-tab" data-tab="settings"><?php esc_html_e( 'Settings', 'blaminhor-essentials' ); ?></button>
				</div>

				<!-- Reorder Tab -->
				<div class="blaminhor-essentials-tab-content active" data-tab-content="reorder">
					<div class="blaminhor-essentials-section">

						<?php if ( empty( $enabled_pts ) && empty( $enabled_tax ) ) : ?>
							<div class="blaminhor-essentials-notice warning">
								<span class="dashicons dashicons-warning"></span>
								<?php esc_html_e( 'No post types or taxonomies are enabled. Go to the Settings tab to enable them first.', 'blaminhor-essentials' ); ?>
							</div>
						<?php else : ?>

							<div class="ap-pto-header">
								<label for="ap-pto-type-select"><strong><?php esc_html_e( 'Select type:', 'blaminhor-essentials' ); ?></strong></label>
								<select id="ap-pto-type-select" class="regular-text">
									<option value=""><?php esc_html_e( '— Select —', 'blaminhor-essentials' ); ?></option>
									<?php if ( ! empty( $enabled_pts ) ) : ?>
										<optgroup label="<?php esc_attr_e( 'Post Types', 'blaminhor-essentials' ); ?>">
											<?php foreach ( $enabled_pts as $pt_slug ) :
												$pt_obj = get_post_type_object( $pt_slug );
												if ( ! $pt_obj ) continue;
											?>
												<option value="<?php echo esc_attr( $pt_slug ); ?>" data-taxonomy="false">
													<?php echo esc_html( $pt_obj->labels->name ); ?>
												</option>
											<?php endforeach; ?>
										</optgroup>
									<?php endif; ?>
									<?php if ( ! empty( $enabled_tax ) ) : ?>
										<optgroup label="<?php esc_attr_e( 'Taxonomies', 'blaminhor-essentials' ); ?>">
											<?php foreach ( $enabled_tax as $tax_slug ) :
												$tax_obj = get_taxonomy( $tax_slug );
												if ( ! $tax_obj ) continue;
											?>
												<option value="<?php echo esc_attr( $tax_slug ); ?>" data-taxonomy="true">
													<?php echo esc_html( $tax_obj->labels->name ); ?>
												</option>
											<?php endforeach; ?>
										</optgroup>
									<?php endif; ?>
								</select>

								<button type="button" id="ap-pto-save-order" class="button button-primary ap-hidden">
									<span class="dashicons dashicons-saved ap-mt-xs"></span>
									<?php esc_html_e( 'Save Order', 'blaminhor-essentials' ); ?>
								</button>
								<button type="button" id="ap-pto-reset-order" class="button ap-hidden">
									<span class="dashicons dashicons-image-rotate ap-mt-xs"></span>
									<?php esc_html_e( 'Reset Order', 'blaminhor-essentials' ); ?>
								</button>
							</div>

							<div id="ap-pto-loading" class="ap-hidden">
								<span class="spinner is-active" style="float:none;margin:0 8px 0 0;"></span>
								<?php esc_html_e( 'Loading items...', 'blaminhor-essentials' ); ?>
							</div>

							<div id="ap-pto-limit-notice" class="blaminhor-essentials-notice warning ap-hidden">
								<span class="dashicons dashicons-warning"></span>
								<?php
								printf(
									/* translators: %d: Maximum number of items */
									esc_html__( 'Only the first %d items are shown. Items beyond this limit will keep their current order.', 'blaminhor-essentials' ),
									500
								);
								?>
							</div>

							<div id="ap-pto-empty" class="ap-hidden">
								<p><?php esc_html_e( 'No items found for this type.', 'blaminhor-essentials' ); ?></p>
							</div>

							<ul id="ap-pto-sortable-list" class="ap-pto-sortable-list ap-hidden"></ul>

						<?php endif; ?>
					</div>
				</div>

				<!-- Settings Tab -->
				<div class="blaminhor-essentials-tab-content" data-tab-content="settings">
					<div class="blaminhor-essentials-section blaminhor-essentials-settings">
						<form method="post" action="">
							<?php $this->render_nonce_field(); ?>

							<div class="settings-section">
								<h3><?php esc_html_e( 'General', 'blaminhor-essentials' ); ?></h3>
								<table class="form-table">
									<tr>
										<th scope="row"><?php esc_html_e( 'Auto Sort', 'blaminhor-essentials' ); ?></th>
										<td>
											<label>
												<input type="checkbox" name="auto_sort" value="1" <?php checked( $auto_sort ); ?>>
												<?php esc_html_e( 'Automatically apply custom order on the frontend', 'blaminhor-essentials' ); ?>
											</label>
											<p class="description"><?php esc_html_e( 'When enabled, posts and terms will be displayed in your custom order on the frontend.', 'blaminhor-essentials' ); ?></p>
										</td>
									</tr>
									<tr>
										<th scope="row">
											<label for="pto_capability"><?php esc_html_e( 'Required Capability', 'blaminhor-essentials' ); ?></label>
										</th>
										<td>
											<select id="pto_capability" name="capability">
												<option value="manage_options" <?php selected( $capability, 'manage_options' ); ?>><?php esc_html_e( 'Administrator', 'blaminhor-essentials' ); ?> (manage_options)</option>
												<option value="edit_others_posts" <?php selected( $capability, 'edit_others_posts' ); ?>><?php esc_html_e( 'Editor', 'blaminhor-essentials' ); ?> (edit_others_posts)</option>
												<option value="edit_posts" <?php selected( $capability, 'edit_posts' ); ?>><?php esc_html_e( 'Author', 'blaminhor-essentials' ); ?> (edit_posts)</option>
											</select>
											<p class="description"><?php esc_html_e( 'Minimum capability required to reorder items.', 'blaminhor-essentials' ); ?></p>
										</td>
									</tr>
								</table>
							</div>

							<div class="settings-section">
								<h3><?php esc_html_e( 'Enabled Post Types', 'blaminhor-essentials' ); ?></h3>
								<p class="description"><?php esc_html_e( 'Select which post types can be reordered.', 'blaminhor-essentials' ); ?></p>
								<div class="duplicator-post-types">
									<?php foreach ( $post_types as $pt ) : ?>
									<label>
										<input type="checkbox"
											   name="post_types[]"
											   value="<?php echo esc_attr( $pt->name ); ?>"
											   <?php checked( in_array( $pt->name, $enabled_pts, true ) ); ?>>
										<?php echo esc_html( $pt->labels->singular_name ); ?>
									</label>
									<?php endforeach; ?>
								</div>
							</div>

							<div class="settings-section">
								<h3><?php esc_html_e( 'Enabled Taxonomies', 'blaminhor-essentials' ); ?></h3>
								<p class="description"><?php esc_html_e( 'Select which taxonomies can be reordered.', 'blaminhor-essentials' ); ?></p>
								<div class="duplicator-post-types">
									<?php foreach ( $taxonomies as $tax ) : ?>
									<label>
										<input type="checkbox"
											   name="taxonomies[]"
											   value="<?php echo esc_attr( $tax->name ); ?>"
											   <?php checked( in_array( $tax->name, $enabled_tax, true ) ); ?>>
										<?php echo esc_html( $tax->labels->singular_name ); ?>
									</label>
									<?php endforeach; ?>
								</div>
							</div>

							<p class="submit">
								<button type="submit" class="button button-primary"><?php esc_html_e( 'Save Settings', 'blaminhor-essentials' ); ?></button>
							</p>
						</form>
					</div>
				</div>
			</div>
		</div>

		<script>
		jQuery(document).ready(function($) {
			if (typeof window.BlaminhorEssentialsPostTypesOrder !== 'undefined') {
				window.BlaminhorEssentialsPostTypesOrder.init({
					nonce: '<?php echo esc_js( wp_create_nonce( 'blaminhor_essentials_admin' ) ); ?>',
					ajaxurl: '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ); ?>',
					strings: {
						saving: '<?php echo esc_js( __( 'Saving...', 'blaminhor-essentials' ) ); ?>',
						saved: '<?php echo esc_js( __( 'Order saved.', 'blaminhor-essentials' ) ); ?>',
						resetting: '<?php echo esc_js( __( 'Resetting...', 'blaminhor-essentials' ) ); ?>',
						resetDone: '<?php echo esc_js( __( 'Order reset.', 'blaminhor-essentials' ) ); ?>',
						confirmReset: '<?php echo esc_js( __( 'Are you sure you want to reset the order for this type?', 'blaminhor-essentials' ) ); ?>',
						ajaxError: '<?php echo esc_js( __( 'An error occurred. Please try again.', 'blaminhor-essentials' ) ); ?>',
						items: '<?php echo esc_js( __( 'items', 'blaminhor-essentials' ) ); ?>',
						publish: '<?php echo esc_js( __( 'Published', 'blaminhor-essentials' ) ); ?>',
						draft: '<?php echo esc_js( __( 'Draft', 'blaminhor-essentials' ) ); ?>',
						pending: '<?php echo esc_js( __( 'Pending', 'blaminhor-essentials' ) ); ?>',
						private: '<?php echo esc_js( __( 'Private', 'blaminhor-essentials' ) ); ?>'
					}
				});
			}
		});
		</script>

		<?php
	}
}
