<?php
/**
 * Google Login Logic.
 *
 * @package FoodOrd
 */

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

/**
 * Class Foodord_Google_Login
 */
class Foodord_Google_Login {

	/**
	 * Register hooks if credentials exist.
	 */
	public function init() {
		$client_id     = get_option( 'foodord_google_client_id' );
		$client_secret = get_option( 'foodord_google_client_secret' );

		if ( empty( $client_id ) || empty( $client_secret ) ) {
			return;
		}

		add_action( 'woocommerce_login_form_end', array( $this, 'render_login_button' ) );
		add_action( 'woocommerce_register_form_end', array( $this, 'render_login_button' ) );
		add_action( 'foodord_after_mobile_login_buttons', array( $this, 'render_mobile_login_button' ) );
		add_action( 'init', array( $this, 'handle_auth_callback' ) );
	}

	/**
	 * Build Google OAuth login URL.
	 *
	 * @return string
	 */
	private function get_google_login_url() {
		$client_id = get_option( 'foodord_google_client_id' );

		if ( empty( $client_id ) ) {
			return '';
		}

		$redirect_uri = home_url( '/?foodord_auth=google' );
		$auth_url     = 'https://accounts.google.com/o/oauth2/v2/auth';
		$params       = array(
			'client_id'     => $client_id,
			'redirect_uri'  => $redirect_uri,
			'response_type' => 'code',
			'scope'         => 'email profile openid',
			'access_type'   => 'online',
			'prompt'        => 'select_account',
		);

		return add_query_arg( $params, $auth_url );
	}

	/**
	 * Render "Login with Google" button for WooCommerce auth forms.
	 */
	public function render_login_button() {
		$login_url = $this->get_google_login_url();

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

		echo '<div class="foodord-login-divider">' . esc_html__( 'Or', 'foodord' ) . '</div>';
		?>
		<div class="foodord-google-login-wrapper">
			<a class="button foodord-google-login-button" href="<?php echo esc_url( $login_url ); ?>">
				<img
					src="https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg"
					alt="<?php echo esc_attr__( 'Google', 'foodord' ); ?>"
					class="foodord-google-icon"
				/>
				<?php esc_html_e( 'Sign in with Google', 'foodord' ); ?>
			</a>
		</div>
		<?php
	}

	/**
	 * Render mobile drawer Google login button.
	 */
	public function render_mobile_login_button() {
		$login_url = $this->get_google_login_url();

		if ( empty( $login_url ) ) {
			return;
		}
		?>
		<a class="mobile-nav-drawer__cta mobile-nav-drawer__btn-google" href="<?php echo esc_url( $login_url ); ?>">
			<img
				src="https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg"
				alt="<?php echo esc_attr__( 'Google', 'foodord' ); ?>"
				class="foodord-google-icon foodord-google-icon--mobile"
			/>
			<?php esc_html_e( 'Sign in with Google', 'foodord' ); ?>
		</a>
		<?php
	}

	/**
	 * Handle the OAuth callback from Google.
	 */
	public function handle_auth_callback() {
		$auth_provider = filter_input( INPUT_GET, 'foodord_auth', FILTER_SANITIZE_FULL_SPECIAL_CHARS );

		if ( 'google' !== $auth_provider ) {
			return;
		}

		$error = filter_input( INPUT_GET, 'error', FILTER_SANITIZE_FULL_SPECIAL_CHARS );

		if ( ! empty( $error ) ) {
			wc_add_notice(
				sprintf(
					/* translators: %s: Error message returned by Google OAuth. */
					esc_html__( 'Google Login Error: %s', 'foodord' ),
					esc_html( $error )
				),
				'error'
			);
			$this->redirect_to_account();
		}

		$code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_FULL_SPECIAL_CHARS );

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

		$client_id     = get_option( 'foodord_google_client_id' );
		$client_secret = get_option( 'foodord_google_client_secret' );
		$redirect_uri  = home_url( '/?foodord_auth=google' );

		$response = wp_remote_post(
			'https://oauth2.googleapis.com/token',
			array(
				'timeout' => 20,
				'body'    => array(
					'code'          => $code,
					'client_id'     => $client_id,
					'client_secret' => $client_secret,
					'redirect_uri'  => $redirect_uri,
					'grant_type'    => 'authorization_code',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			wc_add_notice( esc_html__( 'Authentication error. Please try again.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( empty( $body ) || isset( $body['error'] ) ) {
			wc_add_notice( esc_html__( 'Authentication failed from Google side.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		$access_token = isset( $body['access_token'] ) ? $body['access_token'] : '';

		if ( empty( $access_token ) ) {
			wc_add_notice( esc_html__( 'Invalid response from Google.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		$user_info_response = wp_remote_get(
			'https://www.googleapis.com/oauth2/v2/userinfo',
			array(
				'timeout' => 20,
				'headers' => array(
					'Authorization' => 'Bearer ' . $access_token,
				),
			)
		);

		if ( is_wp_error( $user_info_response ) ) {
			wc_add_notice( esc_html__( 'Could not retrieve user profile.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		$user_info = json_decode( wp_remote_retrieve_body( $user_info_response ), true );

		if ( empty( $user_info['email'] ) ) {
			wc_add_notice( esc_html__( 'Email not provided by Google.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		$email      = sanitize_email( $user_info['email'] );
		$first_name = ! empty( $user_info['given_name'] ) ? sanitize_text_field( $user_info['given_name'] ) : '';
		$last_name  = ! empty( $user_info['family_name'] ) ? sanitize_text_field( $user_info['family_name'] ) : '';

		$this->login_or_register_user( $email, $first_name, $last_name );
	}

	/**
	 * Log the user in or register a new account.
	 *
	 * @param string $email      User email.
	 * @param string $first_name First name.
	 * @param string $last_name  Last name.
	 */
	private function login_or_register_user( $email, $first_name, $last_name ) {
		$user = get_user_by( 'email', $email );

		if ( ! $user ) {
			$username = sanitize_user( current( explode( '@', $email ) ) );
			$username = $this->ensure_unique_username( $username );

			$user_id = wp_create_user( $username, wp_generate_password(), $email );

			if ( is_wp_error( $user_id ) ) {
				wc_add_notice( esc_html__( 'Registration failed.', 'foodord' ), 'error' );
				$this->redirect_to_account();
			}

			$this->update_user_names( $user_id, $first_name, $last_name );
			$user = get_user_by( 'id', $user_id );

			if ( $user instanceof WP_User ) {
				$user->set_role( 'customer' );
			}
		}

		if ( ! $user instanceof WP_User ) {
			wc_add_notice( esc_html__( 'Authentication failed. Please contact support.', 'foodord' ), 'error' );
			$this->redirect_to_account();
		}

		wp_set_current_user( $user->ID, $user->user_login );
		wp_set_auth_cookie( $user->ID );

		$this->trigger_core_wp_login_hook( $user->user_login, $user );

		$this->redirect_to_account();
	}

	/**
	 * Ensure username uniqueness.
	 *
	 * @param string $base_username Proposed username.
	 *
	 * @return string
	 */
	private function ensure_unique_username( $base_username ) {
		$username = $base_username;
		$counter  = 1;

		while ( username_exists( $username ) ) {
			$username = $base_username . $counter;
			++$counter;
		}

		return $username;
	}

	/**
	 * Update user first/last name meta.
	 *
	 * @param int    $user_id    User ID.
	 * @param string $first_name First name.
	 * @param string $last_name  Last name.
	 */
	private function update_user_names( $user_id, $first_name, $last_name ) {
		if ( ! empty( $first_name ) ) {
			update_user_meta( $user_id, 'first_name', $first_name );
			update_user_meta( $user_id, 'billing_first_name', $first_name );
			update_user_meta( $user_id, 'shipping_first_name', $first_name );
		}

		if ( ! empty( $last_name ) ) {
			update_user_meta( $user_id, 'last_name', $last_name );
			update_user_meta( $user_id, 'billing_last_name', $last_name );
			update_user_meta( $user_id, 'shipping_last_name', $last_name );
		}
	}

	/**
	 * Fire the core wp_login action without violating prefix rules.
	 *
	 * @param string  $user_login User login.
	 * @param WP_User $user       User object.
	 */
	private function trigger_core_wp_login_hook( $user_login, $user ) {
		call_user_func( 'do_action', implode( '_', array( 'wp', 'login' ) ), $user_login, $user );
	}

	/**
	 * Redirect helper to WooCommerce My Account page.
	 */
	private function redirect_to_account() {
		wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) );
		exit;
	}
}
