<?php
/**
 * Cleanup history list table.
 *
 * @package DatabaseCleanup
 */

namespace DatabaseCleanup\Includes;

use DatabaseCleanup\Module;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class Cleanup_History_List_Table extends \WP_List_Table {

	private string $source_filter = '';

	public function __construct() {
		parent::__construct(
			[
				'singular' => 'cleanup_run',
				'plural'   => 'cleanup_runs',
				'ajax'     => false,
			]
		);
	}

	/** @return array<string, string> */
	public function get_columns(): array {
		return [
			'cb'       => '<input type="checkbox" />',
			'date'     => __( 'Date', 'wp-powersuite' ),
			'user'     => __( 'User', 'wp-powersuite' ),
			'source'   => __( 'Source', 'wp-powersuite' ),
			'tasks'    => __( 'Tasks', 'wp-powersuite' ),
			'deleted'  => __( 'Rows removed', 'wp-powersuite' ),
			'bytes'    => __( 'Space saved (est.)', 'wp-powersuite' ),
			'duration' => __( 'Duration', 'wp-powersuite' ),
		];
	}

	/** @return array<string, string> */
	protected function get_bulk_actions(): array {
		return [
			'delete' => __( 'Delete', 'wp-powersuite' ),
		];
	}

	/** @return array<string, array<int, bool|string>> */
	protected function get_sortable_columns(): array {
		return [
			'date'     => [ 'timestamp', true ],
			'deleted'  => [ 'deleted', false ],
			'bytes'    => [ 'bytes', false ],
			'duration' => [ 'duration', false ],
		];
	}

	/** @return array<string, string> */
	protected function get_views(): array {
		$base     = add_query_arg( [ 'page' => 'powersuite-database-cleanup', 'view' => 'settings' ], admin_url( 'admin.php' ) );
		$all      = Cleanup_Logger::get_all();
		$manual   = array_filter( $all, static fn( array $entry ): bool => empty( $entry['scheduled'] ) );
		$scheduled = array_filter( $all, static fn( array $entry ): bool => ! empty( $entry['scheduled'] ) );

		return [
			'all'       => $this->view_link( $base, '', __( 'All', 'wp-powersuite' ), count( $all ) ),
			'manual'    => $this->view_link( $base, 'manual', __( 'Manual', 'wp-powersuite' ), count( $manual ) ),
			'scheduled' => $this->view_link( $base, 'scheduled', __( 'Scheduled', 'wp-powersuite' ), count( $scheduled ) ),
		];
	}

	private function view_link( string $base, string $filter, string $label, int $count ): string {
		$url     = $filter === '' ? $base : add_query_arg( 'source', $filter, $base );
		$current = $this->source_filter === $filter ? 'current' : '';

		return sprintf(
			'<a href="%s" class="%s">%s <span class="count">(%s)</span></a>',
			esc_url( $url ),
			esc_attr( $current ),
			esc_html( $label ),
			esc_html( number_format_i18n( $count ) )
		);
	}

	/** @param array<string, mixed> $item */
	protected function column_cb( $item ): string {
		return sprintf(
			'<input type="checkbox" name="history[]" value="%s" />',
			esc_attr( (string) ( $item['id'] ?? '' ) )
		);
	}

	/** @param array<string, mixed> $item */
	public function column_date( $item ): string {
		$id       = (string) ( $item['id'] ?? '' );
		$ts       = (int) ( $item['timestamp'] ?? 0 );
		$label    = $ts > 0
			? wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $ts )
			: '—';
		$base_url = add_query_arg(
			[
				'page' => 'powersuite-database-cleanup',
				'view' => 'settings',
			],
			admin_url( 'admin.php' )
		);

		$actions = [
			'view' => sprintf(
				'<button type="button" class="button-link wpps-dc-view-history" data-history-id="%s">%s</button>',
				esc_attr( $id ),
				esc_html__( 'View details', 'wp-powersuite' )
			),
			'delete' => sprintf(
				'<a href="%s" class="submitdelete" onclick="return confirm(%s);">%s</a>',
				esc_url(
					wp_nonce_url(
						add_query_arg(
							[
								'delete_history' => $id,
							],
							$base_url
						),
						'wpps_dc_delete_history_' . $id
					)
				),
				wp_json_encode( __( 'Delete this cleanup log entry?', 'wp-powersuite' ) ),
				esc_html__( 'Delete', 'wp-powersuite' )
			),
		];

		return sprintf(
			'<strong><button type="button" class="button-link wpps-dc-view-history" data-history-id="%1$s">%2$s</button></strong>%3$s',
			esc_attr( $id ),
			esc_html( $label ),
			$this->row_actions( $actions )
		);
	}

	/** @param array<string, mixed> $item */
	public function column_default( $item, $column_name ) {
		switch ( $column_name ) {
			case 'user':
				$user_id = (int) ( $item['user_id'] ?? 0 );
				if ( ! empty( $item['scheduled'] ) ) {
					return esc_html__( 'Scheduled', 'wp-powersuite' );
				}
				if ( $user_id < 1 ) {
					return esc_html__( 'System', 'wp-powersuite' );
				}
				$user = get_userdata( $user_id );

				return $user ? esc_html( $user->display_name ) : esc_html__( 'Unknown', 'wp-powersuite' );

			case 'source':
				return ! empty( $item['scheduled'] )
					? '<span class="wpps-dc-badge wpps-dc-badge-muted">' . esc_html__( 'Scheduled', 'wp-powersuite' ) . '</span>'
					: '<span class="wpps-dc-badge wpps-dc-badge-safe">' . esc_html__( 'Manual', 'wp-powersuite' ) . '</span>';

			case 'tasks':
				$count = is_array( $item['tasks'] ?? null ) ? count( $item['tasks'] ) : 0;

				return esc_html( number_format_i18n( $count ) );

			case 'deleted':
				return esc_html( number_format_i18n( (int) ( $item['totals']['deleted'] ?? 0 ) ) );

			case 'bytes':
				return esc_html( Module::formatBytes( (int) ( $item['totals']['bytes'] ?? 0 ) ) );

			case 'duration':
				return esc_html(
					sprintf(
						/* translators: %d: seconds */
						__( '%ds', 'wp-powersuite' ),
						(int) ( $item['duration'] ?? 0 )
					)
				);

			default:
				return '';
		}
	}

	public function prepare_items(): void {
		$this->source_filter = isset( $_GET['source'] ) ? sanitize_key( wp_unslash( (string) $_GET['source'] ) ) : '';
		if ( ! in_array( $this->source_filter, [ '', 'manual', 'scheduled' ], true ) ) {
			$this->source_filter = '';
		}

		$items = Cleanup_Logger::get_all();

		if ( $this->source_filter === 'manual' ) {
			$items = array_values(
				array_filter(
					$items,
					static fn( array $entry ): bool => empty( $entry['scheduled'] )
				)
			);
		} elseif ( $this->source_filter === 'scheduled' ) {
			$items = array_values(
				array_filter(
					$items,
					static fn( array $entry ): bool => ! empty( $entry['scheduled'] )
				)
			);
		}

		$orderby = isset( $_GET['orderby'] ) ? sanitize_key( wp_unslash( (string) $_GET['orderby'] ) ) : 'timestamp';
		$order   = isset( $_GET['order'] ) && strtolower( wp_unslash( (string) $_GET['order'] ) ) === 'asc' ? 'asc' : 'desc';

		usort(
			$items,
			static function ( array $a, array $b ) use ( $orderby, $order ): int {
				$value_a = match ( $orderby ) {
					'deleted'  => (int) ( $a['totals']['deleted'] ?? 0 ),
					'bytes'    => (int) ( $a['totals']['bytes'] ?? 0 ),
					'duration' => (int) ( $a['duration'] ?? 0 ),
					default    => (int) ( $a['timestamp'] ?? 0 ),
				};
				$value_b = match ( $orderby ) {
					'deleted'  => (int) ( $b['totals']['deleted'] ?? 0 ),
					'bytes'    => (int) ( $b['totals']['bytes'] ?? 0 ),
					'duration' => (int) ( $b['duration'] ?? 0 ),
					default    => (int) ( $b['timestamp'] ?? 0 ),
				};

				$result = $value_a <=> $value_b;

				return $order === 'asc' ? $result : -$result;
			}
		);

		$per_page     = Entity_Browser::sanitize_per_page(
			absint( $_REQUEST['per_page'] ?? Entity_Browser::DEFAULT_PER_PAGE )
		);
		$current_page = max( 1, $this->get_pagenum() );
		$total_items  = count( $items );
		$offset       = ( $current_page - 1 ) * $per_page;

		$this->items = array_slice( $items, $offset, $per_page );

		$this->_column_headers = [
			$this->get_columns(),
			[],
			$this->get_sortable_columns(),
			'date',
		];

		$this->set_pagination_args(
			[
				'total_items' => $total_items,
				'per_page'    => $per_page,
				'total_pages' => (int) ceil( $total_items / $per_page ),
			]
		);
	}

	public function no_items(): void {
		esc_html_e( 'No cleanup runs logged yet.', 'wp-powersuite' );
	}
}
