<?php
/**
 * Resolve user-facing messages from exception types.
 *
 * @package DhlPolska\Exception
 */

namespace DhlPolska\Exception;

/**
 * Exception message resolver.
 */
class ExceptionMessageResolver {

	public static function resolve_throwable( \Throwable $throwable, string $fallback_exception_class = UnexpectedDhlException::class ): string {
		if ( $throwable instanceof UserFacingException ) {
			return $throwable->get_user_message();
		}

		$validation_message = self::extract_validation_message_from_throwable( $throwable );
		if ( '' !== $validation_message ) {
			return $validation_message;
		}

		$resolved_fallback = self::resolve_user_facing_message_from_class( $fallback_exception_class );
		if ( '' !== $resolved_fallback ) {
			return $resolved_fallback;
		}

		return ( new UnexpectedDhlException() )->get_user_message();
	}

	private static function resolve_user_facing_message_from_class( string $exception_class ): string {
		$normalized_class = trim( $exception_class );
		if ( '' === $normalized_class ) {
			return '';
		}

		if ( 0 !== strpos( $normalized_class, __NAMESPACE__ . '\\' ) ) {
			return '';
		}

		if ( ! class_exists( $normalized_class ) ) {
			return '';
		}

		if ( ! is_subclass_of( $normalized_class, UserFacingException::class ) ) {
			return '';
		}

		/** @var UserFacingException $exception */
		$exception = new $normalized_class();

		return $exception->get_user_message();
	}

	private static function extract_validation_message_from_throwable( \Throwable $throwable ): string {
		$raw_message = trim( (string) $throwable->getMessage() );
		if ( '' === $raw_message ) {
			return '';
		}

		if ( preg_match( '/<faultstring>(.*?)<\\/faultstring>/si', $raw_message, $matches ) ) {
			$raw_message = (string) $matches[1];
		}

		$validation_message = trim( strip_tags( html_entity_decode( $raw_message, ENT_QUOTES, 'UTF-8' ) ) );
		if ( '' === $validation_message ) {
			return '';
		}

		if ( false === stripos( $validation_message, 'walidacji przesyłki' ) ) {
			return '';
		}

		return $validation_message;
	}
}
