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

import java.util.Objects;

/**
 * Opaque locator that allows an adapter to re-find the physical document
 * that was originally discovered by the source-scan adapter.
 * <p>
 * <strong>This type is deliberately opaque to Domain and Application.</strong>
 * Neither layer interprets or constructs the contained value. Only adapters
 * read and write the {@code value} field:
 * <ul>
 *   <li>The {@code SourceDocumentCandidatesPort} adapter writes the value when
 *       constructing a {@link SourceDocumentCandidate}.</li>
 *   <li>The {@code PdfTextExtractionPort} adapter reads the value to locate
 *       the physical file for extraction.</li>
 * </ul>
 * <p>
 * The value itself is an adapter-internal convention (e.g. an absolute path string).
 * Domain and Application never interpret it — they only pass it through.
 * This preserves the hexagonal boundary: no {@code java.nio.file.Path},
 * {@code java.io.File}, or other infrastructure types appear outside the adapter layer.
 * <p>
 * Coupling: Both the scan adapter and the extraction adapter live in the same
 * {@code adapter-out} module and share the same encoding convention for the value.
 * This is an intentional intra-adapter contract, not a cross-layer concern.
 */
public record SourceDocumentLocator(String value) {

    /**
     * Compact constructor with validation.
     *
     * @param value non-null, non-empty opaque locator value; content is an adapter-internal convention
     * @throws NullPointerException     if value is null
     * @throws IllegalArgumentException if value is empty
     */
    public SourceDocumentLocator {
        Objects.requireNonNull(value, "value must not be null");
        if (value.isEmpty()) {
            throw new IllegalArgumentException("value must not be empty");
        }
    }
}
