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

import cn.reghao.jutil.jdk.string.SnowFlake;
import cn.reghao.tnb.search.app.db.repository.WenshuDocRepository;
import cn.reghao.tnb.search.app.lucene.LuceneDocument;
import cn.reghao.tnb.search.app.lucene.LuceneIndex;
import cn.reghao.tnb.search.app.model.po.Wenshu;
import cn.reghao.tnb.search.app.model.po.WenshuDoc;
import cn.reghao.tnb.search.app.model.po.WenshuLucene;
import cn.reghao.tnb.search.app.util.ClassUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.document.Document;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2025-08-20 17:45:35
 */
@Slf4j
@Service
public class WenshuService {
    private String indexName = "wenshu_lucene";
    private SnowFlake idGenerator = new SnowFlake(1, 1);
    private WenshuDocRepository wenshuDocRepository;
    private LuceneIndex luceneIndex;
    private LuceneDocument luceneDocument;

    public WenshuService(WenshuDocRepository wenshuDocRepository, LuceneIndex luceneIndex, LuceneDocument luceneDocument) {
        this.wenshuDocRepository = wenshuDocRepository;
        this.luceneIndex = luceneIndex;
        this.luceneDocument = luceneDocument;
    }

    public void processFile(String filePath) throws IOException {
        // 10MiB
        int bufSize = 1024*1024*10;
        BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)), bufSize);

        List<Wenshu> list = new ArrayList<>();
        // 忽略 CSV 文件的第一行
        String line = in.readLine();
        while((line = in.readLine()) != null) {
            Wenshu wenshu = parseLineByWenshu(line);
            if (wenshu != null) {
                successCount++;
                list.add(wenshu);
                if (list.size() > 10_000) {
                    addLuceneIndex(list);
                    list.clear();
                }
            }
        }
        in.close();

        if (!list.isEmpty()) {
            addLuceneIndex(list);
            list.clear();
        }
    }

    @AllArgsConstructor
    @Getter
    static class Tuple {
        String str;
        String line;
    }

    Tuple getField(String line) {
        try {
            String str = "";
            if (line.startsWith(mark)) {
                line = line.substring(1);
                int idx = line.indexOf(mark);
                str = line.substring(0, idx);
                line = line.substring(idx+2);
            } else {
                int idx = line.indexOf(",");
                str = line.substring(0, idx);
                line = line.substring(idx+1);
            }

            return new Tuple(str, line);
        } catch (Exception e) {
            //e.printStackTrace();
        }

        return null;
    }

    int successCount = 0;
    int failCount = 0;
    int errorCount = 0;
    String mark = "\"";
    private Wenshu parseLineByWenshu(String line) {
        String line1 = line;
        try {
            Tuple tuple = getField(line1);
            String str1 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str2 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str3 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str4 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str5 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str6 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str7 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str8 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str9 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str10 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str11 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str12 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str13 = tuple.getStr();
            line1 = tuple.getLine();

            tuple = getField(line1);
            String str14 = tuple.getStr();
            line1 = tuple.getLine();

            String str15 = line1;

            List<String> fields = new ArrayList<>();
            fields.add("110120119");
            fields.add(str1);
            fields.add(str2);
            fields.add(str3);
            fields.add(str4);
            fields.add(str5);
            fields.add(str6);
            fields.add(str7);
            fields.add(str8);
            fields.add(str9);
            fields.add(str10);
            fields.add(str11);
            fields.add(str12);
            fields.add(str13);
            fields.add(str14);
            fields.add(str15);
            Object object = ClassUtil.getObject(Wenshu.class, fields.toArray(new String[0]));
            return (Wenshu) object;
        } catch (Exception e) {
            log.error("parse line failed -> {}", ++failCount);
            // ignore
        }
        return null;
    }

    private void addLuceneIndex(List<Wenshu> wenshuList) {
        List<WenshuDoc> wenshuDocList = new ArrayList<>();
        List<WenshuLucene> wenshuLuceneList = new ArrayList<>();
        for (Wenshu wenshu : wenshuList) {
            long id = idGenerator.nextId();
            WenshuDoc wenshuDoc = new WenshuDoc(id, wenshu);
            WenshuLucene wenshuLucene = new WenshuLucene(""+id, wenshu);

            wenshuDocList.add(wenshuDoc);
            wenshuLuceneList.add(wenshuLucene);
        }
        List<Document> luceneDocumentList = wenshuLuceneList.stream()
                .map(wenshuLucene -> luceneDocument.getDocumentByWenshuLucene(wenshuLucene))
                .collect(Collectors.toList());
        try {
            wenshuDocRepository.saveAll(wenshuDocList);
            luceneIndex.createIndex(indexName, luceneDocumentList);
            log.info("index {} documents...", wenshuList.size());
        } catch (Exception e) {
            e.printStackTrace();
            errorCount++;
        }
    }

    public void printResult() {
        System.out.printf("success: %s, fail: %s, error: %s", successCount, failCount, errorCount);
    }

    public void deleteAll() throws IOException {
        wenshuDocRepository.deleteAll();
        luceneIndex.deleteAll(indexName);
    }
}
