<?php
/**
 * Registration Functions
 *
 * Processes the registration form
 *
 * @package     Leaky Paywall
 * @subpackage  Login Functions
 * @copyright   Copyright (c) 2016, Zeen101 Development Team
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       4.0.0
 */

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

/**
 * Regsiter a new user
 *
 * @since 4.0.0
 */
function leaky_paywall_process_registration() {
	if ( ! isset( $_POST['leaky_paywall_register_nonce'] ) ) {
		return;
	}

	if ( ! wp_verify_nonce( sanitize_key( $_POST['leaky_paywall_register_nonce'] ), 'leaky-paywall-register-nonce' ) ) {
		leaky_paywall_log('failed nonce verification', 'lp error - register nonce not verified for process registration');
		return;
	}

	$settings = get_leaky_paywall_settings();
	$mode     = leaky_paywall_get_current_mode();
	$site     = leaky_paywall_get_current_site();
	$level_id = isset( $_POST['level_id'] ) ? absint( $_POST['level_id'] ) : false;
	$level    = get_leaky_paywall_subscription_level( $level_id );

	// get the selected payment method.
	// leaving this here for backwards compatibility.
	if ( ! isset( $_POST['gateway'] ) ) {
		$gateway = 'paypal';
	} else {
		$gateway = sanitize_text_field( wp_unslash( $_POST['gateway'] ) );
	}

	if ( isset( $_POST['payment_method'] ) ) {
		$gateway = sanitize_text_field( wp_unslash( $_POST['payment_method'] ) );
	}

	/**
	 * Validate the Form
	 */
	// already done via ajax for Stripe transactions.

	$user_data = leaky_paywall_validate_user_data();

	// Prevent duplicate subscriptions: if a logged-in user already has an
	// active subscription at this level, stop the registration flow before
	// any gateway interaction.
	if ( is_user_logged_in() && leaky_paywall_user_has_active_subscription_at_level( null, $level_id ) ) {
		leaky_paywall_errors()->add(
			'duplicate_subscription',
			__( 'You are already subscribed to this level.', 'leaky-paywall' )
		);
		return;
	}

	// retrieve all error messages, if any.
	$errors = leaky_paywall_errors()->get_error_messages();

	// only send to gateway if their are no errors.
	if ( ! empty( $errors ) ) {
		return;
	}

	$subscription_data = apply_filters(
		'leaky_paywall_subscription_data',
		array(
			'amount'          => $level['price'],
			'description'     => $level['label'],
			'user_id'         => $user_data['id'],
			'user_name'       => $user_data['login'],
			'user_email'      => $user_data['email'],
			'first_name'      => $user_data['first_name'],
			'last_name'       => $user_data['last_name'],
			'level_id'        => $level_id,
			'subscriber_id'   => '',
			'created'         => gmdate( 'Y-m-d H:i:s' ),
			'price'           => $level['price'],
			'plan'            => isset( $_POST['plan_id'] ) ? sanitize_text_field( wp_unslash( $_POST['plan_id'] ) ) : '',
			'currency'        => leaky_paywall_get_currency(),
			'interval_count'  => $level['interval_count'],
			'interval'        => $level['interval'],
			'recurring'       => isset( $_POST['recurring'] ) ? sanitize_text_field( wp_unslash( $_POST['recurring'] ) ) : '',
			'site'            => $site,
			'new_user'        => $user_data['need_new'],
			'payment_gateway' => $gateway,
			'mode'            => $mode,
			'post_data'       => $_POST,
		)
	);

	/**
	 * Send all data to the gateway for processing
	 */
	$gateway_data = leaky_paywall_send_to_gateway( $gateway, $subscription_data );

	// Validate extra fields in gateways.
	do_action( 'leaky_paywall_form_errors', $_POST, $level_id );

	// retrieve all error messages, if any.
	$errors = leaky_paywall_errors()->get_error_messages();

	// only create the user if there are no errors.
	if ( ! empty( $errors ) ) {
		return;
	}

	/**
	 * Merge all data before creating/updating the subscriber
	 */
	$subscriber_data = apply_filters( 'leaky_paywall_registration_user_meta', array_merge( $user_data, $gateway_data ), $user_data );

	if ( apply_filters( 'leaky_paywall_use_alternative_subscriber_registration', false, $subscriber_data, $level ) ) {
		do_action( 'leaky_paywall_alternative_subscriber_registration', $subscriber_data, $level );
	} else {
		leaky_paywall_subscriber_registration( $subscriber_data );
	}
}
add_action( 'init', 'leaky_paywall_process_registration', 100 );

/**
 * Complete the registration process after data is processed by gateway.
 * This allows both the registration form and subscribe card buttons to prepare
 * the subscriber data as needed, and then hand off the subscriber creation here.
 *
 * @since 4.9.3
 *
 * @param array $subscriber_data The subscriber data.
 */
function leaky_paywall_subscriber_registration( $subscriber_data ) {

	if (
		! isset( $_POST['leaky_paywall_register_nonce'] )
		|| ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['leaky_paywall_register_nonce'] ) ), 'leaky-paywall-register-nonce' )
	) {
		leaky_paywall_log($subscriber_data['subscriber_email'], 'lp error - register nonce not verified for subscriber registration' );
	   return;
	}

	$settings = get_leaky_paywall_settings();
	$mode     = leaky_paywall_get_current_mode();
	$site     = leaky_paywall_get_current_site();

	/**
	 * Create or update the WP user for this subscriber
	 */
	if ( is_user_logged_in() || ! empty( $subscriber_data['existing_customer'] ) ) {
		$status  = 'update';
		$user_id = leaky_paywall_update_subscriber( null, $subscriber_data['subscriber_email'], $subscriber_data['subscriber_id'], $subscriber_data );
	} else {
		$status = 'new';

		// create password here so we can send it to the email.
		if ( ! $subscriber_data['password'] ) {
			$subscriber_data['password'] = wp_generate_password();
		}

		$user_id = leaky_paywall_new_subscriber( null, $subscriber_data['subscriber_email'], $subscriber_data['subscriber_id'], $subscriber_data );
	}

	if ( empty( $user_id ) ) {
		leaky_paywall_errors()->add( 'user_not_created', __( 'A user could not be created. Please check your details and try again.', 'leaky-paywall' ), 'register' );
		return;
	}

	$subscriber_data['user_id'] = $user_id;

	if ( leaky_paywall_is_free_registration( $subscriber_data ) ) {
		do_action( 'leaky_paywall_after_free_user_created', $user_id, $_POST );
	}

	do_action( 'leaky_paywall_form_processing', $_POST, $user_id, $subscriber_data['price'], $mode, $site, $subscriber_data['level_id'] );

	$transaction                       = new LP_Transaction( $subscriber_data );
	$transaction_id                    = $transaction->create();
	$subscriber_data['transaction_id'] = $transaction_id;

	leaky_paywall_cleanup_incomplete_user( $subscriber_data['email'] );

	// Send email notifications.
	leaky_paywall_email_subscription_status( $user_id, $status, $subscriber_data );

	// log the user in.
	leaky_paywall_log_in_user( $user_id );

	do_action( 'leaky_paywall_after_process_registration', $subscriber_data );

	$restrictions = new Leaky_Paywall_Restrictions();
	$restrictions->clear_cookie();

	if ( isset( $_COOKIE['lp_nag_loc'] ) ) {
		update_post_meta( $transaction_id, '_nag_location_id', absint( $_COOKIE['lp_nag_loc'] ) );
	}

	// send the newly created user to the appropriate page after logging them in.
	wp_safe_redirect( leaky_paywall_get_redirect_url( $settings, $subscriber_data ) );
	exit;
}

/**
 * Validate first step of multistep registration form
 *
 * @since  4.0.0
 */
function leaky_paywall_process_user_registration_validation() {

	if ( ! check_ajax_referer( 'lp_register_nonce', 'register_nonce', false ) ) {
		$errors['nonce'] = array(
			'message' => __( 'There was an error. Please try again.', 'leaky-paywall' ),
		);
	}

	$form_data = isset( $_POST['form_data'] ) ? htmlspecialchars_decode( wp_kses_post( wp_unslash( $_POST['form_data'] ) ) ) : '';
	parse_str( $form_data, $fields );

	$user     = array();
	$errors   = array();
	$settings = get_leaky_paywall_settings();
	$mode     = leaky_paywall_get_current_mode();
	$site     = leaky_paywall_get_current_site();
	$level_id = $fields['level_id'];
	$level    = get_leaky_paywall_subscription_level( $level_id );

	if ( is_user_logged_in() ) {
		$userdata           = wp_get_current_user();
		$user['id']         = $userdata->ID;
		$user['login']      = $userdata->user_login;
		$user['email']      = $userdata->user_email;
		$user['first_name'] = $fields['first_name'];
		$user['last_name']  = $fields['last_name'];
		$user['level_id']   = $level_id;
		$user['need_new']   = false;
	} else {
		$user['id']               = 0;
		$user['login']            = 'off' === $settings['remove_username_field'] ? $fields['username'] : $fields['email_address'];
		$user['password']         = $fields['password'];
		$user['confirm_password'] = $fields['confirm_password'];
		$user['email']            = $fields['email_address'];
		$user['first_name']       = $fields['first_name'];
		$user['last_name']        = $fields['last_name'];
		$user['level_id']         = $level_id;
		$user['need_new']         = true;
	}

	if ( empty( $user['first_name'] ) ) {
		$errors['firstname_empty'] = array(
			'message' => __( 'Please enter your first name', 'leaky-paywall' ),
		);
	}

	if ( empty( $user['last_name'] ) ) {
		$errors['lastname_empty'] = array(
			'message' => __( 'Please enter your last name', 'leaky-paywall' ),
		);
	}

	if ( ! is_email( $user['email'] ) ) {
		$errors['email_invalid'] = array(
			'message' => __( 'Invalid email', 'leaky-paywall' ),
		);
	}

	if ( ! is_user_logged_in() && email_exists( $user['email'] ) ) {
		$errors['email_exists'] = array(
			'message' => __( 'Email already exists. Please log in.', 'leaky-paywall' ),
		);
	}

	if ( 'off' === $settings['remove_username_field'] ) {
		if ( ! validate_username( $user['login'] ) ) {
			$errors['username_invalid'] = array(
				'message' => __( 'Invalid username', 'leaky-paywall' ),
			);
		}

		if ( ! is_user_logged_in() && username_exists( $user['login'] ) ) {
			$errors['email_exists'] = array(
				'message' => __( 'Username already exists. Please log in or try a different one.', 'leaky-paywall' ),
			);
		}
	}

	if ( 0 === $user['id'] && empty( $user['password'] ) ) {
		$errors['password_empty'] = array(
			'message' => __( 'Please enter a password', 'leaky-paywall' ),
		);
	}

	if ( 0 === $user['id'] && $user['password'] !== $user['confirm_password'] ) {
		$errors['password_mismatch'] = array(
			'message' => __( 'Passwords do not match', 'leaky-paywall' ),
		);
	}

	if ( 'on' === $settings['enable_terms_and_conditions'] && empty( $fields['terms_and_conditions'] ) ) {
		$errors['terms_not_accepted'] = array(
			'message' => __( 'You must agree to the terms and conditions.', 'leaky-paywall' ),
		);
	}

	// allow 3rd party plugins to validate account setup data.
	$errors = apply_filters( 'leaky_paywall_account_setup_validation', $errors, $fields );

	// Prevent duplicate subscriptions: block logged-in users who already have
	// an active subscription at this level.
	if ( is_user_logged_in() && leaky_paywall_user_has_active_subscription_at_level( null, $level_id ) ) {
		$errors['duplicate_subscription'] = array(
			'message' => __( 'You are already subscribed to this level.', 'leaky-paywall' ),
		);
	}

	if ( ! empty( $errors ) ) {
		$return = array(
			'errors' => $errors,
		);
		wp_send_json( $return );
	}

	// if free level, return
	if ($level['price'] < 0.5 ) {
		$return = array(
			'success' => 1,
			'level_type' => 'free'
		);
		wp_send_json($return);
	}

	// if stripe payment method is not active, we are done.
	$enabled_gateways = leaky_paywall_get_enabled_payment_gateways();

	if ( array_key_exists( 'stripe_checkout', $enabled_gateways ) ) {

		$stripe = leaky_paywall_initialize_stripe_api();

		$stripe_price = apply_filters( 'leaky_paywall_stripe_checkout_price', number_format( (float) $level['price'], 2, '', '' ), $fields );
		$stripe_currency = apply_filters( 'leaky_paywall_stripe_checkout_currency', leaky_paywall_get_currency(), $fields );

		// create Stripe customer.
		$customer_array = array(
			'name'        => $user['first_name'] . ' ' . $user['last_name'],
			'email'       => $user['email'],
			'description' => $level['label'],
		);

		$customer_array = apply_filters( 'leaky_paywall_process_stripe_payment_customer_array', $customer_array, $fields );

		try {
			$cu = $stripe->customers->create( $customer_array, leaky_paywall_get_stripe_connect_params() );
		} catch ( \Throwable $th ) {
			$errors['stripe_customer'] = array(
				'message' => __( 'Could not create customer.', 'leaky-paywall' ),
			);
		}

		if ( ! empty( $errors ) ) {
			$return = array(
				'errors' => $errors,
			);
			wp_send_json( $return );
		}

		if ( isset( $level['recurring'] ) && 'on' === $level['recurring'] ) {

			$plan_args = array(
				'stripe_price' => $stripe_price,
				'currency'     => $stripe_currency,
				'secret_key'   => leaky_paywall_get_stripe_secret_key(),
			);

			$stripe_plan = leaky_paywall_get_stripe_plan( $level, $level_id, $plan_args );

			if ( $stripe_plan ) {

				$stripe_session_args = array(
					'customer'             => $cu->id,
					'currency'    			=> $stripe_currency,
					'mode'                 => 'subscription',
					'success_url'          => leaky_paywall_get_stripe_checkout_success_url() . '?lp_stripe_checkout_success=true',
					'cancel_url'           => home_url() . '?lp_stripe_checkout_cancel=true',
				);

				if ( 'on' === $settings['stripe_automatic_tax'] ) {
					$stripe_session_args['automatic_tax'] = array( 'enabled' => true );
				}

				$stripe_session_args['line_items'] = array(
					array(
						'price'    => $stripe_plan->id,
						'quantity' => 1,
					),
				);

				try {
					$checkout_session = $stripe->checkout->sessions->create(
						apply_filters( 'leaky_paywall_stripe_session_recurring_args', $stripe_session_args, $level ),
						leaky_paywall_get_stripe_connect_params()
					);
				} catch ( \Throwable $th ) {
					$errors['checkout_session'] = array(
						'message' => $th->getMessage(),
					);
				}
			} else {
				$errors['checkout_session'] = array(
					'message' => 'No subscription plan found.',
				);
			}
		} else {
			try {

				$stripe_session_args = array(
					'customer'             => $cu->id,
					'currency'     => $stripe_currency,
					'customer_update'		=> array(
						'address'	=> 'auto'
					),
					'mode'                 => 'payment',
					'success_url'          => leaky_paywall_get_stripe_checkout_success_url() . '?lp_stripe_checkout_success=true',
					'cancel_url'           => home_url() . '?lp_stripe_checkout_cancel=true',
				);

				if ( 'on' === $settings['stripe_automatic_tax'] ) {
					$stripe_session_args['automatic_tax'] = array( 'enabled' => true );
					$stripe_session_args['line_items'] = array(
						array(
							'price_data' => array(
								'product_data' => array(
									'name' => $level['label'],
								),
								'tax_behavior' => $settings['stripe_tax_behavior'],
								'currency'     => $stripe_currency,
								'unit_amount'  => $stripe_price,
							),
							'quantity'   => 1,
						),
					);
				} else {
					$stripe_session_args['line_items'] = array(
						array(
							'price_data' => array(
								'product_data' => array(
									'name' => $level['label'],
								),
								'currency'     => $stripe_currency,
								'unit_amount'  => $stripe_price,
							),
							'quantity'   => 1,
						),
					);
				}

				$checkout_session = $stripe->checkout->sessions->create(
					apply_filters( 'leaky_paywall_stripe_session_nonrecurring_args', $stripe_session_args, $level ),
					leaky_paywall_get_stripe_connect_params()
				);
			} catch ( \Throwable $th ) {
				$errors['checkout_session'] = array(
					'message' => $th->getMessage(),
				);
			}
		}

		if ( ! empty( $errors ) ) {
			$return = array(
				'errors' => $errors,
			);
			wp_send_json( $return );
		}

		if (isset($_COOKIE['lp_nag_loc'])) {
			$fields['lp_nag_loc'] = absint($_COOKIE['lp_nag_loc']);
		}

		$fields = apply_filters( 'leaky_paywall_stripe_checkout_fields', $fields );

		leaky_paywall_create_incomplete_user( $user, $cu, $fields );

		$return = array(
			'success'    => 1,
			'session_id' => $checkout_session->id,
		);

		wp_send_json( $return );
	}

	if ( !array_key_exists('stripe', $enabled_gateways)) {

		$return = array(
			'success' => 1,
		);

		wp_send_json( $return );
	}

	$subscriber_id              = get_user_meta( $user['id'], '_issuem_leaky_paywall_' . $mode . '_subscriber_id' . $site, true );
	$subscriber_payment_gateway = get_user_meta( $user['id'], '_issuem_leaky_paywall_' . $mode . '_payment_gateway' . $site, true );

	$stripe = leaky_paywall_initialize_stripe_api();
	// $customer_params = apply_filters('leaky_paywall_process_stripe_payment_customer_params', [], $level);

	if ( ! empty( $subscriber_id ) && 'stripe' === $subscriber_payment_gateway ) {

		// retrieve Stripe customer.
		try {
			$cu = $stripe->customers->retrieve( $subscriber_id, [], leaky_paywall_get_stripe_connect_params() );
		} catch ( \Throwable $th ) {
			leaky_paywall_log($th->getMessage(), 'lp error - Could not retrieve Stripe customer');
			$errors['stripe_customer'] = array(
				'message' => __( 'Could not retrieve customer.', 'leaky-paywall' ),
			);
		}
	} else {

		// create Stripe customer.
		$customer_array = array(
			'name'        => $user['first_name'] . ' ' . $user['last_name'],
			'email'       => $user['email'],
			'description' => $level['label'],
		);

		$customer_array = apply_filters( 'leaky_paywall_process_stripe_payment_customer_array', $customer_array, $fields );

		try {
			$cu = $stripe->customers->create( $customer_array, leaky_paywall_get_stripe_connect_params() );
		} catch ( \Throwable $th ) {

			leaky_paywall_log($th->getMessage(), 'lp error - Could not create Stripe customer');

			$errors['stripe_customer'] = array(
				'message' => __( 'Could not create customer.', 'leaky-paywall' ),
			);
		}
	}

	if ( ! empty( $errors ) ) {
		$return = array(
			'errors' => $errors,
		);
		wp_send_json( $return );
	}

	// temporary place to store the data.
	leaky_paywall_create_incomplete_user( $user, $cu, $fields );

	// if recurring, create a pending subscription
	if ( isset( $level['recurring'] ) && 'on' === $level['recurring'] ) {

		// When automatic tax is enabled, defer subscription creation until the billing
		// address is collected in step 2. The tax preview handler will create the subscription
		// with automatic_tax enabled and return the client_secret.
		if ( 'on' === $settings['stripe_automatic_tax'] && 'on' === $settings['stripe_billing_address'] ) {
			$return = array(
				'success'            => 1,
				'customer_id'        => $cu->id,
				'deferred_tax'       => true,
			);
			wp_send_json( $return );
		}

		$client_secret = leaky_paywall_create_stripe_subscription( $cu, $fields );

		if ( 'subscription_updated' === $client_secret ) {
			$return = array(
				'success'              => 1,
				'subscription_updated' => true,
			);
		} elseif ( $client_secret ) {
			$return = array(
				'success'       => 1,
				'customer_id'   => $cu->id,
				'client_secret' => $client_secret,
			);
		} else {
			$errors['subscription_create'] = array(
				'message' => __( 'Could not create subscription', 'leaky-paywall' ),
			);

			$return = array(
				'errors' => $errors,
			);
		}
		wp_send_json( $return );
	}

	// if not recurring, create a payment intent
	$stripe_price = number_format( floatval( $level['price'] ), 2, '', '' );

	// When automatic tax is enabled, defer payment intent creation until the billing
	// address is collected in step 2. The tax preview handler will create the payment
	// intent with the tax-inclusive amount.
	if ( 'on' === $settings['stripe_automatic_tax'] && 'on' === $settings['stripe_billing_address'] ) {
		$return = array(
			'success'      => 1,
			'customer_id'  => $cu->id,
			'deferred_tax' => true,
		);
		wp_send_json( $return );
	}

	$intent_args = apply_filters(
		'leaky_paywall_payment_intent_args',
		array(
			'amount'             => $stripe_price,
			'currency'           => leaky_paywall_get_currency(),
			'setup_future_usage' => 'off_session',
			'customer'           => $cu->id,
			'description'        => $level['label'],
			'receipt_email'		 => $user['email']
		),
		$level
	);

	// $intent_params = apply_filters( 'leaky_paywall_payment_intent_params', [], $level );

	try {
		$intent = $stripe->paymentIntents->create( $intent_args, leaky_paywall_get_stripe_connect_params() );
	} catch ( \Throwable $th ) {

		leaky_paywall_log($th->getMessage(), 'lp error - Could not create Stripe payment intent' );

		$errors['payment_intent'] = array(
			'message' => __( 'Could not create payment intent.', 'leaky-paywall' ),
		);
	}

	if ( ! empty( $errors ) ) {
		$return = array(
			'errors' => $errors,
		);
		wp_send_json( $return );
	}

	$return = array(
		'success'   => 1,
		'pi_client' => $intent->client_secret,
		'pi_id'     => $intent->id,
	);

	wp_send_json( $return );
}
add_action( 'wp_ajax_nopriv_leaky_paywall_process_user_registration_validation', 'leaky_paywall_process_user_registration_validation' );
add_action( 'wp_ajax_leaky_paywall_process_user_registration_validation', 'leaky_paywall_process_user_registration_validation' );

/**
 * Validate and setup the user data for registration
 *
 * @since  4.0.0
 */
function leaky_paywall_validate_user_data() {

	if (
		! isset( $_POST['leaky_paywall_register_nonce'] )
		|| ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['leaky_paywall_register_nonce'] ) ), 'leaky-paywall-register-nonce' )
	) {
		leaky_paywall_errors()->add( 'not_verified', __( 'Your submission could not be processed.', 'leaky-paywall' ), 'register' );
	   return;
	}

	$user     = array();
	$settings = get_leaky_paywall_settings();

	if ( ! is_user_logged_in() ) {

		if ( 'off' === $settings['remove_username_field'] ) {
			$user_login = isset( $_POST['username'] ) ? sanitize_text_field( wp_unslash( $_POST['username'] ) ) : '';
		} else {
			$user_login = isset( $_POST['email_address'] ) ? sanitize_email( wp_unslash( $_POST['email_address'] ) ) : '';
		}

		$user['id']               = 0;
		$user['login']            = $user_login;
		$user['password']         = isset( $_POST['password'] ) ? sanitize_text_field( wp_unslash( $_POST['password'] ) ) : '';
		$user['confirm_password'] = isset( $_POST['confirm_password'] ) ? sanitize_text_field( wp_unslash( $_POST['confirm_password'] ) ) : '';
		$user['email']            = isset( $_POST['email_address'] ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
		$user['first_name']       = isset( $_POST['first_name'] ) ? sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) : '';
		$user['last_name']        = isset( $_POST['last_name'] ) ? sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) : '';
		$user['need_new']         = true;
	} else {
		$userdata           = get_userdata( get_current_user_id() );
		$user['id']         = $userdata->ID;
		$user['login']      = $userdata->user_login;
		$user['email']      = $userdata->user_email;
		$user['first_name'] = isset( $_POST['first_name'] ) ? sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) : '';
		$user['last_name']  = isset( $_POST['last_name'] ) ? sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) : '';
		$user['need_new']   = false;
	}

	if ( 'on' === $settings['enable_terms_and_conditions'] && empty( $_POST['terms_and_conditions'] ) ) {
		leaky_paywall_errors()->add( 'terms_not_accepted', __( 'You must agree to the terms and conditions.', 'leaky-paywall' ), 'register' );
	}

	if ( isset( $_POST['payment_method'] ) && 'stripe' === $_POST['payment_method'] ) {
		return apply_filters( 'leaky_paywall_user_registration_data', $user );
	}

	if ( empty( $user['first_name'] ) ) {
		leaky_paywall_errors()->add( 'firstname_empty', __( 'Please enter your first name', 'leaky-paywall' ), 'register' );
	}

	if ( empty( $user['last_name'] ) ) {
		leaky_paywall_errors()->add( 'lastname_empty', __( 'Please enter your last name', 'leaky-paywall' ), 'register' );
	}

	if ( ! is_email( $user['email'] ) ) {
		leaky_paywall_errors()->add( 'email_invalid', __( 'Invalid email', 'leaky-paywall' ), 'register' );
	}

	if ( 'off' === $settings['remove_username_field'] ) {
		if ( ! validate_username( $user['login'] ) ) {
			leaky_paywall_errors()->add( 'username_invalid', __( 'Invalid username', 'leaky-paywall' ), 'register' );
		}
	}

	if ( ! is_user_logged_in() && empty( $user['password'] ) ) {
		leaky_paywall_errors()->add( 'password_empty', __( 'Please enter a password', 'leaky-paywall' ), 'register' );
	}

	if ( ! is_user_logged_in() && $user['password'] !== $user['confirm_password'] ) {
		leaky_paywall_errors()->add( 'password_mismatch', __( 'Passwords do not match', 'leaky-paywall' ), 'register' );
	}

	if ( $user['need_new'] ) {

		if ( email_exists( $user['email'] ) ) {
			/* Translators: %s - login url */
			leaky_paywall_errors()->add( 'email_used', wp_kses_post( sprintf( __( 'Email already registered. Please <a href="%s">login</a>.', 'leaky-paywall' ), esc_url( get_page_link( $settings['page_for_login'] ) ) ) ), 'register' );
		}

		if ( username_exists( $user['login'] ) ) {
			leaky_paywall_errors()->add( 'username_unavailable', __( 'Username already taken', 'leaky-paywall' ), 'register' );
		}

		if ( empty( $user['login'] ) ) {
			leaky_paywall_errors()->add( 'username_empty', __( 'Please enter a username', 'leaky-paywall' ), 'register' );
		}
	}

	return apply_filters( 'leaky_paywall_user_registration_data', $user );
}

/**
 * Validate a potential username
 *
 * @access      public
 * @since       4.0.0
 * @param       string $username The username to validate.
 * @return      bool
 */
function leaky_paywall_validate_username( $username = '' ) {
	$sanitized = sanitize_user( $username, false );
	$valid     = ( $sanitized == strtolower( $username ) );
	return (bool) apply_filters( 'leaky_paywall_validate_username', $valid, $username );
}


/**
 * Display the credit card fields on the registration form
 *
 * @since  4.0.0
 */
function leaky_paywall_card_form() {
	?>

	<div class="leaky-paywall-card-details">

		<fieldset id="leaky-paywall-credit-card-form">

			<p class="form-row">
				<label><?php printf( esc_attr__( 'Name on Card', 'leaky-paywall' ) ); ?> <i class="required">*</i></label>
				<input type="text" size="20" name="card_name" class="card-name" value="<?php leaky_paywall_old_form_value( 'card_name' ); ?>" />
			</p>

			<p class="form-row">
				<label><?php printf( esc_attr__( 'Card Number', 'leaky-paywall' ) ); ?> <i class="required">*</i></label>
				<input type="text" size="20" name="card_num" class="card-num" value="<?php leaky_paywall_old_form_value( 'card_num' ); ?>" />
			</p>

			<p class="form-row">
				<label><?php printf( esc_attr__( 'CVC', 'leaky-paywall' ) ); ?> <i class="required">*</i></label>
				<input type="text" size="4" name="cvc" class="cvc" value="<?php leaky_paywall_old_form_value( 'cvc' ); ?>" />
			</p>

			<p class="form-row">
				<label><?php printf( esc_attr__( 'Card Zip or Postal Code', 'leaky-paywall' ) ); ?> <i class="required">*</i></label>
				<input type="text" size="20" name="card_zip" class="card-zip" value="<?php leaky_paywall_old_form_value( 'card_zip' ); ?>" />
			</p>

			<p class="form-row">
				<label><?php printf( esc_attr__( 'Expiration (MM/YYYY)', 'leaky-paywall' ) ); ?> <i class="required">*</i></label>
				<input type="text" size="2" name="exp_month" class="exp-month" value="<?php leaky_paywall_old_form_value( 'exp_month' ); ?>" /> / <input type="text" size="4" name="exp_year" class="exp-year" value="<?php leaky_paywall_old_form_value( 'exp_year' ); ?>" />
			</p>

		</fieldset>

	</div>

	<?php
}


/**
 * Display the full credit card fields on the registration form
 *
 * @since  4.0.0
 */
function leaky_paywall_card_form_full() {
	?>

	<style>
		.lp-card-form { max-width: 480px; }
		.lp-card-form fieldset { border: none; margin: 0 0 16px; padding: 0; }
		.lp-card-form legend { font-size: 14px; font-weight: 600; color: #32325d; margin-bottom: 8px; padding: 0; }
		.lp-card-form .lp-field-row { display: flex; gap: 12px; margin-bottom: 12px; }
		.lp-card-form .lp-field { flex: 1; display: flex; flex-direction: column; }
		.lp-card-form .lp-field--half { flex: 0 0 calc(50% - 6px); }
		.lp-card-form .lp-field--third { flex: 0 0 calc(33.33% - 8px); }
		.lp-card-form label { font-size: 12px; font-weight: 600; color: #6b7c93; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
		.lp-card-form input[type="text"],
		.lp-card-form input[type="tel"],
		.lp-card-form select { width: 100%; padding: 8px 10px; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 14px; color: #32325d; background: #fff; box-sizing: border-box; transition: border-color 0.15s; }
		.lp-card-form input:focus,
		.lp-card-form select:focus { border-color: #6772e5; outline: none; box-shadow: 0 0 0 1px rgba(103, 114, 229, 0.3); }
		.lp-card-form .lp-field-row--expiry-cvc select { min-width: 0; }
		.lp-card-form .lp-expiry-sep { align-self: flex-end; padding-bottom: 10px; color: #aab7c4; font-weight: 600; }
	</style>

	<div class="leaky-paywall-card-details leaky-paywall-card-form-full lp-card-form">

		<fieldset>
			<legend><?php esc_html_e( 'Billing Name', 'leaky-paywall' ); ?></legend>
			<div class="lp-field-row">
				<div class="lp-field lp-field--half">
					<label for="lp-card-first-name"><?php esc_html_e( 'First Name', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-first-name" name="card_first_name" class="card-first-name" placeholder="<?php esc_attr_e( 'Jane', 'leaky-paywall' ); ?>" />
				</div>
				<div class="lp-field lp-field--half">
					<label for="lp-card-last-name"><?php esc_html_e( 'Last Name', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-last-name" name="card_last_name" class="card-last-name" placeholder="<?php esc_attr_e( 'Doe', 'leaky-paywall' ); ?>" />
				</div>
			</div>
		</fieldset>

		<fieldset>
			<legend><?php esc_html_e( 'Billing Address', 'leaky-paywall' ); ?></legend>
			<div class="lp-field-row">
				<div class="lp-field">
					<label for="lp-card-address"><?php esc_html_e( 'Address', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-address" name="card_address" class="card-address" />
				</div>
			</div>
			<div class="lp-field-row">
				<div class="lp-field">
					<label for="lp-card-city"><?php esc_html_e( 'City', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-city" name="card_city" class="card-city" />
				</div>
				<div class="lp-field lp-field--third">
					<label for="lp-card-state"><?php esc_html_e( 'State', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-state" name="card_state" class="card-state" />
				</div>
				<div class="lp-field lp-field--third">
					<label for="lp-card-zip"><?php esc_html_e( 'ZIP', 'leaky-paywall' ); ?></label>
					<input required type="text" id="lp-card-zip" name="card_zip" class="card-zip" />
				</div>
			</div>
			<div class="lp-field-row">
				<div class="lp-field">
					<label for="lp-card-country"><?php esc_html_e( 'Country', 'leaky-paywall' ); ?></label>
					<select id="lp-card-country" name="card_country" class="card-country">
				<option value="">Country</option>
				<option value="US">United States</option>
				<option value="CA">Canada</option>
				<option value="AF">Afghanistan</option>
				<option value="AL">Albania</option>
				<option value="DZ">Algeria</option>
				<option value="AS">American Samoa</option>
				<option value="AD">Andorra</option>
				<option value="AO">Angola</option>
				<option value="AI">Anguilla</option>
				<option value="AQ">Antarctica</option>
				<option value="AG">Antigua and Barbuda</option>
				<option value="AR">Argentina</option>
				<option value="AM">Armenia</option>
				<option value="AW">Aruba</option>
				<option value="AU">Australia</option>
				<option value="AT">Austria</option>
				<option value="AZ">Azerbaidjan</option>
				<option value="BS">Bahamas</option>
				<option value="BH">Bahrain</option>
				<option value="BD">Bangladesh</option>
				<option value="BB">Barbados</option>
				<option value="BY">Belarus</option>
				<option value="BE">Belgium</option>
				<option value="BZ">Belize</option>
				<option value="BJ">Benin</option>
				<option value="BM">Bermuda</option>
				<option value="BT">Bhutan</option>
				<option value="BO">Bolivia</option>
				<option value="BA">Bosnia-Herzegovina</option>
				<option value="BW">Botswana</option>
				<option value="BV">Bouvet Island</option>
				<option value="BR">Brazil</option>
				<option value="IO">British Indian Ocean Territory</option>
				<option value="BN">Brunei Darussalam</option>
				<option value="BG">Bulgaria</option>
				<option value="BF">Burkina Faso</option>
				<option value="BI">Burundi</option>
				<option value="KH">Cambodia</option>
				<option value="CM">Cameroon</option>
				<option value="CV">Cape Verde</option>
				<option value="KY">Cayman Islands</option>
				<option value="CF">Central African Republic</option>
				<option value="TD">Chad</option>
				<option value="CL">Chile</option>
				<option value="CN">China</option>
				<option value="CX">Christmas Island</option>
				<option value="CC">Cocos (Keeling) Islands</option>
				<option value="CO">Colombia</option>
				<option value="KM">Comoros</option>
				<option value="CG">Congo</option>
				<option value="CK">Cook Islands</option>
				<option value="CR">Costa Rica</option>
				<option value="HR">Croatia</option>
				<option value="CU">Cuba</option>
				<option value="CY">Cyprus</option>
				<option value="CZ">Czech Republic</option>
				<option value="DK">Denmark</option>
				<option value="DJ">Djibouti</option>
				<option value="DM">Dominica</option>
				<option value="DO">Dominican Republic</option>
				<option value="TP">East Timor</option>
				<option value="EC">Ecuador</option>
				<option value="EG">Egypt</option>
				<option value="SV">El Salvador</option>
				<option value="GQ">Equatorial Guinea</option>
				<option value="ER">Eritrea</option>
				<option value="EE">Estonia</option>
				<option value="ET">Ethiopia</option>
				<option value="FK">Falkland Islands</option>
				<option value="FO">Faroe Islands</option>
				<option value="FJ">Fiji</option>
				<option value="FI">Finland</option>
				<option value="CS">Former Czechoslovakia</option>
				<option value="SU">Former USSR</option>
				<option value="FR">France</option>
				<option value="FX">France (European Territory)</option>
				<option value="GF">French Guyana</option>
				<option value="TF">French Southern Territories</option>
				<option value="GA">Gabon</option>
				<option value="GM">Gambia</option>
				<option value="GE">Georgia</option>
				<option value="DE">Germany</option>
				<option value="GH">Ghana</option>
				<option value="GI">Gibraltar</option>
				<option value="GB">Great Britain</option>
				<option value="GR">Greece</option>
				<option value="GL">Greenland</option>
				<option value="GD">Grenada</option>
				<option value="GP">Guadeloupe (French)</option>
				<option value="GU">Guam (USA)</option>
				<option value="GT">Guatemala</option>
				<option value="GN">Guinea</option>
				<option value="GW">Guinea Bissau</option>
				<option value="GY">Guyana</option>
				<option value="HT">Haiti</option>
				<option value="HM">Heard and McDonald Islands</option>
				<option value="HN">Honduras</option>
				<option value="HK">Hong Kong</option>
				<option value="HU">Hungary</option>
				<option value="IS">Iceland</option>
				<option value="IN">India</option>
				<option value="ID">Indonesia</option>
				<option value="INT">International</option>
				<option value="IR">Iran</option>
				<option value="IQ">Iraq</option>
				<option value="IE">Ireland</option>
				<option value="IL">Israel</option>
				<option value="IT">Italy</option>
				<option value="CI">Ivory Coast (Cote D&#39;Ivoire)</option>
				<option value="JM">Jamaica</option>
				<option value="JP">Japan</option>
				<option value="JO">Jordan</option>
				<option value="KZ">Kazakhstan</option>
				<option value="KE">Kenya</option>
				<option value="KI">Kiribati</option>
				<option value="KW">Kuwait</option>
				<option value="KG">Kyrgyzstan</option>
				<option value="LA">Laos</option>
				<option value="LV">Latvia</option>
				<option value="LB">Lebanon</option>
				<option value="LS">Lesotho</option>
				<option value="LR">Liberia</option>
				<option value="LY">Libya</option>
				<option value="LI">Liechtenstein</option>
				<option value="LT">Lithuania</option>
				<option value="LU">Luxembourg</option>
				<option value="MO">Macau</option>
				<option value="MK">Macedonia</option>
				<option value="MG">Madagascar</option>
				<option value="MW">Malawi</option>
				<option value="MY">Malaysia</option>
				<option value="MV">Maldives</option>
				<option value="ML">Mali</option>
				<option value="MT">Malta</option>
				<option value="MH">Marshall Islands</option>
				<option value="MQ">Martinique (French)</option>
				<option value="MR">Mauritania</option>
				<option value="MU">Mauritius</option>
				<option value="YT">Mayotte</option>
				<option value="MX">Mexico</option>
				<option value="FM">Micronesia</option>
				<option value="MD">Moldavia</option>
				<option value="MC">Monaco</option>
				<option value="MN">Mongolia</option>
				<option value="MS">Montserrat</option>
				<option value="MA">Morocco</option>
				<option value="MZ">Mozambique</option>
				<option value="MM">Myanmar</option>
				<option value="NA">Namibia</option>
				<option value="NR">Nauru</option>
				<option value="NP">Nepal</option>
				<option value="NL">Netherlands</option>
				<option value="AN">Netherlands Antilles</option>
				<option value="NT">Neutral Zone</option>
				<option value="NC">New Caledonia (French)</option>
				<option value="NZ">New Zealand</option>
				<option value="NI">Nicaragua</option>
				<option value="NE">Niger</option>
				<option value="NG">Nigeria</option>
				<option value="NU">Niue</option>
				<option value="NF">Norfolk Island</option>
				<option value="KP">North Korea</option>
				<option value="MP">Northern Mariana Islands</option>
				<option value="NO">Norway</option>
				<option value="OM">Oman</option>
				<option value="PK">Pakistan</option>
				<option value="PW">Palau</option>
				<option value="PA">Panama</option>
				<option value="PG">Papua New Guinea</option>
				<option value="PY">Paraguay</option>
				<option value="PE">Peru</option>
				<option value="PH">Philippines</option>
				<option value="PN">Pitcairn Island</option>
				<option value="PL">Poland</option>
				<option value="PF">Polynesia (French)</option>
				<option value="PT">Portugal</option>
				<option value="PR">Puerto Rico</option>
				<option value="QA">Qatar</option>
				<option value="RE">Reunion (French)</option>
				<option value="RO">Romania</option>
				<option value="RU">Russian Federation</option>
				<option value="RW">Rwanda</option>
				<option value="GS">S. Georgia & S. Sandwich Isls.</option>
				<option value="SH">Saint Helena</option>
				<option value="KN">Saint Kitts & Nevis Anguilla</option>
				<option value="LC">Saint Lucia</option>
				<option value="PM">Saint Pierre and Miquelon</option>
				<option value="ST">Saint Tome (Sao Tome) and Principe</option>
				<option value="VC">Saint Vincent & Grenadines</option>
				<option value="WS">Samoa</option>
				<option value="SM">San Marino</option>
				<option value="SA">Saudi Arabia</option>
				<option value="SN">Senegal</option>
				<option value="SC">Seychelles</option>
				<option value="SL">Sierra Leone</option>
				<option value="SG">Singapore</option>
				<option value="SK">Slovak Republic</option>
				<option value="SI">Slovenia</option>
				<option value="SB">Solomon Islands</option>
				<option value="SO">Somalia</option>
				<option value="ZA">South Africa</option>
				<option value="KR">South Korea</option>
				<option value="ES">Spain</option>
				<option value="LK">Sri Lanka</option>
				<option value="SD">Sudan</option>
				<option value="SR">Suriname</option>
				<option value="SJ">Svalbard and Jan Mayen Islands</option>
				<option value="SZ">Swaziland</option>
				<option value="SE">Sweden</option>
				<option value="CH">Switzerland</option>
				<option value="SY">Syria</option>
				<option value="TJ">Tadjikistan</option>
				<option value="TW">Taiwan</option>
				<option value="TZ">Tanzania</option>
				<option value="TH">Thailand</option>
				<option value="TG">Togo</option>
				<option value="TK">Tokelau</option>
				<option value="TO">Tonga</option>
				<option value="TT">Trinidad and Tobago</option>
				<option value="TN">Tunisia</option>
				<option value="TR">Turkey</option>
				<option value="TM">Turkmenistan</option>
				<option value="TC">Turks and Caicos Islands</option>
				<option value="TV">Tuvalu</option>
				<option value="UG">Uganda</option>
				<option value="UA">Ukraine</option>
				<option value="AE">United Arab Emirates</option>
				<option value="GB">United Kingdom</option>
				<option value="UY">Uruguay</option>
				<option value="MIL">USA Military</option>
				<option value="UM">USA Minor Outlying Islands</option>
				<option value="UZ">Uzbekistan</option>
				<option value="VU">Vanuatu</option>
				<option value="VA">Vatican City State</option>
				<option value="VE">Venezuela</option>
				<option value="VN">Vietnam</option>
				<option value="VG">Virgin Islands (British)</option>
				<option value="VI">Virgin Islands (USA)</option>
				<option value="WF">Wallis and Futuna Islands</option>
				<option value="EH">Western Sahara</option>
				<option value="YE">Yemen</option>
				<option value="YU">Yugoslavia</option>
				<option value="ZR">Zaire</option>
				<option value="ZM">Zambia</option>
				<option value="ZW">Zimbabwe</option>
			</select>
					</select>
				</div>
			</div>
		</fieldset>

		<fieldset>
			<legend><?php esc_html_e( 'Payment Method', 'leaky-paywall' ); ?></legend>
			<div class="lp-field-row">
				<div class="lp-field">
					<label for="lp-card-number"><?php esc_html_e( 'Card Number', 'leaky-paywall' ); ?></label>
					<input type="tel" id="lp-card-number" maxlength="20" name="card_num" class="card-num card-number" placeholder="1234 1234 1234 1234" autocomplete="cc-number" />
				</div>
			</div>
			<div class="lp-field-row lp-field-row--expiry-cvc">
				<div class="lp-field">
					<label for="lp-exp-month"><?php esc_html_e( 'Expiry Month', 'leaky-paywall' ); ?></label>
					<select id="lp-exp-month" name="exp_month" class="card-expiry-month" autocomplete="cc-exp-month">
						<?php for ( $i = 1; $i <= 12; $i++ ) : ?>
							<option value="<?php echo esc_attr( $i ); ?>"><?php echo esc_html( str_pad( $i, 2, '0', STR_PAD_LEFT ) ) . ' - ' . esc_html( leaky_paywall_get_month_name( $i ) ); ?></option>
						<?php endfor; ?>
					</select>
				</div>
				<span class="lp-expiry-sep">/</span>
				<div class="lp-field">
					<label for="lp-exp-year"><?php esc_html_e( 'Year', 'leaky-paywall' ); ?></label>
					<select id="lp-exp-year" name="exp_year" class="card-expiry-year" autocomplete="cc-exp-year">
						<?php
						$year = gmdate( 'Y' );
						for ( $i = $year; $i <= $year + 10; $i++ ) :
							?>
							<option value="<?php echo esc_attr( $i ); ?>"><?php echo esc_html( $i ); ?></option>
						<?php endfor; ?>
					</select>
				</div>
				<div class="lp-field lp-field--third">
					<label for="lp-cvc"><?php esc_html_e( 'CVC', 'leaky-paywall' ); ?></label>
					<input type="tel" id="lp-cvc" maxlength="4" name="cvc" class="cvc" placeholder="123" autocomplete="cc-csc" />
				</div>
			</div>
		</fieldset>

	</div>
	<?php

}

/**
 * Converts the month number to the month name
 *
 * @access public
 * @since  4.0.0
 *
 * @param  int $n Month number.
 * @return string The name of the month.
 */
function leaky_paywall_get_month_name( $n ) {
	$timestamp = mktime( 0, 0, 0, $n, 1, 2005 );

	return date_i18n( 'F', $timestamp );
}


/**
 * Login in a user
 *
 * @since  4.9.3
 *
 * @param  int $user_id ID of the user.
 */
function leaky_paywall_log_in_user( $user_id ) {

	wp_set_current_user( $user_id );
	wp_set_auth_cookie( $user_id, true );
}



/**
 * Get the redirect url
 *
 * @param array $settings The Leaky Paywall settings.
 * @param array $subscriber_data The subscriber data.
 */
function leaky_paywall_get_redirect_url( $settings, $subscriber_data ) {

	if ( ! empty( $settings['page_for_after_subscribe'] ) ) {
		$redirect_url = get_page_link( $settings['page_for_after_subscribe'] );
	} elseif ( ! empty( $settings['page_for_profile'] ) ) {
		$redirect_url = get_page_link( $settings['page_for_profile'] );
	} elseif ( ! empty( $settings['page_for_subscription'] ) ) {
		$redirect_url = get_page_link( $settings['page_for_subscription'] );
	}

	return apply_filters( 'leaky_paywall_redirect_url', add_query_arg( 'lp_txn_id', $subscriber_data['transaction_id'], $redirect_url ), $subscriber_data );
}


/**
 * Validate frontend registration
 */
function leaky_paywall_validate_frontend_registration() {

	if ( ! check_ajax_referer( 'lp_register_nonce', 'nonce', false ) ) {

		$message = esc_html__('There was an error. Please try again.', 'leaky-paywall');

		$return = array(
			'message' => $message,
			'status'  => 'error',
		);

		wp_send_json( $return );
	}

	if ( isset( $_POST['email'] ) ) {

		$email = sanitize_email( wp_unslash( $_POST['email'] ) );

		if ( ! is_email( $email ) ) {

			$message = esc_html__('This email is invalid. Please enter a different email.', 'leaky-paywall');

			$return = array(
				'message' => $message,
				'status'  => 'error',
			);

			wp_send_json( $return );
		}

		if ( email_exists( $email ) ) {

			$message = esc_html__('This email already exists. Please login or enter a different email.', 'leaky-paywall');

			$return = array(
				'message' => $message,
				'status'  => 'error',
			);

			wp_send_json( $return );
		}
	}

	if ( isset( $_POST['username'] ) ) {

		$username = sanitize_text_field( wp_unslash( $_POST['username'] ) );

		if ( username_exists( $username ) ) {

			$message = esc_html__('Username already taken.', 'leaky-paywall');

			$return = array(
				'message' => $message,
				'status'  => 'error',
			);

			wp_send_json( $return );
		}
	}

	die();
}
add_action( 'wp_ajax_nopriv_leaky_paywall_validate_registration', 'leaky_paywall_validate_frontend_registration' );
add_action( 'wp_ajax_leaky_paywall_validate_registration', 'leaky_paywall_validate_frontend_registration' );

/**
 * Create incomplete user
 *
 * @param array $user_data The user.
 * @param array $customer_data The customer data.
 */
function leaky_paywall_create_incomplete_user( $user_data, $customer_data, $fields ) {

	$data = array(
		'post_title'   => wp_strip_all_tags( $user_data['email'] ),
		'post_content' => '',
		'post_status'  => 'publish',
		'post_author'  => 1,
		'post_type'    => 'lp_incomplete_user',
	);

	$incomplete_user = wp_insert_post( $data );

	update_post_meta( $incomplete_user, '_user_data', $user_data );
	update_post_meta( $incomplete_user, '_customer_data', $customer_data );
	update_post_meta( $incomplete_user, '_field_data', $fields );
	update_post_meta( $incomplete_user, '_email', $user_data['email'] );
}

/**
 * Get incomplete user using their email address
 *
 * @param string $email The email address.
 */
function leaky_paywall_get_incomplete_user_from_email( $email ) {

	$incomplete_id = '';

	$args = array(
		'post_type'       => 'lp_incomplete_user',
		'number_of_posts' => 1,
		'meta_query'      => array(
			array(
				'key'     => '_email',
				'value'   => $email,
				'compare' => '=',
			),
		),
	);

	$incompletes = get_posts( $args );

	if ( ! empty( $incompletes ) ) {
		$incomplete    = $incompletes[0];
		$incomplete_id = $incomplete->ID;
	}

	return $incomplete_id;
}

/**
 * Cleanup incomplete user
 *
 * @param string $email The email address.
 */
function leaky_paywall_cleanup_incomplete_user( $email ) {

	$incomplete_users = get_posts(
		array(
			'post_type'      => 'lp_incomplete_user',
			'posts_per_page' => 99,
			'meta_key'       => '_email',
			'meta_value'     => $email,
		)
	);

	if ( empty( $incomplete_users ) ) {
		return;
	}

	foreach ( $incomplete_users as $incomplete ) {
		wp_trash_post( $incomplete->ID );
	}
}

function leaky_paywall_create_subscriber_from_incomplete_user( $email ) {

	$incomplete_id = leaky_paywall_get_incomplete_user_from_email( $email );

	if ( !$incomplete_id ) {
		return false;
	}

	$update_existing_subscriber = false;
	$user_data = get_post_meta($incomplete_id, '_user_data', true);
	$user = get_user_by('email', $user_data['email']);

	if ($user) {

		$level_id = lp_get_subscriber_meta('level_id', $user);
		$current_level = get_leaky_paywall_subscription_level($level_id);

		if (is_numeric($level_id)) {

			if ( $current_level['price'] > 0 ) {
				return false; // they are already an LP subscriber to a paid level
			}

			$update_existing_subscriber = true;

		}

	}

	$field_data = get_post_meta($incomplete_id, '_field_data', true);
	$customer_data = get_post_meta($incomplete_id, '_customer_data', true);
	$level = get_leaky_paywall_subscription_level($user_data['level_id']);
	$subscriber_id = isset( $customer_data->id ) ? $customer_data->id : '';

	if ( $update_existing_subscriber ) {

		$subscriber_data = array(
			'email' => $user_data['email'],
			'first_name'	=> $user_data['first_name'],
			'last_name'	=> $user_data['last_name'],
			'level_id'	=> $user_data['level_id'],
			'description' => $level['label'],
			'subscriber_id'	=> $subscriber_id,
			'plan'	=> $field_data['plan_id'],
			'price' => $level['price'],
			'interval_count' => $level['interval_count'],
			'interval'	=> $level['interval'],
			'recurring'	=> false,
			'currency' => leaky_paywall_get_currency(),
			'new_user'	=> false,
			'payment_gateway'	=> 'stripe',
			'payment_status'	=> 'active',
			'site'	=> leaky_paywall_get_current_site(),
			'mode' => leaky_paywall_get_current_mode(),
		);

		$user_id = leaky_paywall_update_subscriber(null, $subscriber_data['email'], $subscriber_data['subscriber_id'], $subscriber_data);
	} else {

		$subscriber_data = array(
			'email' => $user_data['email'],
			'password' => isset($user_data['password']) ? $user_data['password'] : '',
			'first_name'	=> $user_data['first_name'],
			'last_name'	=> $user_data['last_name'],
			'level_id'	=> $user_data['level_id'],
			'description' => $level['label'],
			'subscriber_id'	=> $subscriber_id,
			'created'	=> gmdate('Y-m-d H:i:s'),
			'price'	=> $level['price'],
			'plan'	=> $field_data['plan_id'],
			'interval_count' => $level['interval_count'],
			'interval'	=> $level['interval'],
			'recurring'	=> false,
			'currency' => leaky_paywall_get_currency(),
			'new_user'	=> true,
			'payment_gateway'	=> 'stripe',
			'payment_status'	=> 'active',
			'site'	=> leaky_paywall_get_current_site(),
			'mode' => leaky_paywall_get_current_mode(),
		);

		$subscriber_data['need_new'] = true;
		$user_id = leaky_paywall_new_subscriber(NULL, $user_data['email'], $subscriber_id, $subscriber_data);

	}

	$subscriber_data['user_id'] = $user_id;
	$new_user = get_user_by('id', $user_id);

	$transaction = new LP_Transaction($subscriber_data);
	$transaction_id = $transaction->create();
	$subscriber_data['transaction_id'] = $transaction_id;

	update_post_meta($transaction_id, '_field_data', $field_data);

	if (isset($field_data['lp_nag_loc'])) {
		update_post_meta($transaction_id, '_nag_location_id', $field_data['lp_nag_loc']);
	}

	leaky_paywall_cleanup_incomplete_user($user_data['email']);
	leaky_paywall_email_subscription_status($user_id, 'new', $subscriber_data);
	leaky_paywall_sync_stripe_subscription($new_user);

	do_action('leaky_paywall_after_process_registration', $subscriber_data);

	return $new_user;

}

add_action( 'wp_ajax_nopriv_leaky_paywall_store_nag_location', 'leaky_paywall_store_nag_location' );
add_action( 'wp_ajax_leaky_paywall_store_nag_location', 'leaky_paywall_store_nag_location' );

function leaky_paywall_store_nag_location() {

	$post_id = isset( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : '';

	if ( $post_id ) {
		setcookie( 'lp_nag_loc', $post_id, 0, '/' );
	}

}