<?php
/**
 * Email template loader and merge-tag processor.
 *
 * @package Donatico\Emails
 */

declare(strict_types=1);

namespace Donatico\Emails;

use Donatico\Helpers\Currency;
use Donatico\Models\Donation;

/**
 * Loads PHP email templates via output-buffering, makes the Donation object
 * available inside the template, then replaces {merge_tags} in the rendered
 * HTML before returning the final string.
 *
 * Usage pattern:
 *   $renderer = new TemplateRenderer();
 *   $renderer->setDonation($donation);   // resets tags + sets donation tags
 *   $renderer->setSiteTags();            // append site tags
 *   $renderer->setAdminTags();            // append admin-only tags (optional)
 *   $html = $renderer->render($templatePath, ['donation' => $donation]);
 */
class TemplateRenderer {

	/** @var array<string, string> Current tag map (search => replace). */
	private array $tags = array();

	// -------------------------------------------------------------------------
	// Tag setters
	// -------------------------------------------------------------------------

	/**
	 * Reset tags and set all donation-specific merge tags.
	 * Always call this first — it clears any tags from a prior call.
	 *
	 * @param Donation $donation
	 * @return void
	 */
	public function setDonation( Donation $donation ): void {
		$currency        = $donation->getCurrency() ?: (string) \get_option( 'donatico_currency', 'USD' );
		$currency_symbol = Currency::getSymbol( $currency );
		$formatted       = $donation->getFormattedAmount();
		$date_ts         = \strtotime( $donation->getCreatedAt() );

		$this->tags = array(
			'{donor_name}'     => $donation->isAnonymous()
				? \__( 'Anonymous', 'donatico' )
				: $donation->getDonorName(),
			'{donor_email}'    => $donation->getDonorEmail(),
			'{amount}'         => $currency_symbol . $formatted . ' ' . $currency,
			'{amount_raw}'     => $formatted,
			'{currency}'       => $currency,
			'{currency_symbol}' => $currency_symbol,
			'{message}'        => $donation->getMessage() ?? '',
			'{date}'           => (string) \wp_date( (string) \get_option( 'date_format', 'F j, Y' ), $date_ts ),
			'{date_time}'      => (string) \wp_date(
				(string) \get_option( 'date_format', 'F j, Y' ) . ' ' . \get_option( 'time_format', 'g:i a' ),
				$date_ts
			),
			'{donation_id}'    => (string) $donation->getId(),
			'{transaction_id}' => $donation->getStripeSessionId() ?? '',
			'{is_anonymous}'   => $donation->isAnonymous() ? \__( 'Yes', 'donatico' ) : \__( 'No', 'donatico' ),
		);
	}

	/**
	 * Append site-wide merge tags.
	 *
	 * @return void
	 */
	public function setSiteTags(): void {
		$this->tags = \array_merge(
			$this->tags,
			array(
				'{site_name}'    => \get_bloginfo( 'name' ),
				'{site_url}'     => \home_url( '/' ),
				'{site_tagline}' => \get_bloginfo( 'description' ),
				'{admin_email}'  => (string) \get_option( 'admin_email', '' ),
			)
		);
	}

	/**
	 * Append admin-only merge tags (links into the WP dashboard).
	 *
	 * @return void
	 */
	public function setAdminTags(): void {
		$this->tags = \array_merge(
			$this->tags,
			array(
				'{view_admin_url}'     => \admin_url( 'admin.php?page=donatico-donations' ),
				'{donatico_admin_url}' => \admin_url( 'admin.php?page=donatico' ),
			)
		);
	}

	// -------------------------------------------------------------------------
	// Rendering
	// -------------------------------------------------------------------------

	/**
	 * Include a PHP template, capture its output, replace merge tags, return HTML.
	 *
	 * Templates receive:
	 *   $donation (Donation)  — the donation object
	 *   $renderer (self)      — this renderer (for advanced use)
	 *   + any keys in $vars   — extracted into the template scope
	 *
	 * @param string               $template_path Absolute path to the .php template.
	 * @param array<string, mixed> $vars          Extra variables to make available.
	 * @return string Final HTML with all merge tags replaced.
	 */
	public function render( string $template_path, array $vars = array() ): string {
		if ( ! \file_exists( $template_path ) ) {
			if ( \defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
				\error_log( '[Donatico Email] Template not found: ' . $template_path );
			}
			return '';
		}

		// phpcs:ignore WordPress.PHP.DontExtract.extract_extract
		\extract( $vars ); // makes $donation etc. available in the template
		$renderer = $this;

		\ob_start();
		include $template_path;
		$html = (string) \ob_get_clean();

		return $this->replaceTags( $html );
	}

	/**
	 * Replace merge tags in an arbitrary string (e.g. a settings-defined subject).
	 *
	 * @param string $text
	 * @return string
	 */
	public function replaceTags( string $text ): string {
		return \str_replace(
			\array_keys( $this->tags ),
			\array_values( $this->tags ),
			$text
		);
	}

	/**
	 * Return the complete tag map (for use in help text / previews).
	 *
	 * @return array<string, string>
	 */
	public function getTags(): array {
		return $this->tags;
	}
}
