<?php
/**
 * Author Profile Table Management.
 *
 * Handles AJAX operations for loading author profiles, counting users by role,
 * and updating user meta fields for the Author Kit plugin.
 *
 * @package Author_Kit
 * @since 1.0.0
 */

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

/**
 * Class Author_Kit_Profile_Table
 *
 * Manages AJAX-driven author profile data operations including loading paginated profiles,
 * retrieving total author counts by role categories, and updating user meta data.
 * Integrates with WordPress AJAX API to provide dynamic user profile management.
 *
 * @package Author_Kit
 * @since 1.0.0
 */
class Author_Kit_Profile_Table {


	/**
	 * Constructor to initialize AJAX hooks for author profile table operations.
	 *
	 * Registers AJAX actions for loading user data, fetching total authors by role,
	 * and updating user meta information.
	 *
	 * @return void
	 */
	public function __construct() {

		add_action( 'wp_ajax_author_kit_get_user_data', array( $this, 'load_author_profile_table' ) );
		add_action( 'wp_ajax_author_kit_get_total_authors', array( $this, 'get_total_authors_by_role' ) );
		add_action( 'wp_ajax_author_kit_update_user_meta', array( $this, 'update_user_meta_callback' ) );
	}

	/**
	 * Handles AJAX request to load and return paginated author profile data.
	 *
	 * Supports filtering by search query, user role, ordering, and pagination.
	 * Retrieves user profiles with meta data like avatar, display name, roles, and bio widget.
	 * Returns JSON response with user data and pagination details.
	 *
	 * @return void Outputs JSON response containing paginated author profiles and pagination info.
	 */
	public function load_author_profile_table() {

		check_ajax_referer( 'author-profile-loader-nonce', 'nonce' );

		$user_limit      = isset( $_POST['limit'] ) ? intval( wp_unslash( $_POST['limit'] ) ) : 10;
		$current_page    = isset( $_POST['pageId'] ) || -1 !== $user_limit ? intval( wp_unslash( $_POST['pageId'] ) ) : 1;
		$order_by        = isset( $_POST['order_by'] ) ? sanitize_text_field( wp_unslash( $_POST['order_by'] ) ) : 'display_name';
		$order_direction = isset( $_POST['order_direction'] ) ? sanitize_text_field( wp_unslash( $_POST['order_direction'] ) ) : 'ASC';
		$search_query    = isset( $_POST['search'] ) ? sanitize_text_field( wp_unslash( $_POST['search'] ) ) : '';
		$user_role       = isset( $_POST['role'] ) ? sanitize_text_field( wp_unslash( $_POST['role'] ) ) : 'all';

		$all_roles  = wp_roles()->roles; // Get all roles dynamically.
		$role_slugs = array_keys( $all_roles ); // Extract role slugs dynamically.

		// Initialize default values.
		$role_not_in = array();

		$include_subscribers = get_option( 'author_kit_include_subscribers', true ); // default true if not set.

		if ( strtolower( $user_role ) === 'all' ) {
			$role_not_in = $include_subscribers ? array() : array( 'subscriber' );
		} elseif ( strtolower( $user_role ) === 'on-site' ) {
			$role_not_in = array_filter(
				$role_slugs,
				function ( $role ) use ( $include_subscribers ) {
					if ( author_kit_str_contains( $role, 'guest' ) ) {
						return true; // Always exclude guest.
					}
					if ( ! $include_subscribers && 'subscriber' === $role ) {
						return true; // Conditionally exclude subscriber.
					}
					return false;
				}
			);
		} elseif ( strtolower( $user_role ) === 'guest' ) {
			$role_not_in = array_filter(
				$role_slugs,
				function ( $role ) {
					return ! author_kit_str_contains( $role, 'guest' ); // Keep only guest roles.
				}
			);
		} else {
			$role_not_in = $include_subscribers ? array() : array( 'subscriber' );
		}

		// Convert $role_not_in to an array of slugs.
		$role_not_in = array_values( $role_not_in );

		$meta_query = array(
			'relation' => 'OR', // Use OR to combine meta queries.
			array(
				'key'     => 'first_name',
				'value'   => $search_query,
				'compare' => 'LIKE',
			),
			array(
				'key'     => 'last_name',
				'value'   => $search_query,
				'compare' => 'LIKE',
			),
		);

		// Set up WP_User_Query arguments.
		$args = array(
			'role__not_in'   => $role_not_in, // Exclude subscribers.
			'number'         => $user_limit, // Get all users.
			'orderby'        => $order_by,
			'order'          => $order_direction,
			'paged'          => $current_page,  // Limit number of users returned (adjust as needed).
			'search'         => '*' . esc_attr( $search_query ) . '*', // Use the search query.
			'search_columns' => array(
				'user_login',
				'user_nicename',
				'display_name',
				'user_email',
			),
		);

		$user_query = new WP_User_Query( $args );
		$users      = $user_query->get_results();

		$total_users = $user_query->get_total();

		$total_pages  = -1 !== $user_limit ? ceil( $total_users / $user_limit ) : min( 1, 1 * $total_users );
		$start_index  = -1 !== $user_limit ? min( ( $current_page - 1 ) * $user_limit + 1, $total_users ) : min( 1, 1 * $total_users );
		$ending_index = -1 !== $user_limit ? min( $current_page * $user_limit, $total_users ) : $total_users;

		$user_data = array();

		foreach ( $users as $user ) {
			// Initialize default avatar.
			$avatar = get_avatar_url( $user->ID );

			// Retrieve updated meta values.
			$bio_widget = metadata_exists( 'user', $user->ID, 'author_kit_bio_widget' ) ? get_user_meta( $user->ID, 'author_kit_bio_widget', true ) : true;

			$user_data[] = array(
				'ID'           => $user->ID,
				'avatar'       => $avatar, // Use the avatar from metadata or default.
				'display_name' => $user->display_name,
				'username'     => $user->user_login,
				'role'         => ucfirst( implode( ', ', $user->roles ) ),
				'bio_widget'   => $bio_widget,
				'edit_link'    => esc_url(
					add_query_arg(
						array(
							'page'    => 'author-kit-edit-author-profile',  // Assuming the author profile page slug is 'author-profile'.
							'user_id' => $user->ID,      // Unique ID of the user.
							'action'  => 'edit',
						),
						admin_url( 'admin.php' )
					)
				),
			);
		}

		$pagination_data = array(
			'total_users'  => $total_users,
			'total_pages'  => $total_pages,
			'current_page' => $current_page,
			'start_index'  => $start_index,
			'ending_index' => $ending_index,
		);

		wp_send_json(
			array(
				'pagination_data' => $pagination_data,
				'user_data'       => $user_data,
			)
		);

		// Always die in a function handling AJAX requests.
		wp_die();
	}

	/**
	 * Handles AJAX request to get total author counts grouped by role categories.
	 *
	 * Counts users for three groups: all users, on-site users (excluding guests and optionally subscribers),
	 * and guest users (roles containing "guest"). Returns totals for each group as JSON success response.
	 *
	 * @return void Outputs JSON response with total author counts by role category.
	 */
	public function get_total_authors_by_role() {
		// Security check.
		check_ajax_referer( 'author-profile-loader-nonce', 'nonce' );

		$include_subscribers = get_option( 'author_kit_include_subscribers', true ); // default true if not set.

		// Fetch all roles dynamically.
		$all_roles  = wp_roles()->roles;
		$role_slugs = array_keys( $all_roles );

		$results = array();

		// ===== ALL USERS =====
		$all_users_args = array(
			'number' => -1,
		);

		if ( ! $include_subscribers ) {
			$all_users_args['role__not_in'] = array( 'subscriber' );
		}

		$all_users_query = new WP_User_Query( $all_users_args );
		$results['all']  = $all_users_query->get_total();

		// ===== ON-SITE USERS =====
		$on_site_excluded_roles = array_filter(
			$role_slugs,
			function ( $role ) use ( $include_subscribers ) {
				if ( author_kit_str_contains( $role, 'guest' ) ) {
					return true;
				}
				if ( ! $include_subscribers && 'subscriber' === $role ) {
					return true;
				}
				return false;
			}
		);

		$on_site_args = array(
			'number'       => -1,
			'role__not_in' => array_values( $on_site_excluded_roles ),
		);

		$on_site_query      = new WP_User_Query( $on_site_args );
		$results['on-site'] = $on_site_query->get_total();

		// ===== GUEST USERS =====
		$guest_included_roles = array_filter(
			$role_slugs,
			function ( $role ) {
				return author_kit_str_contains( $role, 'guest' );
			}
		);

		$guest_args = array(
			'number'   => -1,
			'role__in' => array_values( $guest_included_roles ),
		);

		$guest_query      = new WP_User_Query( $guest_args );
		$results['guest'] = $guest_query->get_total();

		// Ensure "all" remains first.
		$results = array_merge( array( 'all' => $results['all'] ), $results );

		wp_send_json_success( $results );
	}

	/**
	 * Handles AJAX request to update user meta data for multiple users.
	 *
	 * Verifies nonce and user permissions (must edit own meta or have 'edit_users' capability).
	 * Accepts JSON-encoded updates mapping user IDs to meta key-value pairs.
	 * Converts string boolean values to actual booleans before updating.
	 * Returns JSON success response listing user IDs successfully updated.
	 *
	 * @return void Outputs JSON response with list of updated user IDs or error on invalid data.
	 */
	public function update_user_meta_callback() {
		// Verify nonce for security.
		check_ajax_referer( 'author-profile-loader-nonce', 'nonce' );

		// Decode JSON updates from request.
		$updates = isset( $_POST['updates'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['updates'] ) ), true ) : array();
		if ( ! $updates || ! is_array( $updates ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid Data Format', 'author-kit' ) ), 400 );
		}

		$updated_users   = array(); // Array to track successfully updated users.
		$current_user_id = get_current_user_id();
		$is_edit_users   = current_user_can( 'edit_users' );

		foreach ( $updates as $user_id => $meta_data ) {
			if ( ! is_numeric( $user_id ) ) {
				continue; // Ensure valid user ID.
			}

			$user_id = (int) $user_id;

			// Check permission: allow if updating own meta or if current user has 'edit_users'.
			if ( $user_id !== $current_user_id && ! $is_edit_users ) {
				continue; // Skip unauthorized update.
			}

			foreach ( $meta_data as $meta_key => $meta_value ) {
				// Convert "true"/"false" strings to actual boolean values.
				$meta_value = filter_var( $meta_value, FILTER_VALIDATE_BOOLEAN );

				// Update user meta with boolean value.
				$update_status = update_user_meta( $user_id, $meta_key, $meta_value );
				if ( false !== $update_status ) {
					$updated_users[] = (int) $user_id; // Track successfully updated users.
				}
			}
		}

		// Send response with updated user IDs.
		wp_send_json_success( array( 'updated_users' => array_unique( $updated_users ) ) );
	}
}


// Initialize the class.
new Author_Kit_Profile_Table();
