package com.simuwang.daq.components;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.simuwang.daq.dto.ReportExtInfo;
import com.simuwang.daq.dto.ReportFundInfo;
import com.simuwang.daq.dto.ReportInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class AbstractReportParser<EXT extends ReportExtInfo> implements ReportParser {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    protected String filepath;
    protected Map<String, List<String>> watermarkListMap;

    @Override
    public void parse(Integer fileId, String filepath, String watermarkName) {
        StopWatch watch = new StopWatch();
        watch.start();
        if (this.logger.isInfoEnabled()) {
            this.logger.info("报告{} 开始解析！", filepath);
        }
        this.filepath = filepath;
        this.watermarkListMap = this.generateWatermarkMap(watermarkName);
        ReportInfo reportInfo = null;
        ReportFundInfo reportFundInfo = null;
        List<EXT> exts = null;
        try {
            this.initParse();
            reportInfo = this.parseReportInfo(fileId);
            reportFundInfo = this.parseBaseInfo();
            exts = this.parseExtInfo();
        } catch (Exception e) {
            this.logger.error("报告{} 解析错误\n{}", filepath, ExceptionUtil.stacktraceToString(e));
        }
        this.saveResult(reportInfo, reportFundInfo, exts);
        watch.stop();
        if (this.logger.isInfoEnabled()) {
            this.logger.info("报告{} 解析结束！耗时：{}s", filepath, watch.getTotalTime(TimeUnit.SECONDS));
        }
    }

    protected abstract void initParse() throws IOException;

    protected abstract ReportInfo parseReportInfo(Integer fileId);

    protected abstract ReportFundInfo parseBaseInfo();

    protected abstract List<EXT> parseExtInfo();

    protected abstract void saveResult(ReportInfo reportInfo, ReportFundInfo reportFundInfo, List<EXT> exts);

    private Map<String, List<String>> generateWatermarkMap(String watermarkName) {
        Map<String, List<String>> result = MapUtil.newHashMap(32);
        // 生成水印列表
        String text = watermarkName;
        text = text.replaceAll("[()]", ""); // 移除括号
        List<String> textList = new ArrayList<>(new HashSet<>(convertStringToList(text)));
        Collections.reverse(textList);
        StringBuilder sb = new StringBuilder(textList.size());
        for (String ch : textList) {
            sb.append(ch);
        }
        String joinedText = sb.toString();

        // 基本水印列表
        List<String> wkList = new ArrayList<>();
        for (String ch : textList) {
            wkList.add(ch + "\r\n");
            wkList.add("\r\n" + ch);
        }

        // 查找数字
        List<String> matches = findDigits(watermarkName);
        if (!matches.isEmpty()) {
            for (String match : matches) {
                wkList.add("\r\n" + match);
                wkList.add(match + "\r\n");
            }
        }
        wkList.add("-");
        wkList.add("【");
        wkList.add("】");
        wkList.add("\r");
        wkList.add("\n");
        wkList.add("\r\n");

        String noNumberText = removeDigits(joinedText);

        // 生成不同字段的水印列表
        result.put("report_name", new ArrayList<>(wkList));
        result.get("report_name").addAll(convertStringToList("有限公司"));

        result.put("less", new ArrayList<>(wkList));

        result.put("more", new ArrayList<>(wkList));
        result.get("more").addAll(convertStringToList(noNumberText));

        result.put("leverage", new ArrayList<>(wkList));
        result.get("leverage").addAll(convertStringToList(removeKeywords(noNumberText, "基金资产")));

        result.put("base_info", new ArrayList<>(wkList));
        result.get("base_info").addAll(convertStringToList(removeKeywords(text, "基", "金", "投资", "管理", "有", "份", "融", "资", "产", "本", "号", "收益", "策略", "期")));

        result.put("industry", new ArrayList<>(wkList));
        result.get("industry").addAll(convertStringToList(removeKeywords(noNumberText, "基金融公产")));

        result.put("market_value", new ArrayList<>(Collections.singletonList("\n")));
        return result;
    }

    private List<String> findDigits(String text) {
        List<String> digits = new ArrayList<>();
        Pattern pattern = Pattern.compile("\\d");
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            digits.add(matcher.group());
        }
        return digits;
    }

    private String removeDigits(String text) {
        return text.replaceAll("\\d", "");
    }

    private String removeKeywords(String text, String... keywords) {
        for (String keyword : keywords) {
            text = text.replaceAll(keyword, "");
        }
        return text;
    }

    private List<String> convertStringToList(String text) {
        List<String> charList = new ArrayList<>();
        for (char c : text.toCharArray()) {
            charList.add(c + "");
        }
        return charList;
    }

    protected String processString(List<String> wmList, String string) {
        if (StrUtil.isBlank(string)) {
            return null;
        }
        // 生成正则表达式模式
        String pat = String.join("|", wmList);
        // 使用正则表达式移除wmList中的元素
        string = removeMatches(string, pat);
        // 替换中文括号为英文括号
        string = string.replace("（", "(").replace("）", ")");
        // 移除空格
        string = string.replace(" ", "");
        // 如果字符串以括号开头，则移除第一个字符
        if (startsWithParenthesis(string)) {
            string = string.substring(1);
        }

        return string;
    }

    private String removeMatches(String input, String pattern) {
        // 编译正则表达式
        Pattern compiledPattern = Pattern.compile(pattern);
        // 创建Matcher对象
        Matcher matcher = compiledPattern.matcher(input);
        // 使用replaceAll方法替换所有匹配到的字符为空字符串
        return matcher.replaceAll("");
    }

    private boolean startsWithParenthesis(String input) {
        // 匹配以括号开头的字符串
        Pattern pattern = Pattern.compile("^[()].*");
        Matcher matcher = pattern.matcher(input);
        return matcher.find();
    }
}
