<?php
/**
 * Brevo error code translator.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Support;

use RewindBrevoFormBridge\Api\Response;

defined( 'ABSPATH' ) || exit;

/**
 * Turns Brevo machine error codes and HTTP statuses into sentences a site
 * owner can act on.
 *
 * @since 0.1.0
 */
class Errors {

	/**
	 * Translate a Response into a human explanation.
	 *
	 * @since 0.1.0
	 * @param Response $response The API response.
	 * @return string Translated, human-readable explanation.
	 */
	public static function translate( Response $response ): string {
		// Transport failure: no HTTP conversation happened at all.
		if ( 0 === $response->status() ) {
			$detail = $response->message();

			return '' !== $detail
				? sprintf(
					/* translators: %s: the transport error detail. */
					__( 'Could not reach Brevo: %s', 'rewind-form-bridge-for-brevo' ),
					$detail
				)
				: __( 'Could not reach Brevo. The request never left this server — check connectivity and any firewall.', 'rewind-form-bridge-for-brevo' );
		}

		if ( 425 === $response->status() ) {
			return __( 'Brevo answered "425 Too Early" — a transient state on their side. The request will be retried automatically; no action is needed.', 'rewind-form-bridge-for-brevo' );
		}

		if ( 429 === $response->status() ) {
			return __( 'Brevo\'s rate limit was hit. The request will be retried once the limit window resets.', 'rewind-form-bridge-for-brevo' );
		}

		$code = $response->error_code();
		$map  = self::map();

		if ( '' !== $code && isset( $map[ $code ] ) ) {
			/*
			 * "unauthorized" covers causes that need completely different
			 * fixes: a deleted or regenerated key, a key Brevo has restricted
			 * to other IP addresses, or a suspended account. Only Brevo's own
			 * sentence tells them apart, so carry it through instead of
			 * throwing it away behind our friendlier wording.
			 */
			if ( 'unauthorized' === $code ) {
				$detail = $response->message();

				if ( '' !== $detail ) {
					return $map[ $code ] . ' ' . sprintf(
						/* translators: %s: the verbatim error message Brevo returned. */
						__( 'Brevo\'s own reason: "%s".', 'rewind-form-bridge-for-brevo' ),
						$detail
					);
				}
			}

			return $map[ $code ];
		}

		$api_message = $response->message();

		if ( '' !== $api_message ) {
			return sprintf(
				/* translators: 1: HTTP status code, 2: message returned by Brevo. */
				__( 'Brevo returned HTTP %1$d: %2$s', 'rewind-form-bridge-for-brevo' ),
				$response->status(),
				$api_message
			);
		}

		return sprintf(
			/* translators: %d: HTTP status code. */
			__( 'Brevo returned an unexpected HTTP %d response.', 'rewind-form-bridge-for-brevo' ),
			$response->status()
		);
	}

	/**
	 * Translate a Response from a transactional-email send.
	 *
	 * The generic map talks about field mappings and attribute types, which
	 * is the right advice for a contact push and nonsense on the Email
	 * screen. The failure that actually happens here is an unregistered
	 * sender, so name it — and otherwise let Brevo's own sentence through
	 * rather than a contact-shaped guess.
	 *
	 * @since 0.5.0
	 * @param Response $response The API response.
	 * @return string Translated, human-readable explanation.
	 */
	public static function for_email( Response $response ): string {
		$api_message = $response->message();
		$code        = $response->error_code();

		if ( in_array( $code, array( 'invalid_parameter', 'missing_parameter' ), true ) ) {
			if ( false !== stripos( $api_message, 'sender' ) ) {
				return __( 'Brevo refused the sender address. It has to be a sender you have registered and verified on the Brevo account — add it there, then pick it under "Send from".', 'rewind-form-bridge-for-brevo' );
			}

			if ( '' !== $api_message ) {
				return sprintf(
					/* translators: %s: message returned by Brevo. */
					__( 'Brevo rejected the message: %s', 'rewind-form-bridge-for-brevo' ),
					$api_message
				);
			}
		}

		if ( 'not_enough_credits' === $code ) {
			return __( 'Your Brevo account is out of transactional email credits. Top up or upgrade the plan in Brevo — until then, turn the fallback on so WordPress keeps sending.', 'rewind-form-bridge-for-brevo' );
		}

		return self::translate( $response );
	}

	/**
	 * The code-to-sentence map.
	 *
	 * @since 0.1.0
	 * @return array
	 */
	private static function map(): array {
		return array(
			'unauthorized'             => __( 'Brevo rejected the API key. Check the key in Settings — it may have been regenerated or deleted in your Brevo account.', 'rewind-form-bridge-for-brevo' ),
			'invalid_parameter'        => __( 'Brevo rejected a value in the request as invalid. Check the field mapping for a value that does not fit the attribute type.', 'rewind-form-bridge-for-brevo' ),
			'missing_parameter'        => __( 'A required value was missing from the request. Check that the mapped email field actually held an address, and that required mappings are filled.', 'rewind-form-bridge-for-brevo' ),
			'duplicate_parameter'      => __( 'Brevo reports this value already exists (a duplicate). Often harmless — the contact was already there.', 'rewind-form-bridge-for-brevo' ),
			'duplicate_request'        => __( 'Brevo saw the same request twice in quick succession and ignored the duplicate. Nothing was lost.', 'rewind-form-bridge-for-brevo' ),
			'account_under_validation' => __( 'Your Brevo account is still being validated by Brevo. Contacts cannot be pushed until Brevo finishes reviewing the account.', 'rewind-form-bridge-for-brevo' ),
			'not_enough_credits'       => __( 'Your Brevo account is out of credits for this operation. Top up or upgrade the plan in Brevo.', 'rewind-form-bridge-for-brevo' ),
			'permission_denied'        => __( 'The Brevo account behind this API key does not have permission for that operation.', 'rewind-form-bridge-for-brevo' ),
			'document_not_found'       => __( 'Brevo could not find the requested item — a list, template or contact may have been deleted. Refresh the cached lists and check the feed configuration.', 'rewind-form-bridge-for-brevo' ),
			'out_of_range'             => __( 'A value in the request was outside the range Brevo accepts.', 'rewind-form-bridge-for-brevo' ),
		);
	}
}
