<?php

namespace WeDevs\AppBridge\Core\Auth;

use WeDevs\AppBridge\Core\Contracts\Hookable;
use WP_User;

defined( 'ABSPATH' ) || exit;

/**
 * Password reset OTP mailer.
 *
 * Standalone, WooCommerce-independent mailer that delivers the reset code over
 * a modern, responsive HTML email through wp_mail(). Works for every mobile
 * app integration regardless of which parent plugin is active.
 *
 * Triggered by the `app_bridge_password_reset_otp_notification` action.
 */
class PasswordResetOtpMailer implements Hookable {

	/**
	 * Register WordPress hooks.
	 */
	public function register_hooks(): void {
		add_action( 'app_bridge_password_reset_otp_notification', [ $this, 'send' ], 10, 3 );
	}

	/**
	 * Send the OTP email to the requesting user.
	 *
	 * @param string $user_login User login or email address.
	 * @param string $otp        Plain-text one-time password.
	 * @param int    $expires_at Expiry timestamp (UTC).
	 */
	public function send( $user_login, $otp, $expires_at ): void {
		$user = is_email( $user_login )
			? get_user_by( 'email', $user_login )
			: get_user_by( 'login', $user_login );

		if ( ! $user instanceof WP_User || ! is_email( $user->user_email ) ) {
			return;
		}

		// Render in the recipient's language so translation plugins resolve the
		// right locale, regardless of the locale active during the request.
		$switched = switch_to_locale( get_user_locale( $user ) );

		$site_title         = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
		$expires_in_minutes = max( 1, (int) ceil( ( (int) $expires_at - time() ) / MINUTE_IN_SECONDS ) );

		$subject = sprintf(
			/* translators: %s: site title. */
			__( 'Your %s password reset code', 'app-bridge' ),
			$site_title
		);

		$message = $this->render(
			[
				'user'               => $user,
				'otp'                => (string) $otp,
				'expires_in_minutes' => $expires_in_minutes,
				'site_title'         => $site_title,
			]
		);

		$headers = [ 'Content-Type: text/html; charset=UTF-8' ];

		/**
		 * Filter the OTP email arguments before sending.
		 *
		 * @param array<string, mixed> $mail {
		 *     @type string          $to      Recipient email address.
		 *     @type string          $subject Email subject.
		 *     @type string          $message HTML email body.
		 *     @type array<int, string> $headers Email headers.
		 * }
		 * @param WP_User $user The user requesting the reset.
		 */
		$mail = apply_filters(
			'app_bridge_password_reset_otp_email',
			[
				'to'      => $user->user_email,
				'subject' => $subject,
				'message' => $message,
				'headers' => $headers,
			],
			$user
		);

		wp_mail( $mail['to'], $mail['subject'], $mail['message'], $mail['headers'] );

		if ( $switched ) {
			restore_previous_locale();
		}
	}

	/**
	 * Render the HTML email body from the template.
	 *
	 * @param array<string, mixed> $args Template variables.
	 * @return string
	 */
	protected function render( array $args ): string {
		$template = APP_BRIDGE_DIR . 'templates/emails/password-reset-otp.php';

		/**
		 * Filter the template path used for the OTP email.
		 *
		 * @param string               $template Absolute template path.
		 * @param array<string, mixed> $args     Template variables.
		 */
		$template = apply_filters( 'app_bridge_password_reset_otp_email_template', $template, $args );

		if ( ! is_readable( $template ) ) {
			return '';
		}

		$user               = $args['user'];
		$otp                = $args['otp'];
		$expires_in_minutes = $args['expires_in_minutes'];
		$site_title         = $args['site_title'];

		ob_start();
		include $template;

		return (string) ob_get_clean();
	}
}
