package cz.moneta.test.harness.messaging;

import org.assertj.core.api.AbstractObjectAssert;

/**
 * Response interface for received messages.
 * Provides assertion methods for verifying message content.
 * Shared interface for both Kafka and IBM MQ message responses.
 */
public interface MessageResponse {

    /**
     * Assert that a field in the message body has the expected value.
     * For JSON: uses JSON path (dot/bracket notation).
     * For XML: uses XPath expression.
     *
     * @param path    JSON path or XPath expression
     * @param value   expected value as string
     * @return this instance for fluent assertions
     * @throws AssertionError if assertion fails
     */
    MessageResponse andAssertFieldValue(String path, String value);

    /**
     * Assert that a field exists in the message body.
     *
     * @param path JSON path or XPath expression
     * @return this instance for fluent assertions
     * @throws AssertionError if assertion fails
     */
    MessageResponse andAssertPresent(String path);

    /**
     * Assert that a field does not exist in the message body.
     *
     * @param path JSON path or XPath expression
     * @return this instance for fluent assertions
     * @throws AssertionError if assertion fails
     */
    MessageResponse andAssertNotPresent(String path);

    /**
     * Assert that a header (Kafka header or JMS property) has the expected value.
     *
     * @param headerName name of the header/property
     * @param value      expected value
     * @return this instance for fluent assertions
     * @throws AssertionError if assertion fails
     */
    MessageResponse andAssertHeaderValue(String headerName, String value);

    /**
     * Assert that the message body contains a substring.
     * Primarily used for EBCDIC/UTF-8 raw text assertions.
     *
     * @param substring expected substring
     * @return this instance for fluent assertions
     * @throws AssertionError if assertion fails
     */
    MessageResponse andAssertBodyContains(String substring);

    /**
     * Get AssertJ fluent assertion for complex object assertions.
     *
     * @return AssertJ AbstractObjectAssert for fluent assertions
     */
    AbstractObjectAssert<?, ?> andAssertWithAssertJ();

    /**
     * Extract a value from the message body.
     * For JSON: uses JSON path (dot/bracket notation).
     * For XML: uses XPath expression.
     *
     * @param path JSON path or XPath expression
     * @return JsonPathValue wrapper for the extracted value
     */
    JsonPathValue extract(String path);

    /**
     * Deserialize the message body to a Java object.
     * For JSON: uses Jackson ObjectMapper.
     * For XML: uses JAXB or Jackson XmlMapper.
     *
     * @param type target type
     * @param <T>  target type
     * @return deserialized object
     */
    <T> T mapTo(Class<T> type);

    /**
     * Get the raw message body.
     *
     * @return message body as string
     */
    String getBody();

    /**
     * Get a header value (Kafka header or JMS property).
     *
     * @param name header/property name
     * @return header value or null if not present
     */
    String getHeader(String name);

    /**
     * Get the underlying received message.
     *
     * @return ReceivedMessage instance
     */
    ReceivedMessage getMessage();
}
