<?php
/**
 * Customer order emails.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Emails;

use WPDude\Products\Checkout\Payment_Completion_Service;
use WPDude\Products\Logging\Logger;
use WPDude\Products\Orders\Statuses;
use WPDude\Products\Support\Money;

/**
 * Plain-text customer emails via wp_mail (Downloads pattern).
 */
final class Email_Service {

	public const TYPE_RECEIVED = 'order_received';
	public const TYPE_SHIPPED  = 'order_shipped';
	public const TYPE_REFUND   = 'refund_processed';

	/**
	 * Order received (payment completed).
	 *
	 * @param array<string, mixed> $order    Order.
	 * @param string               $view_url Magic link.
	 */
	public function send_order_received( array $order, string $view_url ): bool {
		$subject = __( 'We received your order — {product_name}', 'dude-commerce' );
		$body    = __( 'Hi {customer_name},', 'dude-commerce' ) . "\n\n"
			. __( 'Thanks for your purchase of {product_name}.', 'dude-commerce' ) . "\n\n"
			. __( 'We have received your order and will process it shortly.', 'dude-commerce' ) . "\n\n"
			. __( 'View your order:', 'dude-commerce' ) . "\n"
			. '{order_url}' . "\n\n"
			. __( 'Amount paid: {amount} {currency}', 'dude-commerce' ) . "\n"
			. __( 'Order ID: {order_id}', 'dude-commerce' ) . "\n\n"
			. __( 'Thanks,', 'dude-commerce' ) . "\n"
			. '{site_name}';

		return $this->send_customer_email( self::TYPE_RECEIVED, $order, $view_url, $subject, $body );
	}

	/**
	 * Order shipped.
	 *
	 * @param array<string, mixed> $order    Order.
	 * @param string               $view_url Magic link.
	 */
	public function send_order_shipped( array $order, string $view_url ): bool {
		$subject = __( 'Your order has shipped — {product_name}', 'dude-commerce' );
		$body    = __( 'Hi {customer_name},', 'dude-commerce' ) . "\n\n"
			. __( 'Good news — your order of {product_name} has shipped.', 'dude-commerce' ) . "\n\n"
			. __( 'View your order:', 'dude-commerce' ) . "\n"
			. '{order_url}' . "\n\n"
			. __( 'Order ID: {order_id}', 'dude-commerce' ) . "\n\n"
			. __( 'Thanks,', 'dude-commerce' ) . "\n"
			. '{site_name}';

		return $this->send_customer_email( self::TYPE_SHIPPED, $order, $view_url, $subject, $body );
	}

	/**
	 * Refund processed.
	 *
	 * @param array<string, mixed> $order    Order.
	 * @param string               $view_url Magic link.
	 */
	public function send_refund_processed( array $order, string $view_url ): bool {
		$subject = __( 'Your refund has been processed — {product_name}', 'dude-commerce' );
		$body    = __( 'Hi {customer_name},', 'dude-commerce' ) . "\n\n"
			. __( 'Your refund for {product_name} has been processed.', 'dude-commerce' ) . "\n\n"
			. __( 'Amount: {amount} {currency}', 'dude-commerce' ) . "\n"
			. __( 'Order ID: {order_id}', 'dude-commerce' ) . "\n\n"
			. __( 'View your order:', 'dude-commerce' ) . "\n"
			. '{order_url}' . "\n\n"
			. __( 'Thanks,', 'dude-commerce' ) . "\n"
			. '{site_name}';

		return $this->send_customer_email( self::TYPE_REFUND, $order, $view_url, $subject, $body );
	}

	/**
	 * Send a plain-text email via wp_mail.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	public function send_plain( string $to, string $subject, string $body, array $order ): bool {
		return $this->send( $to, $subject, $body, $order );
	}

	/**
	 * @param array<string, mixed> $order    Order.
	 * @param string               $view_url Magic link.
	 * @param string               $subject  Subject template.
	 * @param string               $body     Body template.
	 */
	private function send_customer_email( string $type, array $order, string $view_url, string $subject, string $body ): bool {
		$email = (string) ( $order['customer_email'] ?? '' );
		if ( ! is_email( $email ) ) {
			Logger::instance()->warning(
				'Customer email skipped: missing customer email',
				array(
					'type'       => $type,
					'order_uuid' => $order['uuid'] ?? '',
				)
			);
			return false;
		}

		$placeholders = $this->placeholders( $order, $view_url );

		/**
		 * Filter customer email subject.
		 *
		 * @param string               $subject Subject.
		 * @param array<string, mixed> $order   Order.
		 * @param string               $type    Email type.
		 */
		$subject = (string) apply_filters( 'wpdude_dc_customer_email_subject', $subject, $order, $type );

		/**
		 * Filter customer email body.
		 *
		 * @param string               $body  Body.
		 * @param array<string, mixed> $order Order.
		 * @param string               $type  Email type.
		 */
		$body = (string) apply_filters( 'wpdude_dc_customer_email_body', $body, $order, $type );

		$subject = $this->replace( $subject, $placeholders );
		$body    = $this->replace( $body, $placeholders );

		return $this->send( $email, $subject, $body, $order );
	}

	/**
	 * Placeholder tokens shown in Pro email settings (token => short label).
	 *
	 * @return array<string, string>
	 */
	public static function placeholder_labels(): array {
		return array(
			'{customer_name}'       => __( 'Customer name', 'dude-commerce' ),
			'{customer_email}'      => __( 'Customer email', 'dude-commerce' ),
			'{product_name}'        => __( 'Product title', 'dude-commerce' ),
			'{product_description}' => __( 'Product description (plain text)', 'dude-commerce' ),
			'{product_url}'         => __( 'Product page URL', 'dude-commerce' ),
			'{options}'             => __( 'Selected options (e.g. Size: M)', 'dude-commerce' ),
			'{quantity}'            => __( 'Quantity ordered', 'dude-commerce' ),
			'{amount}'              => __( 'Formatted amount paid', 'dude-commerce' ),
			'{currency}'            => __( 'Currency code (e.g. GBP)', 'dude-commerce' ),
			'{order_id}'            => __( 'Order ID', 'dude-commerce' ),
			'{order_status}'        => __( 'Order status label', 'dude-commerce' ),
			'{order_url}'           => __( 'Customer order view link (magic link)', 'dude-commerce' ),
			'{shipping_address}'    => __( 'Shipping address (multi-line)', 'dude-commerce' ),
			'{site_name}'           => __( 'Site name', 'dude-commerce' ),
			'{site_url}'            => __( 'Site home URL', 'dude-commerce' ),
		);
	}

	/**
	 * @param array<string, mixed> $order    Order.
	 * @return array<string, string>
	 */
	private function placeholders( array $order, string $view_url ): array {
		$payload      = Payment_Completion_Service::public_success_payload( $order );
		$product_id   = (int) ( $payload['product_id'] ?? $order['product_id'] ?? 0 );
		$product_name = (string) ( $payload['product_name'] ?? __( 'Product', 'dude-commerce' ) );
		$currency     = strtoupper( (string) ( $order['currency'] ?? 'usd' ) );
		$amount       = Money::format( (int) ( $order['amount'] ?? 0 ), (string) ( $order['currency'] ?? 'usd' ) );
		$status       = Statuses::label( (string) ( $order['status'] ?? '' ) );
		$quantity     = max( 1, (int) ( $payload['qty'] ?? $order['qty'] ?? 1 ) );
		$options      = (string) ( $payload['options_label'] ?? '' );
		$product_url  = $product_id > 0 ? (string) get_permalink( $product_id ) : '';
		if ( ! is_string( $product_url ) ) {
			$product_url = '';
		}

		return array(
			'{customer_name}'       => (string) ( $order['customer_name'] ?: __( 'there', 'dude-commerce' ) ),
			'{customer_email}'      => (string) ( $order['customer_email'] ?? '' ),
			'{product_name}'        => $product_name,
			'{product_description}' => self::product_description( $product_id ),
			'{product_url}'         => $product_url,
			'{options}'             => $options,
			'{quantity}'            => (string) $quantity,
			'{amount}'              => $amount,
			'{currency}'            => $currency,
			'{order_id}'            => (string) ( $order['uuid'] ?? '' ),
			'{order_status}'        => $status,
			'{order_url}'           => $view_url,
			'{shipping_address}'    => self::format_shipping_address( $order ),
			'{site_name}'           => wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ),
			'{site_url}'            => home_url( '/' ),
		);
	}

	/**
	 * Plain-text product description for email templates.
	 */
	private static function product_description( int $product_id ): string {
		if ( $product_id <= 0 ) {
			return '';
		}

		$excerpt = trim( (string) get_post_field( 'post_excerpt', $product_id ) );
		if ( '' !== $excerpt ) {
			return trim( wp_strip_all_tags( $excerpt ) );
		}

		$content = (string) get_post_field( 'post_content', $product_id );
		$content = strip_shortcodes( $content );
		$content = wp_strip_all_tags( $content );
		$content = preg_replace( '/\s+/u', ' ', $content );
		return is_string( $content ) ? trim( $content ) : '';
	}

	/**
	 * Multi-line shipping address from the order payload.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	private static function format_shipping_address( array $order ): string {
		$shipping = is_array( $order['shipping_address'] ?? null ) ? $order['shipping_address'] : array();
		$lines    = array();

		$name = trim( (string) ( $shipping['name'] ?? $order['customer_name'] ?? '' ) );
		if ( '' !== $name ) {
			$lines[] = $name;
		}

		$address = is_array( $shipping['address'] ?? null ) ? $shipping['address'] : $shipping;
		foreach ( array( 'line1', 'line2', 'city', 'state', 'postal_code', 'country' ) as $key ) {
			$val = trim( (string) ( $address[ $key ] ?? '' ) );
			if ( '' !== $val ) {
				$lines[] = $val;
			}
		}

		return implode( "\n", $lines );
	}

	/**
	 * @param array<string, string> $placeholders Placeholders.
	 */
	private function replace( string $text, array $placeholders ): string {
		return str_replace( array_keys( $placeholders ), array_values( $placeholders ), $text );
	}

	/**
	 * @param array<string, mixed> $order Order.
	 */
	private function send( string $to, string $subject, string $body, array $order ): bool {
		$headers = array( 'Content-Type: text/plain; charset=UTF-8' );
		$sent    = wp_mail( $to, $subject, $body, $headers );
		if ( ! $sent ) {
			Logger::instance()->error(
				'Email delivery failure',
				array( 'order_uuid' => $order['uuid'] ?? '' )
			);
		}
		return (bool) $sent;
	}
}
