package de.gecheckt.pdf.umbenenner.domain.model;

import java.util.Objects;

/**
 * Deterministic, complete representation of the request sent to an AI service.
 * <p>
 * This record captures the exact prompt, text, and configuration that were sent
 * to the AI in a single request, allowing for reproducibility and debugging.
 * <p>
 * <strong>Construction:</strong> The Application layer constructs this representation
 * deterministically from:
 * <ul>
 *   <li>The loaded external prompt text</li>
 *   <li>The prompt's stable identifier</li>
 *   <li>The document's extracted PDF text (already limited to max characters)</li>
 *   <li>Structural markers (delimiters, field names) that define the format</li>
 * </ul>
 * <p>
 * <strong>Field semantics:</strong>
 * <ul>
 *   <li>{@link #promptIdentifier()} — stable identifier of the prompt template used</li>
 *   <li>{@link #promptContent()} — the actual prompt text loaded from the external file</li>
 *   <li>{@link #documentText()} — the PDF-extracted text, already limited to the configured
 *       maximum characters before being placed in this representation</li>
 *   <li>{@link #sentCharacterCount()} — the exact number of text characters from
 *       documentText that were included in the request sent to the AI
 *       (may be less than documentText.length() if truncation occurred)</li>
 * </ul>
 * <p>
 * <strong>Persistence:</strong> Both prompt identifier and sent character count
 * are recorded in the processing attempt history for traceability.
 * <p>
 * <strong>Not included:</strong>
 * <ul>
 *   <li>HTTP-specific details (headers, authentication, endpoint URL)</li>
 *   <li>Serialization format (whether sent as JSON, multipart, etc.)</li>
 *   <li>AI provider configuration details</li>
 * </ul>
 *
 * @param promptIdentifier   stable identifier for the prompt template; never null
 * @param promptContent      content of the prompt template; never null (may be empty,
 *                           though typically meaningful)
 * @param documentText       extracted PDF text (already limited to max characters);
 *                           never null (may be empty)
 * @param sentCharacterCount exact number of characters from documentText that were
 *                           sent to the AI; must be &gt;= 0 and &lt;= documentText.length()
 */
public record AiRequestRepresentation(
        PromptIdentifier promptIdentifier,
        String promptContent,
        String documentText,
        int sentCharacterCount) {

    /**
     * Compact constructor validating all fields.
     *
     * @throws NullPointerException if any field except possibly documentText is null
     * @throws IllegalArgumentException if sentCharacterCount is out of valid range
     */
    public AiRequestRepresentation {
        Objects.requireNonNull(promptIdentifier, "promptIdentifier must not be null");
        Objects.requireNonNull(promptContent, "promptContent must not be null");
        Objects.requireNonNull(documentText, "documentText must not be null");
        if (sentCharacterCount < 0 || sentCharacterCount > documentText.length()) {
            throw new IllegalArgumentException(
                    "sentCharacterCount must be >= 0 and <= documentText.length(); " +
                    "got " + sentCharacterCount + " but documentText.length() = " + documentText.length());
        }
    }
}
