<?php
/**
 * High-level mailer used by every SuiteMkt3k module.
 *
 * - Adds the X-SuiteMkt3k header so SMTP override can detect our emails.
 * - Renders HTML using email-safe templates (table-based + inline styles).
 * - Injects the open tracking pixel.
 * - Rewrites links through the click redirector.
 * - Records send events for statistics.
 *
 * @package SuiteMkt3k
 */

namespace SuiteMkt3k\Email;

use SuiteMkt3k\Installer;
use SuiteMkt3k\Modules\Settings\Settings_Manager;
use SuiteMkt3k\Modules\Statistics\Stats_Collector;
use SuiteMkt3k\Utils\Logger;

defined( 'ABSPATH' ) || exit;

class Mailer {

	public const HEADER_TAG = 'X-SuiteMkt3k';

	public static function register(): void {
		if ( class_exists( Email_Assets::class ) ) {
			Email_Assets::register();
		}
	}

	/**
	 * Send a transactional / marketing email.
	 *
	 * @param array $args { to, subject, html, text?, tracking_hash?, headers?, attachments?, context? }
	 * @return bool
	 */
	public function send( array $args ): bool {
		$to      = isset( $args['to'] ) ? (string) $args['to'] : '';
		$subject = isset( $args['subject'] ) ? (string) $args['subject'] : '';
		$html    = isset( $args['html'] ) ? (string) $args['html'] : '';
		$context = isset( $args['context'] ) ? (string) $args['context'] : 'generic';
		$hash    = isset( $args['tracking_hash'] ) ? (string) $args['tracking_hash'] : '';

		if ( '' === $to || '' === $subject || '' === $html ) {
			return false;
		}

		// HARD GUARD: refuse to send anything until the plugin's own SMTP is
		// configured. This prevents the host's `wp_mail()` fallback (or any
		// other SMTP plugin) from being used for our marketing emails.
		if ( ! self::is_smtp_configured() ) {
			Logger::warn(
				'mailer',
				'Blocked email — plugin SMTP is not configured.',
				array( 'context' => $context, 'to_hash' => hash( 'sha256', strtolower( $to ) ) )
			);
			return false;
		}

		$html = Email_Assets::prepare( $html );
		$html = $this->maybe_inject_pixel( $html, $hash );
		$html = $this->maybe_rewrite_links( $html, $hash );

		$company   = (array) Settings_Manager::get( 'company', '', array() );
		$smtp      = (array) Settings_Manager::get( 'smtp', '', array() );
		$from_name = ! empty( $smtp['from_name'] ) ? $smtp['from_name'] : ( $company['name'] ?? get_bloginfo( 'name' ) );
		$from_email = ! empty( $smtp['from_email'] ) ? $smtp['from_email'] : ( $company['email'] ?? get_option( 'admin_email' ) );
		$reply_to   = $company['reply_to'] ?? $from_email;

		$headers   = array(
			'Content-Type: text/html; charset=UTF-8',
			sprintf( 'From: %s <%s>', $this->encode_name( (string) $from_name ), $from_email ),
			sprintf( 'Reply-To: %s', $reply_to ),
			'X-Mailer: SuiteMkt3k',
			self::HEADER_TAG . ': ' . $context,
		);
		if ( ! empty( $args['unsubscribe_url'] ) ) {
			$headers[] = 'List-Unsubscribe: <' . $args['unsubscribe_url'] . '>';
		}
		if ( ! empty( $args['headers'] ) && is_array( $args['headers'] ) ) {
			$headers = array_merge( $headers, $args['headers'] );
		}

		$attachments = isset( $args['attachments'] ) && is_array( $args['attachments'] ) ? $args['attachments'] : array();

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

		if ( $sent ) {
			$meta = array(
				'to_hash' => hash( 'sha256', strtolower( $to ) ),
				'context' => $context,
			);
			if ( '' !== $hash ) {
				$meta['tracking_hash'] = $hash;
			}
			Stats_Collector::record(
				array(
					'event_type'  => 'sent',
					'entity_type' => self::canonical_entity_type( $context ),
					'entity_id'   => isset( $args['entity_id'] ) ? (int) $args['entity_id'] : 0,
					'meta'        => $meta,
				)
			);
		} else {
			Logger::error( 'mailer', 'wp_mail failed', array( 'context' => $context, 'to_hash' => hash( 'sha256', strtolower( $to ) ) ) );
		}

		return (bool) $sent;
	}

	/**
	 * Plugin emails require a fully configured SMTP server to be dispatched.
	 * Everything else (host's wp_mail, other SMTP plugins) is intentionally
	 * blocked so the site owner has explicit control over what is sent.
	 */
	public static function is_smtp_configured(): bool {
		$smtp = (array) Settings_Manager::get( 'smtp', '', array() );
		if ( empty( $smtp['enabled'] ) ) {
			return false;
		}
		if ( empty( $smtp['host'] ) || empty( $smtp['from_email'] ) ) {
			return false;
		}
		return true;
	}

	/**
	 * Map every send-context to a canonical entity_type used by statistics
	 * (`coupon`, `newsletter`, `cart`, `test` or `misc`).
	 */
	private static function canonical_entity_type( string $context ): string {
		if ( 0 === strpos( $context, 'coupon' ) ) {
			return 'coupon';
		}
		if ( 0 === strpos( $context, 'newsletter' ) ) {
			return 'newsletter';
		}
		if ( 0 === strpos( $context, 'cart' ) ) {
			return 'cart';
		}
		if ( 'test' === $context ) {
			return 'test';
		}
		return 'misc';
	}

	public function send_test( string $to ): bool {
		$company = (array) Settings_Manager::get( 'company', '', array() );
		$brand   = $company['name'] ?: get_bloginfo( 'name' );
		$html    = Email_Renderer::render(
			'test',
			array(
				'brand'    => $brand,
				'heading'  => __( 'SuiteMkt3k SMTP test', 'suitemkt3k' ),
				'preheader'=> __( 'If you can read this, SMTP is working.', 'suitemkt3k' ),
				'body'     => __( 'This is a test message sent from your SuiteMkt3k plugin settings. If it arrived in your inbox, your SMTP configuration is correct and ready to deliver coupons, newsletters and cart-recovery emails.', 'suitemkt3k' ),
				'cta_label'=> __( 'Open dashboard', 'suitemkt3k' ),
				'cta_url'  => admin_url( 'admin.php?page=suitemkt3k' ),
			)
		);
		return $this->send(
			array(
				'to'      => $to,
				'subject' => sprintf( '[%s] %s', $brand, __( 'SMTP test', 'suitemkt3k' ) ),
				'html'    => $html,
				'context' => 'test',
			)
		);
	}

	private function maybe_inject_pixel( string $html, string $hash ): string {
		if ( '' === $hash ) {
			return $html;
		}
		$enabled = (bool) Settings_Manager::get( 'advanced', 'enable_pixel', true );
		if ( ! $enabled ) {
			return $html;
		}
		$url   = rest_url( SUITEMKT3K_REST_NAMESPACE . '/track/open/' . rawurlencode( $hash ) );
		$pixel = '<img src="' . esc_url( $url ) . '" alt="" width="1" height="1" style="display:block;border:0;outline:none;text-decoration:none;height:1px;width:1px;" />';
		if ( false !== stripos( $html, '</body>' ) ) {
			return preg_replace( '/<\/body>/i', $pixel . '</body>', $html, 1 );
		}
		return $html . $pixel;
	}

	private function maybe_rewrite_links( string $html, string $hash ): string {
		if ( '' === $hash ) {
			return $html;
		}
		$enabled = (bool) Settings_Manager::get( 'advanced', 'enable_clicks', true );
		if ( ! $enabled ) {
			return $html;
		}
		return preg_replace_callback(
			'/<a\s+([^>]*?)href=(["\'])([^"\']+)\2([^>]*)>/i',
			static function ( $matches ) use ( $hash ) {
				$url = $matches[3];
				if ( 0 === stripos( $url, 'mailto:' ) || 0 === stripos( $url, 'tel:' ) ) {
					return $matches[0];
				}
				if ( false !== strpos( $url, '/track/' ) ) {
					return $matches[0];
				}
				$redirect = rest_url( SUITEMKT3K_REST_NAMESPACE . '/track/click/' . rawurlencode( $hash ) );
				$redirect = add_query_arg( 'u', rawurlencode( $url ), $redirect );
				return '<a ' . $matches[1] . 'href="' . esc_attr( $redirect ) . '"' . $matches[4] . '>';
			},
			$html
		);
	}

	private function encode_name( string $name ): string {
		if ( preg_match( '/[\x80-\xff]/', $name ) ) {
			return '=?UTF-8?B?' . base64_encode( $name ) . '?=';
		}
		return $name;
	}
}
