package cn.reghao.tnb.search.app.log;

import cn.reghao.tnb.search.app.config.ElasticProperties;
import cn.reghao.tnb.search.app.es.*;
import cn.reghao.tnb.search.app.log.model.NginxLog;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.text.TextFile;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author reghao
 * @date 2023-11-08 10:08:02
 */
@Slf4j
@Service
public class NginxLogService {
    public List getChartData() throws ParseException {
        TextFile textFile = new TextFile();
        String filePath = "nginx.log";
        List<String> list = textFile.read(filePath);

        List<NginxLog> nginxLogs = new ArrayList<>();
        for (String line : list) {
            if (!line.startsWith("{")) {
                continue;
            }

            try {
                NginxLog nginxLog = JsonConverter.jsonToObject(line, NginxLog.class);
                nginxLogs.add(nginxLog);
            } catch (Exception e) {
                // e.printStackTrace();
            }
        }

        Map<Long, Integer> map = new TreeMap<>();
        for (NginxLog nginxLog : nginxLogs) {
            String date = nginxLog.getTimeIso8601();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00")
                    .withZone(ZoneId.of("UTC"));
            LocalDateTime localDateTime = LocalDateTime.parse(date, formatter);
            Long timestamp = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
            Long key = timestamp;

            Integer count = map.get(key);
            if (count == null) {
                map.put(key, 1);
            } else {
                int count1 = map.get(key) + 1;
                map.put(key, count1);
            }
        }

        LocalDateTime localDateTime = LocalDateTime.now();
        Long baseKey = localDateTime.toEpochSecond(ZoneOffset.of("+8"));

        List<String> xList = new ArrayList<>();
        List<Integer> yList = new ArrayList<>();
        Set<Long> keys = new HashSet<>();
        for (Long key : map.keySet()) {
            if (key < baseKey) {
                //xList.add(DateTimeConverter.format(key*1000).split(" ")[1]);
                xList.add(DateTimeConverter.format(key*1000));
                yList.add(map.get(key));
                keys.add(key);
            }
        }

        keys.forEach(map::remove);
        keys.clear();
        List results = new ArrayList();
        results.add(xList.toArray());
        results.add(yList.toArray());
        return results;
    }

    public void logTest() {
        TextFile textFile = new TextFile();
        String filePath = "nginx.log";
        List<String> list = textFile.read(filePath);
        List<cn.reghao.bnt.log.NginxLog> nginxLogs = new ArrayList<>();
        for (String line : list) {
            if (!line.startsWith("{")) {
                System.out.println("not json data");
                continue;
            }

            try {
                cn.reghao.bnt.log.NginxLog nginxLog = JsonConverter.jsonToObject(line, cn.reghao.bnt.log.NginxLog.class);
                nginxLogs.add(nginxLog);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        nginxLogs.stream()
                .filter(nginxLog -> nginxLog.getStatus() >= 400)
                .forEach(nginxLog -> {
                    System.out.printf("%s %s -> %s\n", nginxLog.getRequestMethod(), nginxLog.getStatus(), nginxLog.getUpstreamAddr());
                });
        System.out.println();
    }

    Map<Long, Integer> ngxLogMap = new TreeMap<>();
    void handleNginxLog(cn.reghao.bnt.log.NginxLog nginxLog) {
        String date = nginxLog.getTimeIso8601();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00")
                .withZone(ZoneId.of("UTC"));
        LocalDateTime localDateTime = LocalDateTime.parse(date, formatter);
        Long timestamp = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
        Long key = timestamp;
        Integer count = ngxLogMap.get(key);
        if (count == null) {
            ngxLogMap.put(key, 1);
        } else {
            int count1 = ngxLogMap.get(key) + 1;
            ngxLogMap.put(key, count1);
        }
    }

    /**
     * NginxLog 在前端 echarts 中的可视化
     *
     * @param
     * @return
     * @date 2023-12-01 17:41:07
     */
    class PushTask implements Runnable {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                try {
                    if (ngxLogMap.size() < 3) {
                        Thread.sleep(10_000);
                        continue;
                    }

                    LocalDateTime localDateTime = LocalDateTime.now();
                    Long baseKey = localDateTime.toEpochSecond(ZoneOffset.of("+8"));

                    List<String> xList = new ArrayList<>();
                    List<Integer> yList = new ArrayList<>();
                    Set<Long> keys = new HashSet<>();
                    for (Long key : ngxLogMap.keySet()) {
                        if (key < baseKey) {
                            xList.add(DateTimeConverter.format(key*1000).split(" ")[1]);
                            yList.add(ngxLogMap.get(key));
                            keys.add(key);
                        }
                    }

                    keys.forEach(ngxLogMap::remove);
                    keys.clear();
                    List results = new ArrayList();
                    results.add(xList.toArray());
                    results.add(yList.toArray());

                    /*WebSocketSession webSocketSession = getPullSession("admin-service", "172.16.90.200");
                    TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(results));
                    webSocketSession.sendMessage(textMessage);*/
                    Thread.sleep(10_000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ElasticProperties elasticProperties = new ElasticProperties();
        ElasticService elasticService = new ElasticService(elasticProperties);
        IndexService indexService = new IndexService(elasticService);
        MappingService mappingService = new MappingService();

        NginxLogDocument nginxLogDocument = new NginxLogDocument(elasticService);
        NginxLogSearch nginxLogSearch = new NginxLogSearch(elasticService);
        QueryService<NginxLog> queryService = new QueryService<>(elasticService);
        String index = "nginx_log";

        //indexService.getIndex(index);
        //indexService.getMapping(index);

        //documentService.deleteAllDocument(index);
        Map<String, Property> propertyMap = mappingService.getPropertyMapWithNginxLog(NginxLog.class);
        //indexService.deleteIndex(index);
        //indexService.createIndex(index, propertyMap);

        //searchService.search(index);
//        search1(esClient, "app_log");
//        index = "app_log";
//        deleteAll(index);
//        searchService.aggregate(index);

        int pn = 1;
        /*while (pn < 100) {
            List<NginxLog> list = searchService.searchByPage(index, pn, "", "");
            System.out.println();
            pn++;
        }*/

        //searchService.searchAll(index);
//        indexService.updateMapping(index);

        //String queryString = "content";
        //List<NginxLog> list = queryService.queryWithHighlight(index, queryString, pn, ps, NginxLog.class);
        //searchService.searchAll(index);
        nginxLogSearch.aggregate();
        //searchService.count(index);
    }
}
