<?php
/**
 * Mailjet transactional email API provider (Send API v3.1).
 *
 * @package EmailSmtp
 * @link https://dev.mailjet.com/email/reference/overview/
 * @link https://dev.mailjet.com/email/guides/send-api-v31/
 */

namespace EmailSmtp\Providers\Mailjet;

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 {

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

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

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

	public function get_docs_url(): string {
		return 'https://dev.mailjet.com/email/reference/overview/';
	}

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

	public function get_required_fields(): array {
		return [ 'mailjet_api_key', 'mailjet_secret_key' ];
	}


	/**
	 * Basic auth: API Key (public) : Secret Key (private).
	 *
	 * @param array<string, mixed> $settings
	 */
	private function auth_header( array $settings ): string {
		$key    = $this->secret( $settings, 'mailjet_api_key', 'WP_POWERSUITE_MAILJET_API_KEY' );
		$secret = $this->secret( $settings, 'mailjet_secret_key', 'WP_POWERSUITE_MAILJET_SECRET_KEY' );
		return 'Basic ' . base64_encode( $key . ':' . $secret );
	}

	/**
	 * @return array{Email:string, Name?:string}
	 */
	private function address_object( string $email, string $name = '' ): array {
		$row  = [ 'Email' => sanitize_email( $email ) ];
		$name = sanitize_text_field( $name );
		if ( $name !== '' ) {
			$row['Name'] = $name;
		}
		return $row;
	}

	public function connect( array $settings ): DeliveryResult {
		$key    = $this->secret( $settings, 'mailjet_api_key', 'WP_POWERSUITE_MAILJET_API_KEY' );
		$secret = $this->secret( $settings, 'mailjet_secret_key', 'WP_POWERSUITE_MAILJET_SECRET_KEY' );
		if ( $key === '' || $secret === '' ) {
			return DeliveryResult::failure( __( 'Mailjet API key and secret key are required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$response = ApiHttpClient::request(
			'GET',
			'https://api.mailjet.com/v3/REST/user',
			[ 'Authorization' => $this->auth_header( $settings ) ]
		);

		return ApiHttpClient::to_delivery_result(
			$response,
			static function () {
				return [ 'message' => __( 'Mailjet credentials 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, 'mailjet_api_key', 'WP_POWERSUITE_MAILJET_API_KEY' );
		$secret = $this->secret( $settings, 'mailjet_secret_key', 'WP_POWERSUITE_MAILJET_SECRET_KEY' );
		if ( $key === '' || $secret === '' ) {
			return DeliveryResult::failure( __( 'Mailjet API key and secret key are required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$from = $this->from_parts( $message );
		$msg  = [
			'From'    => $this->address_object( $from['email'], $from['name'] ),
			'To'      => array_map( [ $this, 'address_object' ], $message->get_to() ),
			'Subject' => $message->get_subject(),
		];

		if ( $message->is_html() ) {
			$msg['HTMLPart'] = $message->get_body();
			$msg['TextPart'] = $message->get_alt_body() !== ''
				? $message->get_alt_body()
				: wp_strip_all_tags( $message->get_body() );
		} else {
			$msg['TextPart'] = $message->get_body();
		}

		if ( $message->get_cc() !== [] ) {
			$msg['Cc'] = array_map( [ $this, 'address_object' ], $message->get_cc() );
		}
		if ( $message->get_bcc() !== [] ) {
			$msg['Bcc'] = array_map( [ $this, 'address_object' ], $message->get_bcc() );
		}
		if ( is_email( $message->get_reply_to_email() ) ) {
			$msg['ReplyTo'] = $this->address_object(
				$message->get_reply_to_email(),
				$message->get_reply_to_name()
			);
		}

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

		$attachments = $this->attachments_as_base64( $message );
		if ( $attachments !== [] ) {
			$msg['Attachments'] = array_map(
				static function ( array $a ) {
					return [
						'Filename'      => $a['name'],
						'ContentType'   => $a['type'] !== '' ? $a['type'] : 'application/octet-stream',
						'Base64Content' => $a['content'],
					];
				},
				$attachments
			);
		}

		$response = ApiHttpClient::request(
			'POST',
			'https://api.mailjet.com/v3.1/send',
			[ 'Authorization' => $this->auth_header( $settings ) ],
			[ 'Messages' => [ $msg ] ]
		);

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

		$json = $response['json'] ?? null;
		// v3.1 can return HTTP 200 with per-message Status "error".
		if ( is_array( $json ) && isset( $json['Messages'][0] ) && is_array( $json['Messages'][0] ) ) {
			$first  = $json['Messages'][0];
			$status = strtolower( (string) ( $first['Status'] ?? '' ) );

			if ( $status === 'error' ) {
				$parts = [];
				if ( ! empty( $first['Errors'] ) && is_array( $first['Errors'] ) ) {
					foreach ( $first['Errors'] as $err ) {
						if ( ! is_array( $err ) ) {
							continue;
						}
						$msg_text = (string) ( $err['ErrorMessage'] ?? $err['ErrorCode'] ?? '' );
						if ( $msg_text !== '' ) {
							$parts[] = $msg_text;
						}
					}
				}
				$technical = $parts !== [] ? implode( '; ', $parts ) : __( 'Mailjet rejected the message.', 'wp-powersuite' );
				$result    = ErrorNormalizer::from_text( $technical, (string) ( $response['code'] ?? '' ) );
				return DeliveryResult::failure(
					$result->get_user_message(),
					$result->get_technical_message(),
					$result->get_category(),
					(string) ( $response['code'] ?? '' ),
					$result->is_retry_safe(),
					__( 'Verify the From address is an active sender in Mailjet.', 'wp-powersuite' ),
					(int) ( $response['duration_ms'] ?? 0 )
				);
			}

			if ( $status === 'success' ) {
				$id = '';
				foreach ( [ 'To', 'Cc', 'Bcc' ] as $bucket ) {
					if ( empty( $first[ $bucket ][0] ) || ! is_array( $first[ $bucket ][0] ) ) {
						continue;
					}
					$row = $first[ $bucket ][0];
					$id  = (string) ( $row['MessageID'] ?? $row['MessageUUID'] ?? '' );
					if ( $id !== '' ) {
						break;
					}
				}
				return DeliveryResult::success(
					__( 'Mailjet accepted the message.', 'wp-powersuite' ),
					$id,
					(int) ( $response['duration_ms'] ?? 0 )
				);
			}
		}

		return ApiHttpClient::to_delivery_result(
			$response,
			static function ( array $res ) {
				$id = '';
				if ( is_array( $res['json'] ) ) {
					$row = $res['json']['Messages'][0]['To'][0] ?? null;
					if ( is_array( $row ) ) {
						$id = (string) ( $row['MessageID'] ?? $row['MessageUUID'] ?? '' );
					}
				}
				return [
					'message' => __( 'Mailjet accepted the message.', 'wp-powersuite' ),
					'id'      => $id,
				];
			}
		);
	}
}
