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

import java.util.Objects;

import de.gecheckt.pdf.umbenenner.application.dto.AiUsageMetadata;
import de.gecheckt.pdf.umbenenner.domain.model.AiRawResponse;
import de.gecheckt.pdf.umbenenner.domain.model.AiRequestRepresentation;

/**
 * Represents successful HTTP communication with an AI service.
 * <p>
 * The HTTP request was sent and a response body was received. This indicates
 * technical success of the communication, but does NOT guarantee that the response
 * content is valid, parseable, or functionally usable.
 * <p>
 * <strong>Field semantics:</strong>
 * <ul>
 *   <li>{@link #request()} — the exact request that was sent to the AI service,
 *       including prompt, document text, and character counts</li>
 *   <li>{@link #rawResponse()} — the uninterpreted response body returned by the AI,
 *       which may be valid JSON, malformed, empty, or otherwise problematic</li>
 *   <li>{@link #usageMetadata()} — Token-Verbrauchsmetadaten des Aufrufs;
 *       nie {@code null}, einzelne Felder koennen aber {@code null} sein,
 *       wenn der Provider keine Werte oder ungueltige Werte liefert</li>
 * </ul>
 * <p>
 * The Application layer is responsible for:
 * <ul>
 *   <li>Parsing the raw response (JSON extraction, field validation)</li>
 *   <li>Distinguishing between parseable and unparseable responses</li>
 *   <li>Validating the content against rules (title length, date format, etc.)</li>
 *   <li>Classifying any failures as technical or functional</li>
 * </ul>
 * <p>
 * <strong>Persistence:</strong> Both request and response are stored in the
 * processing attempt history for debugging and audit. Token-Daten aus
 * {@link #usageMetadata()} werden zusammen mit einem Preis-Snapshot in
 * {@code processing_attempt} persistiert.
 *
 * @param request       the AI request that was sent; never null
 * @param rawResponse   the uninterpreted response body; never null (but may be empty)
 * @param usageMetadata Token-Verbrauchsmetadaten; never null (kann aber {@link AiUsageMetadata#empty()} sein)
 */
public record AiInvocationSuccess(
        AiRequestRepresentation request,
        AiRawResponse rawResponse,
        AiUsageMetadata usageMetadata) implements AiInvocationResult {

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