package de.gecheckt.pdf.umbenenner.application.port.out;

import java.util.Objects;

import de.gecheckt.pdf.umbenenner.domain.model.AiRequestRepresentation;

/**
 * Represents a technical failure during AI service invocation.
 * <p>
 * The HTTP request could not be sent, or no valid response body was received.
 * This covers network errors, timeouts, endpoint unreachability, connection failures,
 * and other infrastructure-level problems.
 * <p>
 * <strong>Field semantics:</strong>
 * <ul>
 *   <li>{@link #request()} — the request that was attempted to be sent. Stored for
 *       debugging and audit, even though it may not have reached the AI service.</li>
 *   <li>{@link #failureReason()} — a classification of the technical error
 *       (e.g., "TIMEOUT", "ENDPOINT_UNREACHABLE", "CONNECTION_ERROR")</li>
 *   <li>{@link #failureMessage()} — a human-readable description of the error,
 *       suitable for logging and operational troubleshooting</li>
 * </ul>
 * <p>
 * <strong>Retry semantics:</strong> Technical failures are retryable. The Application
 * layer will record this as a transient error, and the document may be retried in
 * a later batch run up to the configured maximum transient-error count.
 * <p>
 * <strong>Distinction from functional errors:</strong> A 200 OK response with an
 * invalid JSON body is NOT a technical failure; it's an invocation success that
 * contains a functional error. Only communication/transport errors are classified here.
 *
 * @param request        the request that was attempted (may not have been successfully sent);
 *                       never null
 * @param failureReason  classification of the error type; never null (may be empty)
 * @param failureMessage human-readable error description; never null (may be empty)
 */
public record AiInvocationTechnicalFailure(
        AiRequestRepresentation request,
        String failureReason,
        String failureMessage) implements AiInvocationResult {

    /**
     * Compact constructor validating mandatory fields.
     *
     * @throws NullPointerException if any field is null
     */
    public AiInvocationTechnicalFailure {
        Objects.requireNonNull(request, "request must not be null");
        Objects.requireNonNull(failureReason, "failureReason must not be null");
        Objects.requireNonNull(failureMessage, "failureMessage must not be null");
    }
}
