<?php

namespace CompactTables;

use WP_PowerSuite\Core\AbstractModule;
use WP_PowerSuite\Core\Contracts\DataLocationsInterface;
use WP_PowerSuite\Core\OptionStoreModuleSettingsRepository;

class Module extends AbstractModule implements DataLocationsInterface {

	private const MODULE_ID = 'compact-tables';
	private const MODULE_VERSION = '1.2.1';

	private ?array $settings_cache = null;

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

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

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

	public function getDescription(): string {
		return __( 'Dense post list tables in the admin—fit more posts, pages, or custom types on one screen.', 'wp-powersuite' );
	}

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

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

	protected function registerHooks(): void {
		if ( ! is_admin() ) {
			return;
		}

		add_action( 'load-edit.php', [ $this, 'registerEditScreenHooks' ] );
		add_filter( 'wp_powersuite_compact_tables_column_key', [ self::class, 'resolveColumnKey' ], 10, 2 );
	}

	public function registerEditScreenHooks(): void {
		$settings     = $this->getSettings();
		$post_types   = $settings['post_types'] ?? [];
		$compact_date = ! empty( $settings['compact_date'] );

		add_action( 'admin_head', [ $this, 'injectCompactStyles' ], 999 );

		if ( ! $compact_date || ! is_array( $post_types ) || $post_types === [] ) {
			return;
		}

		foreach ( $post_types as $pt ) {
			$pt = sanitize_key( (string) $pt );
			if ( $pt === '' || ! post_type_exists( $pt ) ) {
				continue;
			}

			add_filter( $this->postsColumnsHook( $pt ), [ $this, 'addCompactDateColumn' ] );
			add_action( $this->postsCustomColumnHook( $pt ), [ $this, 'renderCompactDateColumn' ], 10, 2 );
			add_filter( $this->sortableColumnsHook( $pt ), [ $this, 'sortableCompactDateColumn' ] );
		}
	}

	/**
	 * Map Admin Columns "date" config keys to compact_date when this module replaces that column.
	 */
	public static function resolveColumnKey( string $column_key, string $post_type = '' ): string {
		if ( $column_key !== 'date' ) {
			return $column_key;
		}

		if ( ! OptionStoreModuleSettingsRepository::isModuleEnabled( self::MODULE_ID ) ) {
			return $column_key;
		}

		$settings = OptionStoreModuleSettingsRepository::forModule( self::MODULE_ID )->all( [] );
		if ( empty( $settings['compact_date'] ) ) {
			return $column_key;
		}

		$post_types = $settings['post_types'] ?? [ 'post', 'page' ];
		if ( ! is_array( $post_types ) ) {
			return $column_key;
		}

		if ( $post_type !== '' && ! in_array( $post_type, $post_types, true ) ) {
			return $column_key;
		}

		return 'compact_date';
	}

	/**
	 * Replace default date column with compact date column.
	 *
	 * @param array<string, string> $columns Column headers.
	 * @return array<string, string> Modified columns.
	 */
	public function addCompactDateColumn( array $columns ): array {
		$new = [];
		foreach ( $columns as $key => $label ) {
			if ( $key === 'date' ) {
				$new['compact_date'] = __( 'Published', 'wp-powersuite' );
				continue;
			}
			$new[ $key ] = $label;
		}
		return $new;
	}

	/**
	 * Render compact date column content.
	 *
	 * @param string $column  Column name.
	 * @param int    $post_id Post ID.
	 */
	public function renderCompactDateColumn( string $column, int $post_id ): void {
		if ( $column !== 'compact_date' ) {
			return;
		}

		$post = get_post( $post_id );
		if ( ! $post instanceof \WP_Post ) {
			return;
		}

		$status = $post->post_status;

		if ( $status === 'publish' ) {
			$date = get_the_date( 'Y/m/d', $post );
			$time = get_the_time( 'g:i a', $post );
			echo '<span style="white-space:nowrap">';
			echo esc_html( $date ) . ' <strong>' . esc_html( $time ) . '</strong>';
			echo '</span>';
			return;
		}

		$status_obj   = get_post_status_object( $status );
		$status_label = $status_obj ? $status_obj->label : ucfirst( $status );
		echo '<strong>' . esc_html( $status_label ) . '</strong>';

		if ( $status === 'future' ) {
			$date = get_the_date( 'Y/m/d', $post );
			$time = get_the_time( 'g:i a', $post );
			echo '<br><span style="white-space:nowrap">' . esc_html( $date ) . ' ' . esc_html( $time ) . '</span>';
		}
	}

	/**
	 * Make compact_date column sortable by date.
	 *
	 * @param array<string, string> $columns Sortable columns.
	 * @return array<string, string> Modified columns.
	 */
	public function sortableCompactDateColumn( array $columns ): array {
		$columns['compact_date'] = 'date';
		return $columns;
	}

	public function injectCompactStyles(): void {
		$screen  = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		$base    = $screen ? ( $screen->base ?? '' ) : '';
		$is_edit = ( $base === 'edit' );

		if ( ! $is_edit ) {
			global $pagenow;
			if ( empty( $pagenow ) || $pagenow !== 'edit.php' ) {
				return;
			}
			$post_type = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : 'post';
		} else {
			$post_type = $screen->post_type ?? ( isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : 'post' );
		}

		$settings   = $this->getSettings();
		$post_types = $settings['post_types'] ?? [];
		if ( ! is_array( $post_types ) || ! in_array( $post_type, $post_types, true ) ) {
			return;
		}

		$row_height   = $this->clamp( (int) ( $settings['row_height'] ?? 28 ), 24, 40 );
		$cell_padding = $this->clamp( (int) ( $settings['cell_padding'] ?? 3 ), 1, 10 );
		$font_size    = $this->clamp( (int) ( $settings['font_size'] ?? 12 ), 10, 14 );
		$compact_date = ! empty( $settings['compact_date'] );

		$sel      = '.wp-list-table';
		$fs       = (int) $font_size;
		$cp       = (int) $cell_padding;
		$rh       = (int) $row_height;
		$img_max  = max( 20, $rh - 4 );
		$fs_small = max( 9, $fs - 1 );
		?>
		<style id="wpps-compact-tables">
			<?php echo esc_html( $sel ); ?> {
				--wpps-ct-row-height: <?php echo esc_attr( (string) $rh ); ?>px;
				--wpps-ct-cell-padding: <?php echo esc_attr( (string) $cp ); ?>px;
				--wpps-ct-font-size: <?php echo esc_attr( (string) $fs ); ?>px;
			}
			<?php echo esc_html( $sel ); ?> thead th,
			<?php echo esc_html( $sel ); ?> tbody td {
				padding: <?php echo esc_attr( (string) $cp ); ?>px 6px !important;
				font-size: <?php echo esc_attr( (string) $fs ); ?>px !important;
				line-height: 1.3 !important;
				vertical-align: middle !important;
			}
			<?php echo esc_html( $sel ); ?> .check-column {
				width: 2em !important;
				padding: <?php echo esc_attr( (string) $cp ); ?>px 0 <?php echo esc_attr( (string) $cp ); ?>px 6px !important;
			}
			<?php echo esc_html( $sel ); ?> .column-title .row-title,
			<?php echo esc_html( $sel ); ?> .column-title strong,
			<?php echo esc_html( $sel ); ?> .column-title,
			<?php echo esc_html( $sel ); ?> .column-name .row-title,
			<?php echo esc_html( $sel ); ?> .column-name strong,
			<?php echo esc_html( $sel ); ?> .column-name {
				font-size: <?php echo esc_attr( (string) $fs ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> .column-title .row-title,
			<?php echo esc_html( $sel ); ?> .column-title strong {
				display: inline-block;
				margin-bottom: 2px;
			}
			<?php echo esc_html( $sel ); ?> .post-state {
				font-size: <?php echo esc_attr( (string) $fs_small ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> tbody tr {
				height: <?php echo esc_attr( (string) $rh ); ?>px !important;
				max-height: <?php echo esc_attr( (string) $rh ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> tbody td {
				height: <?php echo esc_attr( (string) $rh ); ?>px !important;
				max-height: <?php echo esc_attr( (string) $rh ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> .row-actions {
				padding: 0 !important;
				margin: 0 !important;
				line-height: 1.3 !important;
				font-size: <?php echo esc_attr( (string) max( 10, (int) round( $fs * 0.95 ) ) ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> .row-actions span {
				display: inline-block;
				margin: 0 3px 0 0 !important;
			}
			<?php echo esc_html( $sel ); ?> img {
				max-width: <?php echo esc_attr( (string) $img_max ); ?>px !important;
				max-height: <?php echo esc_attr( (string) $img_max ); ?>px !important;
				width: auto !important;
				height: auto !important;
				object-fit: cover;
				vertical-align: middle;
			}
			<?php echo esc_html( $sel ); ?> .column-thumbnail img,
			<?php echo esc_html( $sel ); ?> .column-featured_image img,
			<?php echo esc_html( $sel ); ?> .column-wpps_featured_image img {
				max-width: <?php echo esc_attr( (string) $img_max ); ?>px !important;
				max-height: <?php echo esc_attr( (string) $img_max ); ?>px !important;
			}
			<?php echo esc_html( $sel ); ?> .column-compact_date,
			<?php echo esc_html( $sel ); ?> .column-date,
			<?php echo esc_html( $sel ); ?> .column-modified,
			<?php echo esc_html( $sel ); ?> .column-post_id,
			<?php echo esc_html( $sel ); ?> .column-word_count,
			<?php echo esc_html( $sel ); ?> .column-slug {
				white-space: nowrap !important;
			}
			<?php echo esc_html( $sel ); ?> .column-compact_date abbr,
			<?php echo esc_html( $sel ); ?> .column-date abbr {
				display: inline;
				border: none;
			}
			.tablenav.top,
			.tablenav.bottom {
				padding: 6px 0 !important;
				min-height: 32px !important;
			}
			.tablenav .actions {
				padding: 0 6px 0 0 !important;
			}
			.tablenav select {
				height: 26px !important;
				font-size: 11px !important;
				padding: 2px 20px 2px 6px !important;
			}
			.tablenav .button {
				height: 26px !important;
				line-height: 24px !important;
				padding: 0 8px !important;
				font-size: 11px !important;
			}
			.tablenav-pages {
				margin: 0 !important;
			}
			.tablenav-pages .pagination-links {
				font-size: 11px;
			}
			.tablenav-pages .button {
				height: 24px !important;
				width: 24px !important;
				padding: 0 !important;
				font-size: 13px !important;
			}
			.tablenav-pages .current-page {
				height: 24px !important;
				line-height: 24px !important;
				font-size: 11px !important;
				padding: 0 4px !important;
			}
			.subsubsub {
				margin: 6px 0 !important;
				font-size: 11px !important;
			}
			.subsubsub a {
				padding: 0 4px 0 0 !important;
			}
			.search-box {
				margin: 0 !important;
			}
			.search-box input[type="search"] {
				height: 26px !important;
				font-size: 11px !important;
				padding: 2px 8px !important;
			}
			.search-box input[type="submit"] {
				height: 26px !important;
				line-height: 24px !important;
				padding: 0 8px !important;
				font-size: 11px !important;
			}
			<?php if ( $compact_date ) : ?>
			<?php echo esc_html( $sel ); ?> .column-date br {
				display: none !important;
			}
			<?php echo esc_html( $sel ); ?> .column-date {
				white-space: nowrap !important;
			}
			<?php endif; ?>
		</style>
		<?php
	}

	public function getDataLocations(): array {
		return [
			'option_store_keys' => [ self::MODULE_ID ],
		];
	}

	public function getDefaultSettings(): array {
		return [
			'post_types'   => [ 'post', 'page' ],
			'row_height'   => 28,
			'cell_padding' => 3,
			'font_size'    => 12,
			'compact_date' => true,
		];
	}

	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";
	}

	private function clamp( int $value, int $min, int $max ): int {
		return max( $min, min( $max, $value ) );
	}

	private function getSettings(): array {
		if ( $this->settings_cache !== null ) {
			return $this->settings_cache;
		}

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

		return $this->settings_cache;
	}
}
