<?php
/**
 * Mail.baby email API provider.
 *
 * Docs: https://www.mail.baby/apidoc.html (OpenAPI at api.mailbaby.net)
 *
 * @package EmailSmtp
 */

namespace EmailSmtp\Providers\MailBaby;

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

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

final class Provider extends AbstractApiProvider {

	private const API_BASE = 'https://api.mailbaby.net';

	public function get_id(): string {
		return 'mail-baby';
	}

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

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

	public function get_docs_url(): string {
		return 'https://www.mail.baby/apidoc.html';
	}

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

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

	public function connect( array $settings ): DeliveryResult {
		$key = $this->secret( $settings, 'mail_baby_api_key', 'WP_POWERSUITE_MAIL_BABY_API_KEY' );
		if ( $key === '' ) {
			return DeliveryResult::failure( __( 'Mail.baby API key is required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$response = ApiHttpClient::request(
			'GET',
			self::API_BASE . '/mail',
			[ 'X-API-KEY' => $key ]
		);

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

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

		$key = $this->secret( $settings, 'mail_baby_api_key', 'WP_POWERSUITE_MAIL_BABY_API_KEY' );
		if ( $key === '' ) {
			return DeliveryResult::failure( __( 'Mail.baby API key is required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$from     = $this->from_parts( $message );
		$to       = $message->get_to();
		$order_id = absint( $settings['mail_baby_order_id'] ?? 0 );

		// Match Mail.baby apidoc / OpenAPI examples: form-urlencoded + X-API-KEY.
		$headers = [
			'X-API-KEY'    => $key,
			'Content-Type' => 'application/x-www-form-urlencoded',
		];

		$attachments = $this->attachments_as_base64( $message );
		$needs_adv   = count( $to ) > 1
			|| $message->get_cc() !== []
			|| $message->get_bcc() !== []
			|| $attachments !== []
			|| is_email( $message->get_reply_to_email() );

		if ( ! $needs_adv ) {
			// POST /mail/send — from/to as plain strings (official plugin + OpenAPI SendMail).
			$payload = [
				'from'    => $from['email'],
				'to'      => $to[0] ?? '',
				'subject' => $message->get_subject(),
				'body'    => $message->get_body(),
			];
			if ( $order_id > 0 ) {
				$payload['id'] = $order_id;
			}

			$response = ApiHttpClient::request(
				'POST',
				self::API_BASE . '/mail/send',
				$headers,
				$payload
			);
		} else {
			// POST /mail/advsend — form examples use plain address strings.
			$payload = [
				'from'    => $this->format_address( $from['email'], $from['name'] ),
				'to'      => implode(
					', ',
					array_map(
						static fn( string $email ): string => $email,
						$to
					)
				),
				'subject' => $message->get_subject(),
				'body'    => $message->get_body(),
			];

			if ( $message->get_cc() !== [] ) {
				$payload['cc'] = implode( ', ', $message->get_cc() );
			}
			if ( $message->get_bcc() !== [] ) {
				$payload['bcc'] = implode( ', ', $message->get_bcc() );
			}
			if ( is_email( $message->get_reply_to_email() ) ) {
				$payload['replyto'] = $this->format_address(
					$message->get_reply_to_email(),
					$message->get_reply_to_name()
				);
			}
			if ( $attachments !== [] ) {
				// Form nested arrays: attachments[0][filename], attachments[0][data].
				$payload['attachments'] = array_map(
					static function ( array $a ): array {
						return [
							'filename' => $a['name'],
							'data'     => $a['content'],
						];
					},
					$attachments
				);
			}
			if ( $order_id > 0 ) {
				$payload['id'] = $order_id;
			}

			$response = ApiHttpClient::request(
				'POST',
				self::API_BASE . '/mail/advsend',
				$headers,
				$payload
			);
		}

		$result = ApiHttpClient::to_delivery_result(
			$response,
			static function ( array $res ) {
				$id = '';
				if ( is_array( $res['json'] ) ) {
					$id = (string) ( $res['json']['text'] ?? $res['json']['mailid'] ?? '' );
				}
				return [
					'message' => __( 'Mail.baby accepted the message.', 'wp-powersuite' ),
					'id'      => $id,
				];
			}
		);

		if ( $result->is_success() ) {
			return $result;
		}

		$tech = strtolower( $result->get_technical_message() );
		if ( str_contains( $tech, 'not configured for api' ) || str_contains( $tech, 'apiauth' ) ) {
			return DeliveryResult::failure(
				__( 'This From domain is not authorized for the Mail.baby API. Add a DNS TXT record named _mb with your Mail.baby username, and SPF include:spf-c.mailbaby.net. Guide: https://www.mail.baby/apiauth', 'wp-powersuite' ),
				$result->get_technical_message(),
				'domain',
				$result->get_provider_code(),
				false,
				__( 'Add the _mb TXT record and SPF, wait for DNS to propagate, then send another test.', 'wp-powersuite' ),
				$result->get_duration_ms()
			);
		}

		return $result;
	}
}
