<?php
/**
 * Normalizes structured delivery envelopes before user-facing transport.
 *
 * @package Niwa_AI
 */

defined( 'ABSPATH' ) || exit;

class Niwa_AI_Admin_Autonomy_Delivery_Envelope_Normalizer {

	public static function normalize( $payload ) {
		$raw = trim( (string) $payload );
		if ( '' === $raw ) {
			return array(
				'send'      => false,
				'message'   => '',
				'unwrapped' => false,
			);
		}

		$json = self::strip_json_code_fence( $raw );
		if ( '' === $json || '{' !== substr( $json, 0, 1 ) ) {
			return self::plain( (string) $payload );
		}

		$decoded = json_decode( $json, true );
		if (
			! is_array( $decoded )
			|| ! array_key_exists( 'send', $decoded )
			|| ! array_key_exists( 'message', $decoded )
		) {
			$recovered = self::recover_loose_delivery_envelope( $json );
			if ( null !== $recovered ) {
				return $recovered;
			}

			return self::plain( (string) $payload );
		}

		$message = trim( (string) $decoded['message'] );
		return array(
			'send'      => ! empty( $decoded['send'] ) && '' !== $message,
			'message'   => $message,
			'unwrapped' => true,
		);
	}

	private static function plain( $payload ) {
		return array(
			'send'      => '' !== trim( (string) $payload ),
			'message'   => (string) $payload,
			'unwrapped' => false,
		);
	}

	private static function strip_json_code_fence( $payload ) {
		$payload = trim( (string) $payload );
		if ( false === strpos( $payload, '```' ) ) {
			return $payload;
		}

		$stripped = preg_replace( '/^```(?:json)?\s*/i', '', $payload );
		$stripped = preg_replace( '/\s*```$/', '', is_string( $stripped ) ? $stripped : $payload );
		return trim( is_string( $stripped ) ? $stripped : $payload );
	}

	private static function recover_loose_delivery_envelope( $payload ) {
		$payload = trim( (string) $payload );
		if ( 1 !== preg_match( '/^\{\s*"send"\s*:\s*(true|false)\s*,\s*"message"\s*:\s*"(.*)"\s*\}\s*$/is', $payload, $matches ) ) {
			return null;
		}

		$message = self::decode_loose_json_string( isset( $matches[2] ) ? (string) $matches[2] : '' );
		$message = trim( $message );

		return array(
			'send'      => 'true' === strtolower( (string) $matches[1] ) && '' !== $message,
			'message'   => $message,
			'unwrapped' => true,
		);
	}

	private static function decode_loose_json_string( $value ) {
		$decoded = json_decode( '"' . str_replace( '"', '\"', (string) $value ) . '"', true );
		if ( is_string( $decoded ) ) {
			return $decoded;
		}

		return strtr(
			(string) $value,
			array(
				'\\r\\n' => "\n",
				'\\n'   => "\n",
				'\\r'   => "\n",
				'\\t'   => "\t",
				'\\"'   => '"',
				'\\\\'  => '\\',
			)
		);
	}
}
