<?php
/**
 * MailerSend email API provider.
 *
 * @package EmailSmtp
 * @link https://developers.mailersend.com/api/v1/email
 * @link https://developers.mailersend.com/#mailersend-api
 */

namespace EmailSmtp\Providers\Mailersend;

use EmailSmtp\Includes\AbstractApiProvider;
use EmailSmtp\Includes\ApiHttpClient;
use EmailSmtp\Includes\DeliveryResult;
use EmailSmtp\Includes\EmailMessage;
use EmailSmtp\Includes\ErrorNormalizer;

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

final class Provider extends AbstractApiProvider {

	private const TO_CAP  = 50;
	private const CC_CAP  = 10;
	private const BCC_CAP = 10;

	public function get_id(): string {
		return 'mailersend';
	}

	public function get_name(): string {
		return __( 'MailerSend', 'wp-powersuite' );
	}

	public function get_description(): string {
		return __( 'Send transactional email through the MailerSend Email API v1.', 'wp-powersuite' );
	}

	public function get_recommended_use(): string {
		return __( 'Transactional email with verified sending domains.', 'wp-powersuite' );
	}

	public function get_docs_url(): string {
		return 'https://developers.mailersend.com/api/v1/email';
	}

	public function get_icon(): string {
		return 'dashicons-email-alt';
	}

	public function get_required_fields(): array {
		return [ 'mailersend_api_token' ];
	}


	/**
	 * @param array<string, mixed> $settings
	 * @return array<string, string>
	 */
	private function auth_headers( array $settings ): array {
		$token = $this->secret( $settings, 'mailersend_api_token', 'WP_POWERSUITE_MAILERSEND_API_TOKEN' );
		return [
			'Authorization'    => 'Bearer ' . $token,
			'Content-Type'     => 'application/json',
			'X-Requested-With' => 'XMLHttpRequest',
		];
	}

	/**
	 * @param list<string> $emails
	 * @return list<array{email:string}>
	 */
	private function recipient_objects( array $emails ): array {
		return array_map(
			static fn( string $e ) => [ 'email' => $e ],
			$emails
		);
	}

	public function connect( array $settings ): DeliveryResult {
		$token = $this->secret( $settings, 'mailersend_api_token', 'WP_POWERSUITE_MAILERSEND_API_TOKEN' );
		if ( $token === '' ) {
			return DeliveryResult::failure( __( 'MailerSend API token is required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$response = ApiHttpClient::request(
			'GET',
			'https://api.mailersend.com/v1/domains',
			$this->auth_headers( $settings )
		);

		return ApiHttpClient::to_delivery_result(
			$response,
			static function () {
				return [ 'message' => __( 'MailerSend API token authenticated successfully.', 'wp-powersuite' ) ];
			}
		);
	}

	public function send( EmailMessage $message, array $settings ): DeliveryResult {
		$missing = $this->require_from( $message );
		if ( $missing ) {
			return $missing;
		}

		$token = $this->secret( $settings, 'mailersend_api_token', 'WP_POWERSUITE_MAILERSEND_API_TOKEN' );
		if ( $token === '' ) {
			return DeliveryResult::failure( __( 'MailerSend API token is required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$from    = $this->from_parts( $message );
		$payload = [
			'from'    => array_filter(
				[
					'email' => $from['email'],
					'name'  => $from['name'] !== '' ? $from['name'] : null,
				]
			),
			'to'      => $this->recipient_objects( array_slice( $message->get_to(), 0, self::TO_CAP ) ),
			'subject' => $message->get_subject(),
		];

		if ( $message->is_html() ) {
			$payload['html'] = $message->get_body();
			$payload['text'] = $message->get_alt_body() !== ''
				? $message->get_alt_body()
				: wp_strip_all_tags( $message->get_body() );
		} else {
			$payload['text'] = $message->get_body();
		}

		if ( $message->get_cc() !== [] ) {
			$payload['cc'] = $this->recipient_objects( array_slice( $message->get_cc(), 0, self::CC_CAP ) );
		}
		if ( $message->get_bcc() !== [] ) {
			$payload['bcc'] = $this->recipient_objects( array_slice( $message->get_bcc(), 0, self::BCC_CAP ) );
		}
		if ( is_email( $message->get_reply_to_email() ) ) {
			$payload['reply_to'] = array_filter(
				[
					'email' => $message->get_reply_to_email(),
					'name'  => $message->get_reply_to_name() !== '' ? $message->get_reply_to_name() : null,
				]
			);
		}

		$attachments = $this->attachments_as_base64( $message );
		if ( $attachments !== [] ) {
			$payload['attachments'] = array_map(
				static function ( array $a ) {
					return [
						'filename'    => $a['name'],
						'content'     => $a['content'],
						'disposition' => 'attachment',
					];
				},
				$attachments
			);
		}

		// MailerSend expects headers as [ { "name": "...", "value": "..." } ] (Pro/Enterprise).
		$custom = $this->safe_custom_headers( $message );
		if ( $custom !== [] ) {
			$headers = [];
			foreach ( $custom as $name => $value ) {
				$headers[] = [
					'name'  => (string) $name,
					'value' => (string) $value,
				];
			}
			$payload['headers'] = $headers;
		}

		$response = ApiHttpClient::request(
			'POST',
			'https://api.mailersend.com/v1/email',
			$this->auth_headers( $settings ),
			$payload
		);

		if ( ! empty( $response['error'] ) ) {
			return ErrorNormalizer::from_text( (string) $response['error'] );
		}

		$code = (int) ( $response['code'] ?? 0 );
		$json = is_array( $response['json'] ?? null ) ? $response['json'] : null;
		$id   = (string) ( $response['headers']['x-message-id'] ?? '' );

		// 202 with ALL_SUPPRESSED: no x-message-id — treat as failure.
		if ( $code >= 200 && $code <= 299 && $id === '' && is_array( $json ) && ! empty( $json['warnings'] ) && is_array( $json['warnings'] ) ) {
			foreach ( $json['warnings'] as $warning ) {
				if ( ! is_array( $warning ) ) {
					continue;
				}
				$type = strtoupper( (string) ( $warning['type'] ?? '' ) );
				if ( $type === 'ALL_SUPPRESSED' ) {
					$msg = (string) ( $warning['message'] ?? $warning['warning'] ?? __( 'All recipients were suppressed.', 'wp-powersuite' ) );
					$result = ErrorNormalizer::from_text( $msg, (string) $code );
					return DeliveryResult::failure(
						$result->get_user_message(),
						$result->get_technical_message(),
						'provider',
						(string) $code,
						false,
						__( 'Remove suppressed recipients or update your MailerSend suppressions list.', 'wp-powersuite' ),
						(int) ( $response['duration_ms'] ?? 0 )
					);
				}
			}
		}

		return ApiHttpClient::to_delivery_result(
			$response,
			static function ( array $res ) {
				$msg_id = (string) ( $res['headers']['x-message-id'] ?? '' );
				if ( $msg_id === '' && is_array( $res['json'] ) ) {
					$msg_id = (string) ( $res['json']['message_id'] ?? $res['json']['id'] ?? '' );
				}
				return [
					'message' => __( 'MailerSend accepted the message.', 'wp-powersuite' ),
					'id'      => $msg_id,
				];
			}
		);
	}
}
