<?php
/**
 * Template rendering helpers for WP Mail Doctor.
 *
 * @package MailDoctor
 */

use MailDoctor\Email\CacheService;
use MailDoctor\Email\MergeTagRegistry;
use MailDoctor\Email\PreviewDataFactory;
use MailDoctor\Email\TemplateValidator;
use MailDoctor\WPMD_Email_Renderer;
use MailDoctor\WPMD_Email_Templates;
use MailDoctor\WPMD_Email_Tokens;

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

/**
 * Prepare rendered email payload including subject, heading, and HTML.
 *
 * @param string               $email_type Email identifier.
 * @param int                  $order_id   Order ID.
 * @param array<string, mixed> $context    Additional context.
 * @return array<string, mixed>
 */
function mail_doctor_prepare_email_template( string $email_type, int $order_id = 0, array $context = array() ): array {
	$email_type = sanitize_key( $email_type );

	if ( '' === $email_type ) {
		return array();
	}

	$locale = isset( $context['locale'] ) ? (string) $context['locale'] : ( function_exists( 'determine_locale' ) ? determine_locale() : get_locale() );
	$mode   = isset( $context['render_mode'] ) ? sanitize_key( (string) $context['render_mode'] ) : ( isset( $context['mode'] ) ? sanitize_key( (string) $context['mode'] ) : 'html' );

	$template = array();

	if ( isset( $context['template'] ) && is_array( $context['template'] ) ) {
		$template = wp_parse_args(
			$context['template'],
			array(
				'id'      => isset( $context['template']['id'] ) ? (string) $context['template']['id'] : '',
				'subject' => '',
				'heading' => '',
				'html'    => '',
				'css'     => '',
				'source'  => 'custom',
			)
		);
	} elseif ( class_exists( WPMD_Email_Templates::class ) ) {
		$template = WPMD_Email_Templates::get_template_data( $email_type );

		if ( empty( $template ) && isset( $context['defaults'] ) && is_array( $context['defaults'] ) ) {
			$template = wp_parse_args(
				$context['defaults'],
				array(
					'subject' => '',
					'heading' => '',
					'html'    => '',
					'css'     => '',
					'source'  => 'default',
				)
			);
		}
	} elseif ( isset( $context['defaults'] ) && is_array( $context['defaults'] ) ) {
		$template = wp_parse_args(
			$context['defaults'],
			array(
				'subject' => '',
				'heading' => '',
				'html'    => '',
				'css'     => '',
				'source'  => 'default',
			)
		);
	}

	if ( empty( $template ) ) {
		return array();
	}

	if ( empty( $template['id'] ) && isset( $template['post_id'] ) ) {
		$template['id'] = (string) $template['post_id'];
	} elseif ( empty( $template['id'] ) ) {
		$template['id'] = '';
	}

	$has_wc_order = class_exists( 'WC_Order' );
	$has_wc_email = class_exists( 'WC_Email' );

	$order = $context['order'] ?? null;

	if ( ! $has_wc_order ) {
		$order = null;
	} elseif ( ! $order instanceof WC_Order && $order_id > 0 && function_exists( 'wc_get_order' ) ) {
		$order = wc_get_order( $order_id );
	}

	if ( $has_wc_order && $has_wc_email && ! $order instanceof WC_Order && isset( $context['email'] ) && $context['email'] instanceof WC_Email ) {
		$maybe_order = $context['email']->get_order();
		if ( $maybe_order instanceof WC_Order ) {
			$order = $maybe_order;
		}
	}

	$status = isset( $context['status'] ) ? sanitize_key( (string) $context['status'] ) : '';
	if ( '' === $status && $order instanceof WC_Order && method_exists( $order, 'get_status' ) ) {
		$status = (string) $order->get_status();
	}

	$preview_bundle = PreviewDataFactory::make(
		$email_type,
		array(
			'order_id' => $order_id,
			'order'    => $order,
			'status'   => $status,
			'locale'   => $locale,
			'preview'  => ! empty( $context['preview'] ),
		)
	);

	$store        = isset( $context['store'] ) && is_array( $context['store'] ) ? array_merge( $preview_bundle['store'], $context['store'] ) : $preview_bundle['store'];
	$customer     = isset( $context['customer'] ) && is_array( $context['customer'] ) ? array_merge( $preview_bundle['customer'], $context['customer'] ) : $preview_bundle['customer'];
	$sample       = $preview_bundle['sample'];
	$extra_tokens = array();

	if ( isset( $preview_bundle['extra_tokens'] ) && is_array( $preview_bundle['extra_tokens'] ) ) {
		$extra_tokens = $preview_bundle['extra_tokens'];
	}

	if ( isset( $context['extra_tokens'] ) && is_array( $context['extra_tokens'] ) ) {
		$extra_tokens = array_merge( $extra_tokens, $context['extra_tokens'] );
	}

	$token_context                 = $context;
	$token_context['email_type']   = $email_type;
	$token_context['subject']      = $template['subject'] ?? '';
	$token_context['heading']      = $template['heading'] ?? '';
	$token_context['locale']       = $locale;
	$token_context['extra_tokens'] = $extra_tokens;
	$token_context['store']        = $store;
	$token_context['customer']     = $customer;
	$token_context['sample']       = $sample;
	$token_context['render_mode']  = $mode;
	$token_context['template_id']  = $template['id'] ?? ( $context['template_id'] ?? '' );
	$token_context['email_id']     = $email_type;

	$legacy_tokens = class_exists( WPMD_Email_Tokens::class )
		? WPMD_Email_Tokens::get_map(
			( $has_wc_order && $order instanceof WC_Order ) ? $order : null,
			$token_context
		)
		: array();

	$merge_context = array(
		'order'         => ( $has_wc_order && $order instanceof WC_Order ) ? $order : null,
		'customer'      => $customer,
		'store'         => $store,
		'sample'        => $sample,
		'locale'        => $locale,
		'email_id'      => $email_type,
		'email_subject' => $template['subject'] ?? '',
		'email_heading' => $template['heading'] ?? '',
		'legacy_tokens' => $legacy_tokens,
		'extra_tokens'  => $extra_tokens,
	);

	$merge_tokens = MergeTagRegistry::resolve_all(
		$merge_context,
		array(
			'email_type'    => $email_type,
			'order'         => ( $has_wc_order && $order instanceof WC_Order ) ? $order : null,
			'token_context' => $token_context,
		)
	);

	$subject = WPMD_Email_Renderer::replace_tokens( $template['subject'] ?? '', $merge_tokens );
	$heading = WPMD_Email_Renderer::replace_tokens( $template['heading'] ?? '', $merge_tokens );

	$merge_tokens['subject']       = $subject;
	$merge_tokens['heading']       = $heading;
	$merge_tokens['email.subject'] = $subject;
	$merge_tokens['email.heading'] = $heading;

	$token_context['subject'] = $subject;
	$token_context['heading'] = $heading;

	$template_identifier = '';

	if ( ! empty( $template['id'] ) ) {
		$template_identifier = (string) $template['id'];
	} elseif ( isset( $template['source'] ) && 'default' === $template['source'] ) {
		$template_identifier = 'default-' . $email_type;
	} elseif ( isset( $context['template_id'] ) && '' !== (string) $context['template_id'] ) {
		$template_identifier = (string) $context['template_id'];
	}

	$cache_allowed = ( '' !== $template_identifier ) && 'html' === $mode;

	$hash_input = wp_json_encode(
		array(
			'subject'  => $subject,
			'heading'  => $heading,
			'html'     => $template['html'] ?? '',
			'css'      => $template['css'] ?? '',
			'tokens'   => $merge_tokens,
			'locale'   => $locale,
			'email_id' => $email_type,
		)
	);

	$cache_hash = md5( (string) $hash_input );
	$cache_hit  = false;
	$compiled   = null;

	if ( $cache_allowed ) {
		$compiled  = CacheService::get( $template_identifier, $email_type, $locale, $cache_hash );
		$cache_hit = null !== $compiled;
	}

	if ( null === $compiled ) {
		$compiled = WPMD_Email_Renderer::render(
			array(
				'html' => $template['html'] ?? '',
				'css'  => $template['css'] ?? '',
			),
			$merge_tokens
		);

		if ( $cache_allowed && '' !== $compiled ) {
			CacheService::set( $template_identifier, $email_type, $locale, $cache_hash, $compiled );
		}
	}

	$plain_text = wp_specialchars_decode( wp_strip_all_tags( $compiled ) );

	$warnings = TemplateValidator::validate(
		$email_type,
		array(
			'subject' => $template['subject'] ?? '',
			'heading' => $template['heading'] ?? '',
			'html'    => $template['html'] ?? '',
			'css'     => $template['css'] ?? '',
		)
	);

	$result = array(
		'email_type'   => $email_type,
		'order_id'     => ( $has_wc_order && $order instanceof WC_Order ) ? $order->get_id() : $order_id,
		'subject'      => $subject,
		'heading'      => $heading,
		'html'         => 'plain' === $mode ? '' : $compiled,
		'plain_text'   => $plain_text,
		'tokens'       => $merge_tokens,
		'template'     => $template,
		'order'        => ( $has_wc_order && $order instanceof WC_Order ) ? $order : null,
		'context'      => $context,
		'locale'       => $locale,
		'cache_hit'    => $cache_hit,
		'cache_hash'   => $cache_hash,
		'template_key' => $template_identifier,
		'warnings'     => $warnings,
	);

	/**
	 * Filter prepared template payload.
	 *
	 * @param array<string, mixed> $result Prepared data.
	 * @param string               $email_type Email identifier.
	 * @param WC_Order|null        $order Order instance.
	 * @param array<string, mixed> $context Rendering context.
	 */
	return apply_filters( 'mail_doctor_prepared_email_template', $result, $email_type, ( $has_wc_order && $order instanceof WC_Order ) ? $order : null, $context );
}

/**
 * Render email HTML for a given template.
 *
 * @param string               $email_type Email identifier.
 * @param int                  $order_id   Order ID.
 * @param array<string, mixed> $context    Additional context.
 * @return string
 */
function mail_doctor_render_email( string $email_type, int $order_id = 0, array $context = array() ): string {
	$prepared = mail_doctor_prepare_email_template( $email_type, $order_id, $context );

	return (string) ( $prepared['html'] ?? '' );
}
