package com.smppw.modaq.application.components.report.parser.ai;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.smppw.modaq.application.components.report.parser.AbstractReportParser;
import com.smppw.modaq.common.conts.PatternConsts;
import com.smppw.modaq.common.enums.ReportParseStatus;
import com.smppw.modaq.common.exception.ReportParseException;
import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
import com.smppw.modaq.domain.dto.report.ReportData;
import com.smppw.modaq.domain.dto.report.ReportParserParams;
import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
import com.smppw.modaq.infrastructure.util.DateUtils;
import org.springframework.beans.factory.annotation.Value;

import java.util.Date;
import java.util.Map;

/**
 * 抽象的报告AI解析器
 *
 * @param <T> 泛型参数
 */
public abstract class AbstractAIReportParser<T extends ReportData> extends AbstractReportParser<T> {
    @Value("${email.report.ai-parser-url}")
    private String aiParserUrl;

    protected String aiFileId;

    protected Map<String, Object> allInfoMap;

    public AbstractAIReportParser(EmailFieldMappingMapper fieldMappingMapper) {
        super(fieldMappingMapper);
    }

    @Override
    public T parse(ReportParserParams params) throws ReportParseException {
        if (!isSupportAIParse()) {
            throw new ReportParseException(ReportParseStatus.NO_SUPPORT_AI);
        }
        // 初始化
        this.init();
        // 解析文件内容，并把文件内容解构到 allInfoMap 对象中
        this.parseFileContent(params);
        // 解构话返回解析数据
        T reportData = this.buildReportData(params, params.getFilename());
        if (reportData != null) {
            reportData.setAiFileId(this.aiFileId);
            reportData.setAiParse(true);
        }
        return reportData;
    }


    @Override
    protected void cleaningReportData(T reportData) {
        // do something.
    }

    /**
     * AI解析的提示词
     *
     * @return 返回null就用默认的提示词
     */
    protected String prompt() {
        return null;
    }

    /**
     * 报告是否支持ai工具解析
     *
     * @return /
     */
    protected abstract boolean isSupportAIParse();

    /**
     * 覆盖报告基本信息的方法，报告日期从报告名称获取失败时从内容获取
     *
     * @param params /
     * @return /
     */
    @Override
    protected ReportBaseInfoDTO buildReportInfo(ReportParserParams params) {
        ReportBaseInfoDTO reportInfo = super.buildReportInfo(params);
        if (reportInfo.getReportDate() == null) {
            Date date = DateUtils.toDate(MapUtil.getStr(this.allInfoMap, "报告日期"));
            reportInfo.setReportDate(date);
        }
        return reportInfo;
    }

    /**
     * 处理ai解析结果，方便构建结构化对象
     *
     * @param result ai解析结果
     */
    protected void handleAiResult(String result) throws ReportParseException {
        try {
            JSONObject jsonObject = JSONUtil.parseObj(result);
            this.allInfoMap.putAll(jsonObject);
        } catch (Exception e) {
            throw new ReportParseException(ReportParseStatus.PARSE_HANDLE_FAIL);
        }
    }

    @Override
    protected void init() {
        super.init();
        // 先初始化为null
        this.aiFileId = null;
        this.allInfoMap = MapUtil.newHashMap(128);
    }

    /**
     * 移除 JSON 字符串中的注释
     */
    protected String removeJsonComments(String json) {
        return PatternConsts.JSON_COMMENT_PATTERN.matcher(json).replaceAll(mr -> {
                    // 如果匹配到的是字符串内容（双引号包裹），则保留原内容
                    if (mr.group(1) != null) {
                        return mr.group(1);
                    }
                    // 否则移除注释（替换为空）
                    return "";
                })
                .replaceAll("(?m)^\\s+", "")  // 移除空行
                .trim();
    }

    private void parseFileContent(ReportParserParams params) {
        String filename = params.getFilename();
        Map<String, Object> paramsMap = MapUtil.newHashMap(4);
        paramsMap.put("filepath", params.getFilepath());
        String prompt = this.prompt();
        if (StrUtil.isNotBlank(prompt)) {
            paramsMap.put("user_msg", prompt);
        }
        String body = null;
        try {
            body = HttpUtil.get(this.aiParserUrl, paramsMap);
            JSONObject jsonResult = JSONUtil.parseObj(body);
            this.aiFileId = MapUtil.getStr(jsonResult, "file_id");
            String content = StrUtil.split(jsonResult.getStr("content"), "```").get(1);
            String aiParserContent = "{" + StrUtil.subAfter(content, "{", false) + "}";
            if (StrUtil.isNotBlank(aiParserContent)) {
                String result = this.removeJsonComments(aiParserContent);
                this.handleAiResult(result);
            }
        } catch (ReportParseException e) {
            this.logger.warn("{} ai解析失败，解析结果{}，错误原因：{}", filename, body, ExceptionUtil.stacktraceToString(e));
            throw e;
        } catch (IORuntimeException e) {
            throw new ReportParseException(ReportParseStatus.AI_NOT_FOUND);
        } catch (Exception e) {
            this.logger.warn("报告{} 在AI解析时报错：{}", filename, ExceptionUtil.stacktraceToString(e));
            throw new ReportParseException(ReportParseStatus.SYSTEM_ERROR);
        } finally {
            if (logger.isInfoEnabled()) {
                this.logger.info("报告{} AI解析参数{}，AI解析结果：{}", filename, paramsMap, body);
            }
        }
    }
}
