<?php
/**
 * TurboSMTP email API provider (API v2).
 *
 * @package EmailSmtp
 * @link https://serversmtp.com/turbo-api/
 * @link https://serversmtp.com/turbo-api/turbo-smtp.yaml
 */

namespace EmailSmtp\Providers\TurboSmtp;

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 'turbo-smtp';
	}

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

	public function get_description(): string {
		return __( 'Send email through the TurboSMTP mail API using consumer key credentials.', 'wp-powersuite' );
	}

	public function get_docs_url(): string {
		return 'https://serversmtp.com/turbo-api/';
	}

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

	public function get_required_fields(): array {
		return [ 'turbo_smtp_consumer_key', 'turbo_smtp_consumer_secret' ];
	}


	/**
	 * @param array<string, mixed> $settings
	 */
	private function endpoint( array $settings ): string {
		$region = sanitize_key( (string) ( $settings['turbo_smtp_region'] ?? 'us' ) );
		return $region === 'eu'
			? 'https://api.eu.turbo-smtp.com/api/v2/mail/send'
			: 'https://api.turbo-smtp.com/api/v2/mail/send';
	}

	/**
	 * /mail/send accepts only consumerKey + consumerSecret (not Authorization).
	 *
	 * @return array<string, string>
	 */
	private function auth_headers( string $key, string $secret ): array {
		return [
			'consumerKey'    => $key,
			'consumerSecret' => $secret,
		];
	}

	public function connect( array $settings ): DeliveryResult {
		$key    = $this->secret( $settings, 'turbo_smtp_consumer_key', 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_KEY' );
		$secret = $this->secret( $settings, 'turbo_smtp_consumer_secret', 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_SECRET' );
		if ( $key === '' || $secret === '' ) {
			return DeliveryResult::failure( __( 'TurboSMTP consumer key and secret are required.', 'wp-powersuite' ), '', 'authentication' );
		}

		// Probe /mail/send with invalid addresses: 401 = bad credentials, 400 = auth OK.
		$response = ApiHttpClient::request(
			'POST',
			$this->endpoint( $settings ),
			$this->auth_headers( $key, $secret ),
			[
				'from'    => 'invalid',
				'to'      => 'invalid',
				'subject' => 'connection-test',
				'content' => 'connection-test',
			]
		);

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

		$code = (int) ( $response['code'] ?? 0 );
		if ( $code === 401 ) {
			$technical = ApiHttpClient::extract_error_text( $response );
			$result    = ErrorNormalizer::from_text( $technical, '401' );
			return DeliveryResult::failure(
				__( 'TurboSMTP rejected the consumer key or secret.', 'wp-powersuite' ),
				$result->get_technical_message(),
				'authentication',
				'401',
				false,
				__( 'Check the consumer key/secret and region (Global vs EU).', 'wp-powersuite' ),
				(int) ( $response['duration_ms'] ?? 0 )
			);
		}

		if ( $code === 400 || $code === 200 ) {
			return DeliveryResult::success(
				__( 'TurboSMTP credentials 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, 'turbo_smtp_consumer_key', 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_KEY' );
		$secret = $this->secret( $settings, 'turbo_smtp_consumer_secret', 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_SECRET' );
		if ( $key === '' || $secret === '' ) {
			return DeliveryResult::failure( __( 'TurboSMTP consumer key and secret are required.', 'wp-powersuite' ), '', 'authentication' );
		}

		$from    = $this->from_parts( $message );
		$payload = [
			'from'    => $this->format_address( $from['email'], $from['name'] ),
			'to'      => implode( ',', $message->get_to() ),
			'subject' => $message->get_subject(),
		];

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

		if ( $message->get_cc() !== [] ) {
			$payload['cc'] = implode( ',', $message->get_cc() );
		}
		if ( $message->get_bcc() !== [] ) {
			$payload['bcc'] = implode( ',', $message->get_bcc() );
		}

		$headers = $this->safe_custom_headers( $message );
		if ( is_email( $message->get_reply_to_email() ) ) {
			// Docs sample uses lowercase reply-to inside custom_headers.
			$headers['reply-to'] = $this->format_address( $message->get_reply_to_email(), $message->get_reply_to_name() );
		}
		if ( $headers !== [] ) {
			$payload['custom_headers'] = $headers;
		}

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

		$response = ApiHttpClient::request(
			'POST',
			$this->endpoint( $settings ),
			$this->auth_headers( $key, $secret ),
			$payload
		);

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