<?php
/**
 * CPT Builder taxonomy list table.
 *
 * Uses WordPress WP_List_Table for default admin list styling and row actions.
 *
 * @package CptBuilder
 * @since 1.1.0
 */

namespace CptBuilder;

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

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

/**
 * List table for custom taxonomy definitions.
 */
final class TaxonomyListTable extends \WP_List_Table {

	/**
	 * Taxonomy admin controller.
	 */
	private TaxonomyAdmin $admin;

	/**
	 * Status filter: all, enabled, disabled.
	 */
	private string $status_filter;

	/**
	 * Search query.
	 */
	private string $search_query;

	/**
	 * @param TaxonomyAdmin $admin  Taxonomy admin controller.
	 * @param string        $status Status filter.
	 * @param string        $search Search query.
	 */
	public function __construct( TaxonomyAdmin $admin, string $status = 'all', string $search = '' ) {
		$this->admin         = $admin;
		$this->status_filter = in_array( $status, [ 'all', 'enabled', 'disabled' ], true ) ? $status : 'all';
		$this->search_query  = $search;

		parent::__construct(
			[
				'singular' => 'taxonomy',
				'plural'   => 'taxonomies',
				'ajax'     => false,
			]
		);
	}

	/**
	 * @return array<string, string>
	 */
	public function get_columns(): array {
		return [
			'cb'          => '<input type="checkbox" />',
			'title'       => __( 'Taxonomy', 'wp-powersuite' ),
			'key'         => __( 'Key', 'wp-powersuite' ),
			'status'      => __( 'Status', 'wp-powersuite' ),
			'type'        => __( 'Type', 'wp-powersuite' ),
			'public'      => __( 'Public', 'wp-powersuite' ),
			'rest'        => __( 'REST', 'wp-powersuite' ),
			'post_types'  => __( 'Post Types', 'wp-powersuite' ),
		];
	}

	/**
	 * @return array<string, array<int, bool|string>>
	 */
	protected function get_sortable_columns(): array {
		return [
			'title'  => [ 'title', false ],
			'key'    => [ 'key', false ],
			'status' => [ 'status', false ],
		];
	}

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

	public function prepare_items(): void {
		$definitions = $this->admin->getDefinitionsForList();

		if ( $this->status_filter === 'enabled' ) {
			$definitions = array_filter( $definitions, static fn( array $item ): bool => ! empty( $item['definition']['enabled'] ) );
		} elseif ( $this->status_filter === 'disabled' ) {
			$definitions = array_filter( $definitions, static fn( array $item ): bool => empty( $item['definition']['enabled'] ) );
		}

		if ( $this->search_query !== '' ) {
			$search = strtolower( $this->search_query );
			$definitions = array_filter(
				$definitions,
				static function ( array $item ) use ( $search ): bool {
					$key      = (string) ( $item['key'] ?? '' );
					$labels   = isset( $item['definition']['labels'] ) && is_array( $item['definition']['labels'] ) ? $item['definition']['labels'] : [];
					$name     = (string) ( $labels['name'] ?? '' );
					$singular = (string) ( $labels['singular_name'] ?? '' );

					return str_contains( strtolower( $key ), $search )
						|| str_contains( strtolower( $name ), $search )
						|| str_contains( strtolower( $singular ), $search );
				}
			);
		}

		$orderby = isset( $_REQUEST['orderby'] ) ? sanitize_key( wp_unslash( (string) $_REQUEST['orderby'] ) ) : 'title'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$order   = isset( $_REQUEST['order'] ) && strtolower( wp_unslash( (string) $_REQUEST['order'] ) ) === 'desc' ? 'desc' : 'asc'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		usort(
			$definitions,
			static function ( array $a, array $b ) use ( $orderby, $order ): int {
				$definition_a = $a['definition'] ?? [];
				$definition_b = $b['definition'] ?? [];
				$labels_a     = isset( $definition_a['labels'] ) && is_array( $definition_a['labels'] ) ? $definition_a['labels'] : [];
				$labels_b     = isset( $definition_b['labels'] ) && is_array( $definition_b['labels'] ) ? $definition_b['labels'] : [];

				$va = match ( $orderby ) {
					'key'    => (string) ( $a['key'] ?? '' ),
					'status' => ! empty( $definition_a['enabled'] ) ? '1' : '0',
					default  => (string) ( $labels_a['name'] ?? $a['key'] ?? '' ),
				};
				$vb = match ( $orderby ) {
					'key'    => (string) ( $b['key'] ?? '' ),
					'status' => ! empty( $definition_b['enabled'] ) ? '1' : '0',
					default  => (string) ( $labels_b['name'] ?? $b['key'] ?? '' ),
				};

				$compare = strcasecmp( $va, $vb );
				return $order === 'asc' ? $compare : -$compare;
			}
		);

		$this->items = array_values( $definitions );
		$this->_column_headers = [
			$this->get_columns(),
			[],
			$this->get_sortable_columns(),
			'title',
		];
	}

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

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_title( $item ): string {
		$key        = (string) ( $item['key'] ?? '' );
		$definition = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$labels     = isset( $definition['labels'] ) && is_array( $definition['labels'] ) ? $definition['labels'] : [];
		$plural     = (string) ( $labels['name'] ?? $key );
		$singular   = (string) ( $labels['singular_name'] ?? '' );
		$enabled    = ! empty( $definition['enabled'] );

		$edit_url      = $this->admin->url( [ 'action' => 'edit', 'key' => $key ] );
		$toggle_url    = $this->admin->actionUrl( 'wpps_cptb_tax_toggle', 'wpps_cptb_tax_toggle_' . $key, [ 'key' => $key ] );
		$duplicate_url = $this->admin->actionUrl( 'wpps_cptb_tax_duplicate', 'wpps_cptb_tax_duplicate_' . $key, [ 'key' => $key ] );
		$export_url    = $this->admin->actionUrl( 'wpps_cptb_tax_export', 'wpps_cptb_tax_export', [ 'key' => $key ] );
		$delete_url    = $this->admin->actionUrl( 'wpps_cptb_tax_delete', 'wpps_cptb_tax_delete_' . $key, [ 'key' => $key ] );

		$actions = [
			'edit' => sprintf(
				'<a href="%s">%s</a>',
				esc_url( $edit_url ),
				esc_html__( 'Edit', 'wp-powersuite' )
			),
			'toggle' => sprintf(
				'<a href="%s">%s</a>',
				esc_url( $toggle_url ),
				$enabled ? esc_html__( 'Disable', 'wp-powersuite' ) : esc_html__( 'Enable', 'wp-powersuite' )
			),
			'duplicate' => sprintf(
				'<a href="%s">%s</a>',
				esc_url( $duplicate_url ),
				esc_html__( 'Duplicate', 'wp-powersuite' )
			),
			'export' => sprintf(
				'<a href="%s">%s</a>',
				esc_url( $export_url ),
				esc_html__( 'Export', 'wp-powersuite' )
			),
			'delete' => sprintf(
				'<a href="%s" class="submitdelete cptb-delete">%s</a>',
				esc_url( $delete_url ),
				esc_html__( 'Delete', 'wp-powersuite' )
			),
		];

		$output  = '<strong><a class="row-title" href="' . esc_url( $edit_url ) . '">' . esc_html( $plural ) . '</a></strong>';
		if ( $singular !== '' ) {
			$output .= '<div class="cptb-muted">' . esc_html( $singular ) . '</div>';
		}

		return $output . $this->row_actions( $actions );
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_key( $item ): string {
		return '<code>' . esc_html( (string) ( $item['key'] ?? '' ) ) . '</code>';
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_status( $item ): string {
		$definition = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$enabled    = ! empty( $definition['enabled'] );

		return sprintf(
			'<span class="cptb-status cptb-status--%1$s">%2$s</span>',
			$enabled ? 'on' : 'off',
			$enabled ? esc_html__( 'Enabled', 'wp-powersuite' ) : esc_html__( 'Disabled', 'wp-powersuite' )
		);
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_type( $item ): string {
		$definition   = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$args         = isset( $definition['args'] ) && is_array( $definition['args'] ) ? $definition['args'] : [];
		$hierarchical = ! empty( $args['hierarchical'] );

		return $hierarchical ? esc_html__( 'Hierarchical', 'wp-powersuite' ) : esc_html__( 'Tag-like', 'wp-powersuite' );
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_public( $item ): string {
		$definition = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$args       = isset( $definition['args'] ) && is_array( $definition['args'] ) ? $definition['args'] : [];

		return ! empty( $args['public'] ) ? esc_html__( 'Yes', 'wp-powersuite' ) : esc_html__( 'No', 'wp-powersuite' );
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_rest( $item ): string {
		$definition = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$args       = isset( $definition['args'] ) && is_array( $definition['args'] ) ? $definition['args'] : [];

		return ! empty( $args['show_in_rest'] ) ? esc_html__( 'Yes', 'wp-powersuite' ) : esc_html__( 'No', 'wp-powersuite' );
	}

	/**
	 * @param array<string, mixed> $item Row item.
	 */
	protected function column_post_types( $item ): string {
		$definition   = isset( $item['definition'] ) && is_array( $item['definition'] ) ? $item['definition'] : [];
		$object_types = isset( $definition['object_types'] ) && is_array( $definition['object_types'] ) ? $definition['object_types'] : [];

		if ( $object_types === [] ) {
			return '<span class="cptb-muted">—</span>';
		}

		return esc_html( implode( ', ', array_map( 'strval', $object_types ) ) );
	}

	/**
	 * @param array<string, mixed> $item        Row item.
	 * @param string               $column_name Column name.
	 */
	protected function column_default( $item, $column_name ): string {
		return '';
	}

	public function no_items(): void {
		$all = $this->admin->getDefinitionsForList();
		if ( $all === [] ) {
			esc_html_e( 'No custom taxonomies found.', 'wp-powersuite' );
			return;
		}

		echo esc_html__( 'No taxonomies match your search or filter.', 'wp-powersuite' );
		echo ' <a href="' . esc_url( $this->admin->url() ) . '">' . esc_html__( 'Clear filters', 'wp-powersuite' ) . '</a>';
	}

	/**
	 * @return array<string, string>
	 */
	protected function get_views(): array {
		$all_items = $this->admin->getDefinitionsForList();
		$search_args = $this->search_query !== '' ? [ 's' => $this->search_query ] : [];

		$count_all      = count( $all_items );
		$count_enabled  = count( array_filter( $all_items, static fn( array $item ): bool => ! empty( $item['definition']['enabled'] ) ) );
		$count_disabled = $count_all - $count_enabled;

		return [
			'all' => sprintf(
				'<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
				esc_url( $this->admin->url( array_merge( [ 'status' => 'all' ], $search_args ) ) ),
				$this->status_filter === 'all' ? 'current' : '',
				esc_html__( 'All', 'wp-powersuite' ),
				$count_all
			),
			'enabled' => sprintf(
				'<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
				esc_url( $this->admin->url( array_merge( [ 'status' => 'enabled' ], $search_args ) ) ),
				$this->status_filter === 'enabled' ? 'current' : '',
				esc_html__( 'Enabled', 'wp-powersuite' ),
				$count_enabled
			),
			'disabled' => sprintf(
				'<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
				esc_url( $this->admin->url( array_merge( [ 'status' => 'disabled' ], $search_args ) ) ),
				$this->status_filter === 'disabled' ? 'current' : '',
				esc_html__( 'Disabled', 'wp-powersuite' ),
				$count_disabled
			),
		];
	}
}
