<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

final class TMSMTP_Free_Routing {
	const OPTION = 'titanium_mail_smtp';
	const ADDITIONAL_ID = 'additional';
	const SECRET_MASK = '••••••••••••';
	const ROUTE_LIMIT = 50;
	const ROUTE_GROUP_LIMIT = 20;
	const ROUTE_RULE_LIMIT = 20;
	const ROUTE_TOTAL_RULE_LIMIT = 500;
	const ROUTE_VALUE_LIMIT = 500;
	private static $instance;
	private $connection_contexts = array();
	private $pre_mail_contexts = array();
	private $next_context_id = 1;
	private $forced_connection = '';

	public static function instance() {
		if ( null === self::$instance ) { self::$instance = new self(); }
		return self::$instance;
	}

	private function __construct() {
		add_filter( 'wp_mail', array( $this, 'select_connection' ), PHP_INT_MAX );
		add_filter( 'pre_wp_mail', array( $this, 'begin_pre_mail' ), PHP_INT_MIN, 2 );
		add_filter( 'pre_wp_mail', array( $this, 'finish_pre_mail' ), PHP_INT_MAX, 2 );
		add_action( 'wp_mail_succeeded', array( $this, 'finish_delivery' ), PHP_INT_MAX );
		add_action( 'wp_mail_failed', array( $this, 'finish_delivery' ), PHP_INT_MAX );
		add_filter( 'tmsmtp_runtime_connection', array( $this, 'runtime_connection' ), 10, 1 );
		add_action( 'admin_post_tmsmtp_free_routing_save', array( $this, 'process_save' ) );
		add_action( 'admin_post_tmsmtp_free_routing_test', array( $this, 'process_test' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), 20 );
	}

	private function additional_defaults() {
		return array(
			'name' => __( 'Additional Connection', 'titanium-mail-smtp' ),
			'mailer' => 'postmark',
			'from_email' => get_option( 'admin_email' ),
			'from_name' => get_bloginfo( 'name' ),
			'force_from_email' => 1,
			'force_from_name' => 1,
			'postmark_token' => '',
			'message_stream' => 'outbound',
			'sendgrid_api_key' => '',
			'mailgun_api_key' => '',
			'mailgun_domain' => '',
			'mailgun_region' => 'US',
			'brevo_api_key' => '',
			'ses_access_key' => '',
			'ses_secret_key' => '',
			'ses_session_token' => '',
			'ses_region' => 'us-east-1',
			'smtp_host' => '',
			'smtp_port' => 587,
			'smtp_encryption' => 'tls',
			'smtp_autotls' => 1,
			'smtp_auth' => 1,
			'smtp_user' => '',
			'smtp_pass' => '',
		);
	}

	private function resolve_additional_id( $connections ) {
		$connections = is_array( $connections ) ? $connections : array();
		if ( isset( $connections[ self::ADDITIONAL_ID ] ) && is_array( $connections[ self::ADDITIONAL_ID ] ) ) { return self::ADDITIONAL_ID; }
		foreach ( $connections as $id => $connection ) {
			$id = sanitize_key( (string) $id );
			if ( 'primary' !== $id && '' !== $id && is_array( $connection ) ) { return $id; }
		}
		return self::ADDITIONAL_ID;
	}

	private function settings() {
		$stored = get_option( self::OPTION, array() );
		$stored = is_array( $stored ) ? $stored : array();
		$connections = isset( $stored['connections'] ) && is_array( $stored['connections'] ) ? $stored['connections'] : array();
		$connection_id = $this->resolve_additional_id( $connections );
		$has_connection = isset( $connections[ $connection_id ] ) && is_array( $connections[ $connection_id ] );
		$additional = $has_connection ? $connections[ $connection_id ] : array();
		$additional_enabled = array_key_exists( 'additional_enabled', $stored ) ? ( empty( $stored['additional_enabled'] ) ? 0 : 1 ) : ( $has_connection ? 1 : 0 );
		return array(
			'additional_enabled' => $additional_enabled,
			'connection_id' => $connection_id,
			'connection' => $this->apply_constants( $this->normalize_connection( $additional ) ),
			'routing_enabled' => empty( $stored['routing_enabled'] ) ? 0 : 1,
			'routes' => $this->normalize_routes( isset( $stored['routes'] ) ? $stored['routes'] : array(), $connection_id ),
		);
	}

	private function normalize_connection( $connection ) {
		$connection = wp_parse_args( is_array( $connection ) ? $connection : array(), $this->additional_defaults() );
		$scalar = static function ( $value, $fallback = '' ) { return is_scalar( $value ) ? (string) $value : (string) $fallback; };
		$mailer = sanitize_key( $scalar( $connection['mailer'], 'postmark' ) );
		$encryption = sanitize_key( $scalar( $connection['smtp_encryption'], 'tls' ) );
		$region = strtoupper( $scalar( $connection['mailgun_region'], 'US' ) );
		$allowed_mailers = array( 'postmark', 'amazonses', 'sendgrid', 'mailgun', 'brevo', 'smtp' );
		$normalized = array(
			'name' => sanitize_text_field( $scalar( $connection['name'], __( 'Additional Connection', 'titanium-mail-smtp' ) ) ),
			'mailer' => in_array( $mailer, $allowed_mailers, true ) ? $mailer : 'postmark',
			'from_email' => sanitize_email( $scalar( $connection['from_email'] ) ),
			'from_name' => sanitize_text_field( $scalar( $connection['from_name'] ) ),
			'force_from_email' => empty( $connection['force_from_email'] ) ? 0 : 1,
			'force_from_name' => empty( $connection['force_from_name'] ) ? 0 : 1,
			'postmark_token' => $scalar( $connection['postmark_token'] ),
			'message_stream' => sanitize_text_field( $scalar( $connection['message_stream'], 'outbound' ) ),
			'sendgrid_api_key' => $scalar( $connection['sendgrid_api_key'] ),
			'mailgun_api_key' => $scalar( $connection['mailgun_api_key'] ),
			'mailgun_domain' => sanitize_text_field( $scalar( $connection['mailgun_domain'] ) ),
			'mailgun_region' => in_array( $region, array( 'US', 'EU' ), true ) ? $region : 'US',
			'brevo_api_key' => $scalar( $connection['brevo_api_key'] ),
			'ses_access_key' => $scalar( $connection['ses_access_key'] ),
			'ses_secret_key' => $scalar( $connection['ses_secret_key'] ),
			'ses_session_token' => $scalar( $connection['ses_session_token'] ),
			'ses_region' => sanitize_key( $scalar( $connection['ses_region'], 'us-east-1' ) ),
			'smtp_host' => sanitize_text_field( $scalar( $connection['smtp_host'] ) ),
			'smtp_port' => min( 65535, max( 1, absint( $connection['smtp_port'] ) ) ),
			'smtp_encryption' => in_array( $encryption, array( 'none', 'ssl', 'tls' ), true ) ? $encryption : 'tls',
			'smtp_autotls' => empty( $connection['smtp_autotls'] ) ? 0 : 1,
			'smtp_auth' => empty( $connection['smtp_auth'] ) ? 0 : 1,
			'smtp_user' => sanitize_text_field( $scalar( $connection['smtp_user'] ) ),
			'smtp_pass' => $scalar( $connection['smtp_pass'] ),
		);
		if ( '' === $normalized['name'] ) { $normalized['name'] = __( 'Additional Connection', 'titanium-mail-smtp' ); }
		return array_merge( $connection, $normalized );
	}

	private function connection_constant_name( $type ) {
		$types = array(
			'postmark' => 'TMSMTP_POSTMARK_ADDITIONAL_TOKEN',
			'sendgrid' => 'TMSMTP_SENDGRID_ADDITIONAL_API_KEY',
			'mailgun' => 'TMSMTP_MAILGUN_ADDITIONAL_API_KEY',
			'brevo' => 'TMSMTP_BREVO_ADDITIONAL_API_KEY',
			'ses_access' => 'TMSMTP_SES_ADDITIONAL_ACCESS_KEY',
			'ses_secret' => 'TMSMTP_SES_ADDITIONAL_SECRET_KEY',
			'ses_session' => 'TMSMTP_SES_ADDITIONAL_SESSION_TOKEN',
			'smtp' => 'TMSMTP_SMTP_ADDITIONAL_PASSWORD',
		);
		return isset( $types[ $type ] ) ? $types[ $type ] : '';
	}

	private function apply_constants( $connection ) {
		$map = array(
			'postmark_token' => 'postmark',
			'sendgrid_api_key' => 'sendgrid',
			'mailgun_api_key' => 'mailgun',
			'brevo_api_key' => 'brevo',
			'ses_access_key' => 'ses_access',
			'ses_secret_key' => 'ses_secret',
			'ses_session_token' => 'ses_session',
			'smtp_pass' => 'smtp',
		);
		foreach ( $map as $key => $type ) {
			$current = $this->connection_constant_name( $type );
			$legacy = preg_replace( '/^TMSMTP_/', 'TMS_', $current );
			foreach ( array( $current, $legacy ) as $constant ) {
				if ( $constant && defined( $constant ) ) {
					$value = constant( $constant );
					$connection[ $key ] = is_scalar( $value ) ? (string) $value : '';
					break;
				}
			}
		}
		return $connection;
	}

	public function select_connection( $args ) {
		$connection = $this->forced_connection ? $this->forced_connection : $this->route_connection( is_array( $args ) ? $args : array() );
		$this->connection_contexts[] = array(
			'id' => $this->next_context_id++,
			'connection' => $connection,
		);
		return $args;
	}

	public function begin_pre_mail( $return, $atts ) {
		$context_id = $this->current_context_id();
		if ( $context_id ) {
			$connection = $this->forced_connection ? $this->forced_connection : $this->route_connection( is_array( $atts ) ? $atts : array() );
			$this->update_context_connection( $context_id, $connection );
		}
		$this->pre_mail_contexts[] = $context_id;
		return $return;
	}

	public function finish_pre_mail( $return, $atts ) {
		$context_id = array_pop( $this->pre_mail_contexts );
		if ( null !== $return && $context_id ) { $this->remove_context( $context_id ); }
		return $return;
	}

	public function finish_delivery( $result = null ) {
		$context_id = $this->pre_mail_contexts ? end( $this->pre_mail_contexts ) : $this->current_context_id();
		if ( $context_id ) { $this->remove_context( $context_id ); }
	}

	private function current_context_id() {
		if ( empty( $this->connection_contexts ) ) { return 0; }
		$context = $this->connection_contexts[ count( $this->connection_contexts ) - 1 ];
		return isset( $context['id'] ) ? absint( $context['id'] ) : 0;
	}

	private function update_context_connection( $context_id, $connection ) {
		for ( $index = count( $this->connection_contexts ) - 1; $index >= 0; $index-- ) {
			if ( isset( $this->connection_contexts[ $index ]['id'] ) && (int) $this->connection_contexts[ $index ]['id'] === (int) $context_id ) {
				$this->connection_contexts[ $index ]['connection'] = $connection;
				break;
			}
		}
	}

	private function remove_context( $context_id ) {
		for ( $index = count( $this->connection_contexts ) - 1; $index >= 0; $index-- ) {
			if ( isset( $this->connection_contexts[ $index ]['id'] ) && (int) $this->connection_contexts[ $index ]['id'] === (int) $context_id ) {
				array_splice( $this->connection_contexts, $index, 1 );
				break;
			}
		}
	}

	public function runtime_connection( $primary ) {
		if ( empty( $this->connection_contexts ) ) { return $primary; }
		$context = $this->connection_contexts[ count( $this->connection_contexts ) - 1 ];
		$selected_connection = isset( $context['connection'] ) ? sanitize_key( (string) $context['connection'] ) : 'primary';
		$settings = $this->settings();
		if ( $settings['connection_id'] !== $selected_connection ) { return $primary; }
		if ( empty( $settings['additional_enabled'] ) ) { return $primary; }
		$status = TMSMTP_Plugin::instance()->get_connection_status( $settings['connection'] );
		return ! empty( $status['configured'] ) ? $settings['connection'] : $primary;
	}

	private function route_connection( $args ) {
		$settings = $this->settings();
		if ( empty( $settings['additional_enabled'] ) || empty( $settings['routing_enabled'] ) || empty( $settings['routes'] ) ) { return 'primary'; }
		$status = TMSMTP_Plugin::instance()->get_connection_status( $settings['connection'] );
		if ( empty( $status['configured'] ) ) { return 'primary'; }
		$values = $this->mail_values( $args );
		foreach ( $settings['routes'] as $route ) {
			if ( ! empty( $route['conditionals'] ) && $this->conditionals_match( $route['conditionals'], $values ) ) { return $settings['connection_id']; }
		}
		return 'primary';
	}

	private function mail_values( $args ) {
		$header_input = isset( $args['headers'] ) ? $args['headers'] : array();
		$headers = $this->parse_headers( $header_input );
		$route_headers = $this->routing_headers( $header_input );
		$from_email = ! empty( $headers['from_email'] ) ? $headers['from_email'] : $this->default_from_email();
		$from_name = ! empty( $headers['from_name'] ) ? $headers['from_name'] : 'WordPress';
		return array(
			'subject' => isset( $args['subject'] ) ? $args['subject'] : '',
			'message' => isset( $args['message'] ) ? $args['message'] : '',
			'to_email' => $this->routing_address_values( isset( $args['to'] ) ? $args['to'] : array() ),
			'from_email' => $from_email,
			'from_name' => $from_name,
			'cc' => $this->routing_address_values( isset( $route_headers['cc'] ) ? $route_headers['cc'] : array() ),
			'bcc' => $this->routing_address_values( isset( $route_headers['bcc'] ) ? $route_headers['bcc'] : array() ),
			'reply_to' => $this->routing_address_values( isset( $route_headers['reply-to'] ) ? $route_headers['reply-to'] : array() ),
			'header_name' => array_keys( $route_headers ),
			'header_value' => $this->flatten_values( array_values( $route_headers ) ),
			'initiator' => self::detect_mail_initiator(),
		);
	}

	private function parse_headers( $headers ) {
		$lines = array();
		if ( is_string( $headers ) ) { $lines = preg_split( '/\r\n|\r|\n/', $headers ); }
		elseif ( is_array( $headers ) ) {
			foreach ( $headers as $name => $value ) {
				if ( is_string( $name ) ) {
					foreach ( (array) $value as $item ) { if ( is_scalar( $item ) ) { $lines[] = $name . ': ' . $item; } }
				} elseif ( is_scalar( $value ) ) { $lines[] = (string) $value; }
			}
		}
		$out = array();
		foreach ( (array) $lines as $line ) {
			if ( ! is_string( $line ) || false === strpos( $line, ':' ) ) { continue; }
			list( $name, $value ) = array_map( 'trim', explode( ':', $line, 2 ) );
			$name = strtolower( $name );
			if ( 'from' === $name ) {
				if ( preg_match( '/^(.*)<([^>]+)>$/', $value, $matches ) ) {
					$out['from_name'] = trim( $matches[1], " \t\n\r\0\x0B\"'" );
					$out['from_email'] = sanitize_email( $matches[2] );
				} else { $out['from_email'] = sanitize_email( $value ); }
			}
		}
		return $out;
	}

	private function routing_headers( $headers ) {
		$lines = array();
		if ( is_string( $headers ) ) { $lines = preg_split( '/\r\n|\r|\n/', $headers ); }
		elseif ( is_array( $headers ) ) {
			foreach ( $headers as $name => $value ) {
				if ( is_string( $name ) ) { foreach ( (array) $value as $item ) { if ( is_scalar( $item ) ) { $lines[] = $name . ': ' . $item; } } }
				elseif ( is_scalar( $value ) ) { $lines[] = (string) $value; }
			}
		}
		$parsed = array();
		foreach ( (array) $lines as $line ) {
			if ( ! is_string( $line ) || false === strpos( $line, ':' ) ) { continue; }
			list( $name, $value ) = array_map( 'trim', explode( ':', $line, 2 ) );
			$name = strtolower( $name );
			if ( '' === $name ) { continue; }
			if ( isset( $parsed[ $name ] ) && in_array( $name, array( 'cc', 'bcc', 'reply-to' ), true ) ) { $parsed[ $name ] .= ', ' . $value; }
			else { $parsed[ $name ] = $value; }
		}
		return $parsed;
	}

	private function conditionals_match( $conditionals, $values ) {
		if ( empty( $conditionals ) ) { return true; }
		foreach ( (array) $conditionals as $group ) {
			$group_pass = true;
			foreach ( (array) $group as $rule ) {
				$property = isset( $rule['property'] ) ? sanitize_key( $rule['property'] ) : '';
				$operator = isset( $rule['operator'] ) ? (string) $rule['operator'] : '';
				$expected = strtolower( trim( isset( $rule['value'] ) ? (string) $rule['value'] : '' ) );
				if ( '' === $expected ) { $group_pass = false; break; }
				$actual_values = $this->flatten_values( isset( $values[ $property ] ) ? $values[ $property ] : array() );
				$is_negative = in_array( $operator, array( '!=', '!c' ), true );
				$rule_pass = $is_negative;
				foreach ( $actual_values as $actual ) {
					$actual = strtolower( trim( (string) $actual ) );
					switch ( $operator ) {
						case '==': case '!=': $match = $actual === $expected; break;
						case 'c': case '!c': $match = false !== strpos( $actual, $expected ); break;
						case '^': $match = 0 === strpos( $actual, $expected ); break;
						case '~': $match = substr( $actual, -strlen( $expected ) ) === $expected; break;
						default: $match = false;
					}
					if ( $is_negative && $match ) { $rule_pass = false; break; }
					if ( ! $is_negative && $match ) { $rule_pass = true; break; }
				}
				if ( ! $rule_pass ) { $group_pass = false; break; }
			}
			if ( $group_pass ) { return true; }
		}
		return false;
	}

	private function routing_address_values( $values ) {
		$normalized = array();
		foreach ( $this->flatten_values( $values ) as $value ) {
			$value = trim( (string) $value );
			if ( '' === $value ) { continue; }
			$addresses = str_getcsv( $value, ',', '"', '\\' );
			if ( ! is_array( $addresses ) || empty( $addresses ) ) { $addresses = array( $value ); }
			foreach ( $addresses as $address ) {
				$address = trim( (string) $address );
				if ( '' === $address ) { continue; }
				$normalized[] = $address;
				if ( preg_match( '/<\s*([^<>]+)\s*>$/', $address, $matches ) ) {
					$email = trim( $matches[1] );
					if ( '' !== $email ) { $normalized[] = $email; }
				}
			}
		}
		return array_values( array_unique( $normalized ) );
	}

	private function flatten_values( $values ) {
		$flat = array();
		foreach ( (array) $values as $value ) {
			if ( is_array( $value ) ) { $flat = array_merge( $flat, $this->flatten_values( $value ) ); }
			elseif ( is_scalar( $value ) || null === $value ) { $flat[] = (string) $value; }
		}
		return $flat;
	}

	private function default_from_email() {
		$host = wp_parse_url( network_home_url(), PHP_URL_HOST );
		$host = is_string( $host ) ? preg_replace( '/^www\./i', '', $host ) : '';
		return $host ? 'wordpress@' . $host : get_option( 'admin_email' );
	}

	public static function detect_mail_initiator() {
		$plugin_dir = defined( 'WP_PLUGIN_DIR' ) ? trailingslashit( wp_normalize_path( WP_PLUGIN_DIR ) ) : '';
		$mu_dir = defined( 'WPMU_PLUGIN_DIR' ) ? trailingslashit( wp_normalize_path( WPMU_PLUGIN_DIR ) ) : '';
		$theme_root = function_exists( 'get_theme_root' ) ? trailingslashit( wp_normalize_path( get_theme_root() ) ) : '';
		$wp_admin = defined( 'ABSPATH' ) ? wp_normalize_path( trailingslashit( ABSPATH . 'wp-admin' ) ) : '';
		$wp_include = defined( 'ABSPATH' ) && defined( 'WPINC' ) ? wp_normalize_path( trailingslashit( ABSPATH . WPINC ) ) : '';
		$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 40 ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace
		$start = 0;
		$core = false;
		foreach ( $backtrace as $index => $frame ) { if ( isset( $frame['function'] ) && 'wp_mail' === $frame['function'] ) { $start = $index; break; } }
		for ( $index = $start, $count = count( $backtrace ); $index < $count; $index++ ) {
			if ( empty( $backtrace[ $index ]['file'] ) ) { continue; }
			$file = wp_normalize_path( $backtrace[ $index ]['file'] );
			if ( $file === wp_normalize_path( __FILE__ ) ) { continue; }
			if ( $mu_dir && 0 === strpos( $file, $mu_dir ) ) { return self::resolve_plugin_slug( substr( $file, strlen( $mu_dir ) ), true ); }
			if ( $plugin_dir && 0 === strpos( $file, $plugin_dir ) ) { return self::resolve_plugin_slug( substr( $file, strlen( $plugin_dir ) ), false ); }
			if ( $theme_root && 0 === strpos( $file, $theme_root ) ) { $slug = strtok( substr( $file, strlen( $theme_root ) ), '/' ); return false === $slug ? '' : $slug; }
			if ( ( $wp_admin && 0 === strpos( $file, $wp_admin ) ) || ( $wp_include && 0 === strpos( $file, $wp_include ) ) ) { $core = true; }
		}
		return $core ? 'wp-core' : '';
	}

	private static function resolve_plugin_slug( $relative_file, $must_use ) {
		static $plugin_files = array();
		$relative_file = ltrim( wp_normalize_path( (string) $relative_file ), '/' );
		if ( '' === $relative_file ) { return ''; }
		$key = $must_use ? 'mu' : 'standard';
		if ( ! isset( $plugin_files[ $key ] ) ) {
			if ( ! function_exists( 'get_plugins' ) && defined( 'ABSPATH' ) ) {
				$file = ABSPATH . 'wp-admin/includes/plugin.php';
				if ( is_readable( $file ) ) { require_once $file; }
			}
			$plugins = $must_use && function_exists( 'get_mu_plugins' ) ? get_mu_plugins() : ( function_exists( 'get_plugins' ) ? get_plugins() : array() );
			$plugin_files[ $key ] = array_keys( (array) $plugins );
		}
		$root = false !== strpos( $relative_file, '/' ) ? strtok( $relative_file, '/' ) : $relative_file;
		foreach ( $plugin_files[ $key ] as $plugin_file ) {
			if ( $plugin_file === $relative_file || $plugin_file === $root || 0 === strpos( $plugin_file, $root . '/' ) ) { return $plugin_file; }
		}
		return $root;
	}

	private function sanitize_secret( $submitted, $saved, $was_submitted ) {
		if ( ! $was_submitted || ! is_scalar( $submitted ) ) { return (string) $saved; }
		$value = trim( (string) $submitted );
		return self::SECRET_MASK === $value ? (string) $saved : $value;
	}

	private function sanitize_connection_submission( $submitted, $saved ) {
		$submitted = is_array( $submitted ) ? $submitted : array();
		$saved = $this->normalize_connection( $saved );
		$scalar = static function ( $value, $fallback = '' ) { return is_scalar( $value ) ? (string) $value : (string) $fallback; };
		$mailer = sanitize_key( $scalar( $submitted['mailer'] ?? '', 'postmark' ) );
		$encryption = sanitize_key( $scalar( $submitted['smtp_encryption'] ?? '', 'tls' ) );
		$region = strtoupper( $scalar( $submitted['mailgun_region'] ?? '', 'US' ) );
		$allowed = array( 'postmark', 'amazonses', 'sendgrid', 'mailgun', 'brevo', 'smtp' );
		$connection = array_merge( $saved, array(
			'name' => sanitize_text_field( $scalar( $submitted['name'] ?? '', __( 'Additional Connection', 'titanium-mail-smtp' ) ) ),
			'mailer' => in_array( $mailer, $allowed, true ) ? $mailer : 'postmark',
			'from_email' => sanitize_email( $scalar( $submitted['from_email'] ?? '' ) ),
			'from_name' => sanitize_text_field( $scalar( $submitted['from_name'] ?? '' ) ),
			'force_from_email' => empty( $submitted['force_from_email'] ) ? 0 : 1,
			'force_from_name' => empty( $submitted['force_from_name'] ) ? 0 : 1,
			'postmark_token' => $this->sanitize_secret( isset( $submitted['postmark_token'] ) ? $submitted['postmark_token'] : null, $saved['postmark_token'], array_key_exists( 'postmark_token', $submitted ) ),
			'message_stream' => sanitize_text_field( $scalar( $submitted['message_stream'] ?? '', 'outbound' ) ),
			'sendgrid_api_key' => $this->sanitize_secret( isset( $submitted['sendgrid_api_key'] ) ? $submitted['sendgrid_api_key'] : null, $saved['sendgrid_api_key'], array_key_exists( 'sendgrid_api_key', $submitted ) ),
			'mailgun_api_key' => $this->sanitize_secret( isset( $submitted['mailgun_api_key'] ) ? $submitted['mailgun_api_key'] : null, $saved['mailgun_api_key'], array_key_exists( 'mailgun_api_key', $submitted ) ),
			'mailgun_domain' => sanitize_text_field( $scalar( $submitted['mailgun_domain'] ?? '' ) ),
			'mailgun_region' => in_array( $region, array( 'US', 'EU' ), true ) ? $region : 'US',
			'brevo_api_key' => $this->sanitize_secret( isset( $submitted['brevo_api_key'] ) ? $submitted['brevo_api_key'] : null, $saved['brevo_api_key'], array_key_exists( 'brevo_api_key', $submitted ) ),
			'ses_access_key' => $this->sanitize_secret( isset( $submitted['ses_access_key'] ) ? $submitted['ses_access_key'] : null, $saved['ses_access_key'], array_key_exists( 'ses_access_key', $submitted ) ),
			'ses_secret_key' => $this->sanitize_secret( isset( $submitted['ses_secret_key'] ) ? $submitted['ses_secret_key'] : null, $saved['ses_secret_key'], array_key_exists( 'ses_secret_key', $submitted ) ),
			'ses_session_token' => $this->sanitize_secret( isset( $submitted['ses_session_token'] ) ? $submitted['ses_session_token'] : null, $saved['ses_session_token'], array_key_exists( 'ses_session_token', $submitted ) ),
			'ses_region' => sanitize_key( $scalar( $submitted['ses_region'] ?? '', 'us-east-1' ) ),
			'smtp_host' => sanitize_text_field( $scalar( $submitted['smtp_host'] ?? '' ) ),
			'smtp_port' => min( 65535, max( 1, absint( isset( $submitted['smtp_port'] ) ? $submitted['smtp_port'] : 587 ) ) ),
			'smtp_encryption' => in_array( $encryption, array( 'none', 'ssl', 'tls' ), true ) ? $encryption : 'tls',
			'smtp_autotls' => empty( $submitted['smtp_autotls'] ) ? 0 : 1,
			'smtp_auth' => empty( $submitted['smtp_auth'] ) ? 0 : 1,
			'smtp_user' => sanitize_text_field( $scalar( $submitted['smtp_user'] ?? '' ) ),
			'smtp_pass' => $this->sanitize_secret( isset( $submitted['smtp_pass'] ) ? $submitted['smtp_pass'] : null, $saved['smtp_pass'], array_key_exists( 'smtp_pass', $submitted ) ),
		) );
		return $this->normalize_connection( $connection );
	}

	private function validate_connection( $submitted, $connection ) {
		$submitted = is_array( $submitted ) ? $submitted : array();
		$connection = $this->apply_constants( $this->normalize_connection( $connection ) );
		$mailer = is_scalar( $submitted['mailer'] ?? '' ) ? sanitize_key( (string) $submitted['mailer'] ) : '';
		if ( ! in_array( $mailer, array( 'postmark', 'amazonses', 'sendgrid', 'mailgun', 'brevo', 'smtp' ), true ) ) { return new WP_Error( 'tmsmtp_free_routing_mailer', __( 'Select a valid mailer for the Additional Connection.', 'titanium-mail-smtp' ) ); }
		$raw_from_email = is_scalar( $submitted['from_email'] ?? '' ) ? trim( (string) $submitted['from_email'] ) : '';
		if ( '' !== $raw_from_email && ! is_email( $connection['from_email'] ) ) { return new WP_Error( 'tmsmtp_free_routing_from', __( 'Enter a valid From Email address for the Additional Connection.', 'titanium-mail-smtp' ) ); }
		if ( 'mailgun' === $mailer ) {
			$raw_region = is_scalar( $submitted['mailgun_region'] ?? '' ) ? strtoupper( trim( (string) $submitted['mailgun_region'] ) ) : '';
			if ( ! in_array( $raw_region, array( 'US', 'EU' ), true ) ) { return new WP_Error( 'tmsmtp_free_routing_mailgun_region', __( 'Select a valid Mailgun region for the Additional Connection.', 'titanium-mail-smtp' ) ); }
		}
		if ( 'amazonses' === $mailer ) {
			$raw_region = is_scalar( $submitted['ses_region'] ?? '' ) ? trim( (string) $submitted['ses_region'] ) : '';
			if ( 1 !== preg_match( '/^[a-z]{2}(?:-gov)?-[a-z0-9-]+-\d$/', $raw_region ) ) { return new WP_Error( 'tmsmtp_free_routing_ses_region', __( 'Enter a valid Amazon SES region for the Additional Connection, for example us-east-1.', 'titanium-mail-smtp' ) ); }
		}
		if ( 'smtp' === $mailer ) {
			$raw_port = is_scalar( $submitted['smtp_port'] ?? null ) ? trim( (string) $submitted['smtp_port'] ) : '';
			$valid_port = false !== filter_var( $raw_port, FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1, 'max_range' => 65535 ) ) );
			if ( ! $valid_port ) { return new WP_Error( 'tmsmtp_free_routing_smtp_port', __( 'SMTP port must be a whole number between 1 and 65535.', 'titanium-mail-smtp' ) ); }
			$raw_encryption = is_scalar( $submitted['smtp_encryption'] ?? '' ) ? sanitize_key( (string) $submitted['smtp_encryption'] ) : '';
			if ( ! in_array( $raw_encryption, array( 'none', 'ssl', 'tls' ), true ) ) { return new WP_Error( 'tmsmtp_free_routing_smtp_encryption', __( 'Select a valid SMTP encryption method.', 'titanium-mail-smtp' ) ); }
			if ( ! $this->valid_smtp_host( $connection['smtp_host'] ) ) { return new WP_Error( 'tmsmtp_free_routing_smtp_host', __( 'Enter a valid SMTP host without a URL path or protocol.', 'titanium-mail-smtp' ) ); }
		}
		$status = TMSMTP_Plugin::instance()->get_connection_status( $connection );
		if ( empty( $status['configured'] ) ) { return new WP_Error( 'tmsmtp_free_routing_incomplete', $status['message'] ); }
		return true;
	}

	private function valid_smtp_host( $host ) {
		$host = trim( is_scalar( $host ) ? (string) $host : '' );
		if ( '' === $host || strlen( $host ) > 253 || false !== strpos( $host, '://' ) || preg_match( '/[\s\/?#]/', $host ) ) { return false; }
		if ( '[' === substr( $host, 0, 1 ) && ']' === substr( $host, -1 ) ) { return false !== filter_var( substr( $host, 1, -1 ), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ); }
		if ( false !== filter_var( $host, FILTER_VALIDATE_IP ) ) { return true; }
		return 1 === preg_match( '/^(?=.{1,253}\.?$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.?$/i', $host );
	}

	private function validate_route_submission( $posted_routes, $connection_id ) {
		if ( ! is_array( $posted_routes ) || count( $posted_routes ) > self::ROUTE_LIMIT ) {
			return new WP_Error( 'tmsmtp_free_routes_limit', __( 'Smart Routing accepts a maximum of 50 routes. No changes were saved.', 'titanium-mail-smtp' ) );
		}
		$property_labels = $this->route_property_labels();
		$operator_labels = $this->route_operator_labels();
		$total_rules = 0;
		foreach ( $posted_routes as $route ) {
			if ( ! is_array( $route ) || sanitize_key( isset( $route['connection_id'] ) && is_scalar( $route['connection_id'] ) ? (string) $route['connection_id'] : '' ) !== $connection_id ) {
				return new WP_Error( 'tmsmtp_free_route_invalid', __( 'A Smart Routing route is invalid. No changes were saved.', 'titanium-mail-smtp' ) );
			}
			$groups = isset( $route['groups'] ) ? $route['groups'] : ( isset( $route['conditionals'] ) ? $route['conditionals'] : null );
			if ( ! is_array( $groups ) || ! $groups || count( $groups ) > self::ROUTE_GROUP_LIMIT ) {
				return new WP_Error( 'tmsmtp_free_route_groups', __( 'Each Smart Routing route must contain 1 to 20 condition groups. No changes were saved.', 'titanium-mail-smtp' ) );
			}
			foreach ( $groups as $group ) {
				$rules = is_array( $group ) && array_key_exists( 'rules', $group ) ? $group['rules'] : $group;
				if ( ! is_array( $rules ) || ! $rules || count( $rules ) > self::ROUTE_RULE_LIMIT ) {
					return new WP_Error( 'tmsmtp_free_route_rules', __( 'Each Smart Routing group must contain 1 to 20 conditions. No changes were saved.', 'titanium-mail-smtp' ) );
				}
				foreach ( $rules as $rule ) {
					$property = is_array( $rule ) && is_scalar( $rule['property'] ?? null ) ? sanitize_key( (string) $rule['property'] ) : '';
					$operator = is_array( $rule ) && is_scalar( $rule['operator'] ?? null ) ? sanitize_text_field( (string) $rule['operator'] ) : '';
					$raw_value = is_array( $rule ) && is_scalar( $rule['value'] ?? null ) ? trim( (string) $rule['value'] ) : '';
					$value = sanitize_text_field( $raw_value );
					if ( ! isset( $property_labels[ $property ], $operator_labels[ $operator ] ) || '' === $value || strlen( $raw_value ) > self::ROUTE_VALUE_LIMIT ) {
						return new WP_Error( 'tmsmtp_free_route_rule_invalid', __( 'A Smart Routing condition is empty, invalid, or longer than 500 characters. No changes were saved.', 'titanium-mail-smtp' ) );
					}
					if ( ++$total_rules > self::ROUTE_TOTAL_RULE_LIMIT ) {
						return new WP_Error( 'tmsmtp_free_route_total_limit', __( 'Smart Routing accepts a maximum of 500 conditions in total. No changes were saved.', 'titanium-mail-smtp' ) );
					}
				}
			}
		}
		return true;
	}

	private function normalize_routes( $posted_routes, $connection_id = self::ADDITIONAL_ID ) {
		$normalized = array();
		$property_labels = $this->route_property_labels();
		$operator_labels = $this->route_operator_labels();
		$connection_id = sanitize_key( (string) $connection_id );
		if ( '' === $connection_id || 'primary' === $connection_id ) { $connection_id = self::ADDITIONAL_ID; }
		foreach ( array_slice( (array) $posted_routes, 0, self::ROUTE_LIMIT ) as $route ) {
			if ( ! is_array( $route ) ) { continue; }
			$posted_shape = isset( $route['groups'] );
			$route_connection = isset( $route['connection_id'] ) ? sanitize_key( (string) $route['connection_id'] ) : $connection_id;
			if ( ! $posted_shape && $route_connection !== $connection_id ) { continue; }
			$raw_groups = isset( $route['groups'] ) && is_array( $route['groups'] )
				? $route['groups']
				: ( isset( $route['conditionals'] ) && is_array( $route['conditionals'] ) ? $route['conditionals'] : array() );
			$groups = array();
			foreach ( array_slice( $raw_groups, 0, self::ROUTE_GROUP_LIMIT ) as $group ) {
				$rules = array();
				$raw_rules = $posted_shape && is_array( $group ) && isset( $group['rules'] ) ? $group['rules'] : $group;
				foreach ( array_slice( (array) $raw_rules, 0, self::ROUTE_RULE_LIMIT ) as $rule ) {
					if ( ! is_array( $rule ) ) { continue; }
					$property = sanitize_key( isset( $rule['property'] ) ? $rule['property'] : '' );
					$operator = sanitize_text_field( isset( $rule['operator'] ) ? $rule['operator'] : '' );
					$value = sanitize_text_field( isset( $rule['value'] ) && is_scalar( $rule['value'] ) ? substr( (string) $rule['value'], 0, self::ROUTE_VALUE_LIMIT ) : '' );
					if ( ! isset( $property_labels[ $property ] ) || ! isset( $operator_labels[ $operator ] ) || '' === trim( $value ) ) { continue; }
					$rules[] = array( 'property' => $property, 'operator' => $operator, 'value' => $value );
				}
				if ( $rules ) { $groups[] = $rules; }
			}
			if ( $groups ) { $normalized[] = array( 'connection_id' => $connection_id, 'conditionals' => $groups ); }
		}
		return $normalized;
	}

	public function process_save() {
		if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to manage these settings.', 'titanium-mail-smtp' ) ); }
		check_admin_referer( 'tmsmtp_free_routing_save' );
		$posted = isset( $_POST['tmsmtp_free_routing'] ) && is_array( $_POST['tmsmtp_free_routing'] ) ? wp_unslash( $_POST['tmsmtp_free_routing'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$current = $this->settings();
		$enabled = empty( $posted['additional_enabled'] ) ? 0 : 1;
		$routing_enabled = empty( $posted['routing_enabled'] ) ? 0 : 1;
		$submitted_connection = isset( $posted['connection'] ) && is_array( $posted['connection'] ) ? $posted['connection'] : array();
		$connection = $this->sanitize_connection_submission( $submitted_connection, $current['connection'] );
		if ( $enabled ) {
			$validation = $this->validate_connection( $submitted_connection, $connection );
			if ( is_wp_error( $validation ) ) { $this->redirect_result( false, $validation->get_error_message() ); }
		}
		$posted_routes = isset( $posted['routes'] ) ? $posted['routes'] : array();
		$route_validation = $this->validate_route_submission( $posted_routes, $current['connection_id'] );
		if ( is_wp_error( $route_validation ) ) { $this->redirect_result( false, $route_validation->get_error_message() ); }
		$routes = $this->normalize_routes( $posted_routes, $current['connection_id'] );
		if ( $routing_enabled && ! $enabled ) { $this->redirect_result( false, __( 'Enable and configure the Additional Connection before enabling Smart Routing.', 'titanium-mail-smtp' ) ); }
		$stored = get_option( self::OPTION, array() );
		$stored = is_array( $stored ) ? $stored : array();
		$connections = isset( $stored['connections'] ) && is_array( $stored['connections'] ) ? $stored['connections'] : array();
		$connections[ $current['connection_id'] ] = $connection;
		$stored['connections'] = $connections;
		$stored['additional_enabled'] = $enabled;
		$stored['routing_enabled'] = $routing_enabled;
		$stored['routes'] = $routes;
		update_option( self::OPTION, $stored, false );
		$saved = get_option( self::OPTION, array() );
		$success = is_array( $saved ) && isset( $saved['connections'][ $current['connection_id'] ] ) && $saved['connections'][ $current['connection_id'] ] === $connection && (int) $saved['additional_enabled'] === $enabled && (int) $saved['routing_enabled'] === $routing_enabled && $saved['routes'] === $routes;
		$this->redirect_result( $success, $success ? '' : __( 'The database value did not match the submitted routing settings after writing.', 'titanium-mail-smtp' ) );
	}

	public function process_test() {
		if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to test this connection.', 'titanium-mail-smtp' ) ); }
		check_admin_referer( 'tmsmtp_free_routing_test' );
		$recipient = isset( $_POST['test_to'] ) ? sanitize_email( wp_unslash( $_POST['test_to'] ) ) : '';
		if ( ! is_email( $recipient ) ) { $this->redirect_test( false, __( 'Enter a valid recipient email address.', 'titanium-mail-smtp' ) ); }
		$settings = $this->settings();
		if ( empty( $settings['additional_enabled'] ) ) { $this->redirect_test( false, __( 'Enable the Additional Connection before sending a test email.', 'titanium-mail-smtp' ) ); }
		$status = TMSMTP_Plugin::instance()->get_connection_status( $settings['connection'] );
		if ( empty( $status['configured'] ) ) { $this->redirect_test( false, $status['message'] ); }
		$this->forced_connection = $settings['connection_id'];
		try {
			$result = wp_mail( $recipient, __( 'Titanium Mail SMTP Additional Connection test', 'titanium-mail-smtp' ), __( 'This test email was sent through the Free Additional Connection.', 'titanium-mail-smtp' ) );
		} finally {
			$this->forced_connection = '';
		}
		$this->redirect_test( (bool) $result, $result ? __( 'The test email was sent through the Additional Connection.', 'titanium-mail-smtp' ) : __( 'The Additional Connection test email failed.', 'titanium-mail-smtp' ) );
	}

	private function redirect_result( $success, $message ) {
		if ( '' !== $message ) { set_transient( 'tmsmtp_settings_error_' . get_current_user_id(), $message, 5 * MINUTE_IN_SECONDS ); }
		$query_args = array( 'page' => 'titanium-mail-smtp-settings', 'tab' => 'routing' );
		$query_args[ $success ? 'tmsmtp_saved' : 'tmsmtp_validation_error' ] = 1;
		wp_safe_redirect( add_query_arg( $query_args, admin_url( 'admin.php' ) ) );
		exit;
	}

	private function redirect_test( $success, $message ) {
		set_transient( 'tmsmtp_free_routing_test_' . get_current_user_id(), array( 'success' => $success ? 1 : 0, 'message' => $message ), 5 * MINUTE_IN_SECONDS );
		wp_safe_redirect( add_query_arg( array( 'page' => 'titanium-mail-smtp-settings', 'tab' => 'routing', 'tmsmtp_routing_test' => 1 ), admin_url( 'admin.php' ) ) );
		exit;
	}

	public function enqueue_assets() {
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( 'titanium-mail-smtp-settings' !== $page || 'routing' !== $tab ) { return; }
		wp_enqueue_style( 'tmsmtp-free-routing', TMSMTP_URL . 'assets/free-routing.css', array( 'tmsmtp-admin' ), TMSMTP_VERSION );
		wp_enqueue_script( 'tmsmtp-free-routing', TMSMTP_URL . 'assets/free-routing.js', array(), TMSMTP_VERSION, true );
		$settings = $this->settings();
		wp_localize_script( 'tmsmtp-free-routing', 'tmsmtpFreeRouting', array(
			'formRoot' => 'tmsmtp_free_routing',
			'connectionOptions' => $this->connection_options_html( $settings['connection'], $settings['connection_id'] ),
			'propertyOptions' => $this->property_options_html(),
			'operatorOptions' => $this->operator_options_html(),
			'labels' => array(
				'sendWith' => __( 'Send with', 'titanium-mail-smtp' ),
				'conditionsMet' => __( 'if the following conditions are met...', 'titanium-mail-smtp' ),
				'moveUp' => __( 'Move up', 'titanium-mail-smtp' ),
				'moveDown' => __( 'Move down', 'titanium-mail-smtp' ),
				'delete' => __( 'Delete', 'titanium-mail-smtp' ),
				'addGroup' => __( 'Add New Group', 'titanium-mail-smtp' ),
				'or' => __( 'or', 'titanium-mail-smtp' ),
				'addAnd' => __( 'Add And', 'titanium-mail-smtp' ),
				'deleteGroup' => __( 'Delete Group', 'titanium-mail-smtp' ),
				'deleteRule' => __( 'Delete rule', 'titanium-mail-smtp' ),
			),
		) );
	}

	public function render_admin() {
		$settings = $this->settings();
		if ( filter_input( INPUT_GET, 'tmsmtp_routing_test', FILTER_VALIDATE_INT ) ) {
			$result = get_transient( 'tmsmtp_free_routing_test_' . get_current_user_id() );
			delete_transient( 'tmsmtp_free_routing_test_' . get_current_user_id() );
			if ( is_array( $result ) ) {
				echo '<div class="tmsmtp-result-message tmsmtp-result-' . ( ! empty( $result['success'] ) ? 'success' : 'error' ) . '" role="status"><div class="tmsmtp-result-copy"><strong>' . esc_html( ! empty( $result['success'] ) ? __( 'Additional Connection test succeeded.', 'titanium-mail-smtp' ) : __( 'Additional Connection test failed.', 'titanium-mail-smtp' ) ) . '</strong> <span>' . esc_html( isset( $result['message'] ) ? $result['message'] : '' ) . '</span></div></div>';
			}
		}
		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		wp_nonce_field( 'tmsmtp_free_routing_save' );
		echo '<input type="hidden" name="action" value="tmsmtp_free_routing_save">';
		$this->render_connection_card( $settings );
		$this->render_routing( $settings );
		echo '<div class="tmsmtp-submit-row"><button type="submit" class="button tmsmtp-btn">' . esc_html__( 'Save Settings', 'titanium-mail-smtp' ) . '</button></div></form>';
		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" class="tms-card tms-tools-form">';
		wp_nonce_field( 'tmsmtp_free_routing_test' );
		echo '<input type="hidden" name="action" value="tmsmtp_free_routing_test"><div class="tms-card-head"><div><span class="tms-mini-label">' . esc_html__( 'Additional Connection', 'titanium-mail-smtp' ) . '</span><h2>' . esc_html__( 'Send an Additional Connection test email', 'titanium-mail-smtp' ) . '</h2><p>' . esc_html__( 'This sends one real email directly through the Additional Connection and ignores routing rules for the test.', 'titanium-mail-smtp' ) . '</p></div></div><input type="email" class="regular-text" name="test_to" value="' . esc_attr( get_option( 'admin_email' ) ) . '"><div class="tmsmtp-submit-row"><button type="submit" class="button tmsmtp-btn">' . esc_html__( 'Send Test Email', 'titanium-mail-smtp' ) . '</button></div></form>';
	}

	private function render_connection_card( $settings ) {
		$c = $settings['connection'];
		$p = 'tmsmtp_free_routing[connection]';
		echo '<section class="tms-card tms-connection-card"><div class="tms-card-head"><div><span class="tms-mini-label">' . esc_html__( 'Additional Connection', 'titanium-mail-smtp' ) . '</span><h2>' . esc_html( $c['name'] ) . '</h2><p>' . esc_html__( 'Configure one additional provider connection for Free Smart Routing.', 'titanium-mail-smtp' ) . '</p></div><span class="tms-pill tms-pill-preview">' . esc_html__( 'Included in Free', 'titanium-mail-smtp' ) . '</span></div><div class="tms-switch-row"><label class="tms-switch-label"><input type="checkbox" name="tmsmtp_free_routing[additional_enabled]" value="1" ' . checked( ! empty( $settings['additional_enabled'] ), true, false ) . '> ' . esc_html__( 'Enable the Additional Connection', 'titanium-mail-smtp' ) . '</label></div><table class="form-table tms-form-table">';
		$this->row( __( 'Connection name', 'titanium-mail-smtp' ), '<input class="regular-text" name="' . $p . '[name]" value="' . esc_attr( $c['name'] ) . '">' );
		$this->row( __( 'Mailer', 'titanium-mail-smtp' ), '<select class="tms-select-medium tms-mailer-select" name="' . $p . '[mailer]"><option value="postmark" ' . selected( $c['mailer'], 'postmark', false ) . '>Postmark</option><option value="amazonses" ' . selected( $c['mailer'], 'amazonses', false ) . '>Amazon SES</option><option value="sendgrid" ' . selected( $c['mailer'], 'sendgrid', false ) . '>SendGrid</option><option value="mailgun" ' . selected( $c['mailer'], 'mailgun', false ) . '>Mailgun</option><option value="brevo" ' . selected( $c['mailer'], 'brevo', false ) . '>Brevo</option><option value="smtp" ' . selected( $c['mailer'], 'smtp', false ) . '>' . esc_html__( 'Other SMTP', 'titanium-mail-smtp' ) . '</option></select>' );
		$this->row( __( 'From Email', 'titanium-mail-smtp' ), '<div class="tms-inline-fields"><input type="email" class="regular-text" name="' . $p . '[from_email]" value="' . esc_attr( $c['from_email'] ) . '"><label><input type="checkbox" name="' . $p . '[force_from_email]" value="1" ' . checked( ! empty( $c['force_from_email'] ), true, false ) . '> ' . esc_html__( 'Force', 'titanium-mail-smtp' ) . '</label></div>' );
		$this->row( __( 'From Name', 'titanium-mail-smtp' ), '<div class="tms-inline-fields"><input class="regular-text" name="' . $p . '[from_name]" value="' . esc_attr( $c['from_name'] ) . '"><label><input type="checkbox" name="' . $p . '[force_from_name]" value="1" ' . checked( ! empty( $c['force_from_name'] ), true, false ) . '> ' . esc_html__( 'Force', 'titanium-mail-smtp' ) . '</label></div>' );
		$this->render_provider_rows( $p, $c );
		echo '</table></section>';
	}

	private function secret_input( $name, $saved, $constant, $placeholder = '' ) {
		$placeholder = $placeholder ? $placeholder : __( 'Enter credential', 'titanium-mail-smtp' );
		if ( defined( $constant ) ) { return '<input type="hidden" name="' . esc_attr( $name ) . '" value=""><input type="password" class="regular-text" value="' . esc_attr__( 'Defined in wp-config.php', 'titanium-mail-smtp' ) . '" disabled>'; }
		return '<input type="password" class="regular-text" name="' . esc_attr( $name ) . '" value="' . esc_attr( '' !== trim( (string) $saved ) ? self::SECRET_MASK : '' ) . '" placeholder="' . esc_attr( $placeholder ) . '">';
	}

	private function render_provider_rows( $p, $c ) {
		$this->row( __( 'Postmark Server API Token', 'titanium-mail-smtp' ), $this->secret_input( $p . '[postmark_token]', $c['postmark_token'], $this->connection_constant_name( 'postmark' ) ), 'tms-mailer-field tms-mailer-postmark' );
		$this->row( __( 'Postmark Message Stream', 'titanium-mail-smtp' ), '<input class="regular-text" name="' . $p . '[message_stream]" value="' . esc_attr( $c['message_stream'] ) . '">', 'tms-mailer-field tms-mailer-postmark' );
		$this->row( __( 'SendGrid API Key', 'titanium-mail-smtp' ), $this->secret_input( $p . '[sendgrid_api_key]', $c['sendgrid_api_key'], $this->connection_constant_name( 'sendgrid' ) ), 'tms-mailer-field tms-mailer-sendgrid' );
		$this->row( __( 'Mailgun', 'titanium-mail-smtp' ), '<div class="tms-inline-fields">' . $this->secret_input( $p . '[mailgun_api_key]', $c['mailgun_api_key'], $this->connection_constant_name( 'mailgun' ) ) . '<input class="regular-text" name="' . $p . '[mailgun_domain]" value="' . esc_attr( $c['mailgun_domain'] ) . '" placeholder="' . esc_attr__( 'Sending domain', 'titanium-mail-smtp' ) . '"><select class="tms-select-medium" name="' . $p . '[mailgun_region]"><option value="US" ' . selected( $c['mailgun_region'], 'US', false ) . '>' . esc_html__( 'US region', 'titanium-mail-smtp' ) . '</option><option value="EU" ' . selected( $c['mailgun_region'], 'EU', false ) . '>' . esc_html__( 'EU region', 'titanium-mail-smtp' ) . '</option></select></div>', 'tms-mailer-field tms-mailer-mailgun' );
		$this->row( __( 'Brevo API Key', 'titanium-mail-smtp' ), $this->secret_input( $p . '[brevo_api_key]', $c['brevo_api_key'], $this->connection_constant_name( 'brevo' ) ), 'tms-mailer-field tms-mailer-brevo' );
		$this->row( __( 'Amazon SES', 'titanium-mail-smtp' ), '<div class="tms-inline-fields">' . $this->secret_input( $p . '[ses_access_key]', $c['ses_access_key'], $this->connection_constant_name( 'ses_access' ), __( 'Access key ID', 'titanium-mail-smtp' ) ) . $this->secret_input( $p . '[ses_secret_key]', $c['ses_secret_key'], $this->connection_constant_name( 'ses_secret' ) ) . '<input class="regular-text" name="' . $p . '[ses_region]" value="' . esc_attr( $c['ses_region'] ) . '" placeholder="us-east-1"></div><p class="description">' . esc_html__( 'Optional temporary session token:', 'titanium-mail-smtp' ) . '</p>' . $this->secret_input( $p . '[ses_session_token]', $c['ses_session_token'], $this->connection_constant_name( 'ses_session' ) ), 'tms-mailer-field tms-mailer-amazonses' );
		$this->row( __( 'SMTP host / port', 'titanium-mail-smtp' ), '<div class="tms-inline-fields"><input class="regular-text" name="' . $p . '[smtp_host]" value="' . esc_attr( $c['smtp_host'] ) . '"><input type="number" class="small-text tms-input-small" name="' . $p . '[smtp_port]" min="1" max="65535" value="' . esc_attr( $c['smtp_port'] ) . '"></div>', 'tms-mailer-field tms-mailer-smtp' );
		$this->row( __( 'SMTP security', 'titanium-mail-smtp' ), '<div class="tms-check-row"><select class="tms-select-medium" name="' . $p . '[smtp_encryption]"><option value="none" ' . selected( $c['smtp_encryption'], 'none', false ) . '>' . esc_html__( 'None', 'titanium-mail-smtp' ) . '</option><option value="ssl" ' . selected( $c['smtp_encryption'], 'ssl', false ) . '>SSL</option><option value="tls" ' . selected( $c['smtp_encryption'], 'tls', false ) . '>TLS</option></select><label><input type="checkbox" name="' . $p . '[smtp_autotls]" value="1" ' . checked( ! empty( $c['smtp_autotls'] ), true, false ) . '> ' . esc_html__( 'Auto TLS', 'titanium-mail-smtp' ) . '</label><label><input type="checkbox" name="' . $p . '[smtp_auth]" value="1" ' . checked( ! empty( $c['smtp_auth'] ), true, false ) . '> ' . esc_html__( 'Authentication', 'titanium-mail-smtp' ) . '</label></div>', 'tms-mailer-field tms-mailer-smtp' );
		$this->row( __( 'SMTP username / password', 'titanium-mail-smtp' ), '<div class="tms-inline-fields"><input class="regular-text" name="' . $p . '[smtp_user]" value="' . esc_attr( $c['smtp_user'] ) . '">' . $this->secret_input( $p . '[smtp_pass]', $c['smtp_pass'], $this->connection_constant_name( 'smtp' ) ) . '</div>', 'tms-mailer-field tms-mailer-smtp' );
	}

	private function render_routing( $settings ) {
		echo '<section class="tms-card"><div class="tms-card-head"><div><span class="tms-mini-label">' . esc_html__( 'Smart Routing', 'titanium-mail-smtp' ) . '</span><h2>' . esc_html__( 'Route mail through the Additional Connection', 'titanium-mail-smtp' ) . '</h2><p>' . esc_html__( 'Build visual AND/OR rules from recipients, sender details, subject, content, headers, or the plugin that initiated the email. Messages that do not match use the Primary Connection.', 'titanium-mail-smtp' ) . '</p></div><span class="tms-pill tms-pill-preview">' . esc_html__( 'Advanced Free Routing', 'titanium-mail-smtp' ) . '</span></div><div class="tms-switch-row"><label class="tms-switch-label"><input type="checkbox" name="tmsmtp_free_routing[routing_enabled]" value="1" ' . checked( ! empty( $settings['routing_enabled'] ), true, false ) . '> ' . esc_html__( 'Enable Smart Routing', 'titanium-mail-smtp' ) . '</label></div><div id="tms-route-list" class="tms-route-list">';
		foreach ( $settings['routes'] as $route_index => $route ) { $this->render_route_editor( $route_index, $route, $settings['connection'], $settings['connection_id'] ); }
		echo '</div><div class="tms-actions"><button type="button" id="tms-add-route" class="button tms-btn tms-btn-secondary">' . esc_html__( 'Add New', 'titanium-mail-smtp' ) . '</button></div><p class="tms-routing-reminder">' . wp_kses_post( __( 'Emails that do not match any rule continue through the <strong>Primary Connection</strong>. Free routing does not include backup delivery or automatic retry.', 'titanium-mail-smtp' ) ) . '</p></section>';
	}

	private function route_property_labels() {
		return array(
			'from_email' => __( 'From Email', 'titanium-mail-smtp' ),
			'to_email' => __( 'To Email', 'titanium-mail-smtp' ),
			'subject' => __( 'Subject', 'titanium-mail-smtp' ),
			'message' => __( 'Message', 'titanium-mail-smtp' ),
			'from_name' => __( 'From Name', 'titanium-mail-smtp' ),
			'cc' => __( 'CC', 'titanium-mail-smtp' ),
			'bcc' => __( 'BCC', 'titanium-mail-smtp' ),
			'reply_to' => __( 'Reply-To', 'titanium-mail-smtp' ),
			'header_name' => __( 'Header Name', 'titanium-mail-smtp' ),
			'header_value' => __( 'Header Value', 'titanium-mail-smtp' ),
			'initiator' => __( 'Source plugin or WordPress core', 'titanium-mail-smtp' ),
		);
	}

	private function route_operator_labels() {
		return array(
			'==' => __( 'Equals', 'titanium-mail-smtp' ),
			'!=' => __( 'Does Not Equal', 'titanium-mail-smtp' ),
			'c' => __( 'Contains', 'titanium-mail-smtp' ),
			'!c' => __( 'Does Not Contain', 'titanium-mail-smtp' ),
			'^' => __( 'Starts With', 'titanium-mail-smtp' ),
			'~' => __( 'Ends With', 'titanium-mail-smtp' ),
		);
	}

	private function connection_options_html( $connection, $connection_id = self::ADDITIONAL_ID ) {
		return '<option value="' . esc_attr( $connection_id ) . '">' . esc_html( $connection['name'] ) . '</option>';
	}

	private function property_options_html( $selected = '' ) {
		$html = '';
		foreach ( $this->route_property_labels() as $value => $label ) { $html .= '<option value="' . esc_attr( $value ) . '" ' . selected( $selected, $value, false ) . '>' . esc_html( $label ) . '</option>'; }
		return $html;
	}

	private function operator_options_html( $selected = '' ) {
		$html = '';
		foreach ( $this->route_operator_labels() as $value => $label ) { $html .= '<option value="' . esc_attr( $value ) . '" ' . selected( $selected, $value, false ) . '>' . esc_html( $label ) . '</option>'; }
		return $html;
	}

	private function render_route_editor( $route_index, $route, $connection, $connection_id = self::ADDITIONAL_ID ) {
		$groups = isset( $route['conditionals'] ) && is_array( $route['conditionals'] ) ? $route['conditionals'] : array();
		echo '<div class="tms-route-box" data-route-box data-route-key="' . esc_attr( $route_index ) . '"><div class="tms-route-top"><div class="tms-route-top-main"><span class="tms-route-copy">' . esc_html__( 'Send with', 'titanium-mail-smtp' ) . '</span><select class="tms-select-large" name="tmsmtp_free_routing[routes][' . esc_attr( $route_index ) . '][connection_id]">' . wp_kses( $this->connection_options_html( $connection, $connection_id ), array( 'option' => array( 'value' => true, 'selected' => true ) ) ) . '</select><span class="tms-route-copy">' . esc_html__( 'if the following conditions are met...', 'titanium-mail-smtp' ) . '</span></div><div class="tms-route-tools"><button type="button" class="tms-icon-btn" data-route-up title="' . esc_attr__( 'Move up', 'titanium-mail-smtp' ) . '">↑</button><button type="button" class="tms-icon-btn" data-route-down title="' . esc_attr__( 'Move down', 'titanium-mail-smtp' ) . '">↓</button><button type="button" class="tms-icon-btn tms-mini-btn--danger" data-route-delete title="' . esc_attr__( 'Delete', 'titanium-mail-smtp' ) . '">🗑</button></div></div><div class="tms-route-groups" data-route-groups>';
		foreach ( $groups as $group_index => $rules ) { $this->render_route_group( $route_index, $group_index, $rules ); }
		echo '</div><button type="button" class="tms-mini-btn" data-add-group>' . esc_html__( 'Add New Group', 'titanium-mail-smtp' ) . '</button></div>';
	}

	private function render_route_group( $route_index, $group_index, $rules ) {
		echo '<div class="tms-route-group" data-group data-group-key="' . esc_attr( $group_index ) . '">';
		if ( $group_index > 0 ) { echo '<div class="tms-or-label">' . esc_html__( 'or', 'titanium-mail-smtp' ) . '</div>'; }
		foreach ( (array) $rules as $rule_index => $rule ) { $this->render_route_rule( $route_index, $group_index, $rule_index, $rule ); }
		echo '<button type="button" class="tms-mini-btn" data-add-rule>' . esc_html__( 'Add And', 'titanium-mail-smtp' ) . '</button> <button type="button" class="tms-mini-btn tms-mini-btn--danger" data-delete-group>' . esc_html__( 'Delete Group', 'titanium-mail-smtp' ) . '</button></div>';
	}

	private function render_route_rule( $route_index, $group_index, $rule_index, $rule ) {
		$property = sanitize_key( isset( $rule['property'] ) ? $rule['property'] : 'from_email' );
		$operator = sanitize_text_field( isset( $rule['operator'] ) ? $rule['operator'] : 'c' );
		$value = sanitize_text_field( isset( $rule['value'] ) ? $rule['value'] : '' );
		echo '<div class="tms-rule-row" data-rule><select class="tms-select-medium" name="tmsmtp_free_routing[routes][' . esc_attr( $route_index ) . '][groups][' . esc_attr( $group_index ) . '][rules][' . esc_attr( $rule_index ) . '][property]">' . wp_kses( $this->property_options_html( $property ), array( 'option' => array( 'value' => true, 'selected' => true ) ) ) . '</select><select class="tms-select-medium" name="tmsmtp_free_routing[routes][' . esc_attr( $route_index ) . '][groups][' . esc_attr( $group_index ) . '][rules][' . esc_attr( $rule_index ) . '][operator]">' . wp_kses( $this->operator_options_html( $operator ), array( 'option' => array( 'value' => true, 'selected' => true ) ) ) . '</select><input type="text" name="tmsmtp_free_routing[routes][' . esc_attr( $route_index ) . '][groups][' . esc_attr( $group_index ) . '][rules][' . esc_attr( $rule_index ) . '][value]" value="' . esc_attr( $value ) . '"><button type="button" class="tms-icon-btn tms-mini-btn--danger" data-delete-rule title="' . esc_attr__( 'Delete rule', 'titanium-mail-smtp' ) . '">🗑</button></div>';
	}

	private function row( $label, $field, $class = '' ) {
		echo '<tr' . ( $class ? ' class="' . esc_attr( $class ) . '"' : '' ) . '><th scope="row">' . esc_html( $label ) . '</th><td>' . wp_kses( $field, $this->allowed_form_html() ) . '</td></tr>';
	}

	private function allowed_form_html() {
		return array(
			'div' => array( 'class' => true ),
			'label' => array( 'class' => true ),
			'input' => array( 'type' => true, 'class' => true, 'name' => true, 'value' => true, 'placeholder' => true, 'checked' => true, 'disabled' => true, 'min' => true, 'max' => true ),
			'select' => array( 'class' => true, 'name' => true ),
			'option' => array( 'value' => true, 'selected' => true ),
			'p' => array( 'class' => true ),
			'code' => array(),
		);
	}
}
