<?php
/**
 * Test Email Step
 *
 * Lets the admin send a test email to verify that WordPress's mail stack is
 * working correctly before ambassadors start receiving transactional emails.
 * The step is skippable — mail setup can be verified later via Settings > Tools.
 *
 * @package AmbassadorHub\Admin\Wizard\Steps
 */

namespace AmbassadorHub\Admin\Wizard\Steps;

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

use AmbassadorHub\Admin\Wizard\AbstractWizardStep;
use AmbassadorHub\Admin\Wizard\SetupWizard;
use AmbassadorHub\Mail\MailerService;

/**
 * Wizard step for verifying email delivery.
 */
final class TestEmailStep extends AbstractWizardStep {

	/** Transient key prefix for per-user mail result. */
	private const RESULT_TRANSIENT_PREFIX = 'ambh_wizard_test_mail_';

	/**
	 * {@inheritdoc}
	 */
	public function get_id(): string {
		return 'test-email';
	}

	/**
	 * {@inheritdoc}
	 */
	public function get_title(): string {
		return __( 'Verify email delivery', 'ambassadorhub' );
	}

	/**
	 * {@inheritdoc}
	 *
	 * Mail can be configured later from Settings > Tools.
	 */
	public function is_skippable(): bool {
		return true;
	}

	/**
	 * {@inheritdoc}
	 *
	 * Only sends a test email when the dedicated "Send test email" button is
	 * clicked (ambh_wizard_action === 'send_email'). When the main "Next"
	 * button is used, returns null to let the wizard advance normally.
	 */
	public function handle( array $post_data ): ?string {
		// If the user clicked "Next" (not the send button), just advance.
		$action = sanitize_key( $post_data['ambh_wizard_action'] ?? 'next' );
		if ( 'send_email' !== $action ) {
			return null;
		}

		$to = sanitize_email( $post_data['ambh_wizard_test_mail_to'] ?? '' );

		if ( ! is_email( $to ) ) {
			set_transient( self::RESULT_TRANSIENT_PREFIX . get_current_user_id(), array( 'status' => 'invalid' ), 60 );
		} else {
			$site_name = get_bloginfo( 'name' );

			$subject = sprintf(
				/* translators: %s: site name */
				__( '[%s] Test email from AmbassadorHub', 'ambassadorhub' ),
				$site_name
			);

			$body = '<p>' . esc_html(
				sprintf(
					/* translators: %s: site name */
					__( 'This is a test email sent from %s to confirm that the mail service is configured correctly.', 'ambassadorhub' ),
					$site_name
				)
			) . '</p>'
			. '<p>' . esc_html__( 'If you received this message, your mail setup is working.', 'ambassadorhub' ) . '</p>';

			// Hook wp_mail_failed before sending so we catch SMTP/configuration
			// errors that wp_mail() would otherwise swallow (it returns true as
			// soon as PHP's mail() accepts the message, before delivery is known).
			$mail_error = null;
			$capture    = static function ( \WP_Error $error ) use ( &$mail_error ): void {
				$mail_error = $error;
			};
			add_action( 'wp_mail_failed', $capture );

			$sent = MailerService::send(
				$to,
				$subject,
				$body,
				__( 'Test email from AmbassadorHub — your mail setup is working.', 'ambassadorhub' )
			);

			remove_action( 'wp_mail_failed', $capture );

			// wp_mail_failed is more reliable than the return value: it fires on
			// SMTP auth failures, connection refused, SSL errors, etc.
			if ( $mail_error instanceof \WP_Error ) {
				$sent = false;
			}

			if ( $sent ) {
				update_option( 'ambh_email_configured', '1', false );
			}

			$result = array( 'status' => $sent ? 'sent' : 'failed' );
			if ( ! $sent && $mail_error instanceof \WP_Error ) {
				$result['error'] = $mail_error->get_error_message();
			}

			set_transient( self::RESULT_TRANSIENT_PREFIX . get_current_user_id(), $result, 60 );
		}

		// Stay on this step so the user sees the result; they then click Next.
		return admin_url( 'admin.php?page=' . SetupWizard::PAGE_SLUG );
	}

	/**
	 * {@inheritdoc}
	 */
	public function render(): void {
		$transient  = get_transient( self::RESULT_TRANSIENT_PREFIX . get_current_user_id() );
		$admin_mail = get_option( 'admin_email', '' );

		// Consume the transient so re-renders start clean.
		if ( false !== $transient ) {
			delete_transient( self::RESULT_TRANSIENT_PREFIX . get_current_user_id() );
		}

		// Normalise: the transient is now always an array, but guard against
		// any stale string value left from a previous version.
		$status = '';
		$error  = '';
		if ( is_array( $transient ) ) {
			$status = $transient['status'] ?? '';
			$error  = $transient['error'] ?? '';
		}

		if ( 'sent' === $status ) {
			?>
			<div class="ambh-wizard-notice ambh-wizard-notice--success">
				<strong><?php esc_html_e( 'Email accepted for delivery.', 'ambassadorhub' ); ?></strong>
				<?php esc_html_e( 'Check your inbox now to confirm it actually arrived, then click Next.', 'ambassadorhub' ); ?>
			</div>
			<?php
		} elseif ( 'failed' === $status ) {
			?>
			<div class="ambh-wizard-notice ambh-wizard-notice--error">
				<strong><?php esc_html_e( 'Sending failed.', 'ambassadorhub' ); ?></strong>
				<?php esc_html_e( 'WordPress could not hand the message to the mail server. See the guidance below.', 'ambassadorhub' ); ?>
				<?php if ( '' !== $error ) : ?>
					<br><code style="font-size:12px;word-break:break-all;"><?php echo esc_html( $error ); ?></code>
				<?php endif; ?>
			</div>
			<?php
		} elseif ( 'invalid' === $status ) {
			?>
			<div class="ambh-wizard-notice ambh-wizard-notice--error">
				<?php esc_html_e( 'Please enter a valid email address.', 'ambassadorhub' ); ?>
			</div>
			<?php
		}
		?>
		<p>
			<?php esc_html_e( 'AmbassadorHub sends transactional emails (donation confirmations, ambassador invites) through WordPress\'s built-in mail system. This step checks whether WordPress email is working on your server.', 'ambassadorhub' ); ?>
		</p>
		<p class="description">
			<?php
			printf(
				/* translators: %s: link to WordPress general settings */
				esc_html__( 'If sending fails, install an SMTP plugin such as WP Mail SMTP and configure it under %s.', 'ambassadorhub' ),
				'<a href="' . esc_url( admin_url( 'options-general.php' ) ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Settings → General', 'ambassadorhub' ) . '</a>'
			);
			?>
		</p>
		<table class="form-table" style="margin-top: 12px;">
			<tbody>
				<tr>
					<th scope="row">
						<label for="ambh_wizard_test_mail_to">
							<?php esc_html_e( 'Send to', 'ambassadorhub' ); ?>
						</label>
					</th>
					<td>
						<input
							type="email"
							id="ambh_wizard_test_mail_to"
							name="ambh_wizard_test_mail_to"
							value="<?php echo esc_attr( $admin_mail ); ?>"
							class="regular-text"
							autocomplete="email"
						/>
						<button type="submit" name="ambh_wizard_action" value="send_email"
							class="button" style="margin-left: 8px;">
							<?php esc_html_e( 'Send test email', 'ambassadorhub' ); ?>
						</button>
					</td>
				</tr>
			</tbody>
		</table>
		<?php
	}
}
