<?php

namespace AdminColumnsCustomizer;

use WP_PowerSuite\Core\AbstractModule;

require_once __DIR__ . '/supports.php';
require_once __DIR__ . '/includes/ListTableEnhancements.php';

class Module extends AbstractModule {

	private const MODULE_ID = 'admin-columns-customizer';
	private const MODULE_VERSION = '1.0.0';

private array $settings = [];
	private ?ListTableEnhancements $list_table_enhancements = null;

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Admin Columns Customizer', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Reorder, hide, and customize admin list-table columns for posts, media, comments, users, and taxonomies.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'admin', 'ajax' ];
	}

	public function getDependencies(): array {
		return [];
	}

	private function isLicenseActive(): bool {
		return function_exists( 'wp_powersuite_is_license_valid' ) && wp_powersuite_is_license_valid();
	}

		protected function registerHooks(): void {
		if ( ! $this->isLicenseActive() ) {
			return;
		}

		add_action( $this->adminMenuHook(), [ $this, 'addAdminMenu' ], 20 );
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueueScripts' ] );
		add_action( 'current_screen', [ $this, 'applyColumnSettings' ] );
		add_action( 'current_screen', [ $this, 'addManageColumnsButton' ] );
		add_action( 'wp_ajax_wpps_save_column_config', [ $this, 'handleSaveColumnConfig' ] );
		add_action( 'wp_ajax_wpps_get_column_config', [ $this, 'handleGetColumnConfig' ] );
		add_action( 'wp_ajax_wpps_get_column_types', [ $this, 'handleGetColumnTypes' ] );
		add_action( 'wp_ajax_wpps_get_custom_fields', [ $this, 'handleGetCustomFields' ] );
		add_action( 'wp_ajax_wpps_restore_column_config', [ $this, 'handleRestoreColumnConfig' ] );
		add_action( 'wp_ajax_wpps_reset_all_column_config', [ $this, 'handleResetAllColumnConfig' ] );
		add_filter( 'wp_powersuite_sanitize_module_settings', [ $this, 'finalizeModuleSettingsSanitization' ], 999, 3 );
		$this->listTableEnhancements()->registerHooks();
	}


	public function addAdminMenu(): void {
		$this->registerPowerSuiteSubmenu(
			__( 'Admin Columns Customizer', 'wp-powersuite' ),
			__( 'Admin Columns', 'wp-powersuite' ),
			'powersuite-admin-columns-customizer',
			[ $this, 'renderAdminPage' ]
		);
	}

	public function renderAdminPage(): void {
		if ( ! $this->canManagePlugin() ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-powersuite' ) );
		}

		include __DIR__ . '/admin.php';
	}

	public function enqueueScripts( string $hook ): void {
		if ( $hook !== 'wp-powersuite_page_powersuite-admin-columns-customizer' ) {
			return;
		}

		wp_enqueue_script( 'jquery-ui-sortable' );
		wp_enqueue_style( 'wp-powersuite-admin-columns', $this->getAssetUrl( 'admin-columns.css' ), [], self::MODULE_VERSION );
		wp_enqueue_script( 'wp-powersuite-admin-columns', $this->getAssetUrl( 'admin-columns.js' ), [ 'jquery', 'jquery-ui-sortable' ], self::MODULE_VERSION, true );

		$screen_type = ScreenSupport::sanitizeScreenType(
			isset( $_GET['screen_type'] ) ? sanitize_text_field( wp_unslash( $_GET['screen_type'] ) ) : 'post_type'
		);
		$screen_id   = isset( $_GET['screen_id'] ) ? sanitize_text_field( wp_unslash( $_GET['screen_id'] ) ) : 'post';
		$show_quick_add = ( $screen_type === 'post_type' && ! in_array( $screen_id, [ 'comments', 'attachment' ], true ) && post_type_exists( $screen_id ) );
		$screen_taxonomies = $this->getScreenTaxonomyOptions( $screen_type, $screen_id );
		$taxonomies        = [];
		if ( $show_quick_add ) {
			foreach ( $screen_taxonomies as $tax ) {
				$taxonomies[] = array_merge(
					$tax,
					[ 'column_key' => ScreenSupport::taxonomyListColumnKey( $tax['slug'] ) ]
				);
			}
		}

		wp_localize_script( 'wp-powersuite-admin-columns', 'wppsAdminColumns', [
			'ajaxUrl' => admin_url( 'admin-ajax.php' ),
			'nonce'   => wp_create_nonce( 'wpps_admin_columns' ),
			'quickAdd' => [
				'show'       => $show_quick_add,
				'taxonomies' => $taxonomies,
				'labels'     => [
					'quickAdd'   => __( 'Quick Add', 'wp-powersuite' ),
					'taxonomies' => __( 'Taxonomies', 'wp-powersuite' ),
					'id'         => __( 'ID', 'wp-powersuite' ),
					'dateModified' => __( 'Last Modified', 'wp-powersuite' ),
					'featuredImage' => __( 'Featured Image', 'wp-powersuite' ),
					'wordCount'  => __( 'Word Count', 'wp-powersuite' ),
					'slug'       => __( 'Slug', 'wp-powersuite' ),
					'added'      => __( 'Added', 'wp-powersuite' ),
					'columnExists' => __( 'Column already exists', 'wp-powersuite' ),
				],
			],
			'sortableSupported' => ScreenSupport::supportsSortableConfig( $screen_type, $screen_id ),
			'layoutSupported'   => ScreenSupport::supportsLayoutSettings( $screen_type, $screen_id ),
			'strings' => [
				'saving'          => __( 'Saving...', 'wp-powersuite' ),
				'saved'           => __( 'Settings saved successfully!', 'wp-powersuite' ),
				'error'           => __( 'Unable to save column settings. Please try again.', 'wp-powersuite' ),
				'confirm'         => __( 'Are you sure you want to reset all columns?', 'wp-powersuite' ),
				'confirmRestore'  => __( 'Are you sure you want to restore default columns? This will remove all customizations for this screen.', 'wp-powersuite' ),
				'confirmResetAll' => __( 'Are you sure you want to reset ALL column settings? This will remove all customizations for all screens.', 'wp-powersuite' ),
				'restoring'       => __( 'Restoring...', 'wp-powersuite' ),
				'restored'        => __( 'Columns restored to defaults successfully!', 'wp-powersuite' ),
				'resetting'       => __( 'Resetting...', 'wp-powersuite' ),
				'resetAll'        => __( 'All column settings reset successfully!', 'wp-powersuite' ),
				'addColumn'       => __( 'Add Column', 'wp-powersuite' ),
				'editColumn'      => __( 'Edit Column', 'wp-powersuite' ),
				'loadingTypes'    => __( 'Loading...', 'wp-powersuite' ),
				'selectColumnType'=> __( 'Select Column Type', 'wp-powersuite' ),
				'forceWidth'      => __( 'Force width', 'wp-powersuite' ),
				'cssClass'        => __( 'CSS Class', 'wp-powersuite' ),
				'confirmDelete'   => __( 'Are you sure you want to delete this column?', 'wp-powersuite' ),
				'noCustomFields'  => __( 'No custom fields found.', 'wp-powersuite' ),
				'selectField'     => __( 'Select field', 'wp-powersuite' ),
				'selectTaxonomy'  => __( 'Select Taxonomy', 'wp-powersuite' ),
				'requiredFields'  => __( 'Please fill in all required fields.', 'wp-powersuite' ),
				'metaKeyRequired' => __( 'Please enter or select a custom field key.', 'wp-powersuite' ),
				'taxonomyRequired'=> __( 'Please select a taxonomy.', 'wp-powersuite' ),
				'typesLoadError'  => __( 'Could not load column types. Please refresh and try again.', 'wp-powersuite' ),
				'usingDefaults'   => __( 'No custom column configuration for this screen. WordPress default columns are in use.', 'wp-powersuite' ),
			],
			'screenTaxonomies' => $screen_taxonomies,
		] );
	}

	public function applyColumnSettings(): void {
		$screen = get_current_screen();
		if ( ! $screen ) {
			return;
		}

		$config_key = $this->resolveListTableConfigKey( $screen );
		if ( $config_key === null ) {
			return;
		}

		$settings       = $this->getSettings();
		$column_configs = $settings['column_configs'] ?? [];
		if ( empty( $column_configs[ $config_key ] ) ) {
			return;
		}

		$config = $column_configs[ $config_key ];
		if ( ! $this->hasApplicableListConfig( $config ) ) {
			return;
		}

		$this->registerListTableWrapperAssets( $config );

		if ( $screen->id === 'edit-comments' ) {
			$this->applyCommentsColumns( $config );
			return;
		}

		if ( $screen->id === 'upload' ) {
			$this->applyMediaColumns( $config );
			return;
		}

		if ( $screen->id === 'users' ) {
			$this->applyUserColumns( $config );
			return;
		}

		if ( strpos( $screen->id, 'edit-' ) === 0 && ! empty( $screen->taxonomy ) ) {
			$this->applyTaxonomyColumns( $screen->taxonomy, $config );
			return;
		}

		if ( strpos( $screen->id, 'edit-' ) === 0 ) {
			$post_type = str_replace( 'edit-', '', $screen->id );
			if ( ScreenSupport::isManageablePostType( $post_type ) ) {
				$this->applyPostTypeColumns( $post_type, $config );
			}
		}
	}

	private function resolveListTableConfigKey( \WP_Screen $screen ): ?string {
		if ( $screen->id === 'edit-comments' ) {
			return 'post_type_comments';
		}

		if ( $screen->id === 'upload' ) {
			return 'post_type_attachment';
		}

		if ( $screen->id === 'users' ) {
			return 'users';
		}

		if ( strpos( $screen->id, 'edit-' ) === 0 && ! empty( $screen->taxonomy ) ) {
			$taxonomy = $screen->taxonomy;
			if ( ScreenSupport::isManageableTaxonomy( $taxonomy ) ) {
				return 'taxonomy_' . $taxonomy;
			}
			return null;
		}

		if ( strpos( $screen->id, 'edit-' ) === 0 ) {
			$post_type = str_replace( 'edit-', '', $screen->id );
			if ( ScreenSupport::isManageablePostType( $post_type ) ) {
				return 'post_type_' . $post_type;
			}
		}

		return null;
	}

	private function registerListTableWrapperAssets( array $config ): void {
		static $registered = false;
		if ( $registered ) {
			return;
		}
		$registered = true;

		$disable_scroll = $this->listTableEnhancements()->shouldDisableHorizontalScroll( $config );

		add_filter(
			'admin_body_class',
			static function ( string $classes ) use ( $disable_scroll ): string {
				return $classes . ( $disable_scroll ? ' wpps-acc-no-h-scroll' : ' wpps-acc-h-scroll' );
			}
		);

		add_action(
			'admin_head',
			static function () use ( $disable_scroll ): void {
				if ( $disable_scroll ) {
					return;
				}

				echo '<style type="text/css" id="wpps-acc-list-table-layout">';
				echo 'body.wp-admin.wpps-acc-h-scroll { overflow-x: hidden; }';
				echo '</style>';
			}
		);

		if ( ! $disable_scroll ) {
			$this->listTableEnhancements()->registerListTableWrapperMarkupHook();
		}
	}

	/**
	 * @param array<string, string> $sortable
	 * @param array<int, array<string, mixed>> $config_columns
	 * @return array<string, string>
	 */
	private function mergeConfiguredSortableColumns( array $sortable, array $config_columns, string $post_type = '' ): array {
		foreach ( $config_columns as $column_data ) {
			if ( ! is_array( $column_data ) ) {
				continue;
			}

			$config_key = $column_data['key'] ?? '';
			if ( $config_key === '' || $config_key === 'cb' ) {
				continue;
			}

			$column_key = $this->resolveCompactTablesColumnKey( $config_key, $post_type );

			if ( ! empty( $column_data['hidden'] ) || empty( $column_data['sortable'] ) ) {
				unset( $sortable[ $column_key ], $sortable[ $config_key ] );
				continue;
			}

			$sortable[ $column_key ] = $column_key === 'compact_date' ? 'date' : $column_key;
		}

		return $sortable;
	}

	private function printColumnWidthStyles( array $config, string $post_type = '' ): void {
		$styles         = [];
		$class_map      = [];
		$table_sel      = $this->listTableEnhancements()->listTableCssSelector( $config );
		$disable_scroll = $this->listTableEnhancements()->shouldDisableHorizontalScroll( $config );

		foreach ( $config['columns'] as $column_data ) {
			if ( ! is_array( $column_data ) ) {
				continue;
			}

			$config_key = $column_data['key'] ?? '';
			if ( $config_key === '' || $config_key === 'cb' ) {
				continue;
			}

			if ( ! empty( $column_data['hidden'] ) ) {
				continue;
			}

			$column_key   = $this->resolveCompactTablesColumnKey( $config_key, $post_type );
			$column_class = sanitize_html_class( $column_key );
			$width        = $column_data['width'] ?? null;
			$force_width  = ! empty( $column_data['force_width'] );

			if ( $disable_scroll ) {
				// Equal-width layout is applied after the loop.
			} elseif ( ! empty( $width ) && $width !== 'auto' ) {
				$width_rule = 'width: ' . esc_attr( $width ) . ' !important; min-width: ' . esc_attr( $width ) . ' !important;';
				if ( $force_width ) {
					$width_rule .= ' max-width: ' . esc_attr( $width ) . ' !important;';
				}
				$styles[] = $table_sel . ' th.column-' . esc_attr( $column_class ) . ', ';
				$styles[] = $table_sel . ' td.column-' . esc_attr( $column_class ) . ', ';
				$styles[] = $table_sel . ' .column-' . esc_attr( $column_class ) . ' { ' . $width_rule . ' }';
			}

			if ( ! empty( $column_data['css_class'] ) ) {
				$classes = array_filter( array_map( 'sanitize_html_class', explode( ' ', (string) $column_data['css_class'] ) ) );
				if ( ! empty( $classes ) ) {
					$class_map[ $column_class ] = implode( ' ', $classes );
				}
			}
		}

		if ( $disable_scroll ) {
			$styles = array_merge( $styles, $this->buildEqualNoScrollColumnWidthStyles( $config, $table_sel, $post_type ) );
		}

		if ( ! empty( $styles ) ) {
			echo '<style type="text/css" id="wpps-acc-column-widths">';
			echo implode( "\n", $styles );
			echo '</style>';
		}

		if ( ! empty( $class_map ) ) {
			echo '<script type="text/javascript">';
			echo 'jQuery(function($){ var m=' . wp_json_encode( $class_map ) . '; $.each(m,function(col,cls){ $("th.column-"+col+",td.column-"+col).addClass(cls); }); });';
			echo '</script>';
		}
	}

	/**
	 * Visible data columns only (checkbox column excluded — it keeps the WP default width).
	 *
	 * @return list<string>
	 */
	private function getVisibleDataColumnKeys( array $config, string $post_type = '' ): array {
		$keys = [];

		foreach ( $config['columns'] ?? [] as $column_data ) {
			if ( ! is_array( $column_data ) || ! empty( $column_data['hidden'] ) ) {
				continue;
			}

			$config_key = sanitize_key( $column_data['key'] ?? '' );
			if ( $config_key === '' || $config_key === 'cb' ) {
				continue;
			}

			$keys[] = sanitize_key( $this->resolveCompactTablesColumnKey( $config_key, $post_type ) );
		}

		return $keys;
	}

	/**
	 * Split list-table data columns evenly; checkbox column keeps WordPress default width.
	 *
	 * @return list<string>
	 */
	private function buildEqualNoScrollColumnWidthStyles( array $config, string $table_sel, string $post_type = '' ): array {
		$data_keys = $this->getVisibleDataColumnKeys( $config, $post_type );
		$count     = count( $data_keys );

		if ( $count < 1 ) {
			return [];
		}

		$styles   = [ '@media screen and (min-width: 783px) {' ];
		$styles[] = $table_sel . ' th.check-column, ' . $table_sel . ' td.check-column { width: 2.2em !important; max-width: 2.2em !important; min-width: 2.2em !important; }';

		$equal_width = 'calc((100% - 2.2em) / ' . $count . ')';
		$width_rule  = 'width: ' . $equal_width . ' !important; min-width: 0;';

		foreach ( $data_keys as $column_key ) {
			$column_class = sanitize_html_class( $column_key );
			$selector     = $table_sel . ' th.column-' . esc_attr( $column_class ) . ', ' . $table_sel . ' td.column-' . esc_attr( $column_class );
			$styles[]     = $selector . ' { ' . $width_rule . ' }';
		}

		$styles[] = '}';

		return $styles;
	}

	private function applyPostTypeColumns( string $post_type, array $config ): void {
		if ( empty( $config['columns'] ) || ! is_array( $config['columns'] ) ) {
			return;
		}

		$hook = $post_type === 'post' ? 'manage_posts_columns' : ( $post_type === 'page' ? 'manage_pages_columns' : "manage_{$post_type}_posts_columns" );

		add_filter( $hook, function( array $columns ) use ( $config, $post_type ) {
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$config_key = $column_data['key'] ?? '';
				$column_key = $this->resolveCompactTablesColumnKey( $config_key, $post_type );
				if ( $column_key !== '' && isset( $columns[ $column_key ] ) && ! empty( $column_data['label'] ) ) {
					$columns[ $column_key ] = $column_data['label'];
				}
			}
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$config_key    = $column_data['key'] ?? '';
				$column_key    = $this->resolveCompactTablesColumnKey( $config_key, $post_type );
				$column_custom = ! empty( $column_data['custom'] );

				if ( $column_custom && $column_key !== '' && ! isset( $columns[ $column_key ] ) ) {
					$columns[ $column_key ] = $column_data['label'] ?? $column_key;
				}
			}

			return $this->reorderColumns( $columns, $config['columns'], $post_type );
		}, 200 );

		add_action(
			'admin_head',
			function () use ( $config, $post_type ) {
				$screen = get_current_screen();
				if ( ! $screen || strpos( $screen->id, "edit-{$post_type}" ) !== 0 ) {
					return;
				}

				$this->printColumnWidthStyles( $config, $post_type );
			}
		);

		$sortable_hook = $post_type === 'post' ? 'manage_edit-post_sortable_columns' : ( $post_type === 'page' ? 'manage_edit-page_sortable_columns' : "manage_edit-{$post_type}_sortable_columns" );
		add_filter(
			$sortable_hook,
			function ( array $sortable ) use ( $config, $post_type ) {
				return $this->mergeConfiguredSortableColumns( $sortable, $config['columns'], $post_type );
			},
			200
		);

		add_action(
			'pre_get_posts',
			function ( $query ) use ( $post_type, $config ) {
				if ( ! is_admin() || ! $query->is_main_query() ) {
					return;
				}

				$screen = get_current_screen();
				if ( ! $screen || $screen->post_type !== $post_type ) {
					return;
				}

				$orderby = $query->get( 'orderby' );
				if ( ! $orderby ) {
					return;
				}

				foreach ( $config['columns'] as $column_data ) {
					if ( ! is_array( $column_data ) ) {
						continue;
					}
					$column_key = $column_data['key'] ?? '';
					if ( $orderby === $column_key && ! empty( $column_data['sortable'] ) ) {
						$this->applyColumnSorting( $query, $column_key, $column_data );
						break;
					}
				}
			}
		);

		foreach ( $config['columns'] as $column_data ) {
			if ( ! is_array( $column_data ) ) {
				continue;
			}

			$column_key = $column_data['key'] ?? '';
			if ( empty( $column_key ) ) {
				continue;
			}

			if ( ! empty( $column_data['custom'] ) && ! empty( $column_data['type'] ) ) {
				$display_hook = $post_type === 'post' ? 'manage_posts_custom_column' : ( $post_type === 'page' ? 'manage_pages_custom_column' : "manage_{$post_type}_posts_custom_column" );
				add_action( $display_hook, function( string $column_name, int $post_id ) use ( $column_key, $column_data ) {
					if ( $column_name === $column_key ) {
						echo $this->renderCustomColumn( $column_data, $post_id, 'post' );
					}
				}, 10, 2 );
			}

		}
	}

	private function applyCommentsColumns( array $config ): void {
		if ( empty( $config['columns'] ) || ! is_array( $config['columns'] ) ) {
			return;
		}

		add_filter( 'manage_edit-comments_columns', function( array $columns ) use ( $config ) {
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key = $column_data['key'] ?? '';
				if ( ! empty( $column_key ) && isset( $columns[ $column_key ] ) && ! empty( $column_data['label'] ) ) {
					$columns[ $column_key ] = $column_data['label'];
				}
			}
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key = $column_data['key'] ?? '';
				$column_custom = ! empty( $column_data['custom'] );
				
				if ( $column_custom && ! empty( $column_key ) && ! isset( $columns[ $column_key ] ) ) {
					$columns[ $column_key ] = $column_data['label'] ?? $column_key;
				}
			}
			
			return $this->reorderColumns( $columns, $config['columns'] );
		}, 200 );

		add_action(
			'admin_head',
			function () use ( $config ) {
				$screen = get_current_screen();
				if ( ! $screen || $screen->id !== 'edit-comments' ) {
					return;
				}

				$this->printColumnWidthStyles( $config );
			}
		);

		foreach ( $config['columns'] as $column_data ) {
			if ( ! is_array( $column_data ) ) {
				continue;
			}

			$column_key = $column_data['key'] ?? '';
			if ( empty( $column_key ) ) {
				continue;
			}

			if ( ! empty( $column_data['custom'] ) && ! empty( $column_data['type'] ) ) {
				add_action( 'manage_comments_custom_column', function( string $column_name, int $comment_id ) use ( $column_key, $column_data ) {
					if ( $column_name === $column_key ) {
						echo $this->renderCustomColumn( $column_data, $comment_id, 'comment' );
					}
				}, 10, 2 );
			}
		}
	}

	private function applyMediaColumns( array $config ): void {
		if ( empty( $config['columns'] ) || ! is_array( $config['columns'] ) ) {
			return;
		}

		add_filter( 'manage_media_columns', function( array $columns, $detached = null ) use ( $config ) {
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key = $column_data['key'] ?? '';
				if ( ! empty( $column_key ) && isset( $columns[ $column_key ] ) && ! empty( $column_data['label'] ) ) {
					$columns[ $column_key ] = $column_data['label'];
				}
			}
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key   = $column_data['key'] ?? '';
				$column_custom = ! empty( $column_data['custom'] );
				if ( $column_custom && ! empty( $column_key ) && ! isset( $columns[ $column_key ] ) ) {
					$columns[ $column_key ] = $column_data['label'] ?? $column_key;
				}
			}
			return $this->reorderColumns( $columns, $config['columns'] );
		}, 200 );

		add_action(
			'admin_head',
			function () use ( $config ) {
				$screen = get_current_screen();
				if ( ! $screen || $screen->id !== 'upload' ) {
					return;
				}

				$this->printColumnWidthStyles( $config );
			}
		);

		foreach ( $config['columns'] as $column_data ) {
			if ( ! is_array( $column_data ) ) {
				continue;
			}
			$column_key = $column_data['key'] ?? '';
			if ( empty( $column_key ) ) {
				continue;
			}
			if ( ! empty( $column_data['custom'] ) && ! empty( $column_data['type'] ) ) {
				add_action( 'manage_media_custom_column', function( string $column_name, int $post_id ) use ( $column_key, $column_data ) {
					if ( $column_name === $column_key ) {
						echo $this->renderCustomColumn( $column_data, $post_id, 'post' );
					}
				}, 10, 2 );
			}
		}
	}

	private function applyColumnSorting( $query, string $column_key, array $column_data ): void {
		$type = $column_data['type'] ?? '';

		if ( $type === '' && $column_key !== '' ) {
			$type = $column_key;
		}

		switch ( $type ) {
			case 'custom_field':
			case 'post_meta':
				$meta_key = $column_data['meta_key'] ?? '';
				if ( ! $meta_key ) {
					break;
				}
				$query->set( 'meta_key', $meta_key );
				$field_type = $column_data['field_type'] ?? 'text';
				if ( $field_type === 'number' ) {
					$query->set( 'orderby', 'meta_value_num' );
				} else {
					$query->set( 'orderby', 'meta_value' );
				}
				break;

			case 'comment_count':
			case 'comments':
				$query->set( 'orderby', 'comment_count' );
				break;

			case 'date_modified':
				$query->set( 'orderby', 'modified' );
				break;

			case 'date':
				$query->set( 'orderby', 'date' );
				break;

			case 'title':
				$query->set( 'orderby', 'title' );
				break;

			case 'author':
				$query->set( 'orderby', 'author' );
				break;

			case 'menu_order':
			case 'order':
				$query->set( 'orderby', 'menu_order' );
				break;
		}
	}


	private function applyUserColumns( array $config ): void {
		if ( empty( $config['columns'] ) || ! is_array( $config['columns'] ) ) {
			return;
		}

		add_filter(
			'manage_users_columns',
			function ( array $columns ) use ( $config ) {
				foreach ( $config['columns'] as $column_data ) {
					if ( ! is_array( $column_data ) ) {
						continue;
					}
					$column_key = $column_data['key'] ?? '';
					if ( $column_key !== '' && isset( $columns[ $column_key ] ) && ! empty( $column_data['label'] ) ) {
						$columns[ $column_key ] = $column_data['label'];
					}
				}
				foreach ( $config['columns'] as $column_data ) {
					if ( ! is_array( $column_data ) ) {
						continue;
					}
					$column_key    = $column_data['key'] ?? '';
					$column_custom = ! empty( $column_data['custom'] );
					if ( $column_custom && $column_key !== '' && ! isset( $columns[ $column_key ] ) ) {
						$columns[ $column_key ] = $column_data['label'] ?? $column_key;
					}
				}

				return $this->reorderColumns( $columns, $config['columns'] );
			},
			200
		);

		foreach ( $config['columns'] as $column_data ) {
			if ( ! is_array( $column_data ) || empty( $column_data['custom'] ) || empty( $column_data['type'] ) ) {
				continue;
			}

			$column_key = $column_data['key'] ?? '';
			if ( $column_key === '' ) {
				continue;
			}

			add_filter(
				'manage_users_custom_column',
				function ( string $value, string $column_name, int $user_id ) use ( $column_key, $column_data ) {
					if ( $column_name === $column_key ) {
						return $this->renderCustomColumn( $column_data, $user_id, 'user' );
					}

					return $value;
				},
				10,
				3
			);
		}

		add_action(
			'admin_head',
			function () use ( $config ) {
				$screen = get_current_screen();
				if ( ! $screen || $screen->id !== 'users' ) {
					return;
				}

				$this->printColumnWidthStyles( $config );
			}
		);
	}

	private function applyTaxonomyColumns( string $taxonomy, array $config ): void {
		if ( empty( $config['columns'] ) || ! is_array( $config['columns'] ) ) {
			return;
		}

		$hook = "manage_edit-{$taxonomy}_columns";
		add_filter( $hook, function( array $columns ) use ( $config ) {
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key = $column_data['key'] ?? '';
				if ( ! empty( $column_key ) && isset( $columns[ $column_key ] ) && ! empty( $column_data['label'] ) ) {
					$columns[ $column_key ] = $column_data['label'];
				}
			}
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key   = $column_data['key'] ?? '';
				$column_custom = ! empty( $column_data['custom'] );
				if ( $column_custom && ! empty( $column_key ) && ! isset( $columns[ $column_key ] ) ) {
					$columns[ $column_key ] = $column_data['label'] ?? $column_key;
				}
			}
			return $this->reorderColumns( $columns, $config['columns'] );
		}, 200 );

		$content_hook = "manage_{$taxonomy}_custom_column";
		add_filter( $content_hook, function( string $content, string $column_name, int $term_id ) use ( $config ) {
			foreach ( $config['columns'] as $column_data ) {
				if ( ! is_array( $column_data ) ) {
					continue;
				}
				$column_key = $column_data['key'] ?? '';
				if ( $column_key === $column_name && ! empty( $column_data['custom'] ) && ! empty( $column_data['type'] ) ) {
					return $this->renderCustomColumn( $column_data, $term_id, 'term' );
				}
			}
			return $content;
		}, 10, 3 );
		
		add_action(
			'admin_head',
			function () use ( $config, $taxonomy ) {
				$screen = get_current_screen();
				if ( ! $screen || $screen->taxonomy !== $taxonomy ) {
					return;
				}

				$this->printColumnWidthStyles( $config );
			}
		);
	}

	private function reorderColumns( array $columns, array $config_columns, string $post_type = '' ): array {
		$reordered = [];
		$processed_keys = [];

		if ( isset( $columns['cb'] ) ) {
			$reordered['cb'] = $columns['cb'];
			$processed_keys[] = 'cb';
		}

		foreach ( $config_columns as $column_data ) {
			$config_key = is_array( $column_data ) ? ( $column_data['key'] ?? '' ) : '';
			if ( empty( $config_key ) || $config_key === 'cb' ) {
				continue;
			}

			$column_key = $this->resolveCompactTablesColumnKey( $config_key, $post_type );

			$processed_keys[] = $config_key;
			if ( $column_key !== $config_key ) {
				$processed_keys[] = $column_key;
			}

			$column_hidden = is_array( $column_data ) && ! empty( $column_data['hidden'] );
			$column_custom = is_array( $column_data ) && ! empty( $column_data['custom'] );

			if ( isset( $columns[ $column_key ] ) ) {
				$column_label = is_array( $column_data ) && ! empty( $column_data['label'] )
					? $column_data['label']
					: $columns[ $column_key ];

				if ( ! $column_hidden ) {
					$reordered[ $column_key ] = $column_label;
				}
			} elseif ( $column_custom && ! $column_hidden ) {
				$reordered[ $column_key ] = is_array( $column_data ) ? ( $column_data['label'] ?? $column_key ) : $column_key;
			}
		}

		foreach ( $columns as $key => $label ) {
			if ( ! in_array( $key, $processed_keys, true ) && $key !== 'cb' ) {
				$reordered[ $key ] = $label;
			}
		}

		return $reordered;
	}

	private function resolveCompactTablesColumnKey( string $column_key, string $post_type = '' ): string {
		/** @var string $resolved */
		$resolved = apply_filters( 'wp_powersuite_compact_tables_column_key', $column_key, $post_type );

		return is_string( $resolved ) && $resolved !== '' ? $resolved : $column_key;
	}

	private function renderCustomColumn( array $column_data, int $object_id, string $object_type ): string {
		$type = $column_data['type'] ?? '';
		$output = '';

		switch ( $type ) {
			case 'id':
				if ( $object_type === 'post' || $object_type === 'user' || $object_type === 'comment' ) {
					$output = '<strong>' . esc_html( (string) $object_id ) . '</strong>';
				} elseif ( $object_type === 'term' ) {
					$output = '<strong>' . esc_html( (string) $object_id ) . '</strong>';
				}
				break;

			case 'title':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$output = $post ? esc_html( $post->post_title ) : '';
				}
				break;

			case 'author':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$author = get_the_author_meta( 'display_name', (int) $post->post_author );
						$output = esc_html( $author );
					}
				} elseif ( $object_type === 'comment' ) {
					$comment = get_comment( $object_id );
					$output = $comment ? esc_html( $comment->comment_author ) : '';
				}
				break;

			case 'comment':
				if ( $object_type === 'comment' ) {
					$comment = get_comment( $object_id );
					$output = $comment ? esc_html( wp_trim_words( $comment->comment_content, 20 ) ) : '';
				}
				break;

			case 'response':
				if ( $object_type === 'comment' ) {
					$comment = get_comment( $object_id );
					if ( $comment && $comment->comment_post_ID ) {
						$post_title = get_the_title( (int) $comment->comment_post_ID );
						$edit_link  = get_edit_post_link( (int) $comment->comment_post_ID );
						$output     = $edit_link
							? '<a href="' . esc_url( $edit_link ) . '">' . esc_html( $post_title ) . '</a>'
							: esc_html( $post_title );
					}
				}
				break;

			case 'date':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$output = esc_html(
							mysql2date(
								get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
								$post->post_date
							)
						);
					}
				} elseif ( $object_type === 'comment' ) {
					$comment = get_comment( $object_id );
					if ( $comment ) {
						$output = esc_html(
							mysql2date(
								get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
								$comment->comment_date
							)
						);
					}
				}
				break;

			case 'date_modified':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$output = esc_html(
							mysql2date(
								get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
								$post->post_modified
							)
						);
					}
				}
				break;

			case 'excerpt':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$excerpt = $post ? $post->post_excerpt : '';
					if ( empty( $excerpt ) && $post ) {
						$excerpt = wp_trim_words( $post->post_content, 20 );
					}
					$output = esc_html( $excerpt );
				}
				break;

			case 'content':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$content = $post ? wp_trim_words( $post->post_content, 30 ) : '';
					$output = esc_html( $content );
				}
				break;

			case 'comment_count':
				if ( $object_type === 'post' ) {
					$count = get_comments_number( $object_id );
					$output = '<strong>' . esc_html( (string) $count ) . '</strong>';
				} elseif ( $object_type === 'user' ) {
					$count = get_comments( [ 'user_id' => $object_id, 'count' => true ] );
					$output = '<strong>' . esc_html( (string) $count ) . '</strong>';
				}
				break;

			case 'word_count':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$word_count = str_word_count( strip_tags( $post->post_content ) );
						$output = '<strong>' . esc_html( (string) $word_count ) . '</strong>';
					}
				}
				break;

			case 'status':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$status = $post ? $post->post_status : '';
					$status_labels = get_post_statuses();
					$output = esc_html( $status_labels[ $status ] ?? $status );
				}
				break;

			case 'slug':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$output = esc_html( $post ? $post->post_name : '' );
				} elseif ( $object_type === 'term' ) {
					$term = get_term( $object_id );
					$output = ( $term && ! is_wp_error( $term ) ) ? esc_html( $term->slug ) : '';
				}
				break;

			case 'permalink':
				if ( $object_type === 'post' ) {
					$url = get_permalink( $object_id );
					$output = $url ? '<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $url ) . '</a>' : '';
				}
				break;

			case 'page_template':
				if ( $object_type === 'post' ) {
					$template = get_page_template_slug( $object_id );
					$output = $template ? esc_html( basename( $template ) ) : __( 'Default', 'wp-powersuite' );
				}
				break;

			case 'post_parent':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post && $post->post_parent ) {
						$parent = get_post( $post->post_parent );
						$output = $parent ? '<a href="' . esc_url( get_edit_post_link( $parent->ID ) ) . '">' . esc_html( $parent->post_title ) . '</a>' : '';
					}
				}
				break;

			case 'post_format':
				if ( $object_type === 'post' ) {
					$format = get_post_format( $object_id );
					$output = $format ? esc_html( ucfirst( $format ) ) : __( 'Standard', 'wp-powersuite' );
				}
				break;

			case 'taxonomy':
				if ( $object_type === 'post' ) {
					$taxonomy = $column_data['taxonomy'] ?? '';
					if ( $taxonomy ) {
						$terms = get_the_terms( $object_id, $taxonomy );
						if ( $terms && ! is_wp_error( $terms ) ) {
							$term_names = array_map( function( $term ) {
								return esc_html( $term->name );
							}, $terms );
							$output = implode( ', ', $term_names );
						}
					}
				}
				break;

			case 'custom_field':
			case 'post_meta':
				$meta_key = $column_data['meta_key'] ?? '';
				if ( $meta_key ) {
					$output = $this->renderMetaFieldValue( $object_id, $object_type, $meta_key, $column_data['field_type'] ?? 'text' );
				}
				break;

			case 'user_meta':
				$meta_key = $column_data['meta_key'] ?? '';
				if ( $meta_key ) {
					$output = $this->renderMetaFieldValue( $object_id, 'user', $meta_key, $column_data['field_type'] ?? 'text' );
				}
				break;

			case 'featured_image':
				if ( $object_type === 'post' ) {
					$thumbnail_id = get_post_thumbnail_id( $object_id );
					if ( $thumbnail_id ) {
						$image = wp_get_attachment_image( $thumbnail_id, [ 50, 50 ] );
						$output = $image ? $image : '';
					}
				}
				break;

			case 'post_count':
				if ( $object_type === 'user' ) {
					$count = count_user_posts( $object_id );
					$output = '<strong>' . esc_html( (string) $count ) . '</strong>';
				}
				break;

			case 'count':
				if ( $object_type === 'term' ) {
					$term = get_term( $object_id );
					$cnt  = ( $term && ! is_wp_error( $term ) ) ? (int) $term->count : 0;
					$output = '<strong>' . esc_html( (string) $cnt ) . '</strong>';
				}
				break;

			case 'username':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->user_login ) : '';
				}
				break;

			case 'name':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->display_name ) : '';
				} elseif ( $object_type === 'term' ) {
					$term = get_term( $object_id );
					$output = ( $term && ! is_wp_error( $term ) ) ? esc_html( $term->name ) : '';
				}
				break;

			case 'email':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->user_email ) : '';
				}
				break;

			case 'role':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					if ( $user && ! empty( $user->roles ) ) {
						$roles = array_map( 'translate_user_role', $user->roles );
						$output = esc_html( implode( ', ', $roles ) );
					}
				}
				break;

			case 'registered_date':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					if ( $user ) {
						$output = esc_html( mysql2date( get_option( 'date_format' ), $user->user_registered ) );
					}
				}
				break;

			case 'sticky':
				if ( $object_type === 'post' ) {
					$is_sticky = is_sticky( $object_id );
					$output = $is_sticky ? '<span class="dashicons dashicons-sticky" style="color:#00a32a;" title="' . esc_attr__( 'Sticky', 'wp-powersuite' ) . '"></span>' : '';
				}
				break;

			case 'password_protected':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post && ! empty( $post->post_password ) ) {
						$output = '<span class="dashicons dashicons-lock" style="color:#d63638;" title="' . esc_attr__( 'Password Protected', 'wp-powersuite' ) . '"></span>';
					}
				}
				break;

			case 'ping_status':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$ping_status = $post ? $post->ping_status : '';
					$output = $ping_status === 'open' ? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>' : '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';
				}
				break;

			case 'comment_status':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$comment_status = $post ? $post->comment_status : '';
					$output = $comment_status === 'open' ? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>' : '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';
				}
				break;

			case 'order':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					$output = $post ? esc_html( (string) $post->menu_order ) : '';
				}
				break;

			case 'depth':
				if ( $object_type === 'post' ) {
					$ancestors = get_post_ancestors( $object_id );
					$depth = count( $ancestors ) + 1;
					$output = '<strong>' . esc_html( (string) $depth ) . '</strong>';
				}
				break;

			case 'path':
				if ( $object_type === 'post' ) {
					$url = get_permalink( $object_id );
					$path = $url ? str_replace( home_url(), '', $url ) : '';
					$output = esc_html( $path );
				}
				break;

			case 'shortlink':
				if ( $object_type === 'post' ) {
					$shortlink = wp_get_shortlink( $object_id );
					$output = $shortlink ? '<a href="' . esc_url( $shortlink ) . '" target="_blank">' . esc_html( $shortlink ) . '</a>' : '';
				}
				break;

			case 'shortcodes':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						global $shortcode_tags;
						if ( ! empty( $shortcode_tags ) ) {
							$shortcodes = [];
							foreach ( array_keys( $shortcode_tags ) as $tag ) {
								$pattern = get_shortcode_regex( [ $tag ] );
								if ( preg_match_all( '/' . $pattern . '/s', $post->post_content, $matches ) ) {
									$count = count( $matches[0] );
									$shortcodes[] = '[' . esc_html( $tag ) . ']' . ( $count > 1 ? ' (' . $count . ')' : '' );
								}
							}
							$output = ! empty( $shortcodes ) ? implode( ', ', $shortcodes ) : '';
						}
					}
				}
				break;

			case 'before_more_tag':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$extended = get_extended( $post->post_content );
						if ( ! empty( $extended['extended'] ) ) {
							$output = esc_html( wp_trim_words( $extended['main'], 20 ) );
						}
					}
				}
				break;

			case 'estimated_reading_time':
				if ( $object_type === 'post' ) {
					$post = get_post( $object_id );
					if ( $post ) {
						$word_count = str_word_count( strip_tags( $post->post_content ) );
						$words_per_minute = 200;
						$minutes = ceil( $word_count / $words_per_minute );
						$output = '<strong>' . esc_html( (string) $minutes ) . ' ' . _n( 'min', 'mins', $minutes, 'wp-powersuite' ) . '</strong>';
					}
				}
				break;

			case 'attachment':
				if ( $object_type === 'post' ) {
					$attachments = get_attached_media( '', $object_id );
					if ( ! empty( $attachments ) ) {
						$first = reset( $attachments );
						$image = wp_get_attachment_image( $first->ID, [ 50, 50 ] );
						$output = $image ? $image : '';
					}
				}
				break;

			case 'attachment_count':
				if ( $object_type === 'post' ) {
					$attachments = get_attached_media( '', $object_id );
					$count = count( $attachments );
					$output = '<strong>' . esc_html( (string) $count ) . '</strong>';
				}
				break;

			case 'comments':
				if ( $object_type === 'post' ) {
					$comments = get_comments( [ 'post_id' => $object_id, 'count' => true ] );
					$output = '<strong>' . esc_html( (string) $comments ) . '</strong>';
				}
				break;

			case 'categories':
				if ( $object_type === 'post' ) {
					$categories = get_the_category( $object_id );
					if ( $categories && ! is_wp_error( $categories ) ) {
						$cat_names = array_map( function( $cat ) {
							return esc_html( $cat->name );
						}, $categories );
						$output = implode( ', ', $cat_names );
					}
				}
				break;

			case 'tags':
				if ( $object_type === 'post' ) {
					$tags = get_the_tags( $object_id );
					if ( $tags && ! is_wp_error( $tags ) ) {
						$tag_names = array_map( function( $tag ) {
							return esc_html( $tag->name );
						}, $tags );
						$output = implode( ', ', $tag_names );
					}
				}
				break;

			case 'first_name':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->first_name ) : '';
				}
				break;

			case 'last_name':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->last_name ) : '';
				}
				break;

			case 'nickname':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->nickname ) : '';
				}
				break;

			case 'nicename':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->user_nicename ) : '';
				}
				break;

			case 'display_name':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->display_name ) : '';
				}
				break;

			case 'full_name':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					if ( $user ) {
						$full_name = trim( $user->first_name . ' ' . $user->last_name );
						$output = ! empty( $full_name ) ? esc_html( $full_name ) : esc_html( $user->display_name );
					}
				}
				break;

			case 'url':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$url = $user ? $user->user_url : '';
					$output = $url ? '<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $url ) . '</a>' : '';
				}
				break;

			case 'posts':
				if ( $object_type === 'user' ) {
					$count = count_user_posts( $object_id );
					$output = '<strong>' . esc_html( (string) $count ) . '</strong>';
				}
				break;

			case 'first_post':
				if ( $object_type === 'user' ) {
					$posts = get_posts( [
						'author'      => $object_id,
						'numberposts' => 1,
						'orderby'     => 'date',
						'order'       => 'ASC',
					] );
					if ( ! empty( $posts ) ) {
						$post = $posts[0];
						$output = '<a href="' . esc_url( get_edit_post_link( $post->ID ) ) . '">' . esc_html( $post->post_title ) . '</a>';
					}
				}
				break;

			case 'last_post':
				if ( $object_type === 'user' ) {
					$posts = get_posts( [
						'author'      => $object_id,
						'numberposts' => 1,
						'orderby'     => 'date',
						'order'       => 'DESC',
					] );
					if ( ! empty( $posts ) ) {
						$post = $posts[0];
						$output = '<a href="' . esc_url( get_edit_post_link( $post->ID ) ) . '">' . esc_html( $post->post_title ) . '</a>';
					}
				}
				break;

			case 'description':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$output = $user ? esc_html( $user->description ) : '';
				} elseif ( $object_type === 'term' ) {
					$term = get_term( $object_id );
					$output = ( $term && ! is_wp_error( $term ) ) ? esc_html( $term->description ) : '';
				}
				break;

			case 'rich_editing':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$rich_editing = $user ? get_user_meta( $object_id, 'rich_editing', true ) : '';
					$output = $rich_editing === 'true' ? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>' : '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';
				}
				break;

			case 'show_toolbar':
				if ( $object_type === 'user' ) {
					$user = get_userdata( $object_id );
					$show_toolbar = $user ? get_user_meta( $object_id, 'show_admin_bar_front', true ) : '';
					$output = $show_toolbar === 'true' ? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>' : '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';
				}
				break;
		}

		return $output;
	}

	private function formatCustomFieldValue( $value, string $field_type ): string {
		if ( $value === null || $value === '' || $value === false ) {
			return '';
		}

		switch ( $field_type ) {
			case 'color':
				if ( preg_match( '/^#[a-f0-9]{6}$/i', $value ) ) {
					return '<span style="display:inline-block;width:20px;height:20px;background-color:' . esc_attr( $value ) . ';border:1px solid #ccc;vertical-align:middle;margin-right:5px;"></span>' . esc_html( $value );
				}
				return esc_html( (string) $value );

			case 'date':
				$timestamp = is_numeric( $value ) ? (int) $value : strtotime( $value );
				return $timestamp ? esc_html( date_i18n( get_option( 'date_format' ), $timestamp ) ) : esc_html( (string) $value );

			case 'image':
				if ( is_numeric( $value ) ) {
					$image = wp_get_attachment_image( (int) $value, [ 50, 50 ] );
					return $image ? $image : '';
				} elseif ( filter_var( $value, FILTER_VALIDATE_URL ) ) {
					return '<img src="' . esc_url( $value ) . '" style="max-width:50px;max-height:50px;" />';
				}
				return esc_html( (string) $value );

			case 'number':
				return is_numeric( $value ) ? esc_html( number_format_i18n( (float) $value ) ) : esc_html( (string) $value );

			case 'url':
				if ( filter_var( $value, FILTER_VALIDATE_URL ) ) {
					return '<a href="' . esc_url( $value ) . '" target="_blank">' . esc_html( $value ) . '</a>';
				}
				return esc_html( (string) $value );

			case 'true_false':
			case 'boolean':
				$bool = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
				return $bool ? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>' : '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';

			case 'array':
				if ( is_array( $value ) ) {
					return esc_html( implode( ', ', $value ) );
				}
				return esc_html( (string) $value );

			default:
				if ( is_array( $value ) ) {
					return esc_html( implode( ', ', $value ) );
				}
				return esc_html( (string) $value );
		}
	}

	private function renderMetaFieldValue( int $object_id, string $object_type, string $meta_key, string $field_type ): string {
		if ( function_exists( 'acf_get_field' ) && function_exists( 'get_field' ) ) {
			$acf_field = acf_get_field( $meta_key );
			if ( is_array( $acf_field ) && ! empty( $acf_field['type'] ) ) {
				$acf_object_id = $this->resolveAcfObjectId( $object_id, $object_type );
				$value         = get_field( $meta_key, $acf_object_id );
				return $this->formatAcfFieldValue( $value, $acf_field );
			}
		}

		if ( $object_type === 'term' ) {
			$value = get_term_meta( $object_id, $meta_key, true );
		} elseif ( $object_type === 'user' ) {
			$value = get_user_meta( $object_id, $meta_key, true );
		} else {
			$value = get_post_meta( $object_id, $meta_key, true );
		}

		return $this->formatCustomFieldValue( $value, $field_type );
	}

	/**
	 * @return int|string
	 */
	private function resolveAcfObjectId( int $object_id, string $object_type ) {
		if ( $object_type === 'term' ) {
			$term = get_term( $object_id );
			if ( $term && ! is_wp_error( $term ) ) {
				return $term->taxonomy . '_' . $object_id;
			}
		} elseif ( $object_type === 'user' ) {
			return 'user_' . $object_id;
		}

		return $object_id;
	}

	/**
	 * @param mixed                $value
	 * @param array<string, mixed> $field
	 */
	private function formatAcfFieldValue( $value, array $field ): string {
		if ( $value === null || $value === '' || $value === false ) {
			return '';
		}

		$type = (string) ( $field['type'] ?? 'text' );

		switch ( $type ) {
			case 'image':
				if ( is_array( $value ) && ! empty( $value['ID'] ) ) {
					$image = wp_get_attachment_image( (int) $value['ID'], [ 50, 50 ] );
					return $image ? $image : '';
				}
				if ( is_numeric( $value ) ) {
					$image = wp_get_attachment_image( (int) $value, [ 50, 50 ] );
					return $image ? $image : '';
				}
				if ( is_string( $value ) && filter_var( $value, FILTER_VALIDATE_URL ) ) {
					return '<img src="' . esc_url( $value ) . '" style="max-width:50px;max-height:50px;" alt="" />';
				}
				break;

			case 'file':
				if ( is_array( $value ) && ! empty( $value['url'] ) ) {
					$label = ! empty( $value['title'] ) ? (string) $value['title'] : (string) $value['url'];
					return '<a href="' . esc_url( (string) $value['url'] ) . '" target="_blank" rel="noopener">' . esc_html( $label ) . '</a>';
				}
				break;

			case 'gallery':
				if ( is_array( $value ) ) {
					$images = [];
					foreach ( $value as $item ) {
						$id = is_array( $item ) ? (int) ( $item['ID'] ?? 0 ) : (int) $item;
						if ( $id ) {
							$image = wp_get_attachment_image( $id, [ 40, 40 ] );
							if ( $image ) {
								$images[] = $image;
							}
						}
					}
					return implode( ' ', $images );
				}
				break;

			case 'link':
				if ( is_array( $value ) && ! empty( $value['url'] ) ) {
					$label = ! empty( $value['title'] ) ? (string) $value['title'] : (string) $value['url'];
					return '<a href="' . esc_url( (string) $value['url'] ) . '" target="_blank" rel="noopener">' . esc_html( $label ) . '</a>';
				}
				break;

			case 'post_object':
			case 'page_link':
				if ( is_object( $value ) && isset( $value->ID ) ) {
					return esc_html( get_the_title( (int) $value->ID ) );
				}
				if ( is_numeric( $value ) ) {
					return esc_html( get_the_title( (int) $value ) );
				}
				if ( is_array( $value ) ) {
					$titles = array_map(
						static function ( $item ) {
							if ( is_object( $item ) && isset( $item->ID ) ) {
								return get_the_title( (int) $item->ID );
							}
							if ( is_numeric( $item ) ) {
								return get_the_title( (int) $item );
							}
							return '';
						},
						$value
					);
					return esc_html( implode( ', ', array_filter( $titles ) ) );
				}
				break;

			case 'relationship':
			case 'taxonomy':
				if ( is_array( $value ) ) {
					$names = [];
					foreach ( $value as $item ) {
						if ( is_object( $item ) && isset( $item->name ) ) {
							$names[] = (string) $item->name;
						} elseif ( is_numeric( $item ) ) {
							$term = get_term( (int) $item );
							if ( $term && ! is_wp_error( $term ) ) {
								$names[] = $term->name;
							}
						}
					}
					return esc_html( implode( ', ', $names ) );
				}
				if ( is_object( $value ) && isset( $value->name ) ) {
					return esc_html( (string) $value->name );
				}
				break;

			case 'user':
				if ( is_array( $value ) ) {
					$names = [];
					foreach ( $value as $item ) {
						if ( is_object( $item ) && isset( $item->display_name ) ) {
							$names[] = (string) $item->display_name;
						} elseif ( is_numeric( $item ) ) {
							$user = get_userdata( (int) $item );
							if ( $user ) {
								$names[] = $user->display_name;
							}
						}
					}
					return esc_html( implode( ', ', $names ) );
				}
				if ( is_object( $value ) && isset( $value->display_name ) ) {
					return esc_html( (string) $value->display_name );
				}
				break;

			case 'true_false':
				return ! empty( $value )
					? '<span class="dashicons dashicons-yes-alt" style="color:#00a32a;"></span>'
					: '<span class="dashicons dashicons-dismiss" style="color:#d63638;"></span>';

			case 'color_picker':
				if ( is_string( $value ) && preg_match( '/^#[a-f0-9]{6}$/i', $value ) ) {
					return '<span style="display:inline-block;width:20px;height:20px;background-color:' . esc_attr( $value ) . ';border:1px solid #ccc;vertical-align:middle;margin-right:5px;"></span>' . esc_html( $value );
				}
				break;

			case 'date_picker':
			case 'date_time_picker':
			case 'time_picker':
				$timestamp = is_numeric( $value ) ? (int) $value : strtotime( (string) $value );
				if ( $timestamp ) {
					$format = $type === 'time_picker' ? get_option( 'time_format' ) : get_option( 'date_format' );
					if ( $type === 'date_time_picker' ) {
						$format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
					}
					return esc_html( date_i18n( $format, $timestamp ) );
				}
				break;

			case 'checkbox':
			case 'select':
				if ( is_array( $value ) ) {
					return esc_html( implode( ', ', $value ) );
				}
				break;

			case 'google_map':
				if ( is_array( $value ) && ! empty( $value['address'] ) ) {
					return esc_html( (string) $value['address'] );
				}
				break;

			case 'oembed':
				if ( is_string( $value ) && filter_var( $value, FILTER_VALIDATE_URL ) ) {
					return '<a href="' . esc_url( $value ) . '" target="_blank" rel="noopener">' . esc_html( $value ) . '</a>';
				}
				break;
		}

		if ( is_array( $value ) ) {
			if ( isset( $value['label'] ) ) {
				return esc_html( (string) $value['label'] );
			}
			return esc_html( implode( ', ', array_map( 'strval', $value ) ) );
		}

		if ( is_object( $value ) ) {
			if ( isset( $value->post_title ) ) {
				return esc_html( (string) $value->post_title );
			}
			if ( isset( $value->name ) ) {
				return esc_html( (string) $value->name );
			}
		}

		return $this->formatCustomFieldValue( $value, $type );
	}

	private function sanitizeScreenType( string $screen_type ): string {
		return ScreenSupport::sanitizeScreenType( $screen_type );
	}

	private function validateEditorScreen( string $screen_type, string $screen_id ): bool {
		return ScreenSupport::isSupportedEditorScreen( $screen_type, $screen_id );
	}

	private function getAssetUrl( string $filename ): string {
		$plugin_url = defined( 'WP_POWERSUITE_PLUGIN_URL' ) ? WP_POWERSUITE_PLUGIN_URL : '';
		$base_url = $plugin_url . 'modules/' . self::MODULE_ID . '/assets/';
		return $base_url . $filename;
	}

	private function getSettings(): array {
		$settings = $this->moduleSettings()->all( [] );
		if ( ! is_array( $settings ) ) {
			$settings = [];
		}

		return array_merge( $this->getDefaultSettings(), $settings );
	}

	private function getDefaultSettings(): array {
		return [
			'column_configs' => [],
		];
	}

	private function getDefaultSortableColumns( string $screen_type, string $screen_id ): array {
		if ( $screen_type === 'post_type' ) {
			if ( $screen_id === 'comments' ) {
				return [ 'author', 'date', 'response' ];
			} elseif ( $screen_id === 'post' ) {
				return [ 'title', 'date', 'comments', 'author' ];
			} elseif ( $screen_id === 'page' ) {
				return [ 'title', 'date', 'author' ];
			} else {
				return [ 'title', 'date', 'author' ];
			}
		} elseif ( $screen_type === 'user' ) {
			return [ 'username', 'name', 'email', 'role', 'posts' ];
		} elseif ( $screen_type === 'taxonomy' ) {
			return [ 'name', 'slug', 'posts' ];
		}

		return [];
	}

	/**
	 * @param array<int, mixed> $columns
	 * @return array<int, array<string, mixed>>
	 */
	private function sanitizeColumnsForStorage( array $columns, string $screen_type, string $screen_id ): array {
		$sanitized_columns = [];

		foreach ( $columns as $column ) {
			if ( ! is_array( $column ) ) {
				continue;
			}

			$key = sanitize_key( $column['key'] ?? '' );
			if ( $key === '' ) {
				continue;
			}

			$width = null;
			if ( isset( $column['width'] ) && $column['width'] !== '' && $column['width'] !== null && $column['width'] !== 'auto' ) {
				$width_value = $column['width'];
				if ( is_string( $width_value ) && ( strpos( $width_value, 'px' ) !== false || strpos( $width_value, '%' ) !== false ) ) {
					$width = sanitize_text_field( $width_value );
				} elseif ( is_numeric( $width_value ) ) {
					$width = absint( $width_value ) . 'px';
				}
			}

			$sortable = ScreenSupport::supportsSortableConfig( $screen_type, $screen_id ) && ! empty( $column['sortable'] );

			$column_row = [
				'key'         => $key,
				'label'       => sanitize_text_field( $column['label'] ?? '' ),
				'hidden'      => ! empty( $column['hidden'] ),
				'custom'      => ! empty( $column['custom'] ),
				'type'        => sanitize_text_field( $column['type'] ?? '' ),
				'meta_key'    => sanitize_text_field( $column['meta_key'] ?? '' ),
				'field_type'  => sanitize_text_field( $column['field_type'] ?? '' ),
				'taxonomy'    => sanitize_text_field( $column['taxonomy'] ?? '' ),
				'sortable'    => $sortable,
				'force_width' => ! empty( $column['force_width'] ),
				'css_class'   => sanitize_text_field( $column['css_class'] ?? '' ),
			];

			if ( $width !== null ) {
				$column_row['width'] = $width;
			}

			$sanitized_columns[] = $column_row;
		}

		return $sanitized_columns;
	}

	/**
	 * Normalize column payloads so save comparisons match stored OptionStore values.
	 *
	 * @param array<int, mixed> $columns
	 * @return array<int, array<string, mixed>>
	 */
	private function normalizeColumnsForSaveCompare( array $columns ): array {
		$normalized = [];

		foreach ( $columns as $column ) {
			if ( ! is_array( $column ) ) {
				continue;
			}

			$key = sanitize_key( $column['key'] ?? '' );
			if ( $key === '' ) {
				continue;
			}

			$row = [
				'key'         => $key,
				'label'       => sanitize_text_field( $column['label'] ?? '' ),
				'hidden'      => ! empty( $column['hidden'] ),
				'custom'      => ! empty( $column['custom'] ),
				'type'        => sanitize_text_field( $column['type'] ?? '' ),
				'meta_key'    => sanitize_text_field( $column['meta_key'] ?? '' ),
				'field_type'  => sanitize_text_field( $column['field_type'] ?? '' ),
				'taxonomy'    => sanitize_text_field( $column['taxonomy'] ?? '' ),
				'sortable'    => ! empty( $column['sortable'] ),
				'force_width' => ! empty( $column['force_width'] ),
				'css_class'   => sanitize_text_field( $column['css_class'] ?? '' ),
			];

			if ( ! empty( $column['width'] ) && $column['width'] !== 'auto' ) {
				$row['width'] = sanitize_text_field( (string) $column['width'] );
			}

			$normalized[] = $row;
		}

		return $normalized;
	}

	public function handleSaveColumnConfig(): void {
		try {
			check_ajax_referer( 'wpps_admin_columns', 'nonce' );

			if ( ! $this->canManagePlugin() ) {
				wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
				return;
			}

			$screen_type = sanitize_text_field( $_POST['screen_type'] ?? '' );
			$screen_id = sanitize_text_field( $_POST['screen_id'] ?? '' );
			
			$columns_json = isset( $_POST['columns'] ) ? wp_unslash( $_POST['columns'] ) : '[]';
			$columns = json_decode( $columns_json, true );
			
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				wp_send_json_error( [ 'message' => __( 'Invalid column data format.', 'wp-powersuite' ) ] );
				return;
			}

			if ( ! is_array( $columns ) ) {
				$columns = [];
			}

			if ( ! $this->validateEditorScreen( $screen_type, $screen_id ) ) {
				wp_send_json_error( [ 'message' => __( 'Invalid screen type or ID.', 'wp-powersuite' ) ] );
				return;
			}

			$config_key = ScreenSupport::configKey( $screen_type, $screen_id );

			$module_settings = $this->getModuleSettings();
			if ( ! isset( $module_settings['column_configs'] ) || ! is_array( $module_settings['column_configs'] ) ) {
				$module_settings['column_configs'] = [];
			}

			$sanitized_columns = $this->sanitizeColumnsForStorage( $columns, $screen_type, $screen_id );

			$config_entry = $module_settings['column_configs'][ $config_key ] ?? [];
			if ( ! is_array( $config_entry ) ) {
				$config_entry = [];
			}

			$existing_columns = $this->normalizeColumnsForSaveCompare(
				is_array( $config_entry['columns'] ?? null ) ? $config_entry['columns'] : []
			);
			$existing_layout  = ListTableEnhancements::normalizeLayout( $config_entry['layout'] ?? [] );

			$layout_json    = isset( $_POST['layout'] ) ? wp_unslash( $_POST['layout'] ) : '';
			$new_layout     = $existing_layout;
			$layout_changed = false;
			if ( ScreenSupport::supportsLayoutSettings( $screen_type, $screen_id ) && is_string( $layout_json ) && $layout_json !== '' ) {
				$layout_data = json_decode( $layout_json, true );
				if ( is_array( $layout_data ) ) {
					$new_layout     = ListTableEnhancements::sanitizeLayoutInput( $layout_data );
					$layout_changed = wp_json_encode( $existing_layout ) !== wp_json_encode( $new_layout );
				}
			}

			if ( $sanitized_columns === [] && ! empty( $config_entry['columns'] ) && is_array( $config_entry['columns'] ) ) {
				$sanitized_columns = $this->normalizeColumnsForSaveCompare( $config_entry['columns'] );
			}

			$config_entry['columns'] = $sanitized_columns;
			$config_entry['layout']  = $new_layout;
			$module_settings['column_configs'][ $config_key ] = $config_entry;

			$columns_changed = wp_json_encode( $existing_columns ) !== wp_json_encode(
				$this->normalizeColumnsForSaveCompare( $sanitized_columns )
			);
			if ( ! $columns_changed && ! $layout_changed ) {
				wp_send_json_success( [
					'message'    => __( 'No changes were made.', 'wp-powersuite' ),
					'no_changes' => true,
				] );
				return;
			}

			$success = $this->moduleSettings()->save( $module_settings );

			if ( ! $success ) {
				wp_send_json_error( [ 'message' => __( 'Failed to save column configuration.', 'wp-powersuite' ) ] );
				return;
			}

			wp_send_json_success( [ 'message' => __( 'Column configuration saved successfully.', 'wp-powersuite' ) ] );
		} catch ( \Exception $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Save Error', $e );
			wp_send_json_error( [ 'message' => __( 'An error occurred while saving. Please try again.', 'wp-powersuite' ) ] );
		} catch ( \Error $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Save Fatal Error', $e );
			wp_send_json_error( [ 'message' => $this->handlerFatalErrorMessage() ] );
		}
	}

	public function handleGetColumnConfig(): void {
		check_ajax_referer( 'wpps_admin_columns', 'nonce' );

		if ( ! $this->canManagePlugin() ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
		}

		$screen_type = sanitize_text_field( $_GET['screen_type'] ?? '' );
		$screen_id = sanitize_text_field( $_GET['screen_id'] ?? '' );

		if ( ! $this->validateEditorScreen( $screen_type, $screen_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid screen type or ID.', 'wp-powersuite' ) ] );
		}

		$config_key = ScreenSupport::configKey( $screen_type, $screen_id );

		$settings = $this->getSettings();
		$saved_config = $settings['column_configs'][ $config_key ] ?? null;

		$default_columns = $this->getDefaultColumns( $screen_type, $screen_id );
		if ( ! empty( $saved_config['list_snapshot'] ) && is_array( $saved_config['list_snapshot'] ) && $screen_type === 'post_type' ) {
			foreach ( $saved_config['list_snapshot'] as $key => $label ) {
				if ( ! isset( $default_columns[ $key ] ) && $key !== 'cb' ) {
					$default_columns[ $key ] = $label;
				}
			}
		}
		$default_sortable = $this->getDefaultSortableColumns( $screen_type, $screen_id );
		$columns = [];
		$layout  = ListTableEnhancements::normalizeLayout(
			is_array( $saved_config ) ? ( $saved_config['layout'] ?? [] ) : []
		);

		if ( $saved_config && ! empty( $saved_config['columns'] ) ) {
			$saved_keys = array_column( $saved_config['columns'], 'key' );
			foreach ( $saved_config['columns'] as $saved_col ) {
				if ( ! isset( $saved_col['sortable'] ) && ! empty( $saved_col['key'] ) ) {
					$saved_col['sortable'] = in_array( $saved_col['key'], $default_sortable, true );
				}
				$columns[] = $saved_col;
			}
			foreach ( $default_columns as $key => $label ) {
				if ( $key === 'cb' ) {
					continue;
				}
				
				if ( ! in_array( $key, $saved_keys, true ) ) {
					$clean_label = strip_tags( $label );
					if ( empty( $clean_label ) ) {
						switch ( $key ) {
							case 'comments':
								$clean_label = __( 'Comments', 'wp-powersuite' );
								break;
							default:
								$clean_label = ucfirst( str_replace( [ '_', '-' ], ' ', $key ) );
						}
					}
					$is_plugin_extra = ! empty( $saved_config['extra_columns'][ $key ] );
					$columns[] = [
						'key'      => $key,
						'label'    => $clean_label,
						'hidden'   => false,
						'custom'   => false,
						'sortable' => in_array( $key, $default_sortable, true ),
						'plugin'   => $is_plugin_extra,
					];
				}
			}
		} else {
			foreach ( $default_columns as $key => $label ) {
				if ( $key === 'cb' ) {
					continue;
				}
				
				$clean_label = strip_tags( $label );
				if ( empty( $clean_label ) ) {
					switch ( $key ) {
						case 'comments':
							$clean_label = __( 'Comments', 'wp-powersuite' );
							break;
						default:
							$clean_label = ucfirst( str_replace( [ '_', '-' ], ' ', $key ) );
					}
				}
				$columns[] = [
					'key'      => $key,
					'label'    => $clean_label,
					'hidden'   => false,
					'custom'   => false,
					'sortable' => in_array( $key, $default_sortable, true ),
				];
			}
		}

		wp_send_json_success(
			[
				'config' => [
					'columns'        => $this->normalizeColumnsForEditor( $columns, $screen_type, $screen_id ),
					'layout'         => $layout,
					'extra_columns'  => is_array( $saved_config ) ? ( $saved_config['extra_columns'] ?? [] ) : [],
					'has_list_visit' => is_array( $saved_config ) && ! empty( $saved_config['list_snapshot'] ),
				],
			]
		);
	}

	/**
	 * @param array<int, array<string, mixed>> $columns
	 * @return array<int, array<string, mixed>>
	 */
	private function normalizeColumnsForEditor( array $columns, string $screen_type, string $screen_id ): array {
		if ( ScreenSupport::supportsSortableConfig( $screen_type, $screen_id ) ) {
			return $columns;
		}

		foreach ( $columns as $index => $column ) {
			if ( is_array( $column ) ) {
				$columns[ $index ]['sortable'] = false;
			}
		}

		return $columns;
	}

	private function getDefaultColumns( string $screen_type, string $screen_id ): array {
		$default_columns = [];

		if ( $screen_type === 'post_type' ) {
			if ( $screen_id === 'comments' ) {
				$default_columns = [
					'cb'       => '<input type="checkbox" />',
					'author'   => __( 'Author', 'wp-powersuite' ),
					'comment'  => __( 'Comment', 'wp-powersuite' ),
					'response' => __( 'In Response To', 'wp-powersuite' ),
					'date'     => __( 'Submitted on', 'wp-powersuite' ),
				];
				$columns = apply_filters( 'manage_edit-comments_columns', $default_columns );
				if ( empty( $columns ) || ! is_array( $columns ) ) {
					$columns = $default_columns;
				}
			} elseif ( $screen_id === 'post' ) {
				$default_columns = [
					'cb'          => '<input type="checkbox" />',
					'title'       => __( 'Title', 'wp-powersuite' ),
					'author'      => __( 'Author', 'wp-powersuite' ),
					'categories'  => __( 'Categories', 'wp-powersuite' ),
					'tags'        => __( 'Tags', 'wp-powersuite' ),
					'comments'    => '<span class="vers comment-grey-bubble" title="Comments"><span class="screen-reader-text">Comments</span></span>',
					'date'        => __( 'Date', 'wp-powersuite' ),
				];
				$hook = 'manage_posts_columns';
				$columns = apply_filters( $hook, $default_columns );
				if ( empty( $columns ) || ! is_array( $columns ) ) {
					$columns = $default_columns;
				}
			} elseif ( $screen_id === 'page' ) {
				$default_columns = [
					'cb'          => '<input type="checkbox" />',
					'title'       => __( 'Title', 'wp-powersuite' ),
					'author'      => __( 'Author', 'wp-powersuite' ),
					'comments'    => '<span class="vers comment-grey-bubble" title="Comments"><span class="screen-reader-text">Comments</span></span>',
					'date'        => __( 'Date', 'wp-powersuite' ),
				];
				$hook = 'manage_pages_columns';
				$columns = apply_filters( $hook, $default_columns );
				if ( empty( $columns ) || ! is_array( $columns ) ) {
					$columns = $default_columns;
				}
			} elseif ( $screen_id === 'attachment' ) {
				$default_columns = [
					'cb'          => '<input type="checkbox" />',
					'title'       => __( 'File', 'wp-powersuite' ),
					'author'      => __( 'Author', 'wp-powersuite' ),
					'parent'      => __( 'Uploaded to', 'wp-powersuite' ),
					'comments'    => '<span class="vers comment-grey-bubble" title="Comments"><span class="screen-reader-text">Comments</span></span>',
					'date'        => __( 'Date', 'wp-powersuite' ),
				];
				$hook = 'manage_media_columns';
				$columns = apply_filters( $hook, $default_columns );
				if ( empty( $columns ) || ! is_array( $columns ) ) {
					$columns = $default_columns;
				}
			} else {
				$post_type_obj = get_post_type_object( $screen_id );
				if ( $post_type_obj ) {
					$default_columns = [
						'cb'          => '<input type="checkbox" />',
						'title'       => __( 'Title', 'wp-powersuite' ),
						'author'      => __( 'Author', 'wp-powersuite' ),
						'date'        => __( 'Date', 'wp-powersuite' ),
					];
					if ( post_type_supports( $screen_id, 'comments' ) ) {
						$default_columns['comments'] = '<span class="vers comment-grey-bubble" title="Comments"><span class="screen-reader-text">Comments</span></span>';
					}
					$hook = "manage_{$screen_id}_posts_columns";
					$columns = apply_filters( $hook, $default_columns );
					if ( empty( $columns ) || ! is_array( $columns ) ) {
						$columns = $default_columns;
					}
				} else {
					$columns = [];
				}
			}
		} elseif ( $screen_type === 'user' ) {
			$default_columns = [
				'cb'         => '<input type="checkbox" />',
				'username'   => __( 'Username', 'wp-powersuite' ),
				'name'       => __( 'Name', 'wp-powersuite' ),
				'email'      => __( 'Email', 'wp-powersuite' ),
				'role'       => __( 'Role', 'wp-powersuite' ),
				'posts'      => __( 'Posts', 'wp-powersuite' ),
			];
			$columns = apply_filters( 'manage_users_columns', $default_columns );
			if ( empty( $columns ) || ! is_array( $columns ) ) {
				$columns = $default_columns;
			}
		} elseif ( $screen_type === 'taxonomy' ) {
			$taxonomy_obj = get_taxonomy( $screen_id );
			if ( $taxonomy_obj ) {
				$default_columns = [
					'cb'          => '<input type="checkbox" />',
					'name'        => __( 'Name', 'wp-powersuite' ),
					'description' => __( 'Description', 'wp-powersuite' ),
					'slug'        => __( 'Slug', 'wp-powersuite' ),
					'posts'       => __( 'Count', 'wp-powersuite' ),
				];
				$columns = apply_filters( "manage_edit-{$screen_id}_columns", $default_columns );
				if ( empty( $columns ) || ! is_array( $columns ) ) {
					$columns = $default_columns;
				}
			} else {
				$columns = [];
			}
		} else {
			$columns = [];
		}

		return is_array( $columns ) ? $columns : [];
	}

	public function handleGetColumnTypes(): void {
		check_ajax_referer( 'wpps_admin_columns', 'nonce' );

		if ( ! $this->canManagePlugin() ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
		}

		$screen_type = sanitize_text_field( $_GET['screen_type'] ?? '' );
		$screen_id   = sanitize_text_field( $_GET['screen_id'] ?? '' );

		if ( ! $this->validateEditorScreen( $screen_type, $screen_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid screen type or ID.', 'wp-powersuite' ) ] );
		}

		$column_types = $this->getAvailableColumnTypes( $screen_type, $screen_id );

		wp_send_json_success( [ 'column_types' => $column_types ] );
	}

	public function handleGetCustomFields(): void {
		check_ajax_referer( 'wpps_admin_columns', 'nonce' );

		if ( ! $this->canManagePlugin() ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
		}

		$screen_type = sanitize_text_field( $_GET['screen_type'] ?? '' );
		$screen_id   = sanitize_text_field( $_GET['screen_id'] ?? '' );

		if ( ! $this->validateEditorScreen( $screen_type, $screen_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid screen type or ID.', 'wp-powersuite' ) ] );
		}

		$custom_fields = $this->getAvailableCustomFields( $screen_type, $screen_id );

		wp_send_json_success( [ 'custom_fields' => $custom_fields ] );
	}

	/**
	 * @return list<array{slug: string, label: string}>
	 */
	private function getScreenTaxonomyOptions( string $screen_type, string $screen_id ): array {
		if ( $screen_type !== 'post_type' || in_array( $screen_id, [ 'comments', 'attachment' ], true ) || ! post_type_exists( $screen_id ) ) {
			return [];
		}

		$options = [];
		foreach ( get_object_taxonomies( $screen_id, 'objects' ) as $tax ) {
			if ( ! ScreenSupport::isManageableTaxonomy( $tax->name ) ) {
				continue;
			}
			$options[] = [
				'slug'  => $tax->name,
				'label' => $tax->labels->name,
			];
		}

		return $options;
	}

	private function getAvailableColumnTypes( string $screen_type, string $screen_id = '' ): array {
		$types = [];

		if ( $screen_type === 'post_type' && $screen_id === 'comments' ) {
			$types = [
				'id'          => __( 'ID', 'wp-powersuite' ),
				'author'      => __( 'Author', 'wp-powersuite' ),
				'comment'     => __( 'Comment', 'wp-powersuite' ),
				'response'    => __( 'In Response To', 'wp-powersuite' ),
				'date'        => __( 'Submitted on', 'wp-powersuite' ),
				'custom_field' => __( 'Custom Field', 'wp-powersuite' ),
			];
		} elseif ( $screen_type === 'post_type' && $screen_id === 'attachment' ) {
			$types = [
				'id'           => __( 'ID', 'wp-powersuite' ),
				'title'        => __( 'File', 'wp-powersuite' ),
				'author'       => __( 'Author', 'wp-powersuite' ),
				'post_parent'  => __( 'Uploaded to', 'wp-powersuite' ),
				'date'         => __( 'Date', 'wp-powersuite' ),
				'custom_field' => __( 'Custom Field', 'wp-powersuite' ),
			];
		} elseif ( $screen_type === 'post_type' ) {
			$types = [
				'id'                  => __( 'ID', 'wp-powersuite' ),
				'title'               => __( 'Title', 'wp-powersuite' ),
				'author'               => __( 'Author', 'wp-powersuite' ),
				'date'                 => __( 'Date Published', 'wp-powersuite' ),
				'date_modified'        => __( 'Date Modified', 'wp-powersuite' ),
				'featured_image'       => __( 'Featured Image', 'wp-powersuite' ),
				'excerpt'              => __( 'Excerpt', 'wp-powersuite' ),
				'content'              => __( 'Content', 'wp-powersuite' ),
				'comment_count'        => __( 'Comment Count', 'wp-powersuite' ),
				'comment_status'       => __( 'Allow Comments', 'wp-powersuite' ),
				'comments'             => __( 'Comments', 'wp-powersuite' ),
				'word_count'           => __( 'Word Count', 'wp-powersuite' ),
				'estimated_reading_time' => __( 'Estimated Reading Time', 'wp-powersuite' ),
				'status'               => __( 'Status', 'wp-powersuite' ),
				'slug'                 => __( 'Slug', 'wp-powersuite' ),
				'permalink'            => __( 'Permalink', 'wp-powersuite' ),
				'shortlink'            => __( 'Shortlink', 'wp-powersuite' ),
				'path'                 => __( 'Path', 'wp-powersuite' ),
				'page_template'        => __( 'Page Template', 'wp-powersuite' ),
				'post_parent'          => __( 'Parent', 'wp-powersuite' ),
				'depth'                => __( 'Depth', 'wp-powersuite' ),
				'order'                => __( 'Order', 'wp-powersuite' ),
				'post_format'          => __( 'Post Format', 'wp-powersuite' ),
				'sticky'               => __( 'Sticky', 'wp-powersuite' ),
				'password_protected'   => __( 'Password Protected', 'wp-powersuite' ),
				'ping_status'          => __( 'Ping Status', 'wp-powersuite' ),
				'before_more_tag'      => __( 'Before More Tag', 'wp-powersuite' ),
				'shortcodes'           => __( 'Shortcodes', 'wp-powersuite' ),
				'attachment'           => __( 'Attachment', 'wp-powersuite' ),
				'attachment_count'     => __( 'Attachment Count', 'wp-powersuite' ),
				'taxonomy'             => __( 'Taxonomy', 'wp-powersuite' ),
				'categories'           => __( 'Categories', 'wp-powersuite' ),
				'tags'                 => __( 'Tags', 'wp-powersuite' ),
				'custom_field'         => __( 'Custom Field', 'wp-powersuite' ),
			];
			$types = $this->filterPostTypeColumnTypes( $types, $screen_id );
		} elseif ( $screen_type === 'user' ) {
			$types = [
				'id'              => __( 'ID', 'wp-powersuite' ),
				'username'        => __( 'Username', 'wp-powersuite' ),
				'name'            => __( 'Name', 'wp-powersuite' ),
				'display_name'    => __( 'Display Name', 'wp-powersuite' ),
				'full_name'       => __( 'Full Name', 'wp-powersuite' ),
				'first_name'      => __( 'First Name', 'wp-powersuite' ),
				'last_name'       => __( 'Last Name', 'wp-powersuite' ),
				'nickname'        => __( 'Nickname', 'wp-powersuite' ),
				'nicename'        => __( 'Nicename', 'wp-powersuite' ),
				'email'           => __( 'Email', 'wp-powersuite' ),
				'url'             => __( 'URL', 'wp-powersuite' ),
				'role'            => __( 'Role', 'wp-powersuite' ),
				'registered_date' => __( 'Registered Date', 'wp-powersuite' ),
				'post_count'      => __( 'Post Count', 'wp-powersuite' ),
				'posts'           => __( 'Posts', 'wp-powersuite' ),
				'first_post'      => __( 'First Post', 'wp-powersuite' ),
				'last_post'       => __( 'Last Post', 'wp-powersuite' ),
				'comment_count'   => __( 'Comment Count', 'wp-powersuite' ),
				'description'     => __( 'Description', 'wp-powersuite' ),
				'rich_editing'    => __( 'Rich Editing', 'wp-powersuite' ),
				'show_toolbar'    => __( 'Show Toolbar', 'wp-powersuite' ),
				'custom_field'    => __( 'Custom Field', 'wp-powersuite' ),
			];
		} elseif ( $screen_type === 'taxonomy' ) {
			$types = [
				'id'           => __( 'ID', 'wp-powersuite' ),
				'name'         => __( 'Name', 'wp-powersuite' ),
				'slug'         => __( 'Slug', 'wp-powersuite' ),
				'description'  => __( 'Description', 'wp-powersuite' ),
				'count'        => __( 'Count', 'wp-powersuite' ),
				'custom_field' => __( 'Custom Field', 'wp-powersuite' ),
			];
		}

		return $types;
	}

	/**
	 * Remove column types that do not apply to the current post type screen.
	 *
	 * @param array<string, string> $types
	 * @return array<string, string>
	 */
	private function filterPostTypeColumnTypes( array $types, string $screen_id ): array {
		if ( $screen_id !== 'page' ) {
			unset( $types['page_template'] );
		}

		if ( $screen_id !== 'post' ) {
			unset( $types['sticky'] );
		}

		if ( ! is_object_in_taxonomy( $screen_id, 'category' ) ) {
			unset( $types['categories'] );
		}

		if ( ! is_object_in_taxonomy( $screen_id, 'post_tag' ) ) {
			unset( $types['tags'] );
		}

		if ( empty( $this->getScreenTaxonomyOptions( 'post_type', $screen_id ) ) ) {
			unset( $types['taxonomy'] );
		}

		if ( ! post_type_supports( $screen_id, 'comments' ) ) {
			unset( $types['comments'], $types['comment_count'], $types['comment_status'] );
		}

		if ( ! post_type_supports( $screen_id, 'excerpt' ) ) {
			unset( $types['excerpt'] );
		}

		if ( ! post_type_supports( $screen_id, 'thumbnail' ) ) {
			unset( $types['featured_image'] );
		}

		if ( ! post_type_supports( $screen_id, 'page-attributes' ) ) {
			unset( $types['order'] );
		}

		$post_type_obj = get_post_type_object( $screen_id );
		if ( ! $post_type_obj || ! $post_type_obj->hierarchical ) {
			unset( $types['post_parent'], $types['depth'] );
		}

		return $types;
	}

	private function getAvailableCustomFields( string $screen_type, string $screen_id ): array {
		global $wpdb;

		$cache_key = 'wpps_custom_fields_' . $screen_type . '_' . $screen_id;
		$cached    = wp_cache_get( $cache_key, 'admin_columns_customizer' );
		if ( $cached !== false ) {
			return is_array( $cached ) ? $cached : [];
		}

		$fields = [];

		if ( $screen_type === 'post_type' ) {
			if ( in_array( $screen_id, [ 'comments', 'attachment' ], true ) || ! ScreenSupport::isManageablePostType( $screen_id ) ) {
				wp_cache_set( $cache_key, [], 'admin_columns_customizer', HOUR_IN_SECONDS );
				return [];
			}

			$post_ids = get_posts(
				[
					'post_type'              => $screen_id,
					'posts_per_page'         => 20,
					'post_status'            => 'any',
					'fields'                 => 'ids',
					'orderby'                => 'date',
					'order'                  => 'DESC',
					'no_found_rows'          => true,
					'update_post_meta_cache' => false,
					'update_post_term_cache' => false,
				]
			);

			if ( ! empty( $post_ids ) ) {
				$post_ids     = array_map( 'intval', $post_ids );
				$placeholders = implode( ',', array_fill( 0, count( $post_ids ), '%d' ) );
				$query        = $wpdb->prepare(
					"SELECT DISTINCT pm.meta_key FROM {$wpdb->postmeta} pm
					WHERE pm.post_id IN ($placeholders)
					AND pm.meta_key NOT LIKE %s
					AND pm.meta_key NOT LIKE %s
					ORDER BY pm.meta_key ASC
					LIMIT 200",
					array_merge(
						$post_ids,
						[
							$wpdb->esc_like( '_' ) . '%',
							$wpdb->esc_like( 'field_' ) . '%',
						]
					)
				);
				$fields = $wpdb->get_col( $query ) ?: [];
			}
		} elseif ( $screen_type === 'user' ) {
			$fields = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT DISTINCT meta_key FROM {$wpdb->usermeta}
					WHERE meta_key NOT LIKE %s
					ORDER BY meta_key ASC
					LIMIT 200",
					$wpdb->esc_like( '_' ) . '%'
				)
			) ?: [];
		} elseif ( $screen_type === 'taxonomy' && ScreenSupport::isManageableTaxonomy( $screen_id ) ) {
			$fields = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT DISTINCT tm.meta_key FROM {$wpdb->termmeta} tm
					INNER JOIN {$wpdb->term_taxonomy} tt ON tm.term_id = tt.term_id
					WHERE tm.meta_key NOT LIKE %s
					AND tt.taxonomy = %s
					ORDER BY tm.meta_key ASC
					LIMIT 200",
					$wpdb->esc_like( '_' ) . '%',
					$screen_id
				)
			) ?: [];
		}

		wp_cache_set( $cache_key, $fields, 'admin_columns_customizer', HOUR_IN_SECONDS );

		return $fields;
	}

	public function handleResetAllColumnConfig(): void {
		try {
			check_ajax_referer( 'wpps_admin_columns', 'nonce' );

			if ( ! $this->canManagePlugin() ) {
				wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
				return;
			}

			$module_settings = $this->moduleSettings()->all( [] );
			if ( ! is_array( $module_settings ) ) {
				$module_settings = [];
			}

			$module_settings['column_configs'] = [];

			$success = $this->moduleSettings()->save( $module_settings );

			if ( ! $success ) {
				wp_send_json_error( [ 'message' => __( 'Failed to reset all column configurations.', 'wp-powersuite' ) ] );
				return;
			}

			wp_send_json_success( [ 'message' => __( 'All column settings reset successfully.', 'wp-powersuite' ) ] );
		} catch ( \Exception $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Reset All Error', $e );
			wp_send_json_error( [ 'message' => __( 'An error occurred while resetting. Please try again.', 'wp-powersuite' ) ] );
		} catch ( \Error $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Reset All Fatal Error', $e );
			wp_send_json_error( [ 'message' => $this->handlerFatalErrorMessage() ] );
		}
	}

	public function handleRestoreColumnConfig(): void {
		try {
			check_ajax_referer( 'wpps_admin_columns', 'nonce' );

			if ( ! $this->canManagePlugin() ) {
				wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'wp-powersuite' ) ] );
				return;
			}

			$screen_type = sanitize_text_field( $_POST['screen_type'] ?? '' );
			$screen_id = sanitize_text_field( $_POST['screen_id'] ?? '' );

			if ( ! $this->validateEditorScreen( $screen_type, $screen_id ) ) {
				wp_send_json_error( [ 'message' => __( 'Invalid screen type or ID.', 'wp-powersuite' ) ] );
				return;
			}

			$config_key = ScreenSupport::configKey( $screen_type, $screen_id );

			$module_settings = $this->moduleSettings()->all( [] );
			if ( ! is_array( $module_settings ) ) {
				$module_settings = [];
			}

			if ( ! isset( $module_settings['column_configs'] ) || ! is_array( $module_settings['column_configs'] ) ) {
				$module_settings['column_configs'] = [];
			}

			unset( $module_settings['column_configs'][ $config_key ] );

			$success = $this->moduleSettings()->save( $module_settings );

			if ( ! $success ) {
				wp_send_json_error( [ 'message' => __( 'Failed to restore column configuration.', 'wp-powersuite' ) ] );
				return;
			}

			wp_send_json_success( [ 'message' => __( 'Columns restored to defaults successfully.', 'wp-powersuite' ) ] );
		} catch ( \Exception $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Restore Error', $e );
			wp_send_json_error( [ 'message' => __( 'An error occurred while restoring. Please try again.', 'wp-powersuite' ) ] );
		} catch ( \Error $e ) {
			$this->logHandlerThrowable( 'Admin Columns Customizer Restore Fatal Error', $e );
			wp_send_json_error( [ 'message' => $this->handlerFatalErrorMessage() ] );
		}
	}

	public function addManageColumnsButton(): void {
		if ( ! $this->isEnabled() ) {
			return;
		}

		$screen = get_current_screen();
		if ( ! $screen || ! $this->canManagePlugin() ) {
			return;
		}

		$config_key = $this->resolveListTableConfigKey( $screen );
		if ( $config_key === null ) {
			return;
		}

		if ( $screen->id === 'edit-comments' ) {
			$screen_type        = 'post_type';
			$screen_id_mapped   = 'comments';
		} elseif ( $screen->id === 'upload' ) {
			$screen_type        = 'post_type';
			$screen_id_mapped   = 'attachment';
		} elseif ( $screen->id === 'users' ) {
			$screen_type        = 'user';
			$screen_id_mapped   = 'users';
		} elseif ( strpos( $screen->id, 'edit-' ) === 0 && ! empty( $screen->taxonomy ) ) {
			$screen_type        = 'taxonomy';
			$screen_id_mapped   = $screen->taxonomy;
		} elseif ( strpos( $screen->id, 'edit-' ) === 0 ) {
			$screen_type        = 'post_type';
			$screen_id_mapped   = str_replace( 'edit-', '', $screen->id );
		} else {
			return;
		}

		$url = admin_url(
			'admin.php?page=powersuite-admin-columns-customizer&screen_type=' . rawurlencode( $screen_type ) . '&screen_id=' . rawurlencode( $screen_id_mapped )
		);

		$btn = '<a href="' . esc_url( $url ) . '" class="button wpps-manage-columns-btn">' . esc_html__( 'Manage Columns', 'wp-powersuite' ) . '</a>';

		add_action( 'admin_head', [ $this, 'printManageColumnsButtonStyles' ], 5 );

		add_action(
			'admin_footer',
			function () use ( $btn ) {
				$this->printManageColumnsButtonScript( $btn );
			}
		);
	}

	/**
	 * Inject Manage Columns after the Filter button in the top tablenav row.
	 */
	private function printManageColumnsButtonScript( string $btn ): void {
		$btn_js = str_replace( [ '\\', "'", "\n", "\r" ], [ '\\\\', "\\'", '', '' ], $btn );
		echo '<script type="text/javascript">';
		echo 'jQuery(function($){';
		echo 'if($("a.wpps-manage-columns-btn").length){return;}';
		echo 'var $tablenav=$(".tablenav.top").first();';
		echo 'if(!$tablenav.length){return;}';
		echo 'var btn=\'' . $btn_js . '\';';
		echo 'var $filterBtn=$tablenav.find(".alignleft.actions").last().find(\'input[type="submit"].button,button[type="submit"].button\').last();';
		echo 'if($filterBtn.length){$filterBtn.after(" "+btn);}else{$tablenav.find(".alignleft.actions").last().append(" "+btn);}';
		echo '});';
		echo '</script>';
	}

	public function printManageColumnsButtonStyles(): void {
		if ( ! $this->isEnabled() ) {
			return;
		}
		echo "<style id=\"wpps-manage-columns-btn-styles\">\n";
		echo ".tablenav.top .alignleft.actions .wpps-manage-columns-btn { margin-left: 4px; vertical-align: middle; }\n";
		echo "</style>\n";
	}

	public function getModuleSettings(): array {
		return $this->getSettings();
	}

	public function saveModuleSettings( array $settings ): bool {
		return (bool) $this->moduleSettings()->save( $settings );
	}

	/**
	 * @return array<string, mixed>
	 */
	public function getScreenConfig( string $screen_type, string $screen_id ): array {
		$config_key = ScreenSupport::configKey( $screen_type, $screen_id );
		$settings   = $this->getSettings();
		return $settings['column_configs'][ $config_key ] ?? [];
	}

	public function applyPostTypeColumnHooks( string $post_type, array $config ): void {
		$this->applyPostTypeColumns( $post_type, $config );
	}

	/**
	 * @return array<string, string>
	 */
	public function getDefaultColumnsPublic( string $screen_type, string $screen_id ): array {
		return $this->getDefaultColumns( $screen_type, $screen_id );
	}

	public function resolveListTableConfigKeyPublic( \WP_Screen $screen ): ?string {
		return $this->resolveListTableConfigKey( $screen );
	}

	public function resolveConfigKeyFromRequest(): ?string {
		global $pagenow;

		if ( $pagenow === 'edit-comments.php' ) {
			return 'post_type_comments';
		}

		if ( $pagenow === 'upload.php' ) {
			return 'post_type_attachment';
		}

		if ( $pagenow === 'users.php' ) {
			return 'users';
		}

		if ( $pagenow === 'edit-tags.php' ) {
			$taxonomy = isset( $_GET['taxonomy'] ) ? sanitize_key( wp_unslash( $_GET['taxonomy'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( $taxonomy !== '' && ScreenSupport::isManageableTaxonomy( $taxonomy ) ) {
				return 'taxonomy_' . $taxonomy;
			}
			return null;
		}

		if ( $pagenow === 'edit.php' ) {
			$post_type = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : 'post'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( ScreenSupport::isManageablePostType( $post_type ) ) {
				return 'post_type_' . $post_type;
			}
		}

		return null;
	}

	public function getAssetUrlPublic( string $filename ): string {
		return $this->getAssetUrl( $filename );
	}

	/**
	 * @param array<string, mixed> $config
	 */
	public function hasApplicableListConfig( array $config ): bool {
		if ( ! empty( $config['columns'] ) && is_array( $config['columns'] ) ) {
			return true;
		}

		$layout = ListTableEnhancements::normalizeLayout( $config['layout'] ?? [] );

		return ! empty( $layout['disable_horizontal_scroll'] )
			|| ! empty( $layout['freeze_first_columns'] )
			|| ! empty( $layout['freeze_header_row'] )
			|| ! empty( $layout['default_sort_column'] );
	}

	/**
	 * @param array<string, mixed> $config
	 */
	public function isValidDefaultSortColumn( string $post_type, string $column, array $config ): bool {
		$core = [ 'title', 'author', 'date', 'comments', 'menu_order', 'modified', 'parent' ];
		if ( in_array( $column, $core, true ) ) {
			return true;
		}

		foreach ( $config['columns'] ?? [] as $column_data ) {
			if ( ! is_array( $column_data ) || empty( $column_data['key'] ) ) {
				continue;
			}
			if ( $column_data['key'] === $column && ! empty( $column_data['sortable'] ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @return array<string, mixed>
	 */
	public function finalizeModuleSettingsSanitization( array $settings, string $module_id, string $context ): array {
		if ( $module_id !== self::MODULE_ID || empty( $settings['column_configs'] ) || ! is_array( $settings['column_configs'] ) ) {
			return $settings;
		}

		foreach ( $settings['column_configs'] as $config_key => $config ) {
			if ( ! is_array( $config ) ) {
				continue;
			}

			if ( isset( $config['layout'] ) && is_array( $config['layout'] ) ) {
				$settings['column_configs'][ $config_key ]['layout'] = ListTableEnhancements::normalizeLayout( $config['layout'] );
			}
		}

		return $settings;
	}

	private function listTableEnhancements(): ListTableEnhancements {
		if ( $this->list_table_enhancements === null ) {
			$this->list_table_enhancements = new ListTableEnhancements( $this );
		}

		return $this->list_table_enhancements;
	}

	/**
	 * Log handler failures only when WP_DEBUG is enabled (avoids stack traces on production).
	 */
	private function logHandlerThrowable( string $context, \Throwable $e ): void {
		if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
			return;
		}

		error_log( $context . ': ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	}

	private function handlerFatalErrorMessage(): string {
		return __( 'An error occurred. Please try again.', 'wp-powersuite' );
	}

}
