<?php
/**
 * Ambassadors List Table
 *
 * @package AmbassadorHub\Accounts\Admin
 */

namespace AmbassadorHub\Accounts\Admin;

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

use AmbassadorHub\Accounts\Roles;
use AmbassadorHub\CustomFields\CustomFieldsManager;
use AmbassadorHub\Fundraisers\FundraisersModule;

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

/**
 * List table for the Ambassadors admin screen.
 */
final class Ambassadors_List_Table extends \WP_List_Table {

	/** Nonce action/field for the search form — see Menu.php's wp_nonce_field() call. */
	private const NONCE_ACTION = 'ambh_ambassadors_search';
	private const NONCE_FIELD  = 'ambh_ambassadors_nonce';

	/**
	 * Active filter tab slug.
	 *
	 * @var string
	 */
	private string $current_tab;

	/**
	 * Base URL including the page query arg.
	 *
	 * @var string
	 */
	private string $base_url;

	/**
	 * Current search term.
	 *
	 * @var string
	 */
	private string $search_term;

	/**
	 * Cached status counts (populated lazily).
	 *
	 * @var array<string,int>|null
	 */
	private ?array $counts = null;

	/**
	 * Constructor.
	 *
	 * @param string $current_tab Active filter tab slug ('all', 'verified', 'unverified').
	 * @param string $base_url    Base URL for pagination and action links.
	 */
	public function __construct( string $current_tab, string $base_url ) {
		parent::__construct(
			array(
				'singular' => 'ambassador',
				'plural'   => 'ambassadors',
				'ajax'     => false,
			)
		);

		$this->current_tab = $current_tab;
		$this->base_url    = $base_url;

		// Search only narrows this already-capability-gated screen's display
		// (no state is written), so an invalid/missing nonce just fails open
		// to an unfiltered view rather than wp_die()-ing.
		$nonce_valid = isset( $_GET[ self::NONCE_FIELD ] )
			&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ self::NONCE_FIELD ] ) ), self::NONCE_ACTION );

		$this->search_term = ( $nonce_valid && isset( $_REQUEST['s'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : '';
	}

	/**
	 * Define the columns.
	 *
	 * @return array<string,string>
	 */
	public function get_columns(): array {
		return array(
			'name'        => __( 'Name', 'ambassadorhub' ),
			'email'       => __( 'Email', 'ambassadorhub' ),
			'username'    => __( 'Username', 'ambassadorhub' ),
			'location'    => __( 'Location', 'ambassadorhub' ),
			'fundraisers' => __( 'Fundraisers', 'ambassadorhub' ),
			'registered'  => __( 'Registered', 'ambassadorhub' ),
		);
	}

	/**
	 * Define sortable columns.
	 *
	 * @return array<string,array>
	 */
	protected function get_sortable_columns(): array {
		return array(
			'name'       => array( 'display_name', false ),
			'email'      => array( 'user_email', false ),
			'registered' => array( 'user_registered', true ),
		);
	}

	/**
	 * Primary column (where row actions are rendered).
	 *
	 * @return string
	 */
	protected function get_primary_column_name(): string {
		return 'name';
	}

	/**
	 * No bulk actions on this read-only view.
	 *
	 * @return array<string,string>
	 */
	protected function get_bulk_actions(): array {
		return array();
	}

	/**
	 * Override the "no items" message.
	 *
	 * @return void
	 */
	public function no_items(): void {
		esc_html_e( 'No ambassadors found.', 'ambassadorhub' );
	}

	/**
	 * Lazy-load status counts once per page load.
	 *
	 * @return array<string,int>
	 */
	private function ensure_counts(): array {
		if ( null !== $this->counts ) {
			return $this->counts;
		}

		$base = array(
			'role'        => Roles::ROLE_AMBASSADOR,
			'count_total' => true,
			'number'      => 0,
		);

		$count_all      = (int) ( new \WP_User_Query( $base ) )->get_total();
		$count_verified = (int) ( new \WP_User_Query(
			array_merge(
				$base,
				array(
					'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
					array(
					'key'     => '_ambh_email_verified',
					'value'   => '1',
					'compare' => '=',
						),
					),
				)
			)
		) )->get_total();

		$this->counts = array(
			'all'        => $count_all,
			'verified'   => $count_verified,
			'unverified' => $count_all - $count_verified, // derived — no third query needed
		);

		return $this->counts;
	}

	/**
	 * Filter tab links (All / Verified / Unverified).
	 *
	 * @return array<string,string>
	 */
	protected function get_views(): array {
		$counts = $this->ensure_counts();

		$tabs = array(
			'all'        => __( 'All', 'ambassadorhub' ),
			'verified'   => __( 'Verified', 'ambassadorhub' ),
			'unverified' => __( 'Unverified', 'ambassadorhub' ),
		);

		$links = array();
		foreach ( $tabs as $slug => $label ) {
			$url            = 'all' === $slug
				? remove_query_arg( 'tab', $this->base_url )
				: add_query_arg( 'tab', $slug, $this->base_url );
			$current        = ( $slug === $this->current_tab ) || ( 'all' === $slug && 'all' === $this->current_tab );
			$class          = $current ? ' class="current"' : '';
			$links[ $slug ] = '<a href="' . esc_url( $url ) . '"' . $class . '>'
				. esc_html( $label )
				. ' <span class="count">(' . absint( $counts[ $slug ] ) . ')</span>'
				. '</a>';
		}

		return $links;
	}

	/**
	 * Fetch, filter, sort, and paginate ambassadors.
	 *
	 * @return void
	 */
	public function prepare_items(): void {
		$per_page        = $this->get_items_per_page( 'ambh_ambassadors_per_page', 20 );
		$allowed_orderby = array( 'display_name', 'user_email', 'user_registered' );

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$raw_orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : 'user_registered';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$raw_order = isset( $_GET['order'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ) : 'DESC';

		$orderby      = in_array( $raw_orderby, $allowed_orderby, true ) ? $raw_orderby : 'user_registered';
		$order        = 'ASC' === $raw_order ? 'ASC' : 'DESC';
		$current_page = $this->get_pagenum();

		$meta_query = array();
		if ( 'verified' === $this->current_tab ) {
			$meta_query = array(
				array(
					'key'     => '_ambh_email_verified',
					'value'   => '1',
					'compare' => '=',
				),
			);
		} elseif ( 'unverified' === $this->current_tab ) {
			$meta_query = array(
				'relation' => 'OR',
				array(
					'key'     => '_ambh_email_verified',
					'value'   => '0',
					'compare' => '=',
				),
				array(
					'key'     => '_ambh_email_verified',
					'compare' => 'NOT EXISTS',
				),
			);
		}

		$query_args = array(
			'role'        => Roles::ROLE_AMBASSADOR,
			'number'      => $per_page,
			'paged'       => $current_page,
			'fields'      => array( 'ID', 'user_login', 'user_email', 'display_name', 'user_registered' ),
			'orderby'     => $orderby,
			'order'       => $order,
			'count_total' => true,
			'meta_query'  => $meta_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
		);

		if ( '' !== $this->search_term ) {
			$query_args['search']         = '*' . $this->search_term . '*';
			$query_args['search_columns'] = array( 'user_login', 'user_email', 'display_name' );
		}

		$user_query  = new \WP_User_Query( $query_args );
		$total_items = (int) $user_query->get_total();

		$this->items = $user_query->get_results();

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

		$this->_column_headers = array(
			$this->get_columns(),
			$this->get_hidden_columns(),
			$this->get_sortable_columns(),
			$this->get_primary_column_name(),
		);
	}

	/**
	 * Return the currently hidden columns for this screen.
	 *
	 * @return string[]
	 */
	public function get_hidden_columns(): array {
		$screen = get_current_screen();
		if ( ! $screen ) {
			return array();
		}
		$hidden = get_user_meta( get_current_user_id(), 'manage' . $screen->id . 'columnshidden', true );
		return is_array( $hidden ) ? $hidden : array();
	}

	/**
	 * Name column (primary) — bold display name, verified badge, and optional row action.
	 *
	 * @param \WP_User $item User object.
	 * @return string
	 */
	public function column_name( $item ): string {
		$name        = ! empty( $item->display_name ) ? $item->display_name : $item->user_login;
		$is_verified = (bool) get_user_meta( $item->ID, '_ambh_email_verified', true );

		$badge = ! $is_verified
			? ' &mdash; <span class="post-state">' . esc_html__( 'Unverified', 'ambassadorhub' ) . '</span>'
			: '';

		$profile_url     = admin_url( 'user-edit.php?user_id=' . absint( $item->ID ) );
		$fundraisers_url = add_query_arg(
			array(
				'post_type' => FundraisersModule::POST_TYPE,
				'author'    => $item->ID,
			),
			admin_url( 'edit.php' )
		);
		$consent_url     = add_query_arg(
			array(
				'page'         => 'ambassadorhub-consent-records',
				'subject_type' => 'wp_user',
				'subject_id'   => $item->ID,
			),
			admin_url( 'admin.php' )
		);
		$row_actions     = array(
			'edit'        => '<a href="' . esc_url( $profile_url ) . '">' . esc_html__( 'Edit', 'ambassadorhub' ) . '</a>',
			'fundraisers' => '<a href="' . esc_url( $fundraisers_url ) . '">' . esc_html__( 'Fundraisers', 'ambassadorhub' ) . '</a>',
			'consent'     => '<a href="' . esc_url( $consent_url ) . '">' . esc_html__( 'Consent', 'ambassadorhub' ) . '</a>',
		);

		if ( class_exists( CustomFieldsManager::class ) && ! empty( CustomFieldsManager::get_fields( 'signup' ) ) ) {
			$row_actions['custom_fields'] = '<a href="#" class="ambh-cf-toggle" data-id="' . absint( $item->ID ) . '">' . esc_html__( 'Custom Fields', 'ambassadorhub' ) . '</a>';
		}

		if ( ! $is_verified ) {
			$resend_url = wp_nonce_url(
				add_query_arg(
					array(
						'page'    => 'ambassadorhub-ambassadors',
						'action'  => 'resend_verification',
						'user_id' => $item->ID,
					),
					admin_url( 'admin.php' )
				),
				'resend_verification_' . $item->ID
			);

			$row_actions['resend_verification'] = '<a href="' . esc_url( $resend_url ) . '">'
				. esc_html__( 'Resend Verification Email', 'ambassadorhub' )
				. '</a>';
		}

		return '<strong class="row-title"><a href="' . esc_url( $profile_url ) . '">' . esc_html( $name ) . '</a>' . $badge . '</strong>' . $this->row_actions( $row_actions );
	}

	/**
	 * Render a data row plus an optional hidden custom-fields details row.
	 *
	 * @param \WP_User $item User object.
	 *
	 * @return void
	 */
	public function single_row( $item ): void {
		parent::single_row( $item );

		if ( ! class_exists( CustomFieldsManager::class ) ) {
			return;
		}

		$fields = CustomFieldsManager::get_fields( 'signup' );
		if ( empty( $fields ) ) {
			return;
		}

		$user_id = (int) $item->ID;
		$colspan = count( $this->get_columns() );
		?>
		<tr class="ambh-cf-details-row" id="ambh-cf-row-<?php echo esc_attr( $user_id ); ?>">
			<td colspan="<?php echo esc_attr( $colspan ); ?>" class="ambh-cf-details-cell">
				<div class="ambh-cf-details-inner">
					<table class="ambh-cf-details-table">
						<?php foreach ( $fields as $field ) : ?>
							<?php
							$meta_key = CustomFieldsManager::get_meta_key( $field['id'] );
							$raw      = get_user_meta( $user_id, $meta_key, true );

							if ( 'checkbox' === ( $field['type'] ?? '' ) ) {
								$display = '1' === (string) $raw
									? '<span class="ambh-cf-check">&#10003; ' . esc_html__( 'Yes', 'ambassadorhub' ) . '</span>'
									: '<span class="ambh-cf-uncheck">&#8212;</span>';
							} elseif ( '' !== (string) $raw ) {
								$display = '<span>' . esc_html( (string) $raw ) . '</span>';
							} else {
								$display = '<span class="ambh-cf-empty">' . esc_html__( 'Not filled in', 'ambassadorhub' ) . '</span>';
							}
							?>
							<tr>
								<th><?php echo esc_html( $field['label'] ?? '' ); ?></th>
								<td><?php echo $display; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- each branch is individually escaped above. ?></td>
							</tr>
						<?php endforeach; ?>
					</table>
				</div>
			</td>
		</tr>
		<?php
	}

	/**
	 * Fallback column renderer.
	 *
	 * @param \WP_User $item        User object.
	 * @param string   $column_name Column slug.
	 * @return string
	 */
	public function column_default( $item, $column_name ): string {
		switch ( $column_name ) {
			case 'email':
				return esc_html( $item->user_email );
			case 'username':
				return esc_html( $item->user_login );
			case 'location':
				$parts = array_filter(
					array(
						get_user_meta( $item->ID, 'ambh_city', true ),
						get_user_meta( $item->ID, 'ambh_country', true ),
					)
				);
				return esc_html( implode( ', ', $parts ) );
			case 'fundraisers':
				$count = (int) count_user_posts( $item->ID, FundraisersModule::POST_TYPE, false );
				if ( $count > 0 ) {
					$url = add_query_arg(
						array(
							'post_type' => FundraisersModule::POST_TYPE,
							'author'    => $item->ID,
						),
						admin_url( 'edit.php' )
					);
					return '<a href="' . esc_url( $url ) . '">' . absint( $count ) . '</a>';
				}
				return '0';
			case 'registered':
				return esc_html( date_i18n( get_option( 'date_format' ), strtotime( $item->user_registered ) ) );
		}
		return '';
	}
}
