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

import de.gecheckt.pdf.umbenenner.domain.model.PdfExtractionResult;
import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate;

/**
 * Outbound port for extracting text content and page count from a PDF document.
 * <p>
 * This interface abstracts PDF text extraction, allowing the application layer
 * to remain independent of the underlying PDF library or extraction mechanism.
 * <p>
 * Responsibilities of the implementing adapter:
 * <ul>
 *   <li>Read the PDF file identified by the candidate</li>
 *   <li>Extract all text content from the PDF</li>
 *   <li>Count the total number of pages</li>
 *   <li>Distinguish between content errors (PDF exists but is not extractable) and technical errors</li>
 *   <li>Return a structured {@link PdfExtractionResult} encoding success or failure type</li>
 *   <li>Encapsulate all PDF library details (no PDFBox types appear in domain/application)</li>
 * </ul>
 * <p>
 * Architecture notes:
 * <ul>
 *   <li>The adapter implementation is the ONLY place where PDFBox appears in the codebase</li>
 *   <li>Results are returned as structured types, never as exceptions thrown</li>
 *   <li>The three result variants ({@code PdfExtractionSuccess}, {@code PdfExtractionContentError},
 *       {@code PdfExtractionTechnicalError}) allow callers to distinguish recoverable from non-recoverable failures</li>
 * </ul>
 * <p>
 * Non-goals of this port (handled in later milestones):
 * <ul>
 *   <li>Validation of extracted text content (e.g., minimum length, character sets)</li>
 *   <li>Checking page count against limits</li>
 *   <li>Any form of document fingerprinting</li>
 *   <li>Persistence or caching of results</li>
 * </ul>
 *
 */
public interface PdfTextExtractionPort {

    /**
     * Extracts text content and page count from a single PDF document.
     * <p>
     * Performs a single extraction operation and returns the result.
     * Errors are never thrown as exceptions; they are encoded in the result type.
     * <p>
     * The candidate parameter serves as both:
     * <ul>
     *   <li>Document identification (e.g., filename for logging)</li>
     *   <li>Adapter guidance (the adapter uses the candidate's identifier to locate the actual file)</li>
     * </ul>
     *
     * @param candidate the document to extract; non-null
     * @return a {@link PdfExtractionResult} encoding the outcome:
     *         <ul>
     *           <li>Success: contains extracted text and page count</li>
     *           <li>Content error: PDF exists but is not extractable (e.g., image-only, encrypted)</li>
     *           <li>Technical error: I/O failure, PDFBox library error, etc.</li>
     *         </ul>
     * @throws NullPointerException if candidate is null
     * @see PdfExtractionResult
     */
    PdfExtractionResult extractTextAndPageCount(SourceDocumentCandidate candidate);
}
