<?php

namespace WC_Affiliate\API;

defined( 'ABSPATH' ) || exit;

use WC_Affiliate\Traits\Auth;
use WC_Affiliate\Traits\Rest;
use WC_Affiliate\Traits\Validation;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_User;

/**
 * REST API Controller for User Management.
 *
 * Handles REST API requests related to user creation, management, and authentication.
 *
 * @since 1.0.0
 */
class User {

	use Auth;
	use Rest;
	use Validation;

	/**
	 * Get current user profile
	 *
	 * @return WP_REST_Response|WP_Error Response with user data or error.
	 */
	public function get_user() {
		$user_id = get_current_user_id();

		if ( ! $user_id ) {
			return $this->response_error( __( 'User not authenticated.', 'wc-affiliate' ), 401 );
		}

		$user_model = new \WC_Affiliate\Models\User( $user_id );

		$user_data = $user_model->to_array();

		if ( empty( $user_data ) ) {
			return $this->response_error( __( 'User not found.', 'wc-affiliate' ), 404 );
		}

		$user_data = apply_filters( 'wc_affiliate_rest_api_user_get_data', $user_data, $user_id );

		return $this->response_success( $user_data, __( 'User profile retrieved successfully.', 'wc-affiliate' ), 200 );
	}

	/**
	 * Create a new user
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response|WP_Error Response with user data or error.
	 */
	public function create_user( WP_REST_Request $request ) {
		$username   = sanitize_text_field( $request->get_param( 'username' ) );
		$email      = sanitize_text_field( $request->get_param( 'email' ) );
		$first_name = sanitize_text_field( $request->get_param( 'first_name' ) );
		$last_name  = sanitize_text_field( $request->get_param( 'last_name' ) );
		$password   = sanitize_text_field( $request->get_param( 'password' ) );

		// Validate required fields.
		if ( empty( $username ) || empty( $email ) || empty( $password ) ) {
			return $this->response_error( __( 'Username, email, and password are required.', 'wc-affiliate' ), 400 );
		}

		// Check if username exists.
		if ( username_exists( $username ) ) {
			return $this->response_error( __( 'Username already exists.', 'wc-affiliate' ), 409 );
		}

		// Check if email exists.
		if ( email_exists( $email ) ) {
			return $this->response_error( __( 'Email address already exists.', 'wc-affiliate' ), 409 );
		}

		// Create the user.
		$user_id = wp_create_user( $username, $password, $email );

		if ( is_wp_error( $user_id ) ) {
			return $this->response_error( $user_id->get_error_message(), 400 );
		}

		// Update user meta.
		if ( ! empty( $first_name ) ) {
			wp_update_user(
				array(
					'ID'         => $user_id,
					'first_name' => $first_name,
				)
			);
		}
		if ( ! empty( $last_name ) ) {
			wp_update_user(
				array(
					'ID'        => $user_id,
					'last_name' => $last_name,
				)
			);
		}

		// Assign affiliate role to the newly created user.
		$user_obj = new WP_User( $user_id );
		$user_obj->add_role( 'affiliate' );

		// Fire action after user creation.
		do_action( 'wc_affiliate_user_created', $user_id, $request );

		// Get the created user.
		$user = get_userdata( $user_id );

		if ( ! $user instanceof WP_User ) {
			return $this->response_error( __( 'Failed to retrieve created user.', 'wc-affiliate' ), 500 );
		}

		$user_data = array(
			'id'           => $user->ID,
			'user_login'   => $user->user_login,
			'user_email'   => $user->user_email,
			'first_name'   => $user->first_name,
			'last_name'    => $user->last_name,
			'display_name' => $user->display_name,
		);

		$user_data = apply_filters( 'wc_affiliate_rest_api_user_create_data', $user_data, $user_id, $request );

		return $this->response_success( $user_data, __( 'User created successfully.', 'wc-affiliate' ), 201 );
	}

	/**
	 * Update user profile
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response|WP_Error Response with update status or error.
	 */
	public function update_user( WP_REST_Request $request ) {
		$user_id       = get_current_user_id();
		$email         = sanitize_text_field( $request->get_param( 'email' ) );
		$first_name    = sanitize_text_field( $request->get_param( 'first_name' ) );
		$last_name     = sanitize_text_field( $request->get_param( 'last_name' ) );
		$country       = sanitize_text_field( $request->get_param( 'country' ) );
		$state         = sanitize_text_field( $request->get_param( 'state' ) );
		$city          = sanitize_text_field( $request->get_param( 'city' ) );
		$image_url     = sanitize_text_field( $request->get_param( 'image_url' ) );
		$payout_method = sanitize_text_field( $request->get_param( 'payout_method' ) );
		$account_info  = sanitize_textarea_field( $request->get_param( 'account_info' ) );

		$password  = $request->get_param( 'password' );
		$password2 = $request->get_param( 'password2' );

		// Validate password match if provided.
		if ( ! empty( $password ) && $password !== $password2 ) {
			return $this->response_error( __( 'Passwords do not match.', 'wc-affiliate' ) );
		}

		// Prepare user data for update.
		$user_data = array(
			'ID'         => $user_id,
			'user_email' => $email,
			'first_name' => $first_name,
			'last_name'  => $last_name,
		);

		// Add password if provided.
		if ( ! empty( $password ) ) {
			$user_data['user_pass'] = $password;
		}

		// Update user.
		$result = wp_update_user( $user_data );
		if ( is_wp_error( $result ) ) {
			return $this->response_error( $result->get_error_message(), 400 );
		}

		// Use User model for meta updates.
		$user_model = new \WC_Affiliate\Models\User( $user_id );

		// Update user meta.
		if ( ! empty( $payout_method ) ) {
			$user_model->update_meta( '_wc_affiliate_payout_method', $payout_method );
		}

		if ( ! empty( $image_url ) ) {
			$user_model->update_meta( '_wc_affiliate_avatar', $image_url );
		}

		if ( isset( $city ) ) {
			$user_model->update_meta( '_wc_affiliate_city', $city );
		}

		if ( isset( $state ) ) {
			$user_model->update_meta( '_wc_affiliate_state', $state );
		}

		if ( isset( $country ) ) {
			$user_model->update_meta( '_wc_affiliate_country', $country );
		}

		// Handle manual payment details.
		if ( ! empty( $account_info ) && 'manual' === $payout_method ) {
			$user_model->update_meta( '_wc_affiliate_mannual_payment', sanitize_textarea_field( $account_info ) );
		}

		do_action( 'wc_affiliate_user_profile_updated', $user_id, $request );

		// Get updated user data.
		$user_data = $user_model->to_array();

		if ( empty( $user_data ) ) {
			return $this->response_error( __( 'Failed to retrieve updated user.', 'wc-affiliate' ), 500 );
		}

		$user_data = apply_filters( 'wc_affiliate_rest_api_user_update_data', $user_data, $user_id, $request );

		return $this->response_success( $user_data, __( 'User profile updated successfully.', 'wc-affiliate' ), 200 );
	}

	/**
	 * Update user avatar
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response|WP_Error Response with avatar update status or error.
	 */
	public function update_avatar( WP_REST_Request $request ) {
		$user_id = get_current_user_id();

		if ( ! $user_id ) {
			return $this->response_error( __( 'User not authenticated.', 'wc-affiliate' ), 401 );
		}

		$avatar_url = sanitize_text_field( $request->get_param( 'avatar_url' ) );

		if ( empty( $avatar_url ) ) {
			return $this->response_error( __( 'Avatar URL is required.', 'wc-affiliate' ) );
		}

		// Validate URL format.
		if ( ! filter_var( $avatar_url, FILTER_VALIDATE_URL ) ) {
			return $this->response_error( __( 'Invalid avatar URL format.', 'wc-affiliate' ) );
		}

		// Allow filtering avatar URL before update.
		$avatar_url = apply_filters( 'wc_affiliate_avatar_url_before_update', $avatar_url, $user_id );

		// Use User model for meta update.
		$user_model = new \WC_Affiliate\Models\User( $user_id );
		$result     = $user_model->update_meta( '_wc_affiliate_avatar', $avatar_url );

		if ( false === $result ) {
			return $this->response_error( __( 'Failed to update avatar.', 'wc-affiliate' ), 500 );
		}

		// Fire action after avatar update.
		do_action( 'wc_affiliate_avatar_updated', $user_id, $avatar_url );

		return $this->response_success(
			array( 'avatar_url' => $avatar_url ),
			__( 'Avatar updated successfully.', 'wc-affiliate' ),
			200
		);
	}

	/**
	 * Resend verification email
	 *
	 * @return WP_REST_Response|WP_Error Response with email status or error.
	 */
	public function resend_verification_email() {
		$user = get_user_by( 'ID', get_current_user_id() );

		if ( ! $user instanceof WP_User ) {
			return $this->response_error( __( 'User not found.', 'wc-affiliate' ), 404 );
		}

		// Use filter for email resending logic (similar to AJAX).
		$response = apply_filters(
			'wc_affiliate_resend_verification_email',
			array(
				'status'  => 0,
				'message' => __( 'Something went wrong.', 'wc-affiliate' ),
			),
			$user
		);

		if ( $response['status'] ) {
			return $this->response_success( null, $response['message'] );
		} else {
			return $this->response_error( $response['message'] );
		}
	}

	/**
	 * Get non-admin users who are not affiliates
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Response with user data or error.
	 */
	public function get_available_users( WP_REST_Request $request ): WP_REST_Response {
		$page     = $request->get_param( 'page' );
		$per_page = $request->get_param( 'per_page' );
		$search   = sanitize_text_field( $request->get_param( 'search' ) );

		// Validate pagination parameters.
		$page     = max( 1, intval( $page ) );
		$per_page = min( 100, max( 1, intval( $per_page ) ) );

		// Build user query arguments.
		$user_args = array(
			'role__not_in' => array( 'administrator' ), // Exclude administrators
			'number'       => $per_page,
			'offset'       => ( $page - 1 ) * $per_page,
			'orderby'      => 'display_name',
			'order'        => 'ASC',
		);

		// Add search filter if provided.
		if ( ! empty( $search ) ) {
			$user_args['search']         = '*' . esc_attr( $search ) . '*';
			$user_args['search_columns'] = array( 'display_name', 'user_login', 'user_email' );
		}

		// Add meta query to exclude users who have affiliate status.
		$user_args['meta_query'] = array(
			array(
				'key'     => '_wc_affiliate_status',
				'compare' => 'NOT EXISTS', // Only users without affiliate status
			),
		);

		$users = get_users( $user_args );

		// Format user data.
		$formatted_users = array();
		foreach ( $users as $user ) {
			$formatted_users[] = array(
				'id'    => $user->ID,
				'name'  => $user->display_name ?: $user->user_login,
				'email' => $user->user_email,
			);
		}

		// Get total count for pagination.
		$count_args           = $user_args;
		$count_args['number'] = -1; // Get all for count.
		$count_args['fields'] = 'ID'; // Only need IDs for count.
		$total_users          = count( get_users( $count_args ) );

		$total_pages = ceil( $total_users / $per_page );

		return $this->response_success(
			array(
				'users'      => $formatted_users,
				'pagination' => array(
					'page'        => $page,
					'per_page'    => $per_page,
					'total'       => $total_users,
					'total_pages' => $total_pages,
				),
			),
			__( 'Available users retrieved successfully.', 'wc-affiliate' ),
			200
		);
	}
}
