package org.pdxfinder.repositories;

import org.pdxfinder.dao.Group;
import org.pdxfinder.dao.Patient;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

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

@Repository
public interface PatientRepository extends Neo4jRepository<Patient, Long> {

    Set<Patient> findBySex(String sex);

    @Query("MATCH (p:Patient)--(g:Group) WHERE p.externalId = {externalId} AND id(g) = {g} RETURN p")
    Patient findByExternalIdAndGroup(@Param("externalId") String externalId, @Param("g") Group g);

    @Query("MATCH (mod:ModelCreation)-[ii:IMPLANTED_IN]-(s:Sample) " +
            "MATCH (s:Sample)-[sf:SAMPLED_FROM]-(ps:PatientSnapshot)-[pt:PATIENT]-(p:Patient) " +
            "WHERE mod.sourcePdxId = {modelId} " +
            "RETURN mod, ii, s, ps, p, sf, pt")
    Patient findByModelId(@Param("modelId") String modelId);

    @Query("MATCH (mod:ModelCreation)-[ii:IMPLANTED_IN]-(s:Sample) " +
            "MATCH (s:Sample)--(ps:PatientSnapshot)--(p:Patient) " +
            "WHERE s.sourceSampleId = {sampleId} " +
            "RETURN mod, ii, s, ps, p")
    Patient findBySampleId(@Param("sampleId") String sampleId);


    @Query("MATCH (mod:ModelCreation)-[ii:IMPLANTED_IN]-(s:Sample) " +
            "MATCH (s:Sample)-[sf:SAMPLED_FROM]-(ps:PatientSnapshot)-[pt:PATIENT]-(p:Patient)-[ext:GROUP]-(extdsos:Group) " +
            "WHERE mod.sourcePdxId = {modelId} " +
            "AND toLower(s.dataSource) = toLower({dataSource}) "+
            "RETURN mod, ii, s, ps, p, sf, pt, ext, extdsos")
    Patient findByDataSourceAndModelId(@Param("dataSource") String dataSource, @Param("modelId") String modelId);



    @Query("MATCH(pat:Patient)-[patRel:PATIENT]-(ps:PatientSnapshot)-[sfrm:SAMPLED_FROM]-(psamp:Sample)-[char:CHARACTERIZED_BY]-(molch:MolecularCharacterization)-[assoc:ASSOCIATED_WITH]->(mAss:MarkerAssociation)-[aw:MARKER]-(m:Marker) " +
            "WITH pat,patRel,ps,sfrm,psamp,char,molch,mAss,m " +
            "Match (psamp)-[imp:IMPLANTED_IN]-(mc:ModelCreation) " +
            "            WHERE  psamp.dataSource = {dataSource}  " +
            "            AND    mc.sourcePdxId = {modelId}  " +
            "            AND    (mc.technology = {tech}  OR {tech} = '' ) " +


            "            OR toLower(m.symbol) CONTAINS toLower({search})" +
            "            OR toLower(mc.technology) CONTAINS toLower({search})" +
            "            OR any( property in keys(mAss) where toLower(mAss[property]) CONTAINS toLower({search}) )  " +

            "            RETURN pat,patRel,ps,sfrm,psamp,char,molch,mAss,m SKIP {skip} LIMIT {lim} ")
    Set<Patient> findSpecimenBySourcePdxIdAndPlatform(@Param("dataSource") String dataSource,
                                                       @Param("modelId") String modelId,
                                                       @Param("tech") String tech,
                                                       @Param("search") String search,
                                                       @Param("skip") int skip,
                                                       @Param("lim") int lim);





    @Query("MATCH(pat:Patient)-[patRel:PATIENT]-(ps:PatientSnapshot)-[sfrm:SAMPLED_FROM]-(psamp:Sample)-[char:CHARACTERIZED_BY]-(molch:MolecularCharacterization)-[assoc:ASSOCIATED_WITH]->(mAss:MarkerAssociation)-[aw:MARKER]-(m:Marker) " +
            "WITH pat,patRel,ps,sfrm,psamp,char,molch,mAss,m " +
            "Match (psamp)-[imp:IMPLANTED_IN]-(mc:ModelCreation) " +
            "            WHERE  psamp.dataSource = {dataSource}  " +
            "            AND    mc.sourcePdxId = {modelId}  " +
            "            AND    (mc.technology = {tech}  OR {tech} = '' ) " +

            "            OR toLower(m.symbol) CONTAINS toLower({search}) " +
            "            OR toLower(mc.technology) CONTAINS toLower({search}) " +
            "            OR any( property in keys(mAss) where toLower(mAss[property]) CONTAINS toLower({search}) )  " +
            "            RETURN count(*) ")
    Integer countByBySourcePdxIdAndPlatform(@Param("dataSource") String dataSource,
                                                      @Param("modelId") String modelId,
                                                      @Param("tech") String tech,
                                                      @Param("search") String search);



    @Query("MATCH (p:Patient)--(ps:PatientSnapshot)--(s:Sample)--(mod:ModelCreation) " +
            "WHERE mod.dataSource = {dataSource} " +
            "AND mod.sourcePdxId = {modelId} " +
            "WITH p " +
            "MATCH (p:Patient)--(ps:PatientSnapshot)--(s:Sample)--(mod:ModelCreation) " +
            "WHERE mod.sourcePdxId <> {modelId} " +
            "RETURN DISTINCT mod.sourcePdxId ORDER BY mod.sourcePdxId")
    List<String> getModelsOriginatedFromSamePatientByDataSourceAndModelId(@Param("dataSource") String dataSource,
                                                                          @Param("modelId") String modelId);


    @Query("MATCH (ps:PatientSnapshot)-[ce:COLLECTION_EVENT]-(p:Patient)--(g:Group) WHERE p.externalId = {externalId} AND id(g) = {g} RETURN p, ce, ps")
    Patient findByExternalIdAndGroupWithSnapshots(@Param("externalId") String externalId, @Param("g") Group g);
}

@@ -5236,51 +5236,8 @@
 TCH 
-(ps:PatientSnapshot)-%5Bce:COLLECTION_EVENT%5D-
 (p:P
@@ -5297,32 +5297,131 @@
 AND id(g) = %7Bg%7D 
+%22 +%0A            %22WITH p %22 +%0A            %22OPTIONAL MATCH (p)--(ps:PatientSnapshot) %22 +%0A            %22
 RETURN p, ce, ps
@@ -5417,12 +5417,8 @@
 N p,
- ce,
  ps%22

Optimize method