package com.arms.egovframework.javaservice.esframework.model.vo;

import static java.util.stream.Collectors.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import lombok.Getter;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DocumentResultWrapper<T> implements SearchDocResult {

    private final SearchHits<T> searchHits;

    private final Class<T> clazz;

    @Getter
    private final Long totalHits;

    @Getter
    private final List<Object> lastSortValue;

    public DocumentResultWrapper(SearchHits<T> searchHits, Class<T> clazz) {
        this.totalHits = searchHits.getTotalHits();
        this.searchHits = searchHits;
        this.clazz = clazz;
        int hitsSize = searchHits.getSearchHits().size();
        int lastIndex = hitsSize - 1;
        if(lastIndex>-1){
             this.lastSortValue = searchHits.getSearchHits().get(lastIndex).getSortValues();
        }else{
            this.lastSortValue = new ArrayList<>();
        }
    }

    public List<T> toDocs() {
        return this.searchHits
                .stream()
                .map(SearchHit::getContent)
                .collect(toList());
    }

    public List<SearchHit<T>> toHitDocs() {
         return this.searchHits.getSearchHits();
    }

    public T findFirst() {
        return getT(false);
    }

    private T getT(boolean warningVisible) {
        List<SearchHit<T>> searchHitsDocs = this.toHitDocs();

        if(warningVisible&&searchHitsDocs.size()>1){
            log.warn("2건 이상이 조회 되었습니다.");
        }

        return searchHitsDocs
                .stream()
                .filter(a -> a.getIndex() != null)
                .sorted(Comparator.comparing(SearchHit::getIndex, Comparator.reverseOrder()))
                .map(SearchHit::getContent)
                .findFirst()
                .orElseGet(() -> {
                    try {
                        return clazz.getConstructor().newInstance();
                    } catch (Exception e){
                        throw new IllegalArgumentException(e.getMessage());
                    }
                });
    }


    public T fetchOnlyOne() {
        return getT(true);
    }

}
