package de.gecheckt.pdf.umbenenner.application.usecase;

import java.util.Objects;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.gecheckt.pdf.umbenenner.application.port.out.DocumentPersistenceException;
import de.gecheckt.pdf.umbenenner.application.port.out.UnitOfWorkPort;
import de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint;

/**
 * Use-Case-Implementierung für den feldgenauen Status-Reset aus dem Historien-Tab.
 * <p>
 * Setzt ausschließlich die vier fachlich relevanten Status-Felder zurück,
 * ohne die Versuchshistorie zu löschen:
 * <ul>
 *   <li>{@code overall_status} → {@code READY_FOR_AI}</li>
 *   <li>{@code content_error_count} → {@code 0}</li>
 *   <li>{@code transient_error_count} → {@code 0}</li>
 *   <li>{@code last_failure_instant} → {@code null}</li>
 * </ul>
 * Nicht geändert werden: {@code created_at}, {@code last_success_instant},
 * {@code last_target_path}, {@code last_target_file_name} sowie alle
 * {@code processing_attempt}-Einträge, die vollständig erhalten bleiben.
 * <p>
 * Nach dem Reset gilt das Dokument beim nächsten Verarbeitungslauf als verarbeitbar,
 * da {@code READY_FOR_AI} der einzige Trigger für die Verarbeitungslogik ist.
 * <p>
 * <strong>Abgrenzung:</strong> Dieser Use-Case unterscheidet sich von
 * {@link DefaultResetDocumentStatusUseCase}, der alle Persistenzdaten (Stammsatz und
 * Versuchshistorie) vollständig löscht und das Dokument so behandelt, als wäre es
 * noch nie verarbeitet worden.
 */
public class DefaultHistoryResetDocumentStatusUseCase {

    private static final Logger logger = LogManager.getLogger(DefaultHistoryResetDocumentStatusUseCase.class);

    private final UnitOfWorkPort unitOfWorkPort;

    /**
     * Erzeugt den Use-Case mit dem erforderlichen Persistenz-Port.
     *
     * @param unitOfWorkPort Port für transaktionale Persistenzoperationen; darf nicht {@code null} sein
     * @throws NullPointerException wenn {@code unitOfWorkPort} null ist
     */
    public DefaultHistoryResetDocumentStatusUseCase(UnitOfWorkPort unitOfWorkPort) {
        this.unitOfWorkPort = Objects.requireNonNull(unitOfWorkPort, "unitOfWorkPort darf nicht null sein");
    }

    /**
     * Führt den feldgenauen Status-Reset für den angegebenen Fingerprint durch.
     * <p>
     * Die Operation ist atomar: entweder werden alle vier Felder aktualisiert,
     * oder keine Änderung findet statt (Rollback).
     *
     * @param fingerprint der Dokumentbezeichner, dessen Status zurückgesetzt werden soll;
     *                    darf nicht {@code null} sein
     * @throws DocumentPersistenceException bei technischen Datenbankfehlern
     * @throws NullPointerException         wenn {@code fingerprint} null ist
     */
    public void resetStatus(DocumentFingerprint fingerprint) {
        Objects.requireNonNull(fingerprint, "fingerprint darf nicht null sein");

        unitOfWorkPort.executeInTransaction(tx -> tx.resetDocumentStatusForRetry(fingerprint));

        logger.info("Feldgenauer Status-Reset durchgeführt für Fingerprint: {}", fingerprint.sha256Hex());
    }
}
