<?php
/**
 * Validation, sanitization, and utilities for Email Delivery (SMTP).
 *
 * @package EmailSmtp
 * @since 1.0.1
 */

namespace EmailSmtp\Includes;

use WP_PowerSuite\Email\MailHeaders;

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

use EmailSmtp\Module;
use WP_PowerSuite\Core\OptionStoreModuleSettingsRepository;

final class SmtpSettingsHelper {

	/**
	 * @return array<string, mixed>
	 */
	public static function getDefaults(): array {
		return SettingsSchema::defaults();
	}

	/**
	 * Sanitize and validate module settings before save.
	 *
	 * @param array<string, mixed> $settings Raw settings.
	 * @return array<string, mixed>
	 */
	public static function normalizeSettings( array $settings ): array {
		return SettingsSchema::normalize( $settings );
	}

	public static function sanitizeHost( string $host ): string {
		$host = strtolower( trim( $host ) );
		if ( $host === '' ) {
			return '';
		}

		// Strip scheme/path if pasted from a URL.
		$host = preg_replace( '#^[a-z]+://#', '', $host ) ?? $host;
		$host = preg_replace( '#/.*$#', '', $host ) ?? $host;

		if ( ! preg_match( '/^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/i', $host ) ) {
			return '';
		}

		return sanitize_text_field( $host );
	}

	public static function sanitizeFromName( string $name ): string {
		$name = sanitize_text_field( $name );
		if ( function_exists( 'mb_substr' ) ) {
			return mb_substr( $name, 0, 200 );
		}
		return substr( $name, 0, 200 );
	}

	/**
	 * Re-encrypt legacy plaintext or ENC v1 passwords to ENC2 when possible.
	 */
	public static function migrateStoredPassword( string $stored, callable $encrypt ): string {
		if ( $stored === '' ) {
			return '';
		}
		if ( str_starts_with( $stored, 'ENC2:' ) ) {
			return $stored;
		}

		$plain = \EmailSmtp\Module::decryptPasswordStatic( $stored );
		if ( $plain === '' ) {
			return $stored;
		}

		$encrypted = $encrypt( $plain );
		return $encrypted !== '' ? $encrypted : $stored;
	}

	/**
	 * Detect other active SMTP/mail plugins that may conflict.
	 *
	 * Returns a single generic notice label (no third-party product names).
	 *
	 * @return list<string>
	 */
	public static function detectConflictingPlugins(): array {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$candidates = [
			'wp-mail-smtp/wp_mail_smtp.php',
			'fluent-smtp/fluent-smtp.php',
			'post-smtp/postman-smtp.php',
			'easy-wp-smtp/easy-wp-smtp.php',
			'smtp-mailer/main.php',
			'wp-smtp/wp-smtp.php',
			'gmail-smtp/main.php',
			'suremails/suremails.php',
		];

		foreach ( $candidates as $plugin_file ) {
			if ( is_plugin_active( $plugin_file ) ) {
				return [ __( 'another email delivery plugin', 'wp-powersuite' ) ];
			}
		}

		return [];
	}

	/**
	 * @param array<string, mixed> $settings
	 * @return array<string, mixed>
	 */
	public static function mergeWithDefaults( array $settings ): array {
		return array_merge( self::getDefaults(), $settings );
	}

	/**
	 * Register wp_mail filter once (also invoked from {@see registerPhpMailerHook()}).
	 */
	public static function registerWpMailFilter(): void {
		if ( ! has_filter( 'wp_mail', [ self::class, 'filterWpMailArgs' ] ) ) {
			add_filter( 'wp_mail', [ self::class, 'filterWpMailArgs' ], 5, 1 );
		}
	}

	/**
	 * Apply SMTP identity headers and ensure transport hook is registered for every wp_mail call.
	 *
	 * @param array<string, mixed> $args wp_mail arguments.
	 * @return array<string, mixed>
	 */
	public static function filterWpMailArgs( array $args ): array {
		if ( apply_filters( 'wp_powersuite_skip_smtp_mail_args', false, $args ) ) {
			return $args;
		}
		if ( ! class_exists( OptionStoreModuleSettingsRepository::class ) ) {
			return $args;
		}
		if ( ! OptionStoreModuleSettingsRepository::isModuleEnabled( 'email-smtp' ) ) {
			return $args;
		}

		self::ensureModuleLoaded();
		if ( class_exists( Module::class ) ) {
			Module::registerPhpMailerHook();
		}

		$headers = MailHeaders::normalizeLines( $args['headers'] ?? [] );
		$headers = MailHeaders::dropInvalidAddressHeaders( $headers );

		$args['headers'] = self::appendIdentityHeaders( $headers );

		return $args;
	}

	/**
	 * Ensure SMTP transport is registered and apply configured From / Reply-To headers.
	 *
	 * @param array<int, string> $headers Existing wp_mail headers.
	 * @return array<int, string>
	 */
	public static function prepareOutgoingMailHeaders( array $headers ): array {
		if ( ! class_exists( OptionStoreModuleSettingsRepository::class ) ) {
			return $headers;
		}
		if ( ! OptionStoreModuleSettingsRepository::isModuleEnabled( 'email-smtp' ) ) {
			return $headers;
		}

		self::ensureModuleLoaded();
		if ( class_exists( Module::class ) ) {
			Module::registerPhpMailerHook();
		}

		return self::appendIdentityHeaders( $headers );
	}

	/**
	 * @param array<int, string> $headers
	 * @return array<int, string>
	 */
	public static function appendIdentityHeaders( array $headers ): array {
		$settings = OptionStoreModuleSettingsRepository::forModule( 'email-smtp' )->all( [] );
		$settings = self::mergeWithDefaults( is_array( $settings ) ? $settings : [] );

		$headers = MailHeaders::dropInvalidAddressHeaders( $headers );

		if ( empty( $settings['smtp_host'] ) ) {
			return $headers;
		}

		$override = $settings['override_from'] === '1' || $settings['override_from'] === true;
		if ( $override && ! self::headerExists( $headers, 'From' ) ) {
			$from_email = sanitize_email( (string) $settings['from_email'] );
			if ( ! is_email( $from_email ) ) {
				$from_email = sanitize_email( (string) get_option( 'admin_email' ) );
			}
			if ( is_email( $from_email ) ) {
				$from_name = self::sanitizeFromName( (string) $settings['from_name'] );
				$headers[] = sprintf( 'From: %s <%s>', $from_name, $from_email );
			}
		}

		$reply_email = sanitize_email( (string) ( $settings['reply_to_email'] ?? '' ) );
		if ( is_email( $reply_email ) && ! self::headerExists( $headers, 'Reply-To' ) ) {
			$reply_name = self::sanitizeFromName( (string) ( $settings['reply_to_name'] ?? '' ) );
			$headers[] = sprintf( 'Reply-To: %s <%s>', $reply_name, $reply_email );
		}

		return $headers;
	}

	/**
	 * @param array<int, string> $headers
	 */
	private static function headerExists( array $headers, string $name ): bool {
		$prefix = strtolower( $name ) . ':';
		foreach ( $headers as $header ) {
			if ( stripos( (string) $header, $prefix ) === 0 ) {
				return true;
			}
		}

		return false;
	}

	private static function ensureModuleLoaded(): void {
		if ( class_exists( Module::class ) ) {
			return;
		}
		if ( ! defined( 'WP_POWERSUITE_MODULES_DIR' ) ) {
			return;
		}

		$module_file = WP_POWERSUITE_MODULES_DIR . 'email-smtp' . DIRECTORY_SEPARATOR . 'module.php';
		if ( is_readable( $module_file ) ) {
			require_once $module_file;
		}
	}
}
