<?php
namespace Pay4All\Pro\Services;

use Pay4All\Form\Admin\Settings\Schema;
use Pay4All\Pro\Frontend\AbandonedCarts;

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

/**
 * Mail wrapper for Pay4All PRO features. Currently only carries the
 * abandoned-cart recovery mail; kept as its own service class so the
 * upcoming ticket / license-renewal reminder mails have somewhere to
 * grow without touching Frontend/Admin code.
 *
 * The class is intentionally self-contained: it does NOT depend on the
 * free plugin's Services\Mailer (which lost its send_abandoned_cart_recovery
 * method in pay4all-form 2.0.0). Templates are stored inline with the four
 * activated languages so a vanilla Pro install works without any Réglages
 * › E-mails configuration in the free plugin.
 */
final class Mailer {

	public static function send_abandoned_cart_recovery( array $cart ) : bool {
		$to = (string) ( $cart['email'] ?? '' );
		if ( ! is_email( $to ) ) { return false; }

		$lang = self::pick_language( (string) ( $cart['lang'] ?? '' ) );
		$tpl  = self::abandoned_cart_defaults();
		$row  = $tpl[ $lang ] ?? $tpl['fr'];

		// Overrides du commerçant (Réglages › Abandon panier). Le stockage
		// suit le pattern de l'onglet E-mails : un tableau imbriqué
		// [ $lang => [ subject, body, cta ] ]. Un champ vide fait tomber le
		// rendu sur la valeur par défaut de la langue voulue (le placeholder
		// affiché à l'écran = la valeur qui sera envoyée). Le champ « body »
		// correspond à l'ancien « intro » du template hardcodé — la carte de
		// correspondance est faite ici pour ne pas déplacer heading/outro.
		$saved = (array) Schema::get( 'abandoned_cart_email', [] );
		$over  = (array) ( $saved[ $lang ] ?? [] );
		if ( ! empty( $over['subject'] ) ) { $row['subject'] = (string) $over['subject']; }
		if ( ! empty( $over['body'] ) )    { $row['intro']   = (string) $over['body']; }
		if ( ! empty( $over['cta'] ) )     { $row['cta']     = (string) $over['cta']; }

		$customer = json_decode( (string) ( $cart['customer_data'] ?? '[]' ), true ) ?: [];

		// Recovery URL: adds ?p4all_recover={token} to home_url('/'). The Pro
		// init handler picks it up, stashes the payload in a transient, then
		// redirects to the form page with ?p4all_recovered={transient_key}
		// which the shortcode reads via a filter and pre-fills the fields.
		$recover_url = add_query_arg(
			AbandonedCarts::RECOVER_QUERY,
			(string) ( $cart['token'] ?? '' ),
			home_url( '/' )
		);

		$placeholders = [
			'{site_name}'          => (string) get_bloginfo( 'name' ),
			'{customer_firstname}' => (string) ( $customer['firstname'] ?? $customer['first_name'] ?? '' ),
			'{customer_lastname}'  => (string) ( $customer['lastname']  ?? $customer['last_name']  ?? '' ),
			'{customer_email}'     => $to,
			'{recover_url}'        => $recover_url,
			'{merchant_name}'      => (string) Schema::get( 'merchant_name', '' ),
		];

		$subject = strtr( $row['subject'], $placeholders );
		$heading = strtr( $row['heading'], $placeholders );
		$intro   = strtr( $row['intro'],   $placeholders );
		$outro   = strtr( $row['outro'],   $placeholders );
		$cta     = $row['cta'];

		$button_html = '<p style="text-align:center;margin:24px 0;"><a href="' . esc_url( $recover_url ) . '" '
		             . 'style="display:inline-block;background:#7c3aed;color:#fff;padding:12px 28px;border-radius:6px;'
		             . 'text-decoration:none;font-weight:600;">' . esc_html( $cta ) . '</a></p>';

		$html  = '<div style="font-family:sans-serif;max-width:560px;margin:0 auto;color:#0f172a;">';
		$html .= '<h2 style="font-size:1.4em;">' . esc_html( $heading ) . '</h2>';
		$html .= '<p style="white-space:pre-wrap;">' . nl2br( esc_html( $intro ) ) . '</p>';
		$html .= $button_html;
		if ( $outro !== '' ) {
			$html .= '<p style="white-space:pre-wrap;color:#475569;font-size:.95em;">' . nl2br( esc_html( $outro ) ) . '</p>';
		}
		$html .= '<p style="color:#94a3b8;font-size:.8em;margin-top:32px;">'
		       . esc_html( self::footer_note( $lang ) )
		       . '</p>';
		$html .= '</div>';

		$text = $heading . "\n\n" . $intro . "\n\n" . $cta . ' : ' . $recover_url . "\n\n" . $outro;

		return self::send( $to, $subject, $html, $text );
	}

	/**
	 * Resolves the language for the email:
	 *   1. the cart's captured `lang` if it's one of the activated ones,
	 *   2. otherwise the merchant's primary activated language,
	 *   3. otherwise French (built-in fallback).
	 */
	private static function pick_language( string $captured ) : string {
		if ( class_exists( '\\Pay4All\\Form\\Admin\\Settings\\Schema' )
			&& in_array( $captured, Schema::SUPPORTED_LANGUAGES, true )
		) {
			return $captured;
		}
		$langs = class_exists( '\\Pay4All\\Form\\Admin\\Settings\\Schema' )
			? (array) Schema::get( 'languages', [] )
			: [];
		$langs = array_values( array_intersect( $langs, [ 'fr', 'de', 'it', 'en' ] ) );
		return $langs[0] ?? 'fr';
	}

	/**
	 * Built-in template strings for the four activated Pay4All languages.
	 * Kept literal (rather than wrapped in __()) so the merchant sees the
	 * expected French text on a stock install without waiting for the
	 * `pay4all-pro-{locale}.mo` bundle to be picked up.
	 *
	 * @return array<string, array{subject:string,heading:string,intro:string,outro:string,cta:string}>
	 */
	private static function abandoned_cart_defaults() : array {
		return [
			'fr' => [
				'subject' => '[{site_name}] Vous avez oublié quelque chose ?',
				'heading' => 'Votre panier vous attend',
				'intro'   => "Bonjour {customer_firstname},\nVous avez commencé une commande sur {site_name} il y a quelques jours sans la finaliser.\nVotre panier est encore là :",
				'outro'   => 'Cliquez sur le bouton ci-dessous pour le retrouver et terminer votre commande.',
				'cta'     => 'Retrouver mon panier',
			],
			'de' => [
				'subject' => '[{site_name}] Haben Sie etwas vergessen ?',
				'heading' => 'Ihr Warenkorb wartet auf Sie',
				'intro'   => "Guten Tag {customer_firstname},\nSie haben vor einigen Tagen eine Bestellung auf {site_name} begonnen, aber nicht abgeschlossen.\nIhr Warenkorb ist noch da :",
				'outro'   => 'Klicken Sie auf die Schaltfläche, um ihn wiederzufinden und Ihre Bestellung abzuschliessen.',
				'cta'     => 'Meinen Warenkorb wiederfinden',
			],
			'it' => [
				'subject' => '[{site_name}] Hai dimenticato qualcosa ?',
				'heading' => 'Il tuo carrello ti aspetta',
				'intro'   => "Buongiorno {customer_firstname},\nHai iniziato un ordine su {site_name} qualche giorno fa senza completarlo.\nIl tuo carrello è ancora qui :",
				'outro'   => 'Clicca sul pulsante qui sotto per ritrovarlo e finalizzare il tuo ordine.',
				'cta'     => 'Ritrova il mio carrello',
			],
			'en' => [
				'subject' => '[{site_name}] Did you forget something ?',
				'heading' => 'Your cart is waiting for you',
				'intro'   => "Hello {customer_firstname},\nYou started an order on {site_name} a few days ago but didn't complete it.\nYour cart is still here:",
				'outro'   => 'Click the button below to recover it and finish your order.',
				'cta'     => 'Recover my cart',
			],
		];
	}

	private static function footer_note( string $lang ) : string {
		switch ( $lang ) {
			case 'de': return 'Wenn Sie Ihre Bestellung bereits abgeschlossen haben, können Sie diese Nachricht ignorieren.';
			case 'it': return 'Se hai già completato il tuo ordine, puoi ignorare questo messaggio.';
			case 'en': return 'If you have already completed your order, you can ignore this message.';
			case 'fr':
			default:   return 'Si vous avez déjà finalisé votre commande, vous pouvez ignorer ce message.';
		}
	}

	/**
	 * Direct wp_mail wrapper mirroring the free plugin's private
	 * Mailer::send() so the From: header and multipart alt body match the
	 * order-notification e-mails the merchant already receives.
	 */
	private static function send( string $to, string $subject, string $html, string $text ) : bool {
		$from_email = (string) Schema::get( 'notify_email', get_option( 'admin_email' ) );
		$from_name  = (string) Schema::get( 'merchant_name', get_bloginfo( 'name' ) );
		$headers = [
			'Content-Type: text/html; charset=UTF-8',
			'From: ' . sprintf( '%s <%s>', $from_name, $from_email ),
		];
		// PHPMailer alt body — falls back to the plain-text version for
		// clients that refuse text/html or run in accessible-only modes.
		add_action( 'phpmailer_init', static function ( $mailer ) use ( $text ) {
			$mailer->AltBody = $text;
		} );
		return (bool) wp_mail( $to, $subject, $html, $headers );
	}
}
