<?php
/**
 * Social Connect Hooks
 *
 * @package UM_Social_Login_API
 */

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


/**
 * Link account to user
 *
 * @param string  $provider Provider slug.
 * @param object  $user_profile Hybridauth Response.
 * @param string  $return_url  Return URL.
 * @param boolean $has_linked_account Whether the provider account is linked.
 *
 * @since  2.2
 */
function um_social_link_user_to_social( $provider, $user_profile, $return_url, $has_linked_account = false ) {

	//phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
	update_user_meta( um_user( 'ID' ), '_um_social_login_avatar_provider', $provider );

	$user_profile->photoURL = str_replace( 'width=150', 'width=200', $user_profile->photoURL );

	$user_profile->photoURL = str_replace( 'height=150', '', $user_profile->photoURL );

	update_user_meta( um_user( 'ID' ), 'synced_profile_photo', $user_profile->photoURL );

	$arr_profile = array(
		"_uid_{$provider}"                 => $user_profile->identifier,
		"_save_{$provider}_handle"         => $user_profile->displayName,
		"_save_{$provider}_photo_url_dyn"  => $user_profile->photoURL,
		"_save_{$provider}_photo_url"      => $user_profile->photoURL,
		"_save_{$provider}_link"           => $user_profile->profileURL,
		'_save_synced_profile_photo'       => $user_profile->photoURL,
		'username_exists'                  => $user_profile->email,
		'email_exists'                     => $user_profile->email,
		'_save_' . $provider . '_raw_data' => (array) $user_profile,
	);
	//phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

	UM()->Social_Login_API()->user_connect()->save_user_meta( um_user( 'ID' ), $arr_profile, $provider );

	if ( um_is_core_page( 'account' ) || strpos( isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( $_SERVER['HTTP_REFERER'] ) : '', um_get_core_page( 'account' ) ) !== false ) { //phpcs:ignore
		$return_url = add_query_arg( 'updated', 'social', $return_url );
		$return_url = remove_query_arg( 'ref', $return_url );
	} elseif ( is_user_logged_in() ) { // phpcs:disable WordPress.Security.NonceVerification
		$return_url = add_query_arg( 'updated', 'social', $return_url );
		$return_url = remove_query_arg( array( 'ref', 'um_dynamic_sso', 'provider' ), $return_url );
		wp_safe_redirect( $return_url );
		exit;
	}

	if ( defined( 'UM_SSO_CHILD_WINDOW' ) ) {
		echo "<script type=\"text/javascript\">/*1*/window.close();window.opener.location.href='" . esc_url_raw( $return_url ) . "';</script>";
	}

	if ( ! isset( $_REQUEST['form_id'] ) && ! um_is_core_page( 'account' ) ) { // phpcs:disable WordPress.Security.NonceVerification
		exit;
	}
}
add_action( 'um_social_do_link_user', 'um_social_link_user_to_social', 1, 4 );


/**
 *  Link account to user error
 *
 * @param string  $provider Provider slug.
 * @param object  $user_profile Hybridauth Response.
 * @param string  $return_url  Return URL.
 * @param boolean $has_linked_account Whether the provider account is linked.
 *
 * @since  2.2
 */
function um_social_link_user_to_social_error( $provider, $user_profile, $return_url, $has_linked_account = false ) {

	if ( defined( 'UM_SSO_PARENT_WINDOW' ) && UM_SSO_PARENT_WINDOW === $provider ) {  //phpcs:ignore  WordPress.Security.NonceVerification

		if ( um_is_core_page( 'account' ) ) {
			$return_url = UM()->account()->tab_link( 'social' );
		}

		$return_url = remove_query_arg( 'return_provider', $return_url );

		if ( get_current_user_id() === absint( $has_linked_account ) ) {
			$return_url = add_query_arg( 'updated', 'social', $return_url );
			$return_url = add_query_arg( 'linked_provider', $provider, $return_url );

		} else {
			$return_url = add_query_arg( 'err', "{$provider}_exist", $return_url );
		}

		wp_safe_redirect( $return_url );
		exit;

	}
}
add_action( 'um_social_do_link_user_error', 'um_social_link_user_to_social_error', 10, 4 );


/**
 * Show registration overlay via shortcode
 *
 * @param string $provider Provider slug.
 * @param bool   $has_linked Whethere the Social account is linked.
 * @param object $user_profile Hybridauth Response.
 * @param object $connect um_ext\um_social_login\core\Social_Login_Connect Connect Class.
 * @param string $return_url  Return URL.
 *
 * @since  2.2
 */
function um_social_doing_shortcode_process( $provider, $has_linked, $user_profile, $connect, $return_url ) {

	$sso_session = UM()->Social_Login_API()->hybridauth()->session();
	$sso_session->get( 'um_sso_has_dynamic_return_url' );
	$shortcode_id = $sso_session->get( 'um_sso' );

	if ( $shortcode_id ) {

		$integration_type = get_post_meta( $shortcode_id, '_um_integration_type', true );

		switch ( $integration_type ) {
			case 'register':
				$connect->do_action = 'register';

				break;

			case 'login':
				$connect->do_action = 'login';

				break;

			case 'link_account':
				$connect->do_action = 'link_account';

				break;

			default: // login_register.
				$connect->do_action = 'login_register';

				if ( ! $has_linked ) {
					$connect->do_action = 'register';
				} elseif ( $has_linked ) {
					$connect->do_action = 'login';
				}

				break;

		}

		$sso_current_url = $sso_session->get( 'um_sso_current_url' );
		$sso_current_url = add_query_arg( 'provider', $provider, $sso_current_url );
		$sso_current_url = remove_query_arg( 'um_dynamic_sso', $sso_current_url );

		//phpcs:disable WordPress.Security.NonceVerification
		if ( is_user_logged_in() && isset( $_REQUEST['um_dynamic_sso'] ) && ! um_is_core_page( 'account' ) && ! isset( $_REQUEST['err'] ) && in_array( $connect->do_action, array( 'register', 'login', 'login_register' ), true ) ) {

			wp_safe_redirect( $sso_current_url );
			exit;
		}

		if ( ! isset( $_REQUEST['return_provider'] ) ) {
			echo "<script type=\"text/javascript\">/*2*/if(window.opener != null && !window.opener.closed){ window.opener.location.href='" . esc_url_raw( $sso_current_url ) . "';window.close();}</script>";
			exit;
		}
		//phpcs:enable WordPress.Security.NonceVerification
	}
}
add_action( 'um_social_doing_shortcode', 'um_social_doing_shortcode_process', 10, 5 );


/**
 * Validate email address registration
 *
 * @param string $provider Provider slug.
 * @param bool   $has_linked Whethere the Social account is linked.
 * @param object $user_profile Hybridauth Response.
 * @param object $connect um_ext\um_social_login\core\Social_Login_Connect Connect Class.
 * @param string $return_url  Return URL.
 *
 * @since  2.2
 */
function um_social_one_step_process_matched_email( $provider, $has_linked, $user_profile, $connect, $return_url ) {

	$form_id              = UM()->Social_Login_API()->user_connect()->form_id();
	$enabled_step_process = UM()->Social_Login_API()->user_connect()->get_enabled_step_process( $form_id );

	if ( 0 === absint( $enabled_step_process ) ) { // One-step process.

		$matched_email_process = UM()->Social_Login_API()->user_connect()->get_one_step_matched_email( $form_id );

		switch ( $matched_email_process ) {

			case 1: // Link Accounts & Login immediately.
				if ( ! isset( $_REQUEST['return_provider'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
					return;
				}

				$profile = array( 'email_exists' => $user_profile->email );

				$email_exists = UM()->Social_Login_API()->user_connect()->email_exists( $profile, $provider );

				if ( $email_exists ) {
					$user_id = $email_exists;
					if ( ! $has_linked ) {
						UM()->Social_Login_API()->user_connect()->save_user_meta(
							$user_id,
							array( "_uid_{$provider}" => $user_profile->identifier ),
							$provider
						);
					}

					if ( function_exists( 'um_keep_signed_in' ) ) {
						if ( um_keep_signed_in() ) {
							$_REQUEST['rememberme'] = 1;
						}
					}

					do_action( 'um_social_do_login', $provider, $user_id, $user_profile, $connect, $return_url );
				}

				break;

			case 2: // Link Accounts & Redirect to Login page.
				if ( ! isset( $_REQUEST['return_provider'] ) || ( isset( $_REQUEST['um_form_id'] ) && isset( $_REQUEST['message'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification
					return;
				}

				$profile = array( 'email_exists' => $user_profile->email );

				$email_exists = UM()->Social_Login_API()->user_connect()->email_exists( $profile, $provider );

				if ( $email_exists ) {
					if ( ! $has_linked ) {
						UM()->Social_Login_API()->user_connect()->save_user_meta(
							$email_exists,
							array( "_uid_{$provider}" => $user_profile->identifier ),
							$provider
						);
					}

					$return_url = um_get_core_page( 'login' );
					$return_url = add_query_arg( 'err', 'um_sso_already_linked', $return_url );

					wp_safe_redirect( $return_url );
					exit;
				}

				break;

			case 3: // Allow new account creation with a generated Email
				// default.
				break;

			case 4: // Do not link accounts and prevent from account creation.
				if ( ! isset( $_REQUEST['return_provider'] ) ) {  //phpcs:ignore WordPress.Security.NonceVerification
					return;
				}

				$profile = array( 'email_exists' => $user_profile->email );

				$email_exists = UM()->Social_Login_API()->user_connect()->email_exists( $profile, $provider );

				if ( $email_exists ) {
					$return_url = remove_query_arg( 'return_provider', $return_url );
					$return_url = add_query_arg( 'err', 'um_sso_email_already_linked', $return_url );
					wp_safe_redirect( $return_url );
					exit;
				}

				break;

		}
	}
}
add_action( 'um_social_do_register_authenticated_process', 'um_social_one_step_process_matched_email', 10, 5 );


/**
 * Register Error
 *
 * @param string $provider Provider slug.
 * @param object $user_profile Hybridauth Response.
 * @param object $connect um_ext\um_social_login\core\Social_Login_Connect Connect Class.
 * @param string $return_url  Return URL.
 *
 * @since  2.2
 */
function um_social_do_register_error( $provider, $user_profile, $connect, $return_url ) {

	if ( ! isset( $_REQUEST['return_provider'] ) || ( isset( $_REQUEST['um_form_id'] ) && isset( $_REQUEST['message'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification
		return;
	}

	$return_url = remove_query_arg( 'return_provider', $return_url );

	$return_url = add_query_arg( 'err', 'um_sso_already_linked', $return_url );

	wp_safe_redirect( $return_url );
	exit;
}
add_action( 'um_social_do_register_error', 'um_social_do_register_error', 10, 4 );


/**
 * Authenticated User - oAuth Window Close
 *
 * @param string $provider Provider slug.
 * @param string $return_url  Return URL.
 * @param object $user_profile Hybridauth Response.
 *
 * @since  2.2
 */
function um_social_login_do_close_oauth_window( $provider, $return_url, $user_profile ) {

	$return_url = apply_filters( 'um_social_login_return_url', $return_url, $provider );

	$return_url = apply_filters( "um_social_login_return_url__{$provider}", $return_url );

	$return_url = add_query_arg( 'ref', 4, $return_url );

	if ( um_is_core_page( 'account' ) || strpos( isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( $_SERVER['HTTP_REFERER'] ) : '', um_get_core_page( 'account' ) ) !== false ) { //phpcs:ignore
		$return_url = add_query_arg( 'updated', 'social', $return_url );
	}

	if ( defined( 'UM_SSO_CHILD_WINDOW' ) ) {
		echo "<script type=\"text/javascript\">/*3*/if(window.opener != null && !window.opener.closed){ window.opener.location.href='" . esc_url_raw( $return_url ) . "';window.close();}else{window.location.href='" . esc_url_raw( $return_url ) . "';}</script>";
		exit;
	}
}
add_action( 'um_social_do_oauth_window_process', 'um_social_login_do_close_oauth_window', 10, 3 );


/**
 * Authenticate user - OAuth Window close
 *
 * @param string $provider Provider slug.
 * @param string $return_url  Return URL.
 * @param object $user_profile Hybridauth Response.
 *
 * @since  2.2
 */
function um_social_login_doing_close_oauth_window( $provider, $return_url, $user_profile ) {

	$return_url = apply_filters( 'um_social_login_return_url', $return_url, $provider );

	$return_url = apply_filters( "um_social_login_return_url__{$provider}", $return_url );

	$return_url = add_query_arg( 'ref', 3, $return_url );

	if ( um_is_core_page( 'account' ) || strpos( isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( $_SERVER['HTTP_REFERER'] ) : '', um_get_core_page( 'account' ) ) !== false ) { //phpcs:ignore
		$return_url = add_query_arg( 'updated', 'social', $return_url );
		echo "<script type=\"text/javascript\">/*4*/if(window.opener != null && !window.opener.closed){ window.opener.location.href='" . esc_url_raw( $return_url ) . "';window.close();}else{window.location.href='" . esc_url_raw( $return_url ) . "';}</script>";
	}
}
add_action( 'um_social_doing_oauth_window_process', 'um_social_login_doing_close_oauth_window', 10, 3 );


/**
 * Do log in process
 *
 * @param string  $provider Provider slug.
 * @param integer $user_id User ID.
 * @param object  $user_profile Hybridauth Response.
 * @param object  $connect um_ext\um_social_login\core\Social_Login_Connect Connect Class.
 * @param string  $return_url  Return URL.
 *
 * @since  2.2
 */
function um_social_do_login( $provider, $user_id, $user_profile, $connect, $return_url ) {

	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( defined( 'UM_SSO_CHILD_WINDOW' ) ) {
		return;
	}

	UM()->login()->auth_id = $user_id; // It's required to set auth_id for proper login in UM core while 'um_user_login'.

	um_fetch_user( $user_id );

	$after = um_user( 'after_login' );

	switch ( $after ) {

		case 'redirect_admin':
			$redirect_to = admin_url();
			break;

		case 'redirect_profile':
			$redirect_to = um_user_profile_url();
			break;

		case 'redirect_url':
			$redirect_to = um_user( 'login_redirect_url' );
			break;

		case 'refresh':
			if ( ! isset( $_REQUEST['redirect_to'] ) || empty( $_REQUEST['redirect_to'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification

				$redirect = UM()->Social_Login_API()->redirect();

				if ( true === $redirect['has_redirect'] || 1 === absint( $redirect['is_shortcode'] ) ) {
					$redirect_to = $redirect['redirect_to'];
				}
			} elseif ( isset( $_REQUEST['redirect_to'] ) && ! empty( $_REQUEST['redirect_to'] ) ) {  //phpcs:ignore WordPress.Security.NonceVerification

				$redirect_to = esc_url_raw( $_REQUEST['redirect_to'] );  //phpcs:ignore
			}

			if ( ! isset( $redirect_to ) || empty( $redirect_to ) ) {
				$redirect_to = um_get_core_page( 'login' );
			}

			unset( $_SESSION['um_social_login_redirect'] );

			break;

	}

	$user_status = UM()->Social_Login_API()->user_connect()->check_user_status( $user_id );

	if ( isset( $user_status['error'] ) && true === (bool) $user_status['error'] ) {
		switch ( $user_status['error_code'] ) {
			case 'awaiting_email_confirmation':
				if ( ! empty( $user_status['url'] ) ) {
					$return_url = $user_status['url'];
				} else {
					$return_url = add_query_arg( 'err', $user_status['error_code'], $return_url );
				}
				break;
			case 'awaiting_admin_review':
			case 'inactive':
			case 'rejected':
			default:
				$return_url = add_query_arg( 'err', $user_status['error_code'], $return_url );
				break;
		}

		do_action( 'um_social_do_login_error', $provider, $user_profile, $return_url );

	} else {

		if ( function_exists( 'um_keep_signed_in' ) ) {
			if ( um_keep_signed_in() ) {
				$_REQUEST['rememberme'] = 1;
			}
		}

		$url = UM()->Social_Login_API()->hybridauth()->get_current_url();

		$args               = array();
		$args['rememberme'] = true;

		$parts = wp_parse_url( $url );
		if ( isset( $parts['query'] ) ) {
			parse_str( $parts['query'], $query );
		}

		if ( isset( $query['redirect_to'] ) ) {
			$return_url = $query['redirect_to'];
		}

		$args['redirect_to'] = $redirect_to;

		$sso_session = UM()->Social_Login_API()->hybridauth()->session();

		$um_sso           = $sso_session->get( 'um_sso' );
		$cpt_shortcode_id = get_post_meta( $um_sso, '_um_dynamic_redirection', true );
		if ( empty( $cpt_shortcode_id ) && $um_sso && ! isset( $_REQUEST['redirect_to'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
			$args['redirect_to'] = $sso_session->get( 'um_sso_current_url' );
		}

		$previous_page_url = $sso_session->get( 'um_sso_previous_page' );
		if ( empty( $cpt_shortcode_id ) && ! empty( $previous_page_url ) ) {
			$sso_session->set( 'um_sso_previous_page', null );
			$args['redirect_to'] = $previous_page_url;
		}

		remove_action( 'template_redirect', 'um_social_set_redirect_to_page' );
		$sso_session->clear();

		do_action( 'um_user_login', $args );

		exit;

	}
}
add_action( 'um_social_do_login', 'um_social_do_login', 10, 5 );

/**
 * Maybe dynamic page redirection after approve user on registration.
 *
 * @since 2.5.4
 */
function um_social_register_login() {
	$sso_session      = UM()->Social_Login_API()->hybridauth()->session();
	$um_sso           = $sso_session->get( 'um_sso' );
	$cpt_shortcode_id = get_post_meta( $um_sso, '_um_dynamic_redirection', true );

	if ( empty( $cpt_shortcode_id ) && $um_sso && ! isset( $_REQUEST['redirect_to'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
		um_safe_redirect( urldecode( $sso_session->get( 'um_sso_current_url' ) ) );
	}
}
add_action( 'um_registration_after_auto_login', 'um_social_register_login' );

/**
 * Set cookie for the redirection URL
 */
function um_social_set_redirect_to_page() {

	$sso_session = UM()->Social_Login_API()->hybridauth()->session();
	if ( ! $sso_session ) {
		return;
	}
	if ( method_exists( $sso_session, 'set' ) ) {
		if ( isset( $_REQUEST['redirect_to'] ) && ! empty( $_REQUEST['redirect_to'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
			$current_url = $_REQUEST['redirect_to']; //phpcs:ignore
			$sso_session->set( 'um_sso_previous_page', $current_url );
		} elseif ( ! isset( $_REQUEST['return_provider'] ) && ! isset( $_REQUEST['provider'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
			$sso_session->set( 'um_sso_previous_page', null );
		}
	}
}
add_action( 'template_redirect', 'um_social_set_redirect_to_page' );

/**
 * Auth Window close and redirect to return Url with errors
 *
 * @param string $provider Provide slug.
 * @param object $user_profile Hybridauth Response.
 * @param string $return_url Return URL.
 *
 * @since  2.2
 */
function um_social_do_login_error_not_linked( $provider, $user_profile, $return_url ) {

	if ( ! isset( $_REQUEST['return_provider'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
		return;
	}

	if ( strpos( $return_url, 'err' ) === false ) {
		$return_url = add_query_arg( 'err', 'um_sso_not_linked', $return_url );
	}

	$return_url = remove_query_arg( 'return_provider', $return_url );

	$return_url = apply_filters( 'um_social_login_do_login_error_return_url', $return_url, $provider );

	$return_url = apply_filters( "um_social_login_do_login_error_return_url__{$provider}", $return_url );

	wp_safe_redirect( $return_url );
	exit;
}
add_action( 'um_social_do_login_error', 'um_social_do_login_error_not_linked', 5, 3 );


/**
 * Auth Window close and redirect to return Url with errors
 *
 * @param string $provider Provide slug.
 * @param string $return_url Return URL.
 * @param object $user_profile Hybridauth Response.
 *
 * @since  2.2
 */
function um_social_oauth_window_error_user_denied( $provider, $return_url, $user_profile ) {

	if ( um_is_core_page( 'account' ) ) {
		$return_url = UM()->account()->tab_link( 'social' );
	}

	$return_url = add_query_arg( 'err', 'um_social_user_denied', $return_url );

	$return_url = apply_filters( 'um_social_login_window_process_error_return_url', $return_url, $provider );

	$return_url = apply_filters( "um_social_login_window_process_error_return_url__{$provider}", $return_url );

	$return_url = add_query_arg( 'ref', 1, $return_url );

	echo "<script type=\"text/javascript\">/*5*/if(window.opener != null && !window.opener.closed){ window.opener.location.href='" . esc_url_raw( $return_url ) . "';window.close();}else{window.location.href='" . esc_url_raw( $return_url ) . "';}</script>";
	exit;
}
add_action( 'um_social_oauth_window_process_error', 'um_social_oauth_window_error_user_denied', 10, 3 );


/**
 * Redirect users after login with custom redirect_to url
 *
 * @param string $provider Provider slug.
 *
 * @since  2.2
 */
function um_social_do_redirect_after_login( $provider ) {

	if ( ! isset( $_REQUEST['um_sso_logged_in'] ) || ! isset( $_REQUEST['redirect_to'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification
		return;
	}

	$sso_session = UM()->Social_Login_API()->hybridauth()->session();
	$return_url  = esc_url_raw( $_REQUEST['redirect_to'] ); //phpcs:ignore
	$redirect_to = $sso_session->get( 'um_social_login_redirect' );
	if ( $redirect_to ) {
		$return_url = $redirect_to;
		$sso_session->set( 'um_social_login_redirect', null );
	}

	echo "<script type=\"text/javascript\">/*6*/if(window.opener != null && !window.opener.closed){ window.opener.location.href='" . esc_url_raw( $return_url ) . "';window.close();}else{window.location.href='" . esc_url_raw( $return_url ) . "';}</script>";
	exit;
}
add_action( 'um_social_do_redirect_after_login', 'um_social_do_redirect_after_login', 10, 1 );


/**
 * Make all fields hidden for one-step process
 *
 * @param string $output HTML output.
 * @param array  $data    Field settings.
 *
 * @since  2.2
 */
function um_sso_edit_field_register_hidden( $output, $data ) {

	$field_key = $data['metakey'];

	$field_name = $field_key . UM()->form()->form_suffix;

	$field_value = htmlspecialchars( UM()->fields()->field_value( $field_key, '', $data ) );

	echo '<input  type="hidden" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $field_value ) . '"  />';
}
add_action( 'um_edit_field_register_hidden', 'um_sso_edit_field_register_hidden', 10, 2 );
