package kr.gmtc.gw.elastic.services;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.BaseQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.stereotype.Service;

import kr.gmtc.gw.elastic.parser.logingIndex.ParserAade;
import kr.gmtc.gw.elastic.parser.replayLog.ParserAILocation;
import kr.gmtc.gw.elastic.parser.replayLog.ParserAna;
import kr.gmtc.gw.elastic.parser.replayLog.ParserFusion;
import kr.gmtc.gw.elastic.parser.replayLog.ParserRoute;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;

@Service
public class ElkSearchService {
    
    private ElasticsearchOperations elasticsearchOperations;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final String INDEX_NAME = "replay_log_*";

    private List<ElasticResultMsgVO> logMsgMatches;

    private ParserFusion logParser;

    public ElkSearchService(ElasticsearchOperations elasticsearchOperations){
        this.elasticsearchOperations = elasticsearchOperations;

        logMsgMatches = new ArrayList<ElasticResultMsgVO>();
        //logParser = new ReplayLogParser_Route();
        logParser = new ParserFusion();
    }

    public String elkSearch_replay_log(String sLogType, String sStartDt, String sEndDt) {

        // String sLogType = "3"; // 재생용 로그 S/W구분
        // String sStart_tm = "20240219160000.000"; // 일시(from)
        // String sEnd_tm = "20240219170000.000";   // 일시(to)

        List<Object> sAfter = null;   // 일시(to)

        //logMsgMatches = new ArrayList<ElasticResultMsgVO>();

        String esQuery =    "{                                                   " + //
                            "    \"bool\" : {                                    " + //
                            "      \"filter\" : [                                " + //
                            "        { \"terms\" : {                             " + //
                            "            \"header.msg_type.keyword\" : [         " + //
                            "              "+ sLogType +"             ] } },    " + //
                            "        { \"range\" : {                             " + //
                            "            \"header.recv_time\" : {                " + //
                            "              \"from\" : \""+ sStartDt +"\",        " + //
                            "                \"to\" : \""+ sEndDt +"\" } } } ] } " + //
                            "}";
                        
        Query searchQuery = new StringQuery(esQuery);

        // 한번에 가져올 row수 설정
        ((BaseQuery) searchQuery).setMaxResults(1000);

        // 데이터 정렬할 필드 설정 
        searchQuery.addSort(Sort.by(new Sort.Order(Sort.Direction.ASC, "header.recv_time.keyword")));

        LocalDateTime dt_before = LocalDateTime.now();

        while (true) {

            searchQuery.setSearchAfter(sAfter);

            // 검색 요청하여 검색 결과 가져오기
            SearchHits<ElasticResultMsgVO> searchHits = elasticsearchOperations.search(searchQuery, ElasticResultMsgVO.class, IndexCoordinates.of(INDEX_NAME));

            if (searchHits.getTotalHits() <= 0) break;
            
            Duration diff = Duration.between(dt_before, LocalDateTime.now());
            
            logger.info("elastic Call " + searchHits.getTotalHits() + "건 " + diff.toMillis() + "msec");

            sAfter = searchHits.toList().get(searchHits.toList().size() -1).getSortValues();

            // IndexFusion Object에 데이터 담기
            searchHits.forEach(srcHit -> {
                logMsgMatches.add(srcHit.getContent());
            });

            
            logger.info("map cnt " + logMsgMatches.size() + "건 " );

            if (searchHits.toList().size() != 1000) {
                logParser.logParser(logMsgMatches);
                break;
            }

        }
        

        return "OK";
    }
    
}


// POST replay_log_*/_search
        // {
        //   "size" : 10000,
        //   "track_total_hits": true,
        //   "query" : {
        //     "bool" : {
        //       "filter" : [
        //         {
        //           "terms" : {
        //             "header.msg_type.keyword" : [
        //               10
        //             ]
        //           }
        //         },
        //         {
        //           "range" : {
        //             "header.recv_time" : {
        //               "from" : "20240416090000.000",
        //               "to" : "20240416103059.999"
        //             }
        //           }
        //         }
        //       ]
        //     }
        //   },
        //   "_source": ["@timestamp", "header", "message"],
        //   "sort" : [{"header.recv_time.keyword" : {"order" : "ASC"}}],
        //   "search_after" : ["0"]
        // }