package cn.reghao.tnb.search.app;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import cn.reghao.tnb.search.app.config.ElasticProperties;
import cn.reghao.tnb.search.app.es.*;
import cn.reghao.tnb.search.app.model.po.NginxLog;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.text.TextFile;
import cn.reghao.jutil.tool.id.SnowFlake;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
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 LoggingService {
    static SnowFlake idGenerator = new SnowFlake(1, 1);

    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 static void readFileFileChannel(String filePath, String index, DocumentService documentService) {
        List<String> lines = new ArrayList<>();
        List<NginxLog> nginxLogs = new ArrayList<>();
        File file = new File(filePath);
        try {
            FileInputStream fis = new FileInputStream(file);
            FileChannel fileChannel = fis.getChannel();

            // 10MB
            int capacity = 10*1024*1024;
            ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
            StringBuffer buffer = new StringBuffer();
            while(fileChannel.read(byteBuffer) != -1) {
                //读取后，将位置置为0，将limit置为容量, 以备下次读入到字节缓冲中，从0开始存储
                byteBuffer.clear();
                byte[] bytes = byteBuffer.array();

                String str = new String(bytes);
                buffer.append(str);
                String[] strArray = buffer.toString().split(System.lineSeparator());
                for (int i = 0; i < strArray.length-1; i++) {
                    try {
                        NginxLog nginxLog = JsonConverter.jsonToObject(strArray[i], NginxLog.class);
                        nginxLogs.add(nginxLog);
                    } catch (Exception e) {
                        lines.add(strArray[i]);
                        //e.printStackTrace();
                    }
                }

                String lastLine = strArray[strArray.length-1];
                if (!lastLine.endsWith("}")) {
                    buffer = new StringBuffer();
                    buffer.append(strArray[strArray.length-1]);
                }

                while (nginxLogs.size() > 10_000) {
                    nginxLogs.forEach(nginxLog -> nginxLog.setId(idGenerator.nextId()+""));

                    //NginxLog nginxLog = nginxLogs.get(0);
                    //documentService.update(index, nginxLog);

                    documentService.batchAddDocument(index, nginxLogs);
                    log.info("save {} nginxLogs", nginxLogs.size());
                    nginxLogs.clear();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // TODO close 处理
        }
    }

    static void setLogLevel() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger rootLogger = loggerContext.getLogger("ROOT");
        rootLogger.setLevel(Level.INFO);
    }

    public static void main(String[] args) throws Exception {
        setLogLevel();

        ElasticProperties elasticProperties = new ElasticProperties();
        ElasticService elasticService = new ElasticService(elasticProperties);
        IndexService indexService = new IndexService(elasticService);
        MappingService mappingService = new MappingService();
        DocumentService documentService = new DocumentService(elasticService);
        SearchService searchService = new SearchService(elasticService);
        QueryService<NginxLog> queryService = new QueryService<>(elasticService);
        String index = "nginx_log";

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

        String filePath = "/home/reghao/work/azy/data/access-20231107_073356-20240905_165944.log";
        filePath = "/home/reghao/work/azy/data/access-20240905_165948-20250306_170553.log";
        //readFileFileChannel(filePath, index, documentService);

        //documentService.deleteAllDocument(index);
        Map<String, Property> propertyMap = mappingService.getPropertyMap(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);
        searchService.aggregate(index);
        //searchService.count(index);
    }
}
