<?php
/**
 * Show IDs Module
 *
 * @package ShowIds
 * @since 1.0.0
 */

namespace ShowIds;

use WP_PowerSuite\Core\AbstractModule;

require_once __DIR__ . '/FeatureGate.php';

class Module extends AbstractModule {

	private const MODULE_ID      = 'show-ids';
	private const MODULE_VERSION = '1.3.1';
	private const COLUMN_NAME    = 'wpps_id';

	private ?array $settings_cache = null;

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

	public function getName(): string {
		return __( 'Show IDs', 'wp-powersuite' );
	}

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

	public function getDescription(): string {
		return __( 'Shows content and user IDs in list tables when you need quick reference numbers.', 'wp-powersuite' );
	}

	public function getContext(): string {
		return 'both';
	}

	protected function registerHooks(): void {
		add_filter( 'wp_powersuite_sanitize_module_settings', [ $this, 'filterSanitizeModuleSettings' ], 10, 3 );
		add_action( 'wp_powersuite_module_settings_saved', [ $this, 'onSettingsSaved' ], 10, 2 );

		$settings = $this->getSettings();

		if ( ! empty( $settings['show_frontend_admin_bar'] ) ) {
			add_action( 'admin_bar_menu', [ $this, 'addFrontendAdminBarId' ], 999 );
		}

		if ( ! is_admin() ) {
			return;
		}

		$enabled_post_types = $settings['enabled_post_types'] ?? [];
		if ( is_array( $enabled_post_types ) && $enabled_post_types !== [] ) {
			add_action( 'load-edit.php', [ $this, 'registerPostListHooks' ] );
		}

		if ( ! empty( $settings['show_taxonomy_ids'] ) ) {
			add_action( 'load-edit-tags.php', [ $this, 'registerTaxonomyListHooks' ] );
		}

		if ( ! empty( $settings['show_user_ids'] ) ) {
			add_action( 'load-users.php', [ $this, 'registerUsersListHooks' ] );
		}

		if ( ! empty( $settings['show_media_ids'] ) ) {
			add_action( 'load-upload.php', [ $this, 'registerMediaListHooks' ] );
		}

		if ( ! empty( $settings['show_comment_ids'] ) ) {
			add_action( 'load-edit-comments.php', [ $this, 'registerCommentsListHooks' ] );
		}
	}

	public function registerPostListHooks(): void {
		$settings           = $this->getSettings();
		$enabled_post_types = $settings['enabled_post_types'] ?? [];
		if ( ! is_array( $enabled_post_types ) || $enabled_post_types === [] ) {
			return;
		}

		$post_type = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( (string) $_GET['post_type'] ) ) : 'post';
		if ( $post_type === '' || ! in_array( $post_type, $enabled_post_types, true ) || ! post_type_exists( $post_type ) ) {
			return;
		}

		add_filter( $this->postsColumnsHook( $post_type ), [ $this, 'addIdColumn' ] );
		add_action( $this->postsCustomColumnHook( $post_type ), [ $this, 'displayPostId' ], 10, 2 );
		add_filter( $this->sortableColumnsHook( $post_type ), [ $this, 'makeIdColumnSortable' ] );

		if ( ! empty( $settings['show_id_in_action_row'] ) ) {
			add_filter( "{$post_type}_row_actions", [ $this, 'addIdInActionRow' ], 99, 2 );
		}

		$this->registerListColumnStyles();
	}

	public function registerTaxonomyListHooks(): void {
		$taxonomy = isset( $_GET['taxonomy'] ) ? sanitize_key( wp_unslash( (string) $_GET['taxonomy'] ) ) : '';
		if ( $taxonomy === '' || ! taxonomy_exists( $taxonomy ) ) {
			return;
		}

		$tax_object = get_taxonomy( $taxonomy );
		if ( ! $tax_object instanceof \WP_Taxonomy || ! $tax_object->public ) {
			return;
		}

		$settings = $this->getSettings();

		add_filter( "manage_edit-{$taxonomy}_columns", [ $this, 'addIdColumn' ] );
		add_filter( "manage_{$taxonomy}_custom_column", [ $this, 'displayTermId' ], 10, 3 );

		if ( ! empty( $settings['show_id_in_action_row'] ) ) {
			add_filter( "{$taxonomy}_row_actions", [ $this, 'addIdInActionRow' ], 99, 2 );
		}

		$this->registerListColumnStyles();
	}

	public function registerUsersListHooks(): void {
		$settings = $this->getSettings();

		add_filter( 'manage_users_columns', [ $this, 'addIdColumn' ] );
		add_filter( 'manage_users_custom_column', [ $this, 'displayUserId' ], 10, 3 );
		add_filter( 'manage_users_sortable_columns', [ $this, 'makeIdColumnSortable' ] );

		if ( ! empty( $settings['show_id_in_action_row'] ) ) {
			add_filter( 'user_row_actions', [ $this, 'addIdInActionRow' ], 99, 2 );
		}

		$this->registerListColumnStyles();
	}

	public function registerMediaListHooks(): void {
		$settings = $this->getSettings();

		add_filter( 'manage_media_columns', [ $this, 'addIdColumn' ] );
		add_action( 'manage_media_custom_column', [ $this, 'displayPostId' ], 10, 2 );
		add_filter( 'manage_upload_sortable_columns', [ $this, 'makeIdColumnSortable' ] );

		if ( ! empty( $settings['show_id_in_action_row'] ) ) {
			add_filter( 'media_row_actions', [ $this, 'addIdInActionRow' ], 99, 2 );
		}

		$this->registerListColumnStyles();
	}

	public function registerCommentsListHooks(): void {
		$settings = $this->getSettings();

		add_filter( 'manage_edit-comments_columns', [ $this, 'addIdColumn' ] );
		add_action( 'manage_comments_custom_column', [ $this, 'displayCommentId' ], 10, 2 );

		if ( ! empty( $settings['show_id_in_action_row'] ) ) {
			add_filter( 'comment_row_actions', [ $this, 'addIdInActionRow' ], 99, 2 );
		}

		$this->registerListColumnStyles();
	}

	private function registerListColumnStyles(): void {
		static $registered = false;

		if ( $registered ) {
			return;
		}

		$registered = true;
		add_action( 'admin_head', [ $this, 'addColumnStyles' ] );
	}

	private function postsColumnsHook( string $post_type ): string {
		if ( $post_type === 'post' ) {
			return 'manage_posts_columns';
		}
		if ( $post_type === 'page' ) {
			return 'manage_pages_columns';
		}

		return "manage_{$post_type}_posts_columns";
	}

	private function postsCustomColumnHook( string $post_type ): string {
		if ( $post_type === 'post' ) {
			return 'manage_posts_custom_column';
		}
		if ( $post_type === 'page' ) {
			return 'manage_pages_custom_column';
		}

		return "manage_{$post_type}_posts_custom_column";
	}

	private function sortableColumnsHook( string $post_type ): string {
		if ( $post_type === 'post' ) {
			return 'manage_edit-post_sortable_columns';
		}
		if ( $post_type === 'page' ) {
			return 'manage_edit-page_sortable_columns';
		}

		return "manage_edit-{$post_type}_sortable_columns";
	}

	/**
	 * @param array<string, string> $columns Existing columns.
	 * @return array<string, string>
	 */
	public function addIdColumn( array $columns ): array {
		if ( isset( $columns[ self::COLUMN_NAME ] ) ) {
			return $columns;
		}

		$new      = [];
		$inserted = false;
		$anchors  = [ 'title', 'name', 'username', 'comment' ];

		foreach ( $columns as $key => $label ) {
			if ( ! $inserted && in_array( $key, $anchors, true ) ) {
				$new[ self::COLUMN_NAME ] = __( 'ID', 'wp-powersuite' );
				$inserted                 = true;
			}

			$new[ $key ] = $label;
		}

		if ( ! $inserted ) {
			$new[ self::COLUMN_NAME ] = __( 'ID', 'wp-powersuite' );
		}

		return $new;
	}

	public function displayPostId( string $column_name, $post_id ): void {
		if ( $column_name === self::COLUMN_NAME ) {
			echo '<strong>' . esc_html( (string) (int) $post_id ) . '</strong>';
		}
	}

	public function displayTermId( string $content, string $column_name, $term_id ): string {
		if ( $column_name === self::COLUMN_NAME ) {
			return '<strong>' . esc_html( (string) (int) $term_id ) . '</strong>';
		}

		return $content;
	}

	public function displayUserId( string $content, string $column_name, $user_id ): string {
		if ( $column_name === self::COLUMN_NAME ) {
			return '<strong>' . esc_html( (string) (int) $user_id ) . '</strong>';
		}

		return $content;
	}

	public function displayCommentId( string $column_name, $comment_id ): void {
		if ( $column_name === self::COLUMN_NAME ) {
			echo '<strong>' . esc_html( (string) (int) $comment_id ) . '</strong>';
		}
	}

	/**
	 * @param array<string, string> $columns Sortable columns.
	 * @return array<string, string>
	 */
	public function makeIdColumnSortable( array $columns ): array {
		$columns[ self::COLUMN_NAME ] = 'ID';

		return $columns;
	}

	/**
	 * @param array<string, string> $actions Row actions.
	 * @param object              $object  List table row object.
	 * @return array<string, string>
	 */
	public function addIdInActionRow( array $actions, $object ): array {
		if ( ! current_user_can( 'edit_posts' ) ) {
			return $actions;
		}

		$id = $this->resolveObjectId( $object );
		if ( $id === null ) {
			return $actions;
		}

		$actions['wpps-list-table-item-id'] = sprintf(
			'<span class="wpps-list-table-item-id">%s</span>',
			esc_html(
				sprintf(
					/* translators: %d: object ID number */
					__( 'ID: %d', 'wp-powersuite' ),
					$id
				)
			)
		);

		return $actions;
	}

	public function addColumnStyles(): void {
		?>
		<style type="text/css">
			.wp-list-table .column-<?php echo esc_attr( self::COLUMN_NAME ); ?>,
			.wp-list-table th.column-<?php echo esc_attr( self::COLUMN_NAME ); ?>,
			.wp-list-table td.column-<?php echo esc_attr( self::COLUMN_NAME ); ?> {
				width: 60px;
				max-width: 60px;
				text-align: center;
			}
			.wp-list-table .column-<?php echo esc_attr( self::COLUMN_NAME ); ?> strong {
				font-weight: 600;
			}
			.row-actions .wpps-list-table-item-id {
				color: #50575e;
			}
		</style>
		<?php
	}

	public function addFrontendAdminBarId( \WP_Admin_Bar $wp_admin_bar ): void {
		if ( is_admin() ) {
			return;
		}

		$object_id   = null;
		$object_type = '';

		if ( is_singular() ) {
			global $post;
			if ( $post instanceof \WP_Post ) {
				$object_id   = $post->ID;
				$object_type = ucfirst( $post->post_type );
			}
		} elseif ( is_category() || is_tag() || is_tax() ) {
			$queried_object = get_queried_object();
			if ( $queried_object instanceof \WP_Term ) {
				$object_id   = $queried_object->term_id;
				$object_type = ucfirst( $queried_object->taxonomy );
			}
		} elseif ( is_author() ) {
			$author = get_queried_object();
			if ( $author instanceof \WP_User ) {
				$object_id   = $author->ID;
				$object_type = 'User';
			}
		}

		if ( $object_id === null ) {
			return;
		}

		$wp_admin_bar->add_node(
			[
				'id'     => 'wpps-show-id',
				'title'  => sprintf(
					'<span class="ab-label">%s ID: <strong>%d</strong></span>',
					esc_html( $object_type ),
					(int) $object_id
				),
				'parent' => 'top-secondary',
				'meta'   => [
					'title' => sprintf(
						/* translators: 1: object type label, 2: numeric ID */
						__( '%1$s ID: %2$d', 'wp-powersuite' ),
						$object_type,
						$object_id
					),
				],
			]
		);
	}

	private function resolveObjectId( object $object ): ?int {
		if ( property_exists( $object, 'ID' ) ) {
			return (int) $object->ID;
		}

		if ( property_exists( $object, 'term_id' ) ) {
			return (int) $object->term_id;
		}

		if ( property_exists( $object, 'comment_ID' ) ) {
			return (int) $object->comment_ID;
		}

		return null;
	}

	/**
	 * @param array<string, mixed> $settings
	 * @param string               $module_id
	 * @param string               $context
	 * @return array<string, mixed>
	 */
	public function filterSanitizeModuleSettings( array $settings, string $module_id, string $context ): array {
		unset( $context );

		if ( $module_id !== self::MODULE_ID ) {
			return $settings;
		}

		$existing = $this->moduleSettings()->all( [] );
		$existing = is_array( $existing ) ? $existing : [];

		return FeatureGate::preservePremiumSettingsOnSave( $settings, $existing );
	}

	public function onSettingsSaved( string $module_id, array $settings ): void {
		unset( $settings );

		if ( $module_id === self::MODULE_ID ) {
			$this->settings_cache = null;
		}
	}

	/**
	 * @return array<string, mixed>
	 */
	private function getSettings(): array {
		if ( $this->settings_cache !== null ) {
			return $this->settings_cache;
		}

		$settings = $this->moduleSettings()->all( [] );
		$settings = is_array( $settings ) ? $settings : [];
		$defaults = FeatureGate::getDefaultSettings();

		$merged = array_merge( $defaults, $settings );

		if ( ! is_array( $merged['enabled_post_types'] ) ) {
			$merged['enabled_post_types'] = $defaults['enabled_post_types'];
		}

		$this->settings_cache = FeatureGate::applyPremiumTierLimits( $merged );

		return $this->settings_cache;
	}
}
