<?php
/**
 * System Email Service - Port from Fluent Security
 *
 * @package CustomWpEmails
 */

namespace CustomWpEmails\Includes;

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

class SystemEmailService {

	private const OPTION_KEY = 'wp_powersuite_system_email_settings';

	/** @var array<string, mixed>|null */
	private static ?array $settings_cache = null;

	public static function get_email_indexes(): array {
		$emails = [
			'user_registration_to_user' => [
				'name'                  => 'user_registration_to_user',
				'title'                 => __( 'New User Registration Notification', 'wp-powersuite' ),
				'description'           => __( 'An essential email sent to new users upon account signup.', 'wp-powersuite' ),
				'recipient'             => 'user',
				'hook'                  => 'wp_new_user_notification',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [ '##user.password_set_url##' => __( 'Password Set URL', 'wp-powersuite' ) ],
			],
			'password_reset_to_user' => [
				'name'                  => 'password_reset_to_user',
				'title'                 => __( 'Password Reset Request Email', 'wp-powersuite' ),
				'description'           => __( 'A security-critical email sent when a user requests to reset their password.', 'wp-powersuite' ),
				'recipient'             => 'user',
				'hook'                  => 'retrieve_password',
				'required_smartcodes'   => [ 'user.password_reset_url' ],
				'additional_smartcodes' => [ '##user.password_set_url##' => __( 'Password Set URL', 'wp-powersuite' ) ],
			],
			'email_change_notification_to_user' => [
				'name'                  => 'email_change_notification_to_user',
				'title'                 => __( 'Email Address Change Confirmation', 'wp-powersuite' ),
				'description'           => __( 'Sent to the new email address to confirm an email change request.', 'wp-powersuite' ),
				'recipient'             => 'user',
				'hook'                  => 'wp_email_change_notification',
				'required_smartcodes'   => [ 'user.confirm_email_change_url' ],
				'additional_smartcodes' => [
					'##user.confirm_email_change_url##' => __( 'Confirm Email Change URL', 'wp-powersuite' ),
					'{{user.new_changing_email_id}}'   => __( 'New Email Address', 'wp-powersuite' ),
				],
			],
			'email_change_notification_after_confimation' => [
				'name'                  => 'email_change_notification_after_confimation',
				'title'                 => __( 'Email Address Change Notification After Confirmation', 'wp-powersuite' ),
				'description'           => __( 'Sent to the old email address after the email change is confirmed.', 'wp-powersuite' ),
				'recipient'             => 'user',
				'hook'                  => 'wp_email_change_notification',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [ '{{user._previous_email_address_}}' => __( 'Previous Email Address', 'wp-powersuite' ) ],
			],
			'user_registration_to_admin' => [
				'name'                  => 'user_registration_to_admin',
				'title'                 => __( 'New User Registration Notification', 'wp-powersuite' ),
				'description'           => __( 'An essential email sent to the admin when someone signs up.', 'wp-powersuite' ),
				'recipient'             => 'site_admin',
				'hook'                  => 'wp_new_user_notification',
				'can_disable'           => 'yes',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [ '##user.profile_edit_url##' => __( 'User Profile Edit URL', 'wp-powersuite' ) ],
			],
			'password_change_to_admin' => [
				'name'                  => 'password_change_to_admin',
				'title'                 => __( 'Password Change Notification', 'wp-powersuite' ),
				'description'           => __( 'Sent to the admin when a user changes their password from their profile.', 'wp-powersuite' ),
				'recipient'             => 'site_admin',
				'hook'                  => 'after_password_reset',
				'can_disable'           => 'yes',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [],
			],
			'comment_notification_to_author' => [
				'name'                  => 'comment_notification_to_author',
				'title'                 => __( 'Comment Notification to Post Author', 'wp-powersuite' ),
				'description'           => __( 'Sent to the post author when someone leaves a comment on their post.', 'wp-powersuite' ),
				'recipient'             => 'site_admin',
				'hook'                  => 'wp_notify_postauthor',
				'can_disable'           => 'yes',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [],
			],
			'comment_moderation_to_admin' => [
				'name'                  => 'comment_moderation_to_admin',
				'title'                 => __( 'Comment Moderation Notification', 'wp-powersuite' ),
				'description'           => __( 'Sent to moderators when a new comment is awaiting approval.', 'wp-powersuite' ),
				'recipient'             => 'site_admin',
				'hook'                  => 'wp_notify_moderator',
				'can_disable'           => 'yes',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [],
			],
			'admin_email_change_confirmation' => [
				'name'                  => 'admin_email_change_confirmation',
				'title'                 => __( 'Admin Email Change Confirmation', 'wp-powersuite' ),
				'description'           => __( 'Sent to the new admin email when an administrator requests to change the site admin email address.', 'wp-powersuite' ),
				'recipient'             => 'site_admin',
				'hook'                  => 'update_option_new_admin_email',
				'required_smartcodes'   => [],
				'additional_smartcodes' => [],
			],
		];

		$settings = self::get_global_settings();
		foreach ( $emails as $key => $value ) {
			$emails[ $key ]['status'] = $settings['emails'][ $key ]['status'] ?? 'system';
		}
		return $emails;
	}

	public static function get_global_settings( bool $cached = true ): array {
		if ( $cached && self::$settings_cache !== null ) {
			return self::$settings_cache;
		}
		$emails_default = self::get_email_defaults();
		$template_defaults = [
			'logo'                 => '',
			'body_bg'              => '#f3f4f6',
			'content_bg'           => '#ffffff',
			'content_color'        => '#374151',
			'footer_content_color' => '#6b7280',
			'highlight_bg'         => 'rgb(249, 250, 251)',
			'highlight_color'      => '#374151',
			'font_family'          => '',
			'template'             => 'default',
			'footer_text'          => '',
			'from_name'            => '',
			'from_email'           => '',
			'reply_to_name'        => '',
			'reply_to_email'       => '',
		];
		$raw = get_option( self::OPTION_KEY, [] );
		if ( empty( $raw ) ) {
			self::$settings_cache = [
				'emails'            => $emails_default,
				'template_settings' => $template_defaults,
			];
			return self::$settings_cache;
		}
		$emails = wp_parse_args( $raw['emails'] ?? [], $emails_default );
		$template = wp_parse_args( $raw['template_settings'] ?? [], $template_defaults );
		self::$settings_cache = [ 'emails' => $emails, 'template_settings' => $template ];
		return self::$settings_cache;
	}

	public static function get_email_settings_by_type( string $email_type ): array {
		$settings = self::get_global_settings();
		return $settings['emails'][ $email_type ] ?? [];
	}

	public static function get_email_defaults(): array {
		return [
			'user_registration_to_user' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] - Set Up Your Password',
					'body'    => self::get_default_email_body( 'user_registration_to_user' ),
				],
			],
			'password_reset_to_user' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] Password Reset',
					'body'    => self::get_default_email_body( 'password_reset_to_user' ),
				],
			],
			'email_change_notification_to_user' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] Email Change Request',
					'body'    => self::get_default_email_body( 'email_change_notification_to_user' ),
				],
			],
			'email_change_notification_after_confimation' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] Your email address has been changed',
					'body'    => self::get_default_email_body( 'email_change_notification_after_confimation' ),
				],
			],
			'user_registration_to_admin' => [
				'status' => 'system',
				'email'  => [
					'subject' => 'New User Registration: {{user.display_name}} has joined {{site.name}}',
					'body'    => self::get_default_email_body( 'user_registration_to_admin' ),
				],
			],
			'password_change_to_admin' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] Password Changed',
					'body'    => self::get_default_email_body( 'password_change_to_admin' ),
				],
			],
			'comment_notification_to_author' => [
				'status' => 'system',
				'email'  => [
					'subject' => '',
					'body'    => '',
				],
			],
			'comment_moderation_to_admin' => [
				'status' => 'system',
				'email'  => [
					'subject' => '',
					'body'    => '',
				],
			],
			'admin_email_change_confirmation' => [
				'status' => 'system',
				'email'  => [
					'subject' => '[{{site.name}}] New Admin Email Address',
					'body'    => self::get_default_email_body( 'admin_email_change_confirmation' ),
				],
			],
		];
	}

	public static function get_default_email_body( string $type ): string {
		$accent = '#2271b1';
		if ( class_exists( '\WP_PowerSuite\Email\EmailDesign' ) ) {
			$accent = \WP_PowerSuite\Email\EmailDesign::ACCENT_DEFAULT;
		}
		$btn = 'display:inline-block;padding:11px 22px;font-size:14px;font-weight:600;text-decoration:none;border-radius:8px;color:#ffffff !important;background-color:' . esc_attr( $accent ) . ';text-align:center;';
		$bq = 'margin:0 0 16px;padding:12px 14px;border-left:3px solid #e5e7eb;background:#f9fafb;border-radius:0 8px 8px 0;';
		$p  = 'margin:0 0 14px;font-size:14px;line-height:1.55;';
		$ps = 'margin:0 0 14px;font-size:13px;line-height:1.5;color:#6b7280;';
		$templates = [
			'user_registration_to_user' => '<p style="' . $p . '">Hello <strong>{{user.display_name}}</strong>,</p>
<p style="' . $p . '">Your account has been created on <strong>{{site.name}}</strong>. To set up your password and complete your registration, please click the button below:</p>
<p style="' . $p . '">If you did not create this account, please disregard this email and no action will be taken.</p>
<p style="margin:0 0 16px;text-align:center;">
	<a href="##user.password_set_url##" style="' . $btn . '">Set Your Password</a>
</p>
<p style="' . $ps . '">This link will expire in 24 hours for security reasons.</p>
<p style="' . $ps . '">If you\'re having trouble with the button above, copy and paste the URL below into your web browser:</p>
<blockquote style="' . $bq . '">
	<p style="margin:0;font-size:12px;line-height:1.45;word-break:break-all;">##user.password_set_url##</p>
</blockquote>
<p style="' . $ps . '">Username: {{user.user_login}}</p>
<p style="' . $ps . '">Login URL: {{site.login_url}}</p>
<p style="margin:0;font-size:14px;line-height:1.55;">Regards,<br>All at {{site.name}}<br>{{site.url}}</p>',
			'password_reset_to_user' => '<p style="' . $p . '">Hello <strong>{{user.display_name}}</strong>,</p>
<p style="' . $p . '">A password reset has been requested for your account on <strong>{{site.name}}</strong>.</p>
<blockquote style="' . $bq . '">
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Username: {{user.user_login}}</p>
	<p style="margin:0;font-size:14px;line-height:1.45;">Email: {{user.user_email}}</p>
</blockquote>
<p style="' . $p . '">If you did not request this password reset, please disregard this email and no changes will be made to your account.</p>
<p style="' . $p . '">To proceed with resetting your password, please click the button below:</p>
<p style="margin:0 0 16px;text-align:center;">
	<a href="##user.password_reset_url##" style="' . $btn . '">Reset Your Password</a>
</p>
<p style="' . $ps . '">This password reset link will expire in 24 hours for security reasons.</p>
<p style="' . $ps . '">If you\'re having trouble with the button above, copy and paste the URL below into your web browser:</p>
<blockquote style="' . $bq . '">
	<p style="margin:0;font-size:12px;line-height:1.45;word-break:break-all;">##user.password_reset_url##</p>
</blockquote>
<p style="' . $p . '">If you did not initiate this request, please review your account security and consider changing your password.</p>
<p style="margin:0;font-size:14px;line-height:1.55;">Regards,<br>All at {{site.name}}<br>{{site.url}}</p>',
			'email_change_notification_to_user' => '<p style="' . $p . '">Hello <strong>{{user.display_name}}</strong>,</p>
<p style="' . $p . '">We received a request to change the email address for your account on <strong>{{site.name}}</strong>.</p>
<blockquote style="' . $bq . '">
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Current Email: {{user.user_email}}</p>
	<p style="margin:0;font-size:14px;line-height:1.45;">New Email: {{user.new_changing_email_id}}</p>
</blockquote>
<p style="' . $p . '">If you did not request this change, please disregard this email and no changes will be made to your account.</p>
<p style="' . $p . '">To confirm this email change, please click the button below:</p>
<p style="margin:0 0 16px;text-align:center;">
	<a href="##user.confirm_email_change_url##" style="' . $btn . '">Confirm Email Change</a>
</p>
<p style="' . $ps . '">This link will expire in 24 hours for security reasons.</p>
<p style="' . $ps . '">If you\'re having trouble with the button above, copy and paste the URL below into your web browser:</p>
<blockquote style="' . $bq . '">
	<p style="margin:0;font-size:12px;line-height:1.45;word-break:break-all;">##user.confirm_email_change_url##</p>
</blockquote>
<p style="' . $p . '">If you did not initiate this request, please contact {{site.admin_email}} immediately to secure your account.</p>
<p style="margin:0;font-size:14px;line-height:1.55;">Regards,<br>All at {{site.name}}<br>{{site.url}}</p>',
			'email_change_notification_after_confimation' => '<p style="' . $p . '">Hello {{user.display_name}},</p>
<p style="' . $p . '">Your email address for your account on <strong>{{site.name}}</strong> has been successfully changed.</p>
<blockquote style="' . $bq . '">
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Previous Email: {{user._previous_email_address_}}</p>
	<p style="margin:0;font-size:14px;line-height:1.45;">New Email: {{user.user_email}}</p>
</blockquote>
<p style="' . $p . '">If you did not authorize this change, please contact {{site.admin_email}} immediately to secure your account.</p>
<p style="' . $p . '">You can now use your new email address to sign in at {{site.login_url}}.</p>
<p style="margin:0;font-size:14px;line-height:1.55;">Regards,<br>All at {{site.name}}<br>{{site.url}}</p>',
			'user_registration_to_admin' => '<p style="' . $p . '">Hello there,</p>
<p style="' . $p . '">A new user has registered on your website (<strong>{{site.name}}</strong> — {{site.url}}).</p>
<blockquote style="' . $bq . '">
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Username: {{user.user_login}}</p>
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Email: {{user.user_email}}</p>
	<p style="margin:0 0 6px;font-size:14px;line-height:1.45;">Display Name: {{user.display_name}}</p>
	<p style="margin:0;font-size:14px;line-height:1.45;">Role: {{user.roles}}</p>
</blockquote>
<p style="' . $p . '">Click the button below to view and manage this user\'s profile:</p>
<p style="margin:0 0 16px;text-align:center;">
	<a href="##user.profile_edit_url##" style="' . $btn . '">View User Profile</a>
</p>
<p style="' . $ps . '">This is an automated notification from {{site.name}}.</p>',
			'password_change_to_admin' => '<p style="' . $p . '">Hello there,</p>
<p style="' . $p . '">A user has changed their password on <strong>{{site.name}}</strong>.</p>
<p style="' . $ps . '">Username: {{user.user_login}}</p>
<p style="' . $ps . '">Email: {{user.user_email}}</p>
<p style="' . $ps . '">This is an automated notification from {{site.name}}.</p>',
			'admin_email_change_confirmation' => '<p style="' . $p . '">Howdy,</p>
<p style="' . $p . '">A site administrator (###USERNAME###) recently requested to have the administration email address changed on this site:</p>
<p style="' . $p . '"><a href="###SITEURL###">###SITEURL###</a></p>
<p style="' . $p . '">To confirm this change, please click on the following link:</p>
<p style="margin:0 0 16px;text-align:center;">
	<a href="###ADMIN_URL###" style="' . $btn . '">Confirm Email Change</a>
</p>
<p style="' . $ps . '">You can safely ignore and delete this email if you do not want to take this action.</p>
<p style="' . $ps . '">This email has been sent to ###EMAIL###</p>
<p style="margin:0;font-size:14px;line-height:1.55;">Regards,<br>All at ###SITENAME###<br>###SITEURL###</p>',
		];
		return $templates[ $type ] ?? '';
	}

	/**
	 * @param string|null $footer
	 * @param \WP_User|null $wp_user
	 * @param array|null $template_override Optional override for preview (body_bg, content_bg, etc.)
	 */
	public static function with_html_template( string $body, $footer = null, $wp_user = null, ?array $template_override = null ): string {
		if ( ! class_exists( '\WP_PowerSuite\Email\EmailRenderer' ) ) {
			return $body;
		}

		$config = $template_override ?? ( self::get_global_settings()['template_settings'] ?? [] );
		$footer = $footer ?? ( $config['footer_text'] ?? '' );
		if ( ! empty( $footer ) ) {
			$parser = new SmartCodeParser();
			$footer = $parser->parse( $footer, $wp_user );
		}

		return \WP_PowerSuite\Email\EmailRenderer::wrap(
			[
				'content' => $body,
				'footer'  => $footer,
				'config'  => $config,
				'logo_url' => $config['logo'] ?? '',
			]
		);
	}

	/**
	 * Clear the in-request settings cache after saves.
	 */
	public static function bust_settings_cache(): void {
		self::$settings_cache = null;
		if ( class_exists( '\WP_PowerSuite\Email\EmailRenderer' ) ) {
			\WP_PowerSuite\Email\EmailRenderer::bustBrandingCache();
		}
	}

	/**
	 * Resolve a subject/body field, falling back when empty string.
	 */
	public static function resolve_email_field( array $email_config, string $field, string $fallback ): string {
		if ( ! isset( $email_config[ $field ] ) ) {
			return $fallback;
		}
		$value = trim( (string) $email_config[ $field ] );
		return $value !== '' ? $value : $fallback;
	}

	/**
	 * Allowed status values for an email type.
	 *
	 * @return list<string>
	 */
	public static function get_allowed_statuses( string $email_id ): array {
		$allowed = [ 'system', 'active' ];
		$indexes = self::get_email_indexes();
		if ( ! empty( $indexes[ $email_id ]['can_disable'] ) ) {
			$allowed[] = 'disabled';
		}
		return $allowed;
	}

	/**
	 * Sanitize and validate email status for storage.
	 */
	public static function sanitize_email_status( string $email_id, string $status ): string {
		return in_array( $status, self::get_allowed_statuses( $email_id ), true ) ? $status : 'system';
	}

	/**
	 * Validate required SmartCode placeholders for security-critical emails.
	 *
	 * @return string|null Error message when invalid, null when OK.
	 */
	public static function validate_required_smartcodes( string $email_id, string $subject, string $body ): ?string {
		$indexes  = self::get_email_indexes();
		$required = $indexes[ $email_id ]['required_smartcodes'] ?? [];
		if ( empty( $required ) ) {
			return null;
		}
		$combined = $subject . $body;
		foreach ( $required as $code ) {
			$found = str_contains( $combined, '{{' . $code . '}}' )
				|| str_contains( $combined, '##' . $code . '##' );
			if ( ! $found ) {
				return sprintf(
					/* translators: %s: required SmartCode placeholder */
					__( 'Required placeholder missing: %s', 'wp-powersuite' ),
					'{{' . $code . '}}'
				);
			}
		}
		return null;
	}

	/**
	 * Sanitize a display name used in mail headers.
	 */
	public static function sanitize_header_name( string $name ): string {
		$name = sanitize_text_field( $name );
		if ( function_exists( 'mb_substr' ) ) {
			return mb_substr( $name, 0, 200 );
		}
		return substr( $name, 0, 200 );
	}

	/**
	 * Allowed font-family values for the email shell.
	 *
	 * @return list<string>
	 */
	public static function get_allowed_font_families(): array {
		return [
			'',
			'Arial, sans-serif',
			'Georgia, serif',
			"'Times New Roman', serif",
			'Verdana, sans-serif',
			"'Helvetica Neue', Helvetica, sans-serif",
			'Tahoma, sans-serif',
		];
	}

	/**
	 * Sanitize font family against the admin allowlist.
	 */
	public static function sanitize_font_family( string $font ): string {
		return in_array( $font, self::get_allowed_font_families(), true ) ? $font : '';
	}

	/**
	 * Sanitize a CSS color value for inline email styles.
	 */
	public static function sanitize_color_value( string $color, string $default = '#f3f4f6' ): string {
		$color = trim( $color );
		if ( preg_match( '/^#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$/', $color ) ) {
			return $color;
		}
		if ( preg_match( '/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/', $color, $matches ) ) {
			return sprintf(
				'rgb(%d, %d, %d)',
				min( 255, max( 0, (int) $matches[1] ) ),
				min( 255, max( 0, (int) $matches[2] ) ),
				min( 255, max( 0, (int) $matches[3] ) )
			);
		}
		return $default;
	}

	/**
	 * Build wp_mail headers with HTML content type and optional sender overrides.
	 *
	 * @param array<int, string>|string $existing Existing headers.
	 * @return list<string>
	 */
	public static function build_mail_headers( $existing = [] ): array {
		if ( is_string( $existing ) ) {
			$existing = array_filter( array_map( 'trim', explode( "\n", $existing ) ) );
		}
		$headers = is_array( $existing ) ? $existing : [];

		$has_content_type = false;
		foreach ( $headers as $header ) {
			if ( stripos( (string) $header, 'Content-Type:' ) === 0 ) {
				$has_content_type = true;
				break;
			}
		}
		if ( ! $has_content_type ) {
			$headers[] = 'Content-Type: text/html; charset=UTF-8';
		}

		$cfg = self::get_global_settings()['template_settings'] ?? [];

		$from_email = sanitize_email( (string) ( $cfg['from_email'] ?? '' ) );
		if ( is_email( $from_email ) ) {
			$from_name = self::sanitize_header_name( (string) ( $cfg['from_name'] ?? '' ) );
			$headers[] = $from_name
				? sprintf( 'From: %s <%s>', $from_name, $from_email )
				: 'From: <' . $from_email . '>';
		}

		$reply_email = sanitize_email( (string) ( $cfg['reply_to_email'] ?? '' ) );
		if ( is_email( $reply_email ) ) {
			$reply_name = self::sanitize_header_name( (string) ( $cfg['reply_to_name'] ?? '' ) );
			$headers[] = $reply_name
				? sprintf( 'Reply-To: %s <%s>', $reply_name, $reply_email )
				: 'Reply-To: <' . $reply_email . '>';
		}

		return $headers;
	}

	public static function get_option_key(): string {
		return self::OPTION_KEY;
	}
}
