<?php

/**
 * AJAX Authentication Handler
 *
 * Handles login and signup AJAX requests.
 *
 * @package RadiusBooking\Ajax
 * @version 1.0.0
 */

namespace RadiusTheme\RadiusBooking\Ajax;


use RadiusTheme\RadiusBooking\Core\Container\Container;
use RadiusTheme\RadiusBooking\Services\UserService;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Auth class for handling authentication AJAX requests.
 *
 * @since 1.0.0
 */
class Auth {

	/**
	 * Initialize authentication AJAX handlers.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public static function init() {
		add_action( 'wp_ajax_nopriv_radius_booking_login', array( __CLASS__, 'login' ) );
		add_action( 'wp_ajax_nopriv_radius_booking_signup', array( __CLASS__, 'signup' ) );
		add_action( 'wp_ajax_radius_booking_login', array( __CLASS__, 'login' ) );
		add_action( 'wp_ajax_radius_booking_signup', array( __CLASS__, 'signup' ) );
	}

	/**
	 * Handle the signup action via AJAX.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public static function signup() {
		$nonce_value = isset( $_REQUEST['radius_booking_signup_nonce'] )
			? sanitize_text_field( wp_unslash( $_REQUEST['radius_booking_signup_nonce'] ) )
			: '';

		$valid_nonce = wp_verify_nonce( $nonce_value, 'radius-booking-signup' );

		if ( ! $valid_nonce ) {
			wp_send_json_error(
				array(
					'message' => __( 'Security check failed. Please refresh the page and try again.', 'radius-booking' ),
				)
			);
		}

		if ( ! isset( $_POST['email'], $_POST['password'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Please fill in all required fields.', 'radius-booking' ),
				)
			);
		}

		try {
			$email            = sanitize_email( wp_unslash( $_POST['email'] ) );
			$password         = sanitize_text_field( wp_unslash( $_POST['password'] ) );
			$confirm_password = isset( $_POST['confirm_password'] )
				? sanitize_text_field( wp_unslash( $_POST['confirm_password'] ) )
				: '';
			$full_name        = isset( $_POST['full_name'] )
				? sanitize_text_field( wp_unslash( $_POST['full_name'] ) )
				: '';
			$phone            = isset( $_POST['phone'] )
				? sanitize_text_field( wp_unslash( $_POST['phone'] ) )
				: '';

			// Validate email.
			if ( empty( $email ) || ! is_email( $email ) ) {
				throw new \Exception( __( 'Please enter a valid email address.', 'radius-booking' ) );
			}

			// Check if email already exists.
			if ( email_exists( $email ) ) {
				throw new \Exception( __( 'An account with this email already exists.', 'radius-booking' ) );
			}

			// Validate password.
			if ( empty( $password ) ) {
				throw new \Exception( __( 'Please enter a password.', 'radius-booking' ) );
			}

			if ( strlen( $password ) < 8 ) {
				throw new \Exception( __( 'Password must be at least 8 characters long.', 'radius-booking' ) );
			}

			// Validate password confirmation.
			if ( $password !== $confirm_password ) {
				throw new \Exception( __( 'Passwords do not match.', 'radius-booking' ) );
			}

			// Validate terms acceptance.
			if ( ! isset( $_POST['terms_accepted'] ) || empty( $_POST['terms_accepted'] ) ) {
				throw new \Exception( __( 'You must accept the terms and conditions.', 'radius-booking' ) );
			}

			/**
			 * Fires before user registration validation.
			 *
			 * @param string $email User email.
			 * @param string $password User password.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_before_signup_validation', $email, $password );

			/**
			 * Filter to add custom validation errors during signup.
			 *
			 * @param \WP_Error $errors Validation errors.
			 * @param string $email User email.
			 * @param string $password User password.
			 *
			 * @since 1.0.0
			 */
			$validation_errors = apply_filters(
				'radius_booking_signup_validation_errors',
				new \WP_Error(),
				$email,
				$password
			);

			if ( $validation_errors->has_errors() ) {
				throw new \Exception( $validation_errors->get_error_message() );
			}

			// Prepare user data.
			$user_data = array(
				'user_login'   => $email,
				'user_email'   => $email,
				'user_pass'    => $password,
				'display_name' => ! empty( $full_name ) ? $full_name : $email,
				'first_name'   => self::get_first_name( $full_name ),
				'last_name'    => self::get_last_name( $full_name ),
				'role'         => apply_filters( 'radius_booking_default_customer_role', 'radius_booking_customer' ),

			);

			/**
			 * Filter user data before insertion.
			 *
			 * @param array $user_data User data array.
			 *
			 * @since 1.0.0
			 */
			$user_data = apply_filters( 'radius_booking_signup_user_data', $user_data );

			// Create the user.
			$user_id = wp_insert_user( $user_data );

			if ( $user_id ) {
				$customer_data = array(
					'first_name' => $user_data['first_name'] ?? '',
					'last_name'  => $user_data['last_name'] ?? '',
					'email'      => $user_data['user_email'] ?? '',
					'user_type'  => 'customer',
					'wp_user_id' => $user_id
				);
				$customer      = Container::resolve( UserService::class );
				$customer->createUser( $customer_data );
			}

			if ( is_wp_error( $user_id ) ) {
				throw new \Exception( $user_id->get_error_message() );
			}

			// Save phone number as user meta.
			if ( ! empty( $phone ) ) {
				update_user_meta( $user_id, 'radius_booking_phone', $phone );
			}

			// Save marketing consent if provided.
			if ( isset( $_POST['marketing_consent'] ) && ! empty( $_POST['marketing_consent'] ) ) {
				update_user_meta( $user_id, 'radius_booking_marketing_consent', 'yes' );
			}

			/**
			 * Fires after a new user is created.
			 *
			 * @param int $user_id The new user ID.
			 * @param array $user_data User data array.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_after_signup', $user_id, $user_data );

			// Auto-login the user.
			$creds = array(
				'user_login'    => $email,
				'user_password' => $password,
				'remember'      => true,
			);

			$user = wp_signon( $creds, is_ssl() );

			if ( is_wp_error( $user ) ) {
				throw new \Exception( $user->get_error_message() );
			}

			// Determine redirect URL.
			$redirect_url = self::get_redirect_url( 'signup' );

			/**
			 * Fires after successful signup and login.
			 *
			 * @param int $user_id The user ID.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_signup_success', $user_id );

			wp_send_json_success(
				array(
					'message'      => __( 'Account created successfully.', 'radius-booking' ),
					'redirect_url' => $redirect_url,
				)
			);

		} catch ( \Exception $e ) {
			/**
			 * Fires when signup fails.
			 *
			 * @param string $error_message Error message.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_signup_failed', $e->getMessage() );

			wp_send_json_error(
				array(
					'message' => $e->getMessage(),
				)
			);
		}
	}

	/**
	 * Handle the login action via AJAX.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public static function login() {
		$nonce_value = isset( $_REQUEST['radius_booking_login_nonce'] )
			? sanitize_text_field( wp_unslash( $_REQUEST['radius_booking_login_nonce'] ) )
			: '';

		$valid_nonce = wp_verify_nonce( $nonce_value, 'radius-booking-login' );

		if ( ! $valid_nonce ) {
			wp_send_json_error(
				array(
					'message' => __( 'Security check failed. Please refresh the page and try again.', 'radius-booking' ),
				)
			);
		}

		if ( ! isset( $_POST['username'], $_POST['password'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Please fill in all required fields.', 'radius-booking' ),
				)
			);
		}

		try {
			$username = sanitize_text_field( wp_unslash( $_POST['username'] ) );
			$password = sanitize_text_field( wp_unslash( $_POST['password'] ) );
			$remember = isset( $_POST['rememberme'] ) && ! empty( $_POST['rememberme'] );

			// Validate username.
			if ( empty( $username ) ) {
				throw new \Exception( __( 'Username or email is required.', 'radius-booking' ) );
			}

			// Validate password.
			if ( empty( $password ) ) {
				throw new \Exception( __( 'Password is required.', 'radius-booking' ) );
			}

			/**
			 * Filter to add custom validation errors during login.
			 *
			 * @param \WP_Error $errors Validation errors.
			 * @param string $username Username or email.
			 *
			 * @since 1.0.0
			 */
			$validation_errors = apply_filters(
				'radius_booking_login_validation_errors',
				new \WP_Error(),
				$username
			);

			if ( $validation_errors->has_errors() ) {
				throw new \Exception( $validation_errors->get_error_message() );
			}

			// Handle multisite - ensure user exists on current site.
			if ( is_multisite() ) {
				$user_data = get_user_by( is_email( $username ) ? 'email' : 'login', $username );

				if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
					add_user_to_blog( get_current_blog_id(), $user_data->ID, 'subscriber' );
				}
			}

			/**
			 * Fires before login attempt.
			 *
			 * @param string $username Username or email.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_before_login', $username );

			// Perform the login.
			$creds = array(
				'user_login'    => $username,
				'user_password' => $password,
				'remember'      => $remember,
			);

			$user = wp_signon( $creds, is_ssl() );

			if ( is_wp_error( $user ) ) {
				throw new \Exception( __( 'Invalid username or password.', 'radius-booking' ) );
			}

			// Determine redirect URL.
			$redirect_url = self::get_redirect_url( 'login' );

			/**
			 * Fires after successful login.
			 *
			 * @param \WP_User $user The logged in user.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_login_success', $user );

			wp_send_json_success(
				array(
					'message'      => __( 'Successfully logged in.', 'radius-booking' ),
					'redirect_url' => $redirect_url,
				)
			);

		} catch ( \Exception $e ) {
			/**
			 * Fires when login fails.
			 *
			 * @param string $error_message Error message.
			 *
			 * @since 1.0.0
			 */
			do_action( 'radius_booking_login_failed', $e->getMessage() );

			wp_send_json_error(
				array(
					'message' => $e->getMessage(),
				)
			);
		}
	}


	/**
	 * Get the redirect URL after authentication.
	 *
	 * @param string $context The authentication context ('login' or 'signup').
	 *
	 * @return string Redirect URL.
	 * @since 1.0.0
	 */
	private static function get_redirect_url( $context = 'login' ) {
		// Check for custom redirect URL in POST data.
		if ( isset( $_POST['redirect_to'] ) && ! empty( $_POST['redirect_to'] ) ) {
			return esc_url_raw( wp_unslash( $_POST['redirect_to'] ) );
		}

		// Default to current URL.
		$default_redirect = self::get_current_url();

		/**
		 * Filter the redirect URL after authentication.
		 *
		 * @param string $redirect_url The redirect URL.
		 * @param string $context The authentication context ('login' or 'signup').
		 *
		 * @since 1.0.0
		 */
		return apply_filters( 'radius_booking_auth_redirect_url', $default_redirect, $context );
	}

	/**
	 * Get the current page URL.
	 *
	 * @return string Current URL.
	 * @since 1.0.0
	 */
	private static function get_current_url() {
		global $wp;

		// Try to get from referer first (more reliable for AJAX).
		if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
			return esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) );
		}

		// Fallback to home URL with current request.
		return home_url( add_query_arg( array(), $wp->request ) );
	}

	/**
	 * Extract first name from full name.
	 *
	 * @param string $full_name The full name.
	 *
	 * @return string First name.
	 * @since 1.0.0
	 */
	private static function get_first_name( $full_name ) {
		if ( empty( $full_name ) ) {
			return '';
		}

		$parts = explode( ' ', trim( $full_name ), 2 );

		return isset( $parts[0] ) ? $parts[0] : '';
	}

	/**
	 * Extract last name from full name.
	 *
	 * @param string $full_name The full name.
	 *
	 * @return string Last name.
	 * @since 1.0.0
	 */
	private static function get_last_name( $full_name ) {
		if ( empty( $full_name ) ) {
			return '';
		}

		$parts = explode( ' ', trim( $full_name ), 2 );

		return isset( $parts[1] ) ? $parts[1] : '';
	}
}