package at.procon.ted.repository;

import at.procon.ted.model.entity.TedDailyPackage;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

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

/**
 * Repository für TED Daily Package Entities.
 *
 * @author Martin.Schweitzer@procon.co.at and claude.ai
 */
@Repository
public interface TedDailyPackageRepository extends JpaRepository<TedDailyPackage, UUID> {

    /**
     * Findet ein Package anhand des Identifiers (YYYYSSSSS).
     */
    Optional<TedDailyPackage> findByPackageIdentifier(String packageIdentifier);

    /**
     * Findet ein Package anhand von Jahr und Seriennummer.
     */
    Optional<TedDailyPackage> findByYearAndSerialNumber(Integer year, Integer serialNumber);

    /**
     * Prüft ob ein Package bereits existiert.
     */
    boolean existsByPackageIdentifier(String packageIdentifier);

    /**
     * Findet das zuletzt erfolgreich heruntergeladene Package.
     */
    @Query("SELECT p FROM TedDailyPackage p " +
           "WHERE p.downloadStatus IN ('DOWNLOADED', 'PROCESSING', 'COMPLETED') " +
           "ORDER BY p.year DESC, p.serialNumber DESC " +
           "LIMIT 1")
    Optional<TedDailyPackage> findLatestDownloaded();

    /**
     * Findet das Package mit der höchsten Seriennummer für ein bestimmtes Jahr.
     */
    @Query("SELECT p FROM TedDailyPackage p " +
           "WHERE p.year = :year " +
           "ORDER BY p.serialNumber DESC " +
           "LIMIT 1")
    Optional<TedDailyPackage> findLatestByYear(@Param("year") Integer year);

    /**
     * Findet das Package mit der niedrigsten Seriennummer für ein bestimmtes Jahr.
     */
    @Query("SELECT p FROM TedDailyPackage p " +
           "WHERE p.year = :year " +
           "ORDER BY p.serialNumber ASC " +
           "LIMIT 1")
    Optional<TedDailyPackage> findFirstByYear(@Param("year") Integer year);

    /**
     * Findet alle Packages mit einem bestimmten Status.
     */
    List<TedDailyPackage> findByDownloadStatus(TedDailyPackage.DownloadStatus status);

    /**
     * Findet alle Packages die noch verarbeitet werden müssen.
     */
    @Query("SELECT p FROM TedDailyPackage p " +
           "WHERE p.downloadStatus IN ('DOWNLOADED', 'PROCESSING') " +
           "ORDER BY p.year ASC, p.serialNumber ASC")
    List<TedDailyPackage> findPendingProcessing();

    /**
     * Checks if there is a NOT_FOUND package directly after the given serial number.
     * Returns 1 if the next package (fromSerial+1) is NOT_FOUND, 0 otherwise.
     */
    @Query("SELECT COUNT(p) FROM TedDailyPackage p " +
           "WHERE p.year = :year " +
           "AND p.serialNumber = :fromSerial + 1 " +
           "AND p.downloadStatus = 'NOT_FOUND'")
    long countConsecutiveNotFound(@Param("year") Integer year, @Param("fromSerial") Integer fromSerial);

    /**
     * Findet alle Packages eines Jahres.
     */
    List<TedDailyPackage> findByYearOrderBySerialNumberAsc(Integer year);
}
