<?php
/**
 * @package Hafenstudios\Kurato
 */

namespace Hafenstudios\Kurato\Campaign;

use Hafenstudios\Core\Core;
use Hafenstudios\Core\Mail\Message;
use Hafenstudios\Kurato\Db\ContactRepository;
use Hafenstudios\Kurato\Db\MailEventRepository;
use Hafenstudios\Kurato\Mail\DriverFactory;
use Hafenstudios\Kurato\Mail\EmailRenderer;
use Hafenstudios\Kurato\Mail\LinkToken;
use Hafenstudios\Kurato\Preferences\PreferenceCenter;

defined( 'ABSPATH' ) || exit;

/**
 * Willkommensmail-Automatik (K4-Konzept Abschnitt 10 Punkt 5, K4e-2).
 *
 * Bewusst EINE Mail bei Abo-Bestaetigung, ohne Sequenz-Unterbau: ein einfacher
 * Hook auf das Flotten-Event `subscription_confirmed`. Sie geht als Einzelmail
 * DIREKT ueber den aktuellen Treiber (DriverFactory), nicht durch die
 * Marketing-Queue. Sie wird bewusst NICHT gemessen (kein Tracking-Pixel, keine
 * Link-Umschreibung) - die einfachste ehrliche Linie fuer die eine Free-Mail.
 *
 * Idempotenz je Kontakt+Liste ueber ein `welcome`-Ereignis (Typ in
 * {@see MailEventRepository::TYPES}): kommt das Event mehrfach (Replay, weitere
 * Quellen), wird nur einmal gesendet. Die Wiederanmeldung im Preference Center
 * feuert bewusst KEIN `subscription_confirmed` (K4d-2), loest also keine zweite
 * Willkommensmail aus.
 *
 * Nicht final; `config()` und `send()` sind Test-Seams (Muster PreferenceCenter),
 * damit die Logik ohne echtes Core/wpdb/Treiber pruefbar bleibt.
 */
class WelcomeMailService {

	private ContactRepository $contacts;

	private MailEventRepository $events;

	private EmailRenderer $renderer;

	private LinkToken $tokens;

	/**
	 * @param ContactRepository   $contacts Kontakt-Repository.
	 * @param MailEventRepository $events   Ereignis-Log (Idempotenz + Nachweis).
	 * @param EmailRenderer       $renderer HTML-Renderer.
	 * @param LinkToken           $tokens   Signierer fuer Abmelde-/Preference-Links.
	 */
	public function __construct( ContactRepository $contacts, MailEventRepository $events, EmailRenderer $renderer, LinkToken $tokens ) {
		$this->contacts = $contacts;
		$this->events   = $events;
		$this->renderer = $renderer;
		$this->tokens   = $tokens;
	}

	/**
	 * Verdrahtet den Event-Listener.
	 *
	 * @return void
	 */
	public function register(): void {
		\Hafenstudios\Core\Events\EventBus::on( 'subscription_confirmed', array( $this, 'on_subscription_confirmed' ), 10, 1 );
	}

	/**
	 * Sendet - falls aktiviert und noch nicht geschehen - die Willkommensmail.
	 *
	 * @param mixed $payload subscription_confirmed-Payload (contact_id, list_id, ...).
	 * @return void
	 */
	public function on_subscription_confirmed( $payload ): void {
		if ( ! is_array( $payload ) ) {
			return;
		}
		$contact_id = (int) ( $payload['contact_id'] ?? 0 );
		$list_id    = (int) ( $payload['list_id'] ?? 0 );
		if ( $contact_id <= 0 ) {
			return;
		}

		$config = $this->config();
		if ( empty( $config['enabled'] ) ) {
			return;
		}
		$post_id = (int) ( $config['post_id'] ?? 0 );
		if ( $post_id <= 0 ) {
			return;
		}

		// Inhalt der gewaehlten Mail. Fehlt der Post (kein Titel, kein Inhalt),
		// wird nichts gesendet (defensiver "fehlender Post"-Fall).
		$subject    = trim( (string) get_the_title( $post_id ) );
		$inner_html = do_blocks( (string) get_post_field( 'post_content', $post_id ) );
		if ( '' === $subject && '' === trim( $inner_html ) ) {
			return;
		}
		if ( '' === $subject ) {
			$subject = __( 'Willkommen', 'kurato' );
		}

		// Idempotenz je Kontakt+Liste (welcome-Ereignis, campaign_id 0 -> NULL).
		if ( $this->events->exists_for( 0, $contact_id, 'welcome', 'list:' . $list_id ) ) {
			return;
		}

		$contact = $this->contacts->get( $contact_id );
		if ( null === $contact ) {
			return;
		}
		$to_email = sanitize_email( (string) ( $contact['email'] ?? '' ) );
		if ( '' === $to_email || 'active' !== (string) ( $contact['email_status'] ?? 'active' ) ) {
			return;
		}

		$message = $this->build_message( $contact_id, $to_email, $subject, $inner_html, $config );
		if ( ! $this->send( $message ) ) {
			return;
		}

		// Nachweis fuer die Idempotenz (und als Ereignis im Log).
		$this->events->record( 0, $contact_id, 'welcome', array( 'detail' => 'list:' . $list_id ) );
	}

	/**
	 * Baut die personalisierte Willkommensmail (mit Pflicht-Footer via Renderer,
	 * ohne Tracking-Pixel/Umschreibung).
	 *
	 * @param int                  $contact_id Kontakt.
	 * @param string               $to_email   Zieladresse.
	 * @param string               $subject    Betreff.
	 * @param string               $inner_html Gerenderter Inhalt.
	 * @param array<string, mixed> $config     Absender-/Einstellungswerte.
	 * @return Message
	 */
	private function build_message( int $contact_id, string $to_email, string $subject, string $inner_html, array $config ): Message {
		$unsubscribe_url = add_query_arg(
			'token',
			$this->tokens->create( $contact_id, 0, LinkToken::PURPOSE_UNSUBSCRIBE ),
			rest_url( 'kurato/v1/unsubscribe' )
		);
		$preferences_url = PreferenceCenter::url( PreferenceCenter::token_for( $this->tokens, $contact_id ) );

		$context = array(
			'first_name'      => (string) ( $this->contacts->get( $contact_id )['first_name'] ?? '' ),
			'display_name'    => (string) ( $this->contacts->get( $contact_id )['display_name'] ?? '' ),
			'email'           => $to_email,
			'unsubscribe_url' => $unsubscribe_url,
			'preferences_url' => $preferences_url,
			'sender_name'     => (string) ( $config['from_name'] ?? '' ),
			'sender_address'  => (string) ( $config['sender_address'] ?? '' ),
			'subject'         => $subject,
		);

		$message            = new Message( $to_email, $subject, $this->renderer->render_html( $inner_html, $context ) );
		$message->is_html   = true;
		// Multipart-Alternative (Zustellbarkeit): Klartext aus demselben Inhalt
		// inkl. Pflicht-Footer (EmailRenderer::render_text).
		$message->text_body = $this->renderer->render_text( $inner_html, $context );

		$from_email = (string) ( $config['from_email'] ?? '' );
		if ( '' !== $from_email ) {
			$message->from_email = $from_email;
			$message->from_name  = (string) ( $config['from_name'] ?? '' );
		}

		// RFC 8058: auch die Willkommensmail traegt den Abmelde-Footer, also den Header.
		$message->headers['List-Unsubscribe']      = '<' . $unsubscribe_url . '>';
		$message->headers['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click';

		return $message;
	}

	/**
	 * Liest die Willkommens-/Absender-Einstellungen. Test-Seam.
	 *
	 * @return array{enabled:bool,post_id:int,from_name:string,from_email:string,sender_address:string}
	 */
	protected function config(): array {
		$s = Core::instance()->settings( 'kurato' );
		return array(
			'enabled'        => (bool) $s->get( 'welcome.enabled', false ),
			'post_id'        => (int) $s->get( 'welcome.post_id', 0 ),
			'from_name'      => (string) $s->get( 'mail.sender.from_name', '' ),
			'from_email'     => (string) $s->get( 'mail.sender.from_email', '' ),
			'sender_address' => (string) $s->get( 'mail.sender.address', '' ),
		);
	}

	/**
	 * Versendet die Einzelmail direkt ueber den aktuellen Treiber. Test-Seam.
	 *
	 * @param Message $message Nachricht.
	 * @return bool
	 */
	protected function send( Message $message ): bool {
		return ( new DriverFactory() )->current()->send( $message );
	}
}
