<?php
/**
 * SMTP settings admin page.
 *
 * @package SubmissionInbox
 */

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

/**
 * Renders and saves SMTP settings.
 */
class SUBIN_SmtpSettingsPage {
	const SAVE_NONCE_ACTION = 'subin_save_smtp_settings';
	const SAVE_NONCE_NAME   = 'subin_smtp_settings_nonce';
	const TEST_NONCE_ACTION = 'subin_send_test_email';
	const TEST_NONCE_NAME   = 'subin_test_email_nonce';

	/**
	 * Settings repository.
	 *
	 * @var SUBIN_SettingsRepository
	 */
	private $settings;

	/**
	 * Shared Email Health verification sender.
	 *
	 * @var \SUBIN\Mail\EmailVerificationService
	 */
	private $verification;

	/**
	 * Constructor.
	 *
	 * @param SUBIN_SettingsRepository $settings Settings repository.
	 */
	public function __construct( SUBIN_SettingsRepository $settings ) {
		$this->settings     = $settings;
		$this->verification = new \SUBIN\Mail\EmailVerificationService( $settings );
	}

	/**
	 * Render page.
	 *
	 * @return void
	 */
	public function render() {
		if ( ! \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::MANAGE_SENDING ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'submission-inbox' ) );
		}

		$this->safe_admin_redirect( admin_url( 'admin.php?page=subin-settings&subin_settings_tab=sending' ) );
	}

	/**
	 * Render SMTP settings inside the main Settings page.
	 *
	 * @return void
	 */
	public function render_embedded() {
		if ( ! \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::MANAGE_SENDING ) ) {
			wp_die( esc_html__( 'You do not have permission to manage sending settings.', 'submission-inbox' ) );
		}

		$settings = $this->settings->all();
		$this->render_configuration_warnings( $settings );
		$this->render_settings_form( $settings );
		if ( \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::SEND_TEST_EMAILS ) ) {
			$this->render_test_email_form();
		}
	}

	/**
	 * Handle submitted SMTP page actions.
	 *
	 * @return void
	 */
	public function maybe_handle_post() {
		$request_method = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) );
		if ( 'POST' !== strtoupper( $request_method ) ) {
			return;
		}

		$raw_action = $_POST['subin_smtp_action'] ?? ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- The allowlisted action selects a nonce- and capability-protected handler below.
		$action     = is_scalar( $raw_action ) ? sanitize_key( wp_unslash( $raw_action ) ) : '';

		if ( 'save_settings' === $action ) {
			if ( ! \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::MANAGE_SENDING ) ) {
				wp_die( esc_html__( 'You do not have permission to manage sending settings.', 'submission-inbox' ) );
			}
			$this->save_settings();
			return;
		}

		if ( 'send_test_email' === $action ) {
			if ( ! \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::SEND_TEST_EMAILS ) ) {
				wp_die( esc_html__( 'You do not have permission to send verification emails.', 'submission-inbox' ) );
			}
			$this->send_test_email();
		}
	}

	/**
	 * Render SMTP settings form.
	 *
	 * @param array<string,mixed> $settings Settings.
	 * @return void
	 */
	private function render_settings_form( array $settings ) {
		?>
		<form method="post" action="" class="subin-settings-form" data-subin-settings-form data-subin-sending-settings>
			<input type="hidden" name="subin_smtp_action" value="save_settings" />
			<?php wp_nonce_field( self::SAVE_NONCE_ACTION, self::SAVE_NONCE_NAME ); ?>
			<div class="subin-settings-section">
				<h2>
					<?php esc_html_e( 'Notification defaults', 'submission-inbox' ); ?>
					<?php SUBIN_View::help_tooltip( __( 'Global sender and recipient defaults. Individual forms and auto-reply rules may override them.', 'submission-inbox' ) ); ?>
				</h2>
				<p><?php esc_html_e( 'Set the identity used by InboxMend notifications. Configure form-specific recipients under Forms and visitor messages under Auto-replies.', 'submission-inbox' ); ?></p>
			<table class="form-table" role="presentation">
				<tbody>
					<tr>
						<th scope="row">
							<label for="subin-from-email"><?php esc_html_e( 'From Email', 'submission-inbox' ); ?></label>
							<?php SUBIN_View::help_tooltip( __( 'The email address WordPress uses as the sender.', 'submission-inbox' ) ); ?>
						</th>
						<td><input type="email" id="subin-from-email" name="from_email" class="regular-text" value="<?php echo esc_attr( $settings['from_email'] ); ?>" /></td>
					</tr>
					<tr>
						<th scope="row"><label for="subin-from-name"><?php esc_html_e( 'From Name', 'submission-inbox' ); ?></label></th>
						<td><input type="text" id="subin-from-name" name="from_name" class="regular-text" value="<?php echo esc_attr( $settings['from_name'] ); ?>" /></td>
					</tr>
					<tr>
						<th scope="row"><label for="subin-notification-recipient-email"><?php esc_html_e( 'Default admin notification recipient', 'submission-inbox' ); ?></label></th>
						<td>
							<input type="email" id="subin-notification-recipient-email" name="notification_recipient_email" class="regular-text" value="<?php echo esc_attr( $settings['notification_recipient_email'] ); ?>" />
							<p class="description"><?php esc_html_e( 'Used for form admin notifications unless a form has a custom recipient.', 'submission-inbox' ); ?></p>
						</td>
					</tr>
				</tbody>
			</table>
			</div>
			<div class="subin-settings-section">
				<div class="subin-settings-section__header">
					<div><h2><?php esc_html_e( 'Email transport', 'submission-inbox' ); ?></h2><p><?php esc_html_e( 'Use the WordPress default mail method, or configure a custom SMTP server for all WordPress email.', 'submission-inbox' ); ?></p></div>
					<?php SUBIN_View::badge( ! empty( $settings['enable_smtp'] ) ? __( 'Custom SMTP', 'submission-inbox' ) : __( 'WordPress default', 'submission-inbox' ), ! empty( $settings['enable_smtp'] ) ? 'info' : 'muted' ); ?>
				</div>
			<table class="form-table" role="presentation">
				<tbody>
					<tr>
						<th scope="row"><?php esc_html_e( 'Delivery method', 'submission-inbox' ); ?></th>
						<td>
							<input type="hidden" name="enable_smtp" value="0" />
							<?php SUBIN_View::checkbox_field( 'enable_smtp', __( 'Send WordPress email through custom SMTP', 'submission-inbox' ), (bool) $settings['enable_smtp'] ); ?>
							<?php if ( '' !== (string) $settings['smtp_password'] ) : ?>
								<label class="subin-settings-inline-check"><input type="checkbox" name="smtp_clear_password" value="1" /> <?php esc_html_e( 'Remove the saved SMTP password', 'submission-inbox' ); ?></label>
							<?php endif; ?>
						</td>
					</tr>
					<tr data-subin-show-when="enable_smtp">
						<th scope="row">
							<label for="subin-smtp-host"><?php esc_html_e( 'SMTP Host', 'submission-inbox' ); ?></label>
							<?php SUBIN_View::help_tooltip( __( 'The server used to send WordPress emails through SMTP.', 'submission-inbox' ) ); ?>
						</th>
						<td><input type="text" id="subin-smtp-host" name="smtp_host" class="regular-text" value="<?php echo esc_attr( $settings['smtp_host'] ); ?>" /></td>
					</tr>
					<tr data-subin-show-when="enable_smtp">
						<th scope="row"><label for="subin-smtp-port"><?php esc_html_e( 'SMTP Port', 'submission-inbox' ); ?></label></th>
						<td><input type="number" id="subin-smtp-port" name="smtp_port" class="small-text" min="1" max="65535" value="<?php echo esc_attr( (string) $settings['smtp_port'] ); ?>" /></td>
					</tr>
					<tr data-subin-show-when="enable_smtp">
						<th scope="row"><label for="subin-smtp-encryption"><?php esc_html_e( 'Encryption', 'submission-inbox' ); ?></label></th>
						<td>
							<select id="subin-smtp-encryption" name="smtp_encryption">
								<option value="none" <?php selected( $settings['smtp_encryption'], 'none' ); ?>><?php esc_html_e( 'None', 'submission-inbox' ); ?></option>
								<option value="ssl" <?php selected( $settings['smtp_encryption'], 'ssl' ); ?>><?php esc_html_e( 'SSL', 'submission-inbox' ); ?></option>
								<option value="tls" <?php selected( $settings['smtp_encryption'], 'tls' ); ?>><?php esc_html_e( 'TLS', 'submission-inbox' ); ?></option>
							</select>
						</td>
					</tr>
					<tr data-subin-show-when="enable_smtp">
						<th scope="row"><?php esc_html_e( 'SMTP Auth', 'submission-inbox' ); ?></th>
						<td>
							<?php SUBIN_View::checkbox_field( 'smtp_auth', __( 'Require username and password authentication', 'submission-inbox' ), (bool) $settings['smtp_auth'] ); ?>
						</td>
					</tr>
					<tr data-subin-show-when="enable_smtp,smtp_auth">
						<th scope="row"><label for="subin-smtp-username"><?php esc_html_e( 'Username', 'submission-inbox' ); ?></label></th>
						<td><input type="text" id="subin-smtp-username" name="smtp_username" class="regular-text" value="<?php echo esc_attr( $settings['smtp_username'] ); ?>" autocomplete="off" /></td>
					</tr>
					<tr data-subin-show-when="enable_smtp,smtp_auth">
						<th scope="row">
							<label for="subin-smtp-password"><?php esc_html_e( 'Password', 'submission-inbox' ); ?></label>
							<?php SUBIN_View::help_tooltip( __( 'For security, the saved password is never shown in the field.', 'submission-inbox' ) ); ?>
						</th>
						<td>
							<input type="password" id="subin-smtp-password" name="smtp_password" class="regular-text" value="" placeholder="<?php echo esc_attr( $this->password_placeholder( $settings ) ); ?>" autocomplete="new-password" />
							<p class="description"><?php esc_html_e( 'The saved password is never printed into the page.', 'submission-inbox' ); ?></p>
						</td>
					</tr>
				</tbody>
			</table>
			</div>
			<div class="subin-settings-savebar" data-subin-settings-savebar data-subin-dirty-label="<?php echo esc_attr__( 'Unsaved changes', 'submission-inbox' ); ?>" data-subin-clean-label="<?php echo esc_attr__( 'No unsaved changes', 'submission-inbox' ); ?>">
				<div class="subin-settings-savebar__state"><span class="dashicons dashicons-saved" aria-hidden="true"></span><span data-subin-settings-state aria-live="polite"><?php esc_html_e( 'No unsaved changes', 'submission-inbox' ); ?></span></div>
				<div class="subin-settings-savebar__actions"><button type="button" class="button button-secondary" data-subin-settings-discard hidden><?php esc_html_e( 'Discard changes', 'submission-inbox' ); ?></button><?php submit_button( __( 'Save changes', 'submission-inbox' ), 'primary', 'submit', false ); ?></div>
			</div>
		</form>
		<?php
	}

	/**
	 * Render test email form.
	 *
	 * @return void
	 */
	private function render_test_email_form() {
		$can_view_email_health = \SUBIN\Security\Capabilities::can_current_user( \SUBIN\Security\Capabilities::VIEW_EMAIL_HEALTH );
		?>
		<div class="subin-settings-section">
			<div class="subin-settings-section__header">
				<div><h2><?php esc_html_e( 'Verify saved configuration', 'submission-inbox' ); ?></h2><p><?php esc_html_e( 'Send a verification email using the last saved transport settings. Save changes above before testing.', 'submission-inbox' ); ?></p></div>
				<?php if ( $can_view_email_health ) : ?>
					<a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=subin-email-status' ) ); ?>"><?php esc_html_e( 'Open Email Health', 'submission-inbox' ); ?></a>
				<?php endif; ?>
			</div>
			<form method="post" action="" data-subin-settings-test-form>
				<input type="hidden" name="subin_smtp_action" value="send_test_email" />
				<?php wp_nonce_field( self::TEST_NONCE_ACTION, self::TEST_NONCE_NAME ); ?>
				<table class="form-table" role="presentation">
					<tbody>
						<tr>
							<th scope="row"><label for="subin-test-email-to"><?php esc_html_e( 'Send test email to', 'submission-inbox' ); ?></label></th>
							<td><input type="email" id="subin-test-email-to" name="test_email_to" class="regular-text" value="" required /></td>
						</tr>
					</tbody>
				</table>
				<?php submit_button( __( 'Send verification email', 'submission-inbox' ), 'secondary', 'submit', true, array( 'data-subin-settings-test-submit' => '1' ) ); ?>
			</form>
		</div>
		<?php
	}

	/**
	 * Save SMTP settings.
	 *
	 * @return void
	 */
	private function save_settings() {
		if ( ! $this->verify_nonce( self::SAVE_NONCE_ACTION, self::SAVE_NONCE_NAME ) ) {
			return;
		}

		$result = $this->settings->update_smtp_settings( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- SMTP settings nonce is verified above before this POST payload is sanitized by the repository.

		if ( is_wp_error( $result ) ) {
			add_settings_error(
				'subin_messages',
				$result->get_error_code(),
				$result->get_error_message(),
				'error'
			);
			return;
		}

		add_settings_error(
			'subin_messages',
			'subin_smtp_saved',
			__( 'Settings saved.', 'submission-inbox' ),
			'updated'
		);
	}

	/**
	 * Send a test email.
	 *
	 * @return void
	 */
	private function send_test_email() {
		if ( ! $this->verify_nonce( self::TEST_NONCE_ACTION, self::TEST_NONCE_NAME ) ) {
			return;
		}

		$recipient = wp_unslash( $_POST['test_email_to'] ?? '' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Test email nonce is verified above and the verification service validates the scalar address.
		$result    = $this->verification->send( $recipient, get_current_user_id() );

		if ( ! is_wp_error( $result ) ) {
			add_settings_error(
				'subin_messages',
				'subin_test_email_sent',
				$result['message'],
				'updated'
			);
			return;
		}

		add_settings_error(
			'subin_messages',
			$result->get_error_code(),
			$result->get_error_message(),
			'error'
		);
	}

	/**
	 * Render current configuration warnings.
	 *
	 * @param array<string,mixed> $settings Settings.
	 * @return void
	 */
	private function render_configuration_warnings( array $settings ) {
		if ( ! empty( $settings['enable_smtp'] ) && '' === (string) $settings['smtp_host'] ) {
			?>
			<div class="notice notice-warning">
				<p><?php esc_html_e( 'SMTP is enabled, but SMTP Host is empty.', 'submission-inbox' ); ?></p>
			</div>
			<?php
		}

		if ( '' !== (string) $settings['from_email'] && ! is_email( $settings['from_email'] ) ) {
			?>
			<div class="notice notice-warning">
				<p><?php esc_html_e( 'From Email must be a valid email address.', 'submission-inbox' ); ?></p>
			</div>
			<?php
		} elseif ( '' === (string) $settings['from_email'] ) {
			$admin_email = sanitize_email( (string) get_option( 'admin_email' ) );
			?>
			<div class="notice notice-warning">
				<p>
					<?php
					if ( is_email( $admin_email ) ) {
						printf(
							/* translators: %s: Site admin email address. */
							esc_html__( 'From Email is empty. WordPress will use the site admin email as the sender: %s.', 'submission-inbox' ),
							esc_html( $admin_email )
						);
					} else {
						esc_html_e( 'From Email is empty and the site admin email is not valid. Add a valid From Email before sending mail.', 'submission-inbox' );
					}
					?>
				</p>
			</div>
			<?php
		}

		if ( ! empty( $settings['smtp_auth'] ) && '' === (string) $settings['smtp_username'] ) {
			?>
			<div class="notice notice-warning">
				<p><?php esc_html_e( 'SMTP authentication is enabled, but Username is empty.', 'submission-inbox' ); ?></p>
			</div>
			<?php
		}
	}

	/**
	 * Verify a submitted nonce and show a controlled error.
	 *
	 * @param string $action Nonce action.
	 * @param string $name Nonce field name.
	 * @return bool
	 */
	private function verify_nonce( $action, $name ) {
		if ( isset( $_POST[ $name ] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ $name ] ) ), $action ) ) {
			return true;
		}

		add_settings_error(
			'subin_messages',
			'subin_security_check_failed',
			__( 'Security check failed. Please try again.', 'submission-inbox' ),
			'error'
		);

		return false;
	}

	/**
	 * Get password placeholder text.
	 *
	 * @param array<string,mixed> $settings Settings.
	 * @return string
	 */
	private function password_placeholder( array $settings ) {
		return '' !== (string) $settings['smtp_password']
			? __( 'Password is saved. Leave blank to keep existing password.', 'submission-inbox' )
			: '';
	}

	/**
	 * Redirect from an admin page callback without header warnings.
	 *
	 * @param string $url Target URL.
	 * @return void
	 */
	private function safe_admin_redirect( $url ) {
		$url = esc_url_raw( $url );
		if ( ! headers_sent() ) {
			wp_safe_redirect( $url );
			exit;
		}

		wp_die(
			wp_kses_post(
				sprintf(
					/* translators: %s: redirect URL. */
					__( 'The request was processed. <a href="%s">Continue</a>.', 'submission-inbox' ),
					esc_url( $url )
				)
			),
			esc_html__( 'Redirect', 'submission-inbox' ),
			array( 'response' => 303 )
		);
		exit;
	}
}
