<?php
/**
 * Elastic Email REST API v4 provider.
 *
 * @package EmailSmtp
 * @link https://elasticemail.com/developers/api-documentation/rest-api
 */

namespace EmailSmtp\Providers\ElasticEmail;

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 BASE = 'https://api.elasticemail.com/v4';

	public function get_id(): string {
		return 'elastic-email';
	}

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

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

	public function get_docs_url(): string {
		return 'https://elasticemail.com/developers/api-documentation/rest-api';
	}

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

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


	/**
	 * @param array<string, mixed> $settings
	 * @return array<string, string>
	 */
	private function auth_headers( array $settings ): array {
		$key = $this->secret( $settings, 'elastic_email_api_key', 'WP_POWERSUITE_ELASTIC_EMAIL_API_KEY' );
		return [
			'Content-Type'          => 'application/json',
			'X-ElasticEmail-ApiKey' => $key,
		];
	}

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

		// ViewSettings: confirms the key; SendHttp-only keys may get 403 (still valid for send).
		$response = ApiHttpClient::request(
			'GET',
			self::BASE . '/domains',
			$this->auth_headers( $settings )
		);

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

		$code = (int) ( $response['code'] ?? 0 );
		if ( $code === 401 ) {
			return DeliveryResult::failure(
				__( 'Elastic Email authentication failed. Check the API key.', 'wp-powersuite' ),
				ApiHttpClient::extract_error_text( $response ),
				'authentication',
				'401'
			);
		}
		if ( $code === 403 ) {
			return DeliveryResult::success(
				__( 'Elastic Email API key accepted (limited permissions). Sending requires SendHttp access.', 'wp-powersuite' )
			);
		}

		return ApiHttpClient::to_delivery_result(
			$response,
			static function () {
				return [ 'message' => __( 'Elastic Email 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, 'elastic_email_api_key', 'WP_POWERSUITE_ELASTIC_EMAIL_API_KEY' );
		if ( $key === '' ) {
			return DeliveryResult::failure( __( 'Elastic Email API key is required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$from = $this->from_parts( $message );
		$body = [];

		if ( $message->is_html() ) {
			$body[] = [
				'ContentType' => 'HTML',
				'Content'     => $message->get_body(),
				'Charset'     => 'utf-8',
			];
			$text = $message->get_alt_body() !== ''
				? $message->get_alt_body()
				: wp_strip_all_tags( $message->get_body() );
			if ( $text !== '' ) {
				$body[] = [
					'ContentType' => 'PlainText',
					'Content'     => $text,
					'Charset'     => 'utf-8',
				];
			}
		} else {
			$body[] = [
				'ContentType' => 'PlainText',
				'Content'     => $message->get_body(),
				'Charset'     => 'utf-8',
			];
		}

		$content = [
			'Body'    => $body,
			'From'    => $this->format_address( $from['email'], $from['name'] ),
			'Subject' => $message->get_subject(),
		];

		if ( is_email( $message->get_reply_to_email() ) ) {
			$content['ReplyTo'] = $this->format_address(
				$message->get_reply_to_email(),
				$message->get_reply_to_name()
			);
		}

		$headers = $this->safe_custom_headers( $message );
		if ( $headers !== [] ) {
			$content['Headers'] = $headers;
		}

		$attachments = $this->attachments_as_base64( $message );
		if ( $attachments !== [] ) {
			$content['Attachments'] = array_map(
				static function ( array $a ) {
					$binary = base64_decode( $a['content'], true );
					$row    = [
						'BinaryContent' => $a['content'],
						'Name'          => $a['name'],
						'ContentType'   => $a['type'] !== '' ? $a['type'] : 'application/octet-stream',
					];
					if ( $binary !== false ) {
						$row['Size'] = strlen( $binary );
					}
					return $row;
				},
				$attachments
			);
		}

		$recipients = [
			'To' => $message->get_to(),
		];
		if ( $message->get_cc() !== [] ) {
			$recipients['CC'] = $message->get_cc();
		}
		if ( $message->get_bcc() !== [] ) {
			$recipients['BCC'] = $message->get_bcc();
		}

		$response = ApiHttpClient::request(
			'POST',
			self::BASE . '/emails/transactional',
			$this->auth_headers( $settings ),
			[
				'Recipients' => $recipients,
				'Content'    => $content,
			]
		);

		return ApiHttpClient::to_delivery_result(
			$response,
			static function ( array $res ) {
				$id = '';
				if ( is_array( $res['json'] ) ) {
					$id = (string) ( $res['json']['MessageID'] ?? $res['json']['TransactionID'] ?? '' );
				}
				return [
					'message' => __( 'Elastic Email accepted the message.', 'wp-powersuite' ),
					'id'      => $id,
				];
			}
		);
	}
}
