<?php
/**
 * Class Noesia Cs Email Service.
 *
 * @package Noesia_Commerce_Suite
 */

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

/**
 * Class implementation.
 */
class Noesia_CS_Email_Service {
	const EMAIL_LOG_OPTION = 'noesia_cs_email_logs';

	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $passport_service;
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $temporary_sender_name = '';

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $passport_service Passport service.
	 */
	public function __construct( Noesia_CS_Passport_Service $passport_service ) {
		$this->passport_service = $passport_service;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $recipient Recipient.
	 */
	public function send_test_email( $recipient = '' ) {
		$settings   = Noesia_CS_Settings::get_all();
		$recipient  = sanitize_email( $recipient ? $recipient : $settings['test_email_recipient'] );

		if ( ! $recipient ) {
			$this->add_log( 'failed', 'verification', __( 'A valid verification email recipient is required.', 'noesia-commerce-suite' ) );
			return new WP_Error( 'noesia_cs_invalid_recipient', __( 'A valid verification email recipient is required.', 'noesia-commerce-suite' ) );
		}

		$subject  = $settings['passport_email_subject'] ? $settings['passport_email_subject'] : __( 'Your order care page', 'noesia-commerce-suite' );
		$body     = $settings['passport_email_body'] ? $settings['passport_email_body'] : __( 'Open your secure Order Care Hub for review, reorder and support actions.', 'noesia-commerce-suite' );
		$button   = $settings['passport_email_button_label'] ? $settings['passport_email_button_label'] : __( 'Open Order Care Hub', 'noesia-commerce-suite' );
		$tokens   = $this->preview_tokens();
		$subject  = $this->replace_tokens( $subject, $tokens );
		$body     = $this->replace_tokens( $body, $tokens );
		$html     = $this->build_email_html( $subject, $body, $button, home_url( '/' ), $settings, true );

		$sent = $this->send_html_mail( $recipient, $subject, $html, $settings );

		if ( ! $sent ) {
			$this->add_log( 'failed', 'verification', __( 'WordPress could not send the verification email from this server.', 'noesia-commerce-suite' ) );
			return new WP_Error( 'noesia_cs_mail_failed', __( 'WordPress could not send the verification email from this server.', 'noesia-commerce-suite' ) );
		}

		$this->add_log( 'sent', 'verification', __( 'Verification email sent. No customer/order data was included.', 'noesia-commerce-suite' ) );
		return true;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function render_order_email_block( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		if ( 'yes' !== Noesia_CS_Settings::get( 'enable_care_page', 'yes' ) || 'yes' !== Noesia_CS_Settings::get( 'passport_email_enabled', 'no' ) || 'yes' !== Noesia_CS_Settings::get( 'email_integration', 'no' ) || 'yes' !== Noesia_CS_Settings::get( 'show_qr_emails', 'no' ) ) {
			return;
		}

		$url = $this->passport_service->get_care_url_for_order( $order );
		if ( ! $url ) {
			return;
		}

		$settings  = Noesia_CS_Settings::get_all();
		$title     = $settings['passport_email_subject'] ? $settings['passport_email_subject'] : __( 'Your order care page', 'noesia-commerce-suite' );
		$body      = $settings['passport_email_body'] ? $settings['passport_email_body'] : __( 'Open your secure Order Care Hub for review, reorder and support actions.', 'noesia-commerce-suite' );
		$button    = $settings['passport_email_button_label'] ? $settings['passport_email_button_label'] : __( 'Open Order Care Hub', 'noesia-commerce-suite' );
		$tokens    = $this->order_tokens( $order );
		$title     = $this->replace_tokens( $title, $tokens );
		$body      = $this->replace_tokens( $body, $tokens );

		$fragment = $this->build_woocommerce_email_fragment( $title, $body, $button, $url, $settings );
		// The fragment escapes every dynamic value internally and must keep inline styles for email clients.
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $fragment;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $item Item.
	 * @param mixed $unsubscribe_url Unsubscribe url.
	 */
	public function send_reorder_reminder( $order, $item, $unsubscribe_url = '' ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) || ! $item ) {
			$this->add_log( 'failed', 'reorder', __( 'A valid order and order item are required.', 'noesia-commerce-suite' ) );
			return new WP_Error( 'noesia_cs_invalid_reorder_context', __( 'A valid order and order item are required.', 'noesia-commerce-suite' ) );
		}

		$email = sanitize_email( $order->get_billing_email() );
		if ( ! $email ) {
			$this->add_log( 'failed', 'reorder', __( 'The order has no valid customer email.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_missing_customer_email', __( 'The order has no valid customer email.', 'noesia-commerce-suite' ) );
		}

		$settings      = Noesia_CS_Settings::get_all();
		$product_name  = method_exists( $item, 'get_name' ) ? $item->get_name() : __( 'your product', 'noesia-commerce-suite' );
		$reorder_url   = $this->passport_service->get_reorder_url_for_item( $item );
		if ( ! $reorder_url ) {
			$this->add_log( 'failed', 'reorder', __( 'The reorder URL could not be created.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_missing_reorder_url', __( 'The reorder URL could not be created.', 'noesia-commerce-suite' ) );
		}

		$subject  = $settings['reorder_email_subject'] ? $settings['reorder_email_subject'] : __( 'It may be time to reorder', 'noesia-commerce-suite' );
		$body     = $settings['reorder_email_body'] ? $settings['reorder_email_body'] : __( 'Based on your previous purchase, it may be time to reorder {product_name}.', 'noesia-commerce-suite' );
		$button   = $settings['reorder_email_button_label'] ? $settings['reorder_email_button_label'] : __( 'Reorder Now', 'noesia-commerce-suite' );

		$tokens   = $this->order_tokens( $order, $product_name );
		$subject  = $this->replace_tokens( $subject, $tokens );
		$body     = $this->replace_tokens( $body, $tokens );

		$extra_footer = '';
		if ( 'yes' === $settings['reorder_opt_out_enabled'] && $unsubscribe_url ) {
			$extra_footer .= '<p style="margin:18px 0 0;color:#6b7280;font-size:12px;line-height:1.5;">' . esc_html( $settings['unsubscribe_text'] ) . ' <a href="' . esc_url( $unsubscribe_url ) . '" style="color:#6f45ff;text-decoration:underline;">' . esc_html__( 'Opt out of reorder reminders', 'noesia-commerce-suite' ) . '</a></p>';
		}

		$html  = $this->build_email_html( $subject, $body, $button, $reorder_url, $settings, false, $extra_footer );
		$sent  = $this->send_html_mail( $email, $subject, $html, $settings );
		if ( ! $sent ) {
			$this->add_log( 'failed', 'reorder', __( 'WordPress could not send the reorder reminder email from this server.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_mail_failed', __( 'WordPress could not send the reorder reminder email from this server.', 'noesia-commerce-suite' ) );
		}

		$this->add_log( 'sent', 'reorder', __( 'Reorder reminder email sent.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
		return true;
	}


	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $item Item.
	 * @param mixed $unsubscribe_url Unsubscribe url.
	 * @param mixed $recipient Recipient.
	 */
	public function send_reorder_reminder_test_copy( $order, $item, $unsubscribe_url = '', $recipient = '' ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) || ! $item ) {
			$this->add_log( 'failed', 'reorder_test', __( 'A valid order and order item are required for the reorder reminder test copy.', 'noesia-commerce-suite' ) );
			return new WP_Error( 'noesia_cs_invalid_reorder_test_context', __( 'A valid order and order item are required.', 'noesia-commerce-suite' ) );
		}

		$settings   = Noesia_CS_Settings::get_all();
		$recipient  = sanitize_email( $recipient ? $recipient : $settings['test_email_recipient'] );
		if ( ! $recipient ) {
			$recipient = sanitize_email( get_option( 'admin_email' ) );
		}
		if ( ! $recipient ) {
			$this->add_log( 'failed', 'reorder_test', __( 'A valid admin/test recipient is required.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_invalid_test_recipient', __( 'A valid admin/test recipient is required.', 'noesia-commerce-suite' ) );
		}

		$product_name  = method_exists( $item, 'get_name' ) ? $item->get_name() : __( 'your product', 'noesia-commerce-suite' );
		$reorder_url   = $this->passport_service->get_reorder_url_for_item( $item );
		if ( ! $reorder_url ) {
			$this->add_log( 'failed', 'reorder_test', __( 'The reorder URL could not be created for the test copy.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_missing_reorder_test_url', __( 'The reorder URL could not be created.', 'noesia-commerce-suite' ) );
		}

		$subject  = $settings['reorder_email_subject'] ? $settings['reorder_email_subject'] : __( 'It may be time to reorder', 'noesia-commerce-suite' );
		$body     = $settings['reorder_email_body'] ? $settings['reorder_email_body'] : __( 'Based on your previous purchase, it may be time to reorder {product_name}.', 'noesia-commerce-suite' );
		$button   = $settings['reorder_email_button_label'] ? $settings['reorder_email_button_label'] : __( 'Reorder Now', 'noesia-commerce-suite' );

		$tokens   = $this->order_tokens( $order, $product_name );
		$subject  = '[Test] ' . $this->replace_tokens( $subject, $tokens );
		$body     = $this->replace_tokens( $body, $tokens );

		$extra_footer  = '<p style="margin:18px 0 0;color:#6b7280;font-size:12px;line-height:1.5;"><strong>' . esc_html__( 'Admin test copy:', 'noesia-commerce-suite' ) . '</strong> ' . esc_html__( 'This preview was sent to the admin/test recipient and did not change any customer reminders.', 'noesia-commerce-suite' ) . '</p>';
		if ( 'yes' === $settings['reorder_opt_out_enabled'] && $unsubscribe_url ) {
			$extra_footer .= '<p style="margin:10px 0 0;color:#6b7280;font-size:12px;line-height:1.5;">' . esc_html( $settings['unsubscribe_text'] ) . ' <a href="' . esc_url( $unsubscribe_url ) . '" style="color:#6f45ff;text-decoration:underline;">' . esc_html__( 'Opt out of reorder reminders', 'noesia-commerce-suite' ) . '</a></p>';
		}

		$html  = $this->build_email_html( $subject, $body, $button, $reorder_url, $settings, false, $extra_footer );
		$sent  = $this->send_html_mail( $recipient, $subject, $html, $settings );
		if ( ! $sent ) {
			$this->add_log( 'failed', 'reorder_test', __( 'WordPress could not send the reorder reminder test copy from this server.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
			return new WP_Error( 'noesia_cs_test_mail_failed', __( 'WordPress could not send the reorder reminder test copy from this server.', 'noesia-commerce-suite' ) );
		}

		$this->add_log( 'sent', 'reorder_test', __( 'Reorder reminder test copy sent to admin/test recipient.', 'noesia-commerce-suite' ), absint( $order->get_id() ) );
		return true;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $type Type.
	 */
	public function get_preview_html( $type = 'passport' ) {
		$settings  = Noesia_CS_Settings::get_all();
		$tokens    = $this->preview_tokens();
		if ( 'reorder' === $type ) {
			$subject  = $settings['reorder_email_subject'] ? $settings['reorder_email_subject'] : __( 'It may be time to reorder', 'noesia-commerce-suite' );
			$body     = $settings['reorder_email_body'] ? $settings['reorder_email_body'] : __( 'Based on your previous purchase, it may be time to reorder {product_name}.', 'noesia-commerce-suite' );
			$button   = $settings['reorder_email_button_label'] ? $settings['reorder_email_button_label'] : __( 'Reorder Now', 'noesia-commerce-suite' );
			$subject  = $this->replace_tokens( $subject, $tokens );
			$body     = $this->replace_tokens( $body, $tokens );
			return $this->build_email_html( $subject, $body, $button, home_url( '/' ), $settings, true, '<p style="margin:18px 0 0;color:#6b7280;font-size:12px;line-height:1.5;">' . esc_html( $settings['unsubscribe_text'] ) . '</p>' );
		}

		$subject  = $settings['passport_email_subject'] ? $settings['passport_email_subject'] : __( 'Your order care page', 'noesia-commerce-suite' );
		$body     = $settings['passport_email_body'] ? $settings['passport_email_body'] : __( 'Open your secure Order Care Hub for review, reorder and support actions.', 'noesia-commerce-suite' );
		$button   = $settings['passport_email_button_label'] ? $settings['passport_email_button_label'] : __( 'Open Order Care Hub', 'noesia-commerce-suite' );
		$subject  = $this->replace_tokens( $subject, $tokens );
		$body     = $this->replace_tokens( $body, $tokens );
		return $this->build_email_html( $subject, $body, $button, home_url( '/' ), $settings, true );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $limit Limit.
	 */
	public function get_recent_logs( $limit = 12 ) {
		$logs  = get_option( self::EMAIL_LOG_OPTION, array() );
		$logs  = is_array( $logs ) ? $logs : array();
		return array_slice( $logs, 0, absint( $limit ) );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function get_log_count() {
		$logs = get_option( self::EMAIL_LOG_OPTION, array() );
		return is_array( $logs ) ? count( $logs ) : 0;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $page Page.
	 * @param mixed $per_page Per page.
	 */
	public function get_logs_page( $page = 1, $per_page = 20 ) {
		$logs      = get_option( self::EMAIL_LOG_OPTION, array() );
		$logs      = is_array( $logs ) ? $logs : array();
		$page      = max( 1, absint( $page ) );
		$per_page  = max( 1, min( 100, absint( $per_page ) ) );
		$offset    = ( $page - 1 ) * $per_page;
		return array_slice( $logs, $offset, $per_page );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $recipient Recipient.
	 * @param mixed $subject Subject.
	 * @param mixed $html Html.
	 * @param mixed $settings Settings.
	 */
	private function send_html_mail( $recipient, $subject, $html, $settings ) {
		$headers  = array( 'Content-Type: text/html; charset=UTF-8' );
		$sender   = ! empty( $settings['email_sender_name'] ) ? sanitize_text_field( $settings['email_sender_name'] ) : '';
		if ( $sender ) {
			$this->temporary_sender_name = $sender;
			add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ) );
		}

		$sent = wp_mail( $recipient, wp_strip_all_tags( $subject ), $html, $headers );

		if ( $sender ) {
			remove_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ) );
			$this->temporary_sender_name = '';
		}

		return $sent;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $name Name.
	 */
	public function filter_mail_from_name( $name ) {
		return $this->temporary_sender_name ? $this->temporary_sender_name : $name;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $message Message.
	 */
	public function log_order_email_block_failure( $order, $message = '' ) {
		$order_id  = ( $order && is_a( $order, 'WC_Order' ) ) ? absint( $order->get_id() ) : 0;
		$message   = $message ? sanitize_text_field( $message ) : __( 'The Order Care Hub email block could not be rendered, but the WooCommerce email was allowed to continue.', 'noesia-commerce-suite' );
		$this->add_log( 'failed', 'order-care-email-block', $message, $order_id );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $status Status.
	 * @param mixed $type Type.
	 * @param mixed $message Message.
	 * @param mixed $order_id Order id.
	 */
	private function add_log( $status, $type, $message, $order_id = 0 ) {
		$logs            = get_option( self::EMAIL_LOG_OPTION, array() );
		$logs            = is_array( $logs ) ? $logs : array();
		$retention_days  = max( 1, absint( Noesia_CS_Settings::get( 'email_log_retention_days', 15 ) ) );
		$cutoff          = time() - ( $retention_days * DAY_IN_SECONDS );
		$logs = array_values(
			array_filter(
				$logs,
				function ( $log ) use ( $cutoff ) {
					$time = is_array( $log ) && isset( $log['time'] ) ? absint( $log['time'] ) : 0;
					return ! $time || $time >= $cutoff;
				}
			)
		);
		array_unshift(
			$logs,
			array(
				'time'      => time(),
				'status'    => sanitize_key( $status ),
				'type'      => sanitize_key( $type ),
				'order_id'  => absint( $order_id ),
				'message'   => sanitize_text_field( $message ),
			)
		);
		$logs = array_slice( $logs, 0, 300 );
		update_option( self::EMAIL_LOG_OPTION, $logs, false );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $product_name Product name.
	 */
	private function order_tokens( $order, $product_name = '' ) {
		$settings = Noesia_CS_Settings::get_all();
		$tokens   = array(
			'{store_name}'    => ! empty( $settings['company_name'] ) ? $settings['company_name'] : get_bloginfo( 'name' ),
			'{order_number}'  => '',
			'{product_name}'  => $product_name ? $product_name : __( 'Purchased product', 'noesia-commerce-suite' ),
		);

		if ( $order && is_a( $order, 'WC_Order' ) ) {
			$tokens['{order_number}'] = $order->get_order_number();
		}

		return $tokens;
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function preview_tokens() {
		$settings = Noesia_CS_Settings::get_all();
		return array(
			'{store_name}'    => ! empty( $settings['company_name'] ) ? $settings['company_name'] : get_bloginfo( 'name' ),
			'{order_number}'  => __( 'Order reference', 'noesia-commerce-suite' ),
			'{product_name}'  => __( 'Purchased product', 'noesia-commerce-suite' ),
		);
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $text Text.
	 * @param mixed $tokens Tokens.
	 */
	private function replace_tokens( $text, $tokens ) {
		$text = is_scalar( $text ) ? (string) $text : '';
		return strtr( $text, is_array( $tokens ) ? $tokens : array() );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function get_supported_placeholders() {
		return array(
			'{store_name}'    => __( 'Your shop name, filled from Noesia settings.', 'noesia-commerce-suite' ),
			'{order_number}'  => __( 'The customer’s WooCommerce order number.', 'noesia-commerce-suite' ),
			'{product_name}'  => __( 'The product the customer bought, useful for reorder reminder emails.', 'noesia-commerce-suite' ),
		);
	}


	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $title Title.
	 * @param mixed $body Body.
	 * @param mixed $button_label Button label.
	 * @param mixed $url Url.
	 * @param mixed $settings Settings.
	 */
	private function build_woocommerce_email_fragment( $title, $body, $button_label, $url, $settings ) {
		$primary  = ! empty( $settings['email_button_color'] ) ? sanitize_hex_color( $settings['email_button_color'] ) : '';
		$primary  = $primary ? $primary : '#6f45ff';
		$title    = is_scalar( $title ) ? (string) $title : '';
		$body     = is_scalar( $body ) ? (string) $body : '';
		$button   = is_scalar( $button_label ) ? (string) $button_label : __( 'Open Order Care Hub', 'noesia-commerce-suite' );
		$url      = is_scalar( $url ) ? (string) $url : '';

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

		ob_start();
		?>
		<div class="noesia-cs-email-care-fragment" style="margin:24px 0;padding:20px;border:1px solid #e8e5ff;border-radius:18px;background:#f8f7ff;">
			<h3 style="margin:0 0 8px;color:#111827;font-size:18px;line-height:1.3;"><?php echo esc_html( $title ); ?></h3>
			<p style="margin:0 0 16px;color:#4b5563;font-size:14px;line-height:1.55;"><?php echo nl2br( esc_html( $body ) ); ?></p>
			<a href="<?php echo esc_url( $url ); ?>" target="_blank" rel="noopener noreferrer" style="display:inline-block;background:<?php echo esc_attr( $primary ); ?>;color:#ffffff;text-decoration:none;border-radius:999px;padding:11px 16px;font-weight:700;font-size:14px;line-height:1.2;"><?php echo esc_html( $button ); ?></a>
		</div>
		<?php
		return (string) ob_get_clean();
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $title Title.
	 * @param mixed $body Body.
	 * @param mixed $button_label Button label.
	 * @param mixed $url Url.
	 * @param mixed $settings Settings.
	 * @param mixed $is_test Is test.
	 * @param mixed $extra_footer_html Extra footer html.
	 */
	private function build_email_html( $title, $body, $button_label, $url, $settings, $is_test, $extra_footer_html = '' ) {
		$html = Noesia_CS_Template_Loader::get(
			'emails/base-email.php',
			array(
				'title'              => $title,
				'body'               => $body,
				'button_label'       => $button_label,
				'button_url'         => $url,
				'settings'           => $settings,
				'is_preview'         => $is_test,
				'extra_footer_html'  => $extra_footer_html,
			)
		);

		if ( $html ) {
			return $html;
		}

		return '<p>' . esc_html( $title ) . '</p><p>' . nl2br( esc_html( $body ) ) . '</p><p><a href="' . esc_url( $url ) . '">' . esc_html( $button_label ) . '</a></p>';
	}

}
