import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import cn.reghao.jutil.tool.id.SnowFlake;
import cn.reghao.tnb.search.api.dto.VideoSummary;
import cn.reghao.tnb.search.app.SearchApplication;
import cn.reghao.tnb.search.app.es.*;
import cn.reghao.tnb.search.app.lucene.LuceneDocument;
import cn.reghao.tnb.search.app.lucene.LuceneIndex;
import cn.reghao.tnb.search.app.lucene.LuceneQuery;
import cn.reghao.tnb.search.app.model.po.VideoText;
import cn.reghao.tnb.search.app.model.po.Wenshu;
import cn.reghao.tnb.search.app.util.ClassUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch.indices.AnalyzeRequest;
import co.elastic.clients.elasticsearch.indices.AnalyzeResponse;
import co.elastic.clients.elasticsearch.indices.analyze.AnalyzeToken;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.ActiveProfiles;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.*;

/**
 * @author reghao
 * @date 2025-03-18 15:51:21
 */
@Slf4j
@ActiveProfiles("dev")
@SpringBootTest(classes = SearchApplication.class)
public class SearchTest {
    SnowFlake idGenerator = new SnowFlake(1, 1);
    @Autowired
    ElasticService elasticService;
    @Autowired
    IndexService indexService;
    @Autowired
    MappingService mappingService;
    @Autowired
    DocumentService documentService;
    @Autowired
    QueryService<Wenshu> queryService;
    String index = Wenshu.class.getSimpleName().toLowerCase(Locale.ROOT);

    void readByFileChannel(String filePath, DocumentService documentService) {
        List<Wenshu> list = new ArrayList<>();
        File file = new File(filePath);
        try {
            FileInputStream fis = new FileInputStream(file);
            FileChannel fileChannel = fis.getChannel();

            int total = 0;
            // 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++) {
                    String line = strArray[i];
                    Wenshu wenshu = parseLine(line);
                    if (wenshu != null) {
                        list.add(wenshu);
                    } else {
                        log.error("error parse line: {}", ++total);
                    }

                    if (list.size() > 10_000) {
                        documentService.batchAddDocument1(index, list);
                        log.info("add {} documents to es", list.size());
                        list.clear();
                    }
                }

                String lastLine = strArray[strArray.length-1];
                if (!lastLine.endsWith("}")) {
                    buffer = new StringBuffer();
                    buffer.append(strArray[strArray.length-1]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // TODO close 处理
        }
    }

    public void indexTest() throws IOException {
        Map<String, Property> propertyMap = mappingService.getWenshuPropertyMap();
        indexService.deleteIndex(index);
        indexService.createIndex(index, propertyMap);
    }

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

    public void addDocTest() {
        setLogLevel();
        documentService.deleteAllDocument(index);
        String filePath = "/home/reghao/Downloads/2021年01月裁判文书数据.csv";
        readByFileChannel(filePath, documentService);
    }

    private Wenshu parseLine(String line) {
        String[] arr = line.split(",");
        try {
            List<String> fields = new ArrayList<>();
            String id = idGenerator.nextId()+"";
            fields.add(id);

            String originalUrl = arr[0];
            String caseId = arr[1];
            String caseName = arr[2];
            String court = arr[3];
            String region = arr[4];
            String caseType = arr[5];
            String caseTypeId = arr[6];
            fields.addAll(Arrays.asList(arr).subList(0, 7));
            String procedure = arr[8];
            fields.add(procedure);
            String judgmentDate = arr[9];
            fields.add(judgmentDate);
            String publicDate = arr[10];
            fields.add(publicDate);
            String parties = arr[11];
            fields.add(parties);

            String cause = "";
            String legalBasis = "";
            String fullText = "";
            if (arr.length == 13) {
                cause = arr[12];
            } else if (arr.length == 14) {
                cause = arr[12];
                legalBasis = arr[13];
            } else if (arr.length == 15) {
                cause = arr[12];
                legalBasis = arr[13];
                fullText = arr[14];
            } else if (arr.length > 15) {
                cause = arr[12];
                legalBasis = arr[13];
                String str = line.split(legalBasis)[1];
                fullText = str.substring(1);
            }

            fields.add(cause);
            fields.add(legalBasis);
            fields.add(fullText);

            Object object = ClassUtil.getObject(Wenshu.class, fields.toArray(new String[0]));
            if (object instanceof  Wenshu) {
                return (Wenshu) object;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public void queryTest() {
        setLogLevel();

        int pn = 1;
        int ps = 10;
        String queryString = "拐卖";
        /*List<Wenshu> page = queryService.queryWithHighlight(index, queryString, pn, ps, Wenshu.class);
        while (!page.isEmpty()) {
            pn++;
            page = queryService.queryWithHighlight(index, queryString, pn, ps, Wenshu.class);
        }*/

        System.out.println();

        Page<Wenshu> page = queryService.queryWithHighlight(index, queryString, pn, ps, Wenshu.class);
        long total = page.getTotalElements();
        int totalPages = page.getTotalPages();
        while (pn <= totalPages) {
            page = queryService.queryWithHighlight(index, queryString, pn, ps, Wenshu.class);
            List<Wenshu> list = page.getContent();
            Wenshu wenshu = list.get(0);
            Wenshu wenshu1 = queryService.queryById(Wenshu.class, index, wenshu.getId());
            pn++;
        }
    }

    @Autowired
    LuceneQuery luceneQuery;
    @Autowired
    LuceneIndex luceneIndex;
    @Autowired
    LuceneDocument luceneDocument;
    @Autowired
    QueryService<VideoSummary> esQuery;
    @Autowired
    SearchService searchService;
    @Test
    public void storeTest() throws Exception {
        int pn = 1;
        int ps = 12;
        PageRequest pageRequest = PageRequest.of(pn-1, ps);
        String videoId = "ao1n8ggYOg";
        /*Document document = luceneIndex.getDocument(videoId);
        VideoSummary videoSummary = (VideoSummary) luceneDocument.getObject(VideoSummary.class, document);

        String title = "哈哈哈哈哈5哈哈哈哈4哈1";
        videoSummary.setTitle(title);
        videoSummary.setId("");
        videoSummary.setDescription("");

        Document document1 = luceneDocument.getVideoSummaryDoc(videoSummary);
        luceneIndex.updateIndex(videoId, document1);

        Document document2 = luceneIndex.getDocument(videoId);
        Object object2 = luceneDocument.getObject(VideoSummary.class, document2);*/

        String index = VideoText.class.getSimpleName().toLowerCase(Locale.ROOT);
        String kw = "隔壁";
        /*Page<VideoSummary> page = hibernateQuery.queryWithHighlight(kw, pn, ps);
        Page<VideoSummary> page1 = luceneQuery.queryWithHighlight("", kw, pn, ps);*/
        //Page<VideoSummary> page2 = esQuery.queryWithHighlight(index, kw, pn, ps, VideoSummary.class);
        System.out.println();

        Map<String, Property> propertyMap = mappingService.getVideoTextPropertyMap();
//        indexService.deleteIndex(index);
//        indexService.createIndex(index, propertyMap);
        //indexService.getIndex(index);
        indexService.deleteIndex(index);
        //indexService.getIndex(index);
        //indexService.updateMapping(index);
        //searchService.searchAll(index);
        //searchService.count(index);
    }

    @Test
    public void analyzerTest() throws IOException {
        String text = "中华人民共和国国歌";
        String analyzer = "standard";
        analyzer = "ik_max_word";
        //analyzer = "ik_smart";
        AnalyzeRequest analyzeRequest = new AnalyzeRequest.Builder()
                .text(text)
                .analyzer(analyzer)
                .build();
        ElasticsearchClient esClient = elasticService.getElasticsearchClient();
        AnalyzeResponse analyzeResponse = esClient.indices().analyze(analyzeRequest);
        List<AnalyzeToken> tokens = analyzeResponse.tokens();
    }
}
