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

import java.util.List;
import java.util.Optional;

import de.gecheckt.pdf.umbenenner.application.dto.ModelPriceChangeSet;
import de.gecheckt.pdf.umbenenner.application.dto.ModelPriceEntry;
import de.gecheckt.pdf.umbenenner.application.dto.ModelPriceView;

/**
 * Outbound-Port fuer die Verwaltung persistierter Modell-Preise.
 *
 * <p><strong>Schreibpfad-Konvention:</strong> GUI und CLI nutzen ausschlie&szlig;lich
 * {@link #saveAllChanges(ModelPriceChangeSet)} fuer transaktionale Batch-
 * Speicherungen. Die Methoden {@link #upsert(ModelPriceEntry)} und
 * {@link #delete(String, String)} sind ausschlie&szlig;lich fuer Tests und
 * Werkzeuge gedacht; sie sind keine Bestandteile des regul&auml;ren
 * Bedienpfads.
 *
 * <p>Lesemethoden liefern {@link ModelPriceView} (mit nullable
 * {@link ModelPriceView#updatedAt()} bei besch&auml;digten DB-Werten).
 * Schreibmethoden akzeptieren ausschlie&szlig;lich {@link ModelPriceEntry},
 * dessen Konstruktor s&auml;mtliche Wertgrenzen pr&uuml;ft.
 */
public interface ModelPriceRepository {

    /**
     * Liefert alle persistierten Modell-Preise.
     *
     * @return unveraenderbare Liste aller Eintraege; nie {@code null}
     */
    List<ModelPriceView> findAll();

    /**
     * Liefert den Preis-Eintrag zu einem Composite-Key.
     *
     * @param provider  Provider-Identifikator
     * @param modelName Modellname
     * @return {@link Optional} mit Eintrag, leer wenn nicht vorhanden
     */
    Optional<ModelPriceView> findByProviderAndModelName(String provider, String modelName);

    /**
     * Atomarer Insert oder Update.
     *
     * <p>@internal Nicht von GUI/CLI direkt verwenden – nur fuer Tests/Werkzeuge.
     * Der regulaere Bedienpfad verlaeuft ueber
     * {@link #saveAllChanges(ModelPriceChangeSet)}.
     *
     * @param entry zu schreibender Eintrag; nicht {@code null}
     */
    void upsert(ModelPriceEntry entry);

    /**
     * Loescht den Eintrag eines Composite-Keys.
     *
     * <p>@internal Nicht von GUI/CLI direkt verwenden – nur fuer Tests/Werkzeuge.
     * Der regulaere Bedienpfad verlaeuft ueber
     * {@link #saveAllChanges(ModelPriceChangeSet)}.
     *
     * @param provider  Provider-Identifikator
     * @param modelName Modellname
     */
    void delete(String provider, String modelName);

    /**
     * Persistiert eine Sammlung von Preisaenderungen atomar.
     *
     * <p>Die Konfliktvalidierung des ChangeSets erfolgt vor der Transaktion im
     * Use Case. Die Implementierung fuehrt alle Operationen innerhalb einer
     * JDBC-Transaktion mit {@code autoCommit=false} aus und rollt bei
     * Auftreten eines Fehlers vollstaendig zurueck.
     *
     * @param changeSet Sammlung aus Upserts und Loeschungen; nicht {@code null}
     */
    void saveAllChanges(ModelPriceChangeSet changeSet);
}
