<?php
/**
 * Transactional email service.
 *
 * @package Lucrativeit_Subscription_Recurring_Billing
 */

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

/**
 * Renders and sends templated emails.
 */
class LUCRSURE_Emails {

	/**
	 * Register mail transport hooks.
	 */
	public static function init() {
		add_action( 'phpmailer_init', array( __CLASS__, 'configure_phpmailer' ) );
		add_filter( 'pre_wp_mail', array( __CLASS__, 'maybe_log_mail' ), 10, 2 );
	}

	/**
	 * Apply plugin SMTP settings to PHPMailer.
	 *
	 * @param PHPMailer\PHPMailer\PHPMailer $phpmailer Mailer instance.
	 */
	public static function configure_phpmailer( $phpmailer ) {
		$settings = get_option( 'lucrsure_settings', array() );
		$email    = isset( $settings['email'] ) ? $settings['email'] : array();
		$driver   = isset( $email['mail_driver'] ) ? $email['mail_driver'] : 'wp_mail';

		if ( 'smtp' !== $driver ) {
			return;
		}

		$host = isset( $email['smtp_host'] ) ? trim( $email['smtp_host'] ) : '';
		if ( '' === $host ) {
			return;
		}

		$phpmailer->isSMTP();
		$phpmailer->Host = $host;
		$phpmailer->Port = isset( $email['smtp_port'] ) ? (int) $email['smtp_port'] : 587;

		$username = isset( $email['smtp_username'] ) ? $email['smtp_username'] : '';
		if ( '' !== $username ) {
			$phpmailer->SMTPAuth = true;
			$phpmailer->Username = $username;
			$phpmailer->Password = isset( $email['smtp_password'] ) ? $email['smtp_password'] : '';
		}

		$encryption = isset( $email['encryption'] ) ? $email['encryption'] : 'none';
		if ( 'tls' === $encryption ) {
			$phpmailer->SMTPSecure = 'tls';
		} elseif ( 'ssl' === $encryption ) {
			$phpmailer->SMTPSecure = 'ssl';
		} else {
			$phpmailer->SMTPSecure  = '';
			$phpmailer->SMTPAutoTLS = false;
		}

		$from_addr = isset( $email['from_address'] ) ? $email['from_address'] : get_option( 'admin_email' );
		$from_name = isset( $email['from_name'] ) ? $email['from_name'] : get_bloginfo( 'name' );
		if ( $from_addr ) {
			try {
				$phpmailer->setFrom( $from_addr, $from_name, false );
			} catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
				// wp_mail headers may already set From; ignore invalid addresses.
			}
		}
	}

	/**
	 * Log emails instead of sending when the log driver is selected.
	 *
	 * @param null|bool $short_circuit Short-circuit value.
	 * @param array     $atts          wp_mail() arguments.
	 * @return null|bool
	 */
	public static function maybe_log_mail( $short_circuit, $atts ) {
		$settings = get_option( 'lucrsure_settings', array() );
		$email    = isset( $settings['email'] ) ? $settings['email'] : array();
		$driver   = isset( $email['mail_driver'] ) ? $email['mail_driver'] : 'wp_mail';

		if ( 'log' !== $driver ) {
			return $short_circuit;
		}

		if ( function_exists( 'wc_get_logger' ) ) {
			wc_get_logger()->info(
				wp_json_encode( $atts ),
				array( 'source' => 'lucrsure-email' )
			);
		} else {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
			error_log( '[LUCRSURE Email] ' . wp_json_encode( $atts ) );
		}

		return true;
	}

	/**
	 * Replace template placeholders with real values.
	 *
	 * @param string $content Template content.
	 * @param array  $data    Replacement data.
	 * @return string
	 */
	public static function parse( $content, array $data ) {
		$settings = get_option( 'lucrsure_settings', array() );

		$map = array(
			'{{customer_name}}'  => isset( $data['customer_name'] ) ? $data['customer_name'] : '',
			'{{invoice_number}}' => isset( $data['invoice_number'] ) ? $data['invoice_number'] : '',
			'{{package_name}}'   => isset( $data['package_name'] ) ? $data['package_name'] : '',
			'{{amount}}'         => isset( $data['amount'] ) ? number_format( (float) $data['amount'], 2 ) : '',
			'{{currency}}'       => isset( $data['currency'] ) ? $data['currency'] : '',
			'{{due_date}}'       => isset( $data['due_date'] ) ? self::format_date( $data['due_date'] ) : '',
			'{{payment_url}}'    => isset( $data['payment_url'] ) ? $data['payment_url'] : '',
			'{{company_name}}'   => isset( $settings['company_name'] ) ? $settings['company_name'] : get_bloginfo( 'name' ),
			'{{billing_cycle}}'  => isset( $data['billing_cycle'] ) ? $data['billing_cycle'] : '',
			'{{start_date}}'     => isset( $data['start_date'] ) ? self::format_date( $data['start_date'] ) : '',
			'{{next_billing_date}}' => isset( $data['next_billing_date'] ) ? self::format_date( $data['next_billing_date'] ) : '',
			'{{subscription_status}}' => isset( $data['subscription_status'] ) ? $data['subscription_status'] : '',
		);

		return strtr( $content, $map );
	}

	/**
	 * Send a templated email.
	 *
	 * @param string $template_key Template key (e.g. invoice_payment_request).
	 * @param string $to           Recipient email.
	 * @param array  $data         Replacement data.
	 * @return bool
	 */
	public static function send( $template_key, $to, array $data ) {
		$templates = get_option( 'lucrsure_email_templates', lucrsure_default_email_templates() );

		if ( ! isset( $templates[ $template_key ] ) ) {
			return false;
		}

		if ( isset( $data['gateway'] ) && 'manual' === $data['gateway'] ) {
			$data['payment_url'] = '';
		}

		$subject       = self::parse( $templates[ $template_key ]['subject'], $data );
		$body_template = $templates[ $template_key ]['body'];
		$body          = self::render_template_body( $template_key, $body_template, $data );

		$settings  = get_option( 'lucrsure_settings', array() );
		$from_name = isset( $settings['email']['from_name'] ) ? $settings['email']['from_name'] : get_bloginfo( 'name' );
		$from_addr = isset( $settings['email']['from_address'] ) ? $settings['email']['from_address'] : get_option( 'admin_email' );

		$headers = array(
			'Content-Type: text/html; charset=UTF-8',
			sprintf( 'From: %s <%s>', $from_name, $from_addr ),
		);

		$attachments = array();
		$pdf_path    = '';

		if ( ! empty( $data['invoice_id'] ) && lucrsure_should_attach_pdf_invoice( $template_key ) ) {
			$pdf_path = LUCRSURE_Invoice_PDF::generate( (int) $data['invoice_id'] );
			if ( $pdf_path ) {
				$attachments[] = $pdf_path;
			}
		}

		$sent = wp_mail( $to, $subject, $body, $headers, $attachments );

		if ( $pdf_path && file_exists( $pdf_path ) ) {
			wp_delete_file( $pdf_path );
		}

		return $sent;
	}

	/**
	 * Render a templated email body HTML string.
	 *
	 * @param string $template_key  Template key.
	 * @param string $body_template Raw template body from storage or editor.
	 * @param array  $data          Replacement data.
	 * @return string
	 */
	public static function render_template_body( $template_key, $body_template, array $data ) {
		if ( isset( $data['gateway'] ) && 'manual' === $data['gateway'] ) {
			$data['payment_url'] = '';
		}

		$intro        = lucrsure_email_ensure_greeting( lucrsure_email_intro_body( $body_template, $template_key ) );
		$intro        = self::strip_inline_payment_links( $intro, $data );
		$content_html = self::parse( $intro, $data );
		$content_html = self::strip_inline_payment_links( $content_html, $data );
		if ( false === strpos( $content_html, '<' ) ) {
			$content_html = self::markdown_to_html( $content_html );
		}
		$content_html = self::strip_inline_payment_links( $content_html, $data );
		$blocks = self::build_blocks( $data, $template_key, $content_html );
		$brand  = apply_filters( 'lucrsure_email_branding_settings', lucrsure_default_email_branding() );
		$layout = apply_filters(
			'lucrsure_email_layout_html',
			lucrsure_basic_email_layout_html( $brand ),
			$brand
		);

		return self::apply_blocks( $layout, $blocks, $data );
	}

	/**
	 * Build an email preview (subject + HTML body) using sample data.
	 *
	 * @param string $template_key Template key.
	 * @param string $body         Template body from the editor.
	 * @param string $subject      Subject line with placeholders.
	 * @return array{subject:string,body:string}
	 */
	public static function preview( $template_key, $body, $subject = '' ) {
		$data = lucrsure_email_preview_sample_data( $template_key );

		return array(
			'subject' => $subject ? self::parse( $subject, $data ) : '',
			'body'    => self::render_template_body( $template_key, $body, $data ),
		);
	}

	/**
	 * Format a datetime string for display in emails.
	 *
	 * @param string $datetime MySQL datetime.
	 * @return string
	 */
	protected static function format_date( $datetime ) {
		if ( '' === $datetime ) {
			return '';
		}
		$timestamp = strtotime( $datetime );
		if ( ! $timestamp ) {
			return $datetime;
		}
		return wp_date( get_option( 'date_format' ), $timestamp );
	}

	/**
	 * Build dynamic email blocks for template rendering.
	 *
	 * @param array  $data         Replacement data.
	 * @param string $template_key Template key.
	 * @param string $content_html Optional main content HTML (legacy layout mode).
	 * @return array<string,string>
	 */
	protected static function build_blocks( array $data, $template_key, $content_html = '' ) {
		$settings = get_option( 'lucrsure_settings', array() );
		$company  = isset( $settings['company_name'] ) ? $settings['company_name'] : get_bloginfo( 'name' );
		$brand    = apply_filters( 'lucrsure_email_branding_settings', lucrsure_default_email_branding() );

		$cta = 'subscription_active' === $template_key
			? ''
			: self::build_payment_cta( $data, $template_key, $settings, $brand );

		$content = $content_html ? wpautop( $content_html ) : '';

		$header = (string) apply_filters( 'lucrsure_email_header_html', '', $brand, $company );
		$footer = (string) apply_filters( 'lucrsure_email_footer_html', '', $brand, $company );

		return array(
			'header'   => $header,
			'greeting' => '',
			'content'  => $content,
			'info_box' => '',
			'cta'      => $cta,
			'footer'   => $footer,
		);
	}

	/**
	 * Replace block and data placeholders in an email template.
	 *
	 * @param string $template HTML template.
	 * @param array  $blocks   Dynamic blocks.
	 * @param array  $data     Replacement data.
	 * @return string
	 */
	protected static function apply_blocks( $template, array $blocks, array $data ) {
		$replacements = array();
		foreach ( $blocks as $key => $html ) {
			$replacements[ '{{' . $key . '}}' ] = $html;
		}

		$html = strtr( $template, $replacements );

		return self::parse( $html, $data );
	}

	/**
	 * Wrap intro content in a branded HTML email layout.
	 *
	 * @param string $intro_html   Parsed intro paragraph HTML.
	 * @param array  $data         Replacement data.
	 * @param string $template_key Template key.
	 * @return string
	 */
	protected static function wrap_layout( $intro_html, array $data, $template_key ) {
		$blocks = self::build_blocks( $data, $template_key, $intro_html );
		$brand  = apply_filters( 'lucrsure_email_branding_settings', lucrsure_default_email_branding() );
		$layout = apply_filters(
			'lucrsure_email_layout_html',
			lucrsure_basic_email_layout_html( $brand ),
			$brand
		);

		return self::apply_blocks( $layout, $blocks, $data );
	}

	/**
	 * Build the payment call-to-action block for invoice emails.
	 *
	 * @param array  $data         Replacement data.
	 * @param string $template_key Template key.
	 * @param array  $settings     Plugin settings.
	 * @param array  $brand        Branding settings.
	 * @return string
	 */
	protected static function build_payment_cta( array $data, $template_key, array $settings, array $brand = array() ) {
		if ( 'payment_success' === $template_key ) {
			return '';
		}

		$brand = wp_parse_args( $brand, lucrsure_default_email_branding() );

		$payment_url = isset( $data['payment_url'] ) ? $data['payment_url'] : '';
		$gateway     = isset( $data['gateway'] ) ? $data['gateway'] : '';
		$is_manual   = 'manual' === $gateway;

		if ( $is_manual ) {
			$payment_url = '';
		}

		if ( $is_manual ) {
			$support = isset( $settings['support_email'] ) ? $settings['support_email'] : get_option( 'admin_email' );
			$cta     = '<table cellpadding="0" cellspacing="0" border="0" width="100%" style="margin:24px 0 8px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;">
				<tr>
					<td style="padding:16px 20px;font-size:14px;color:' . esc_attr( $brand['content_text_color'] ) . ';line-height:1.7;">
						<strong style="color:' . esc_attr( $brand['heading_color'] ) . ';">' . esc_html__( 'Manual payment', 'lucrativeit-subscription-recurring-billing' ) . '</strong><br>
						' . esc_html__( 'This invoice is payable offline. No online payment link is included. Please complete payment using your agreed method and reference your invoice number.', 'lucrativeit-subscription-recurring-billing' );
			if ( $support ) {
				$cta .= '<br><br>' . esc_html__( 'Questions?', 'lucrativeit-subscription-recurring-billing' ) . ' <a href="mailto:' . esc_attr( $support ) . '" style="color:' . esc_attr( $brand['accent_color'] ) . ';text-decoration:none;">' . esc_html( $support ) . '</a>';
			}
			$cta .= '
					</td>
				</tr>
			</table>';

			return $cta;
		}

		if ( ! $payment_url ) {
			return '';
		}

		return '<table cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 8px;">
			<tr>
				<td style="border-radius:6px;background:' . esc_attr( $brand['button_bg'] ) . ';">
					<a href="' . esc_url( $payment_url ) . '" style="display:inline-block;padding:14px 36px;font-size:15px;font-weight:bold;color:' . esc_attr( $brand['button_text_color'] ) . ';text-decoration:none;border-radius:6px;">' . esc_html__( 'Pay Now', 'lucrativeit-subscription-recurring-billing' ) . '</a>
				</td>
			</tr>
		</table>';
	}

	/**
	 * Remove inline Pay Now markdown/HTML links when no online payment URL is available.
	 *
	 * @param string $text Template fragment (plain text or HTML).
	 * @param array  $data Replacement data.
	 * @return string
	 */
	protected static function strip_inline_payment_links( $text, array $data ) {
		$gateway     = isset( $data['gateway'] ) ? $data['gateway'] : '';
		$payment_url = isset( $data['payment_url'] ) ? trim( (string) $data['payment_url'] ) : '';

		if ( 'manual' !== $gateway && '' !== $payment_url ) {
			return $text;
		}

		// Markdown links with an empty URL (after placeholders are replaced).
		$text = preg_replace( '/\s*\[[^\]]+\]\(\s*\)/', '', $text );
		// Markdown links still pointing at the payment_url placeholder.
		$text = preg_replace( '/\s*\[[^\]]+\]\(\s*\{\{payment_url\}\}\s*\)/', '', $text );
		// HTML links with an empty href (after markdown conversion).
		$text = preg_replace( '/\s*<a\s[^>]*href=(["\'])\s*\1[^>]*>.*?<\/a>/', '', $text );

		return trim( preg_replace( '/\n{3,}/', "\n\n", $text ) );
	}

	/**
	 * Very small markdown subset converter (bold + links).
	 *
	 * @param string $text Markdown.
	 * @return string
	 */
	protected static function markdown_to_html( $text ) {
		$text = preg_replace( '/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2" style="color:#2563eb;">$1</a>', $text );
		$text = preg_replace( '/\*\*([^*]+)\*\*/', '<strong>$1</strong>', $text );
		return $text;
	}

	/**
	 * Send a test email.
	 *
	 * @param string $to Recipient.
	 * @return bool
	 */
	public static function send_test( $to ) {
		$settings  = get_option( 'lucrsure_settings', array() );
		$from_name = isset( $settings['email']['from_name'] ) ? $settings['email']['from_name'] : get_bloginfo( 'name' );
		$from_addr = isset( $settings['email']['from_address'] ) ? $settings['email']['from_address'] : get_option( 'admin_email' );

		$headers = array(
			'Content-Type: text/html; charset=UTF-8',
			sprintf( 'From: %s <%s>', $from_name, $from_addr ),
		);

		$intro = self::markdown_to_html(
			__( 'This is a test email. Your email configuration is working correctly.', 'lucrativeit-subscription-recurring-billing' )
		);
		$body  = self::wrap_layout(
			$intro,
			array(
				'customer_name' => __( 'Customer', 'lucrativeit-subscription-recurring-billing' ),
			),
			'subscription_active'
		);

		return wp_mail(
			$to,
			sprintf(
				/* translators: %s: plugin name */
				__( 'Test email from %s', 'lucrativeit-subscription-recurring-billing' ),
				lucrsure_plugin_name()
			),
			$body,
			$headers
		);
	}
}
