<?php

namespace WC_Affiliate\Helpers\Email;

defined( 'ABSPATH' ) || exit;

/**
 * Mailer class to handle platform-specific email sending.
 * Provides unified interface for sending emails across different platforms.
 */
class Mailer {

	/**
	 * Controller constructor
	 *
	 * Automatically registers email hooks on instantiation
	 */
	public function __construct() {
		$this->register_hooks();
	}

	/**
	 * Register hooks for email controller
	 *
	 * @return void
	 */
	protected function register_hooks(): void {
		// Email content section filters.
		add_filter( 'wc_affiliate_email_greeting_content', array( $this, 'get_greeting_content' ), 10, 2 );
		add_filter( 'wc_affiliate_email_highlight_content', array( $this, 'get_highlight_content' ), 10, 2 );
		add_filter( 'wc_affiliate_email_button_content', array( $this, 'get_button_content' ), 10, 3 );
		add_filter( 'wc_affiliate_email_signature_content', array( $this, 'get_signature_content' ), 10, 2 );
		add_filter( 'wc_affiliate_email_stats_content', array( $this, 'get_stats_section_content' ), 10, 2 );

		// Email content type filter.
		add_filter( 'wp_mail_content_type', array( $this, 'set_email_content_type' ) );
	}

	/**
	 * Set email content type to HTML
	 *
	 * @return string Email content type
	 */
	public function set_email_content_type(): string {
		/**
		 * Filter to modify email content type.
		 *
		 * @param string $content_type Email content type.
		 */
		return apply_filters( 'wc_affiliate_email_content_type', 'text/html' );
	}

	/**
	 * Get greeting section
	 *
	 * @param string $default Default content (empty string).
	 * @param string $name User name.
	 *
	 * @return string HTML greeting
	 */
	public function get_greeting_content( string $default, string $name ): string {
		return wca_get_template( 'components/greeting', 'views/emails', array( 'name' => $name ) );
	}

	/**
	 * Get call-to-action button
	 *
	 * @param string $default Default content (empty string).
	 * @param string $url Button URL.
	 * @param string $text Button text.
	 *
	 * @return string HTML button
	 */
	public function get_button_content( string $default, string $url, string $text ): string {
		return wca_get_template(
			'components/button',
			'views/emails',
			array(
				'url'  => $url,
				'text' => $text,
			)
		);
	}

	/**
	 * Get highlight box
	 *
	 * @param string $default Default content (empty string).
	 * @param string $content Content to highlight.
	 *
	 * @return string HTML highlight box
	 */
	public function get_highlight_content( string $default, string $content ): string {
		return wca_get_template( 'components/highlight', 'views/emails', array( 'content' => $content ) );
	}

	/**
	 * Get statistics section
	 *
	 * @param string $default Default content (empty string).
	 * @param array  $stats Statistics array.
	 *
	 * @return string HTML stats section
	 */
	public function get_stats_section_content( string $default, array $stats ): string {
		return wca_get_template( 'components/stats', 'views/emails', array( 'stats' => $stats ) );
	}

	/**
	 * Get signature section
	 *
	 * @param string $default Default content (empty string).
	 * @param string $site_name Site name.
	 *
	 * @return string HTML signature
	 */
	public function get_signature_content( string $default, string $site_name ): string {
		return wca_get_template( 'components/signature', 'views/emails', array( 'site_name' => $site_name ) );
	}

	/**
	 * Get email template wrapper
	 *
	 * @param string $content Email content.
	 * @param string $title Email title.
	 * @param bool   $is_admin_email Whether this is an admin email.
	 *
	 * @return string HTML email template
	 */
	public function get_email_template( string $content, string $title = '', bool $is_admin_email = false ): string {
		$site_name = get_bloginfo( 'name' );
		$site_url  = get_bloginfo( 'url' );

		return wca_get_template(
			'layouts/template',
			'views/emails',
			array(
				'content'        => $content,
				'title'          => $title,
				'site_name'      => $site_name,
				'site_url'       => $site_url,
				'is_admin_email' => $is_admin_email,
			)
		);
	}

	/**
	 * Replace placeholders in email content
	 *
	 * @param string $content Content with placeholders.
	 * @param array  $context Context data for replacement.
	 *
	 * @return string Content with placeholders replaced.
	 */
	public function replace_placeholders( string $content, array $context = array() ): string {
		$placeholders = apply_filters(
			'wc_affiliate_email_placeholders',
			array(
				'%%site_title%%'       => get_bloginfo( 'name' ),
				'%%site_url%%'         => get_bloginfo( 'url' ),
				'%%website_url%%'      => get_bloginfo( 'url' ),
				'%%admin_email%%'      => wca_admin_email(),
				'%%currency%%'         => wca_get_currency_symbol(),
				'%%current_year%%'     => wp_date( 'Y' ),
				'%%current_month%%'    => wp_date( 'M' ),
				'%%current_date%%'     => wp_date( 'd-m-Y-H-i-s' ),
				'%%dashboard_url%%'    => wca_get_dashboard(),
				'%%registration_url%%' => get_permalink( wca_get_registration_page_id() ),
			),
			$context
		);

		foreach ( $context as $placeholder => $value ) {
			$blocked_placeholders = array( 'referred_by', 'affiliate' );
			$blocked_placeholders = apply_filters( 'wc_affiliate_email_blocked_placeholders', $blocked_placeholders, $placeholder, $value );
			if ( in_array( $placeholder, $blocked_placeholders, true ) ) {
				continue;
			}

			if ( is_numeric( $value ) ) {
				$value = number_format( (float) $value, 2 );
			}

			$currency_fields = array( 'amount_formatted', 'referral_commission', 'affiliate_total_earnings', 'affiliate_pending_commissions', 'order_total', 'payout_fee', 'average_commission' );
			$currency_fields = apply_filters( 'wc_affiliate_email_currency_fields', $currency_fields );

			if ( in_array( $placeholder, $currency_fields, true ) ) {
				$value = wca_get_currency_symbol() . $value;
			}

			$placeholders[ "%%$placeholder%%" ] = $value;
		}

		// Allow final modification of all placeholders before replacement.
		$placeholders = apply_filters( 'wc_affiliate_email_placeholders_data', $placeholders, $content, $context );

		return str_replace( array_keys( $placeholders ), array_values( $placeholders ), $content );
	}

	/**
	 * Send email using an email system or custom HTML template
	 *
	 * @param string $to             Email recipient.
	 * @param string $subject        Email subject.
	 * @param string $message        Email message.
	 * @param array  $context        Context data for placeholder replacement (optional).
	 * @param bool   $is_admin_email Whether this is an admin email (optional).
	 * @param string $attachments    Email attachments (optional).
	 * @param bool   $use_template   Whether to use email template or custom HTML template (optional).
	 * @param array  $headers        Email headers (optional).
	 *
	 * @return void
	 */
	public function send( string $to, string $subject, string $message, array $context = array(), bool $is_admin_email = false, string $attachments = '', bool $use_template = true, array $headers = array( 'Content-Type: text/html; charset=UTF-8' ) ): void {
		// Replace placeholders in subject and message.
		$subject = $this->replace_placeholders( $subject, $context );
		$message = $this->replace_placeholders( $message, $context );

		// Allow filtering email parameters before sending.
		$email_args = apply_filters(
			'wc_affiliate_email_args',
			array(
				'to'             => $to,
				'subject'        => $subject,
				'message'        => $message,
				'context'        => $context,
				'is_admin_email' => $is_admin_email,
				'attachments'    => $attachments,
				'use_template'   => $use_template,
				'headers'        => $headers,
			)
		);

		$to             = $email_args['to'];
		$subject        = $email_args['subject'];
		$message        = $email_args['message'];
		$is_admin_email = $email_args['is_admin_email'];
		$attachments    = $email_args['attachments'];
		$headers        = $email_args['headers'];
		$use_template   = $email_args['use_template'];

		// If message is already HTML and template is requested, wrap it.
		if ( $use_template && strpos( $message, '<!DOCTYPE html>' ) === false ) {
			$message = $this->get_email_template( $message, $subject, $is_admin_email );
		}

		// Allow filtering final message before sending.
		$message = apply_filters( 'wc_affiliate_email_message', $message, $to, $subject, $use_template );

		$result = $this->send_via_wordpress( $to, $subject, $message, $attachments, $headers );

		// Fire action after email is sent.
		do_action( 'wc_affiliate_email_sent', $result, $to, $subject, $message, $attachments, $headers, $use_template, $is_admin_email );
	}

	/**
	 * Send email using WordPress wp_mail function.
	 *
	 * @param string $to Recipient email address.
	 * @param string $subject Email subject.
	 * @param string $message Email message content.
	 * @param string $attachments Email attachments.
	 * @param array  $headers Email headers.
	 *
	 * @return bool Whether the email was sent successfully.
	 */
	public function send_via_wordpress( string $to, string $subject, string $message, string $attachments, array $headers ): bool {
		$wp_headers = $headers;

		return \wp_mail( $to, $subject, $message, $wp_headers, (array) $attachments );
	}
}
