<?php

namespace Limb_Chatbot\Includes\Services\Notifications\Channels;

use Limb_Chatbot\Includes\Data_Objects\Chatbot_User;
use Limb_Chatbot\Includes\Interfaces\Notification_Channel_Interface;
use Limb_Chatbot\Includes\Services\Notifications\Notification_Envelope;

/**
 * Email notification channel.
 *
 * Sends notifications via wp_mail to the Chatbot_User's email (WP user or meta).
 *
 * @package Limb_Chatbot\Includes\Services\Notifications\Channels
 * @since 1.0.15
 */
class Email_Notification_Channel implements Notification_Channel_Interface {

	/**
	 * @inheritDoc
	 */
	public function get_channel_key(): string {
		return 'email';
	}

	/**
	 * @inheritDoc
	 */
	public function send( Chatbot_User $recipient, Notification_Envelope $envelope ): bool {
		$payload           = $envelope->get_payload();
		$to_emails_raw = $payload['to_emails'] ?? null;
		$to_emails     = [];

		// Preferred path: role-derived + custom emails resolved by Notification_Service.
		if ( is_array( $to_emails_raw ) ) {
			$to_emails = array_values( array_unique( array_filter( array_map( 'trim', $to_emails_raw ) ) ) );
			$to_emails = array_values( array_filter( $to_emails, function ( $email ) {
				return is_string( $email ) && is_email( $email );
			} ) );
		} else {
			// Backwards-compatible fallback for older payload formats.
			$send_recipient    = $payload['send_recipient_email'] ?? true;
			$custom_emails_raw = $payload['custom_emails'] ?? [];
			$custom_emails     = is_array( $custom_emails_raw ) ? $custom_emails_raw : [];

			if ( (bool) $send_recipient ) {
				$recipient_email = $this->get_recipient_email( $recipient );
				if ( ! empty( $recipient_email ) && is_email( $recipient_email ) ) {
					$to_emails[] = $recipient_email;
				}
			}

			foreach ( $custom_emails as $email ) {
				if ( is_string( $email ) && is_email( $email ) ) {
					$to_emails[] = $email;
				}
			}

			$to_emails = array_values( array_unique( array_filter( $to_emails ) ) );
		}

		if ( empty( $to_emails ) ) {
			return false;
		}

		$subject = $envelope->get_subject();
		$body    = $envelope->get_body();
		$content_type = $envelope->get_content_type();
		// If templates were authored as plain text with `\n`, but we send as HTML,
		// convert line breaks so email clients render them properly.
		if ( is_string( $content_type ) && str_contains( (string) $content_type, 'html' ) ) {
			$body = (string) $body;
			// Convert multiple consecutive newlines to paragraph-ish breaks.
			$body = preg_replace( "/(\r\n|\r|\n){2,}/", "<br><br>", $body );
			// Convert remaining newlines to <br>.
			$body = preg_replace( "/(\r\n|\r|\n)/", "<br>", $body );
		}
		$headers = $this->get_headers( $envelope );

		$to = count( $to_emails ) === 1 ? $to_emails[0] : implode( ',', $to_emails );

		return (bool) wp_mail( $to, $subject, $body, $headers );
	}

	/**
	 * @inheritDoc
	 */
	public function can_deliver_to( Chatbot_User $recipient ): bool {
		// Email delivery is decided by Notification_Service via envelope payload.
		// This method is kept permissive so we don't block queued jobs where the
		// context chatbot user may not have an email.
		return true;
	}

	/**
	 * Get email address for the chatbot user.
	 *
	 * @param  Chatbot_User  $recipient  Chatbot user.
	 *
	 * @return string|null
	 * @since 1.0.15
	 */
	private function get_recipient_email( Chatbot_User $recipient ): ?string {
		$email = $recipient->email();
		if ( is_string( $email ) ) {
			return $email;
		}

		return null;
	}

	/**
	 * Build email headers (e.g. Content-Type: text/html).
	 *
	 * @param  Notification_Envelope  $envelope  Envelope (payload may contain headers).
	 *
	 * @return array
	 * @since 1.0.15
	 */
	private function get_headers( Notification_Envelope $envelope ): array {
		$payload = $envelope->get_payload();
		$headers = $payload['headers'] ?? [];

		if ( empty( $headers ) ) {
			$content_type = $envelope->get_content_type();
			$headers[]    = 'Content-Type: ' . $content_type . '; charset=UTF-8';
		}

		return is_array( $headers ) ? $headers : [ $headers ];
	}
}
