<?php
/**
 * Normalized email delivery / connection result.
 *
 * @package EmailSmtp
 * @since 1.1.0
 */

namespace EmailSmtp\Includes;

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

final class DeliveryResult {

	private bool $success;

	private string $user_message;

	private string $technical_message;

	private string $category;

	private string $provider_code;

	private bool $retry_safe;

	private string $suggested_action;

	private string $provider_message_id;

	private int $duration_ms;

	/** @var array<string, mixed> */
	private array $meta;

	/**
	 * @param array<string, mixed> $meta
	 */
	public function __construct(
		bool $success,
		string $user_message,
		string $technical_message = '',
		string $category = 'unknown',
		string $provider_code = '',
		bool $retry_safe = false,
		string $suggested_action = '',
		string $provider_message_id = '',
		int $duration_ms = 0,
		array $meta = []
	) {
		$this->success             = $success;
		$this->user_message        = $user_message;
		$this->technical_message   = $technical_message !== '' ? $technical_message : $user_message;
		$this->category            = sanitize_key( $category ) ?: 'unknown';
		$this->provider_code       = $provider_code;
		$this->retry_safe          = $retry_safe;
		$this->suggested_action    = $suggested_action;
		$this->provider_message_id = $provider_message_id;
		$this->duration_ms         = max( 0, $duration_ms );
		$this->meta                = $meta;
	}

	/**
	 * @param array<string, mixed> $meta
	 */
	public static function success(
		string $user_message,
		string $provider_message_id = '',
		int $duration_ms = 0,
		array $meta = []
	): self {
		return new self(
			true,
			$user_message,
			$user_message,
			'',
			'',
			false,
			'',
			$provider_message_id,
			$duration_ms,
			$meta
		);
	}

	/**
	 * @param array<string, mixed> $meta
	 */
	public static function failure(
		string $user_message,
		string $technical_message = '',
		string $category = 'unknown',
		string $provider_code = '',
		bool $retry_safe = false,
		string $suggested_action = '',
		int $duration_ms = 0,
		array $meta = []
	): self {
		return new self(
			false,
			$user_message,
			$technical_message,
			$category,
			$provider_code,
			$retry_safe,
			$suggested_action,
			'',
			$duration_ms,
			$meta
		);
	}

	public function is_success(): bool {
		return $this->success;
	}

	public function get_user_message(): string {
		return $this->user_message;
	}

	public function get_technical_message(): string {
		return $this->technical_message;
	}

	public function get_category(): string {
		return $this->category;
	}

	public function get_provider_code(): string {
		return $this->provider_code;
	}

	public function is_retry_safe(): bool {
		return $this->retry_safe;
	}

	public function get_suggested_action(): string {
		return $this->suggested_action;
	}

	public function get_provider_message_id(): string {
		return $this->provider_message_id;
	}

	public function get_duration_ms(): int {
		return $this->duration_ms;
	}

	/**
	 * @return array<string, mixed>
	 */
	public function get_meta(): array {
		return $this->meta;
	}

	public function to_wp_error(): \WP_Error {
		return new \WP_Error(
			$this->provider_code !== '' ? $this->provider_code : 'email_delivery_failed',
			$this->user_message,
			[
				'technical'        => $this->technical_message,
				'category'         => $this->category,
				'retry_safe'       => $this->retry_safe,
				'suggested_action' => $this->suggested_action,
			]
		);
	}

	/**
	 * @return array<string, mixed>
	 */
	public function to_array(): array {
		return [
			'success'             => $this->success,
			'user_message'        => $this->user_message,
			'technical_message'   => $this->technical_message,
			'category'            => $this->category,
			'provider_code'       => $this->provider_code,
			'retry_safe'          => $this->retry_safe,
			'suggested_action'    => $this->suggested_action,
			'provider_message_id' => $this->provider_message_id,
			'duration_ms'         => $this->duration_ms,
		];
	}
}
