package com.arms.api.issue.almapi.service;

import com.arms.api.issue.almapi.model.entity.AlmIssueEntity;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;

public class EsDataValidationTest {

    final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    private final Function<String,LinkedListVO> retrieveAlmF;

    public EsDataValidationTest(EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper,Function<String,LinkedListVO> retrieveAlmF) {
        this.esCommonRepositoryWrapper = esCommonRepositoryWrapper;
        this.retrieveAlmF = retrieveAlmF;
    }
    public void dataValid(List<AlmIssueEntity> docs){
        AlmIssueEntity reqEntity = docs.stream().filter(AlmIssueEntity::izReqTrue).findAny().get();

        assertThat(reqEntity).isNotNull();

        for (AlmIssueEntity doc : docs) {

            if(doc.izReqTrue()){
                assertThat(doc.getUpperKey()).isNull();
                assertThat(doc.getParentReqKey()).isNull();
                assertThat(doc.getPdServiceId()).isNotNull();
                assertThat(doc.getPdServiceVersions()).isNotNull();
                assertThat(doc.getCReqLink()).isNotNull();
                assertThat(doc.getCReqProperty()).isNotNull();
                assertThat(doc.getRecentId()).isEqualTo(doc.getJira_server_id()+"_"+doc.getProject().getKey()+"_"+doc.getKey());
            }
            if(doc.izReqFalse()){

                if(doc.getUpperKey()==null&&doc.getParentReqKey()==null){
                    assertThat(doc.getCReqLink()).isNull();
                    assertThat(doc.getCReqProperty()).isNull();
                    assertThat(doc.getRecentId()).isEqualTo(doc.getJira_server_id()+"_"+doc.getProject().getKey()+"_"+doc.getKey());
                }

                if(doc.getUpperKey()!=null||doc.getParentReqKey()!=null){
                    assertThat(doc.getUpperKey()).isNotNull();
                    assertThat(doc.getParentReqKey()).isNotNull();
                    assertThat(doc.getRecentId()).isEqualTo(doc.getJira_server_id()+"_"+doc.getProject().getKey()+"_"+doc.getKey());
                }
            }
        }

        Map<String, AlmIssueEntity> entityMap
                = docs.stream().collect(Collectors.toMap(AlmIssueEntity::getRecentId, a -> a));

        List<AlmIssueEntity> almIssueEntities = docs.stream().toList();

        for (AlmIssueEntity almIssueEntity : almIssueEntities) {

            LinkedListVO vo = retrieveAlmF.apply(almIssueEntity.getKey());

            if(!almIssueEntity.getKey().equals(vo.getKey())){
                almIssueEntity = almIssueEntities.stream().filter(a->a.getKey().equals(vo.getKey())).findAny(). get();
            }

            if(almIssueEntity.getLinkedIssues() == null){
                assertThat(vo.getList()).isEmpty();
            }else{
                for (String linkedIssue : almIssueEntity.getLinkedIssues()) {
                    AlmIssueEntity actual = entityMap.get(linkedIssue);
                    assertThat(actual).isNotNull();
                    assertThat(actual.getLinkedIssues().contains(almIssueEntity.getRecentId())).isTrue();
                }
            }
        }

        List<AlmIssueEntity> isReqFalseList = almIssueEntities.stream().filter(AlmIssueEntity::izReqFalse).toList();

        Set<String> isReqTrueSet = almIssueEntities.stream().filter(AlmIssueEntity::izReqTrue).map(AlmIssueEntity::getRecentId).collect(Collectors.toSet());

        for (AlmIssueEntity almIssueEntity : isReqFalseList) {
            Queue<String> queue = new LinkedList<>();
            Set<String> visited = new HashSet<>();
            queue.add(almIssueEntity.getRecentId());
            boolean findReqFlag = false;
            while(!queue.isEmpty()){
                String poll = queue.poll();
                if(!visited.contains(poll)){
                    visited.add(poll);
                    AlmIssueEntity almIssueEntity1 = entityMap.get(poll);
                    assertThat(almIssueEntity1).isNotNull();
                    if(isReqTrueSet.contains(poll)){
                        findReqFlag = true;
                        queue.clear();
                    }else{
                        for (AlmIssueEntity upperKey : esCommonRepositoryWrapper.findRecentHits(SimpleQuery.termQueryFilter("upperKey", almIssueEntity1.getKey())).toDocs()) {
                            queue.add(upperKey.getRecentId());
                        }
                        queue.addAll(almIssueEntity1.getLinkedIssues());
                        if(almIssueEntity1.getUpperKey()!=null){
                            queue.add(almIssueEntity1.getJira_server_id()+"_"+almIssueEntity1.getProject().getKey()+"_"+almIssueEntity1.getUpperKey());
                        }
                    }
                }
            }
            assertThat(findReqFlag).isTrue();
        }
    }
}
