package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository;

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

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionarySummaryResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.TypeRankSummary;

public interface TypeRepository extends JpaRepository<TypeEntity, String> {

    @Query("select t from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and "
           + "(CASE "
           + "  WHEN :dossierId is null THEN t.dossierId is null "
           + "  WHEN :dossierId is not null THEN t.dossierId = :dossierId "
           + "END) and t.rank = :rank  and t.softDeletedTime is null")
    List<TypeEntity> findByDossierTemplateIdAndDossierIdAndRank(@Param("dossierTemplateId") String dossierTemplateId,
                                                                @Param("dossierId") String dossierId,
                                                                @Param("rank") int rank);


    List<TypeEntity> findByDossierId(String dossierId);


    @Query("select t from TypeEntity t where t.id = :typeId and t.softDeletedTime is null")
    Optional<TypeEntity> findByIdAndNotDeleted(@Param("typeId") String typeId);


    @Modifying
    @Query("update TypeEntity t set t.version = t.version + 1 where t.id = :typeId")
    void updateByIdSetIncrementVersionByOne(@Param("typeId") String typeId);


    @Query("select t from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and t.type = :type and t.dossierId is not null")
    List<TypeEntity> getAllDossierTypesForDossierTemplateAndType(@Param("dossierTemplateId") String dossierTemplateId, @Param("type") String type);


    @Query("select t from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and t.dossierId is null")
    List<TypeEntity> getAllTypesForDossierTemplate(@Param("dossierTemplateId") String dossierTemplateId);

    @Query("select t from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and t.dossierId is null and t.systemManaged = false")
    List<TypeEntity> getAllTypesForDossierTemplateWithoutSystemManagedTypes(@Param("dossierTemplateId") String dossierTemplateId);


    @Query("select t from TypeEntity t where t.dossierTemplateId = :dossierTemplateId or t.dossierId = :dossierId")
    List<TypeEntity> findAllTypesByDossierTemplateIdOrDossierId(@Param("dossierTemplateId") String dossierTemplateId, @Param("dossierId") String dossierId);


    List<TypeEntity> findAllByDossierTemplateIdAndDossierId(String dossierTemplateId, String dossierId);


    @Query("select coalesce(sum(t.version), 0) from TypeEntity t where t.dossierId = :dossierId")
    long getVersionForDossierId(@Param("dossierId") String dossierId);


    @Query("select coalesce(sum(t.version), 0) from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and t.dossierId is null")
    long getVersionForDossierTemplateId(@Param("dossierTemplateId") String dossierTemplateId);


    @Query("""
            select new com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionarySummaryResponse(dt.id, t.id, t.type, t.label, count(e))
            from DossierTemplateEntity dt
            left join TypeEntity t on t.dossierTemplateId = dt.id
            left join DictionaryEntryEntity e on e.typeId = t.id
            where t.softDeletedTime is null and dt.id in :dossierTemplateIds and t.dossierId is null and (e.entryId is null or e.deleted = false)
            group by dt.id, t.id, t.type, t.label""")
    List<DictionarySummaryResponse> findDictionarySummaryList(@Param("dossierTemplateIds") Set<String> dossierTemplateIds);


    @Query("""
            select new com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.TypeRankSummary(t.dossierTemplateId, t.dossierId, t.rank, count(t))
            from TypeEntity t where t.dossierTemplateId = :dossierTemplateId and t.softDeletedTime is null
            group by t.dossierTemplateId, t.dossierId, t.rank
            order by t.rank""")
    List<TypeRankSummary> findTypeRankSummaryList(@Param("dossierTemplateId") String dossierTemplateId);


    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("Update TypeEntity t set t.softDeletedTime = offset_datetime where t.id = :typeId")
    void softDeleteTypeById(@Param("typeId") String typeId);


    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("Update TypeEntity t set t.softDeletedTime = null where t.id = :typeId and t.softDeletedTime is not null")
    int unSoftDeleteTypeById(@Param("typeId") String typeId);


    @Modifying
    @Query("Update TypeEntity t set t.rank = :newRank, t.version = t.version + 1 where t.id = :typeId")
    void updateRankForType(@Param("typeId") String typeId, @Param("newRank") int newRank);


    @Modifying
    @Query("update TypeEntity t set t.version = :version, t.aiCreationVersion = :aiCreationVersion where t.id = :typeId")
    void updateVersionsForType(@Param("typeId") String typeId, @Param("version") long version, @Param("aiCreationVersion") long aiCreationVersion);

}
