<?php
/**
 * Mandrill (Mailchimp Transactional) API provider.
 *
 * @package EmailSmtp
 * @link https://mailchimp.com/developer/transactional/api/
 * @link https://mailchimp.com/developer/transactional/api/messages/send-new-message/
 */

namespace EmailSmtp\Providers\Mandrill;

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 'mandrill';
	}

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

	public function get_description(): string {
		return __( 'Send transactional email through Mandrill (Mailchimp Transactional).', 'wp-powersuite' );
	}

	public function get_docs_url(): string {
		return 'https://mailchimp.com/developer/transactional/api/';
	}

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

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


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

		// POST /users/ping — validates key; response body is the string "PONG!".
		$response = ApiHttpClient::request(
			'POST',
			'https://mandrillapp.com/api/1.0/users/ping.json',
			[ 'Content-Type' => 'application/json' ],
			[ 'key' => $key ]
		);

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

		$body = trim( (string) ( $response['body'] ?? '' ) );
		$code = (int) ( $response['code'] ?? 0 );
		$json = $response['json'] ?? null;

		// API error object: { "status": "error", "name": "...", "message": "..." }
		if ( is_array( $json ) && (string) ( $json['status'] ?? '' ) === 'error' ) {
			$technical = (string) ( $json['message'] ?? $json['name'] ?? 'Invalid API key' );
			$result    = ErrorNormalizer::from_text( $technical, (string) $code );
			return DeliveryResult::failure(
				__( 'Mandrill rejected the API key.', 'wp-powersuite' ),
				$result->get_technical_message(),
				'authentication',
				(string) $code,
				false,
				__( 'Create a Transactional API key in your Mandrill / Mailchimp Transactional account.', 'wp-powersuite' ),
				(int) ( $response['duration_ms'] ?? 0 )
			);
		}

		if ( $code >= 200 && $code < 300 && ( $body === '"PONG!"' || $body === 'PONG!' || str_contains( $body, 'PONG' ) ) ) {
			return DeliveryResult::success(
				__( 'Mandrill API key authenticated successfully.', 'wp-powersuite' ),
				'',
				(int) ( $response['duration_ms'] ?? 0 )
			);
		}

		return ApiHttpClient::to_delivery_result( $response );
	}

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

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

		$from = $this->from_parts( $message );
		$to   = [];
		foreach ( $message->get_to() as $email ) {
			$to[] = [ 'email' => $email, 'type' => 'to' ];
		}
		foreach ( $message->get_cc() as $email ) {
			$to[] = [ 'email' => $email, 'type' => 'cc' ];
		}
		foreach ( $message->get_bcc() as $email ) {
			$to[] = [ 'email' => $email, 'type' => 'bcc' ];
		}

		$msg = [
			'subject'    => $message->get_subject(),
			'from_email' => $from['email'],
			'to'         => $to,
		];

		if ( $from['name'] !== '' ) {
			$msg['from_name'] = $from['name'];
		}

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

		$headers = $this->safe_custom_headers( $message );
		if ( is_email( $message->get_reply_to_email() ) ) {
			$headers['Reply-To'] = $this->format_address(
				$message->get_reply_to_email(),
				$message->get_reply_to_name()
			);
		}
		if ( $headers !== [] ) {
			$msg['headers'] = $headers;
		}

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

		$response = ApiHttpClient::request(
			'POST',
			'https://mandrillapp.com/api/1.0/messages/send.json',
			[ 'Content-Type' => 'application/json' ],
			[
				'key'     => $key,
				'message' => $msg,
			]
		);

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

		$json = $response['json'] ?? null;

		// API-level error object (invalid key, validation, etc.).
		if ( is_array( $json ) && (string) ( $json['status'] ?? '' ) === 'error' ) {
			$technical = (string) ( $json['message'] ?? $json['name'] ?? 'Mandrill error' );
			$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(),
				$result->get_suggested_action(),
				(int) ( $response['duration_ms'] ?? 0 )
			);
		}

		// Success: array of per-recipient results (sent | queued | scheduled | rejected | invalid).
		if ( is_array( $json ) && isset( $json[0] ) && is_array( $json[0] ) ) {
			$accepted_id = '';
			$rejected    = [];

			foreach ( $json as $row ) {
				if ( ! is_array( $row ) ) {
					continue;
				}
				$status = (string) ( $row['status'] ?? '' );
				if ( in_array( $status, [ 'sent', 'queued', 'scheduled' ], true ) ) {
					if ( $accepted_id === '' ) {
						$accepted_id = (string) ( $row['_id'] ?? '' );
					}
				} else {
					$rejected[] = $row;
				}
			}

			if ( $accepted_id !== '' || count( $rejected ) < count( $json ) ) {
				// At least one recipient was accepted.
				if ( $accepted_id === '' ) {
					foreach ( $json as $row ) {
						if ( is_array( $row ) && ! empty( $row['_id'] ) ) {
							$accepted_id = (string) $row['_id'];
							break;
						}
					}
				}
				return DeliveryResult::success(
					__( 'Mandrill accepted the message.', 'wp-powersuite' ),
					$accepted_id,
					(int) ( $response['duration_ms'] ?? 0 )
				);
			}

			$first  = $rejected[0] ?? $json[0];
			$reason = (string) ( $first['reject_reason'] ?? $first['status'] ?? '' );
			return DeliveryResult::failure(
				$reason !== '' ? $reason : __( 'Mandrill rejected the message.', 'wp-powersuite' ),
				wp_json_encode( $first ),
				'provider',
				(string) ( $response['code'] ?? '' ),
				false,
				__( 'Check the From domain is verified in Mandrill and the recipient is not on a denylist.', 'wp-powersuite' ),
				(int) ( $response['duration_ms'] ?? 0 )
			);
		}

		return ApiHttpClient::to_delivery_result( $response );
	}
}
