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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.smppw.modaq.application.components.ReportParseUtils;
import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
import com.smppw.modaq.common.enums.ReportParseStatus;
import com.smppw.modaq.common.exception.ReportParseException;
import com.smppw.modaq.domain.dto.report.*;
import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component(ReportParserConstant.PARSER_AI_QUARTERLY)
public class AIQuarterlyReportParser<T extends QuarterlyReportData> extends AbstractAIReportParser<T> {
    public AIQuarterlyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
        super(fieldMappingMapper);
    }

    @Override
    protected boolean isSupportAIParse() {
        return true;
    }

    @Override
    protected String prompt() {
        return """
                识别文件中的基金基本情况、投资组合情况，
                投资组合情况包含期末基金资产组合情况、报告期末按行业分类的股票投资组合，
                报告期末按行业分类的股票投资组合又包含报告期末按行业分类的境内股票投资组合、报告期末按行业分类的港股通投资股票投资组合，
                结果用json返回，json中不要注释
                """;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected T parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
                                       ReportFundInfoDTO fundInfo) throws ReportParseException {
        QuarterlyReportData reportData = new QuarterlyReportData(reportInfo, fundInfo);
        // 这俩有分级基金，先不解析
        reportData.setShareChange(null);
        reportData.setFinancialIndicators(null);
        // 资产配置组合
        Integer fileId = reportInfo.getFileId();
        String reportName = reportInfo.getReportName();
        Object assetInfo = this.allInfoMap.get("投资组合情况");
        if (assetInfo == null) {
            throw new ReportParseException(ReportParseStatus.PARSE_ASSET_INFO_FAIL, reportName);
        }
        Map<String, Object> assetInfoMap = (Map<String, Object>) assetInfo;
        reportData.setAssetAllocation(this.buildAssetAllocationInfo(fileId, reportName, assetInfoMap));
        reportData.setInvestmentIndustry(this.buildInvestmentIndustryInfo(fileId, reportName, assetInfoMap));
        @SuppressWarnings("unchecked")
        T t = (T) reportData;
        return t;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
        // 获取并移除基金基本情况信息
        Object fundInfo = this.allInfoMap.get("基金基本情况");
        if (fundInfo == null) {
            throw new ReportParseException(ReportParseStatus.PARSE_FUND_INFO_FAIL, params.getFilename());
        }
        Map<String, Object> fundInfoMap = (Map<String, Object>) fundInfo;
        return this.buildDto(params.getFileId(), ReportFundInfoDTO.class, fundInfoMap);
    }

    @SuppressWarnings("unchecked")
    private List<ReportAssetAllocationDTO> buildAssetAllocationInfo(Integer fileId, String reportName,
                                                                    Map<String, Object> assetInfoMap) {
        Object allocationInfo = assetInfoMap.get("期末基金资产组合情况");
        if (allocationInfo == null) {
            throw new ReportParseException(ReportParseStatus.PARSE_ASSET_INFO_FAIL, reportName);
        }
        List<Map<String, Object>> allocationList = ListUtil.list(false);
        try {
            allocationList = (List<Map<String, Object>>) allocationInfo;
        } catch (Exception ignored) {
        }

        List<ReportAssetAllocationDTO> dtos = ListUtil.list(false);
        for (Map<String, Object> allocation : allocationList) {
            String detail = ReportParseUtils.cleaningValue(allocation.get("子项"));
            if (StrUtil.isBlank(detail)) {
                detail = ReportParseUtils.cleaningValue(allocation.get("项目"));
            }
            if (!ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.containsKey(detail)) {
                continue;
            }
            String marketValueAndRemark = ReportParseUtils.cleaningValue(allocation.get("金额"), false);
            // 大类
            ReportParseUtils.buildAssetAllocation(fileId, detail, marketValueAndRemark, dtos);
        }
        return dtos;
    }

    @SuppressWarnings("unchecked")
    private List<ReportInvestmentIndustryDTO> buildInvestmentIndustryInfo(Integer fileId, String reportName,
                                                                          Map<String, Object> assetInfoMap) {
        Object industryInfo = assetInfoMap.get("报告期末按行业分类的股票投资组合");
        if (industryInfo == null) {
            throw new ReportParseException(ReportParseStatus.PARSE_INDUSTRY_INFO_FAIL, reportName);
        }
        Map<String, Object> industryMap = MapUtil.empty();
        try {
            industryMap = (Map<String, Object>) industryInfo;
        } catch (Exception ignored) {
        }
        List<ReportInvestmentIndustryDTO> dtos = ListUtil.list(false);
        this.buildIndustryInfo(fileId, 1, industryMap, dtos);
        this.buildIndustryInfo(fileId, 2, industryMap, dtos);
        return dtos;
    }

    @SuppressWarnings("unchecked")
    private void buildIndustryInfo(Integer fileId, Integer industryType,
                                   Map<String, Object> industryMap,
                                   List<ReportInvestmentIndustryDTO> dtos) {
        String industryKey = industryType == 1 ? "报告期末按行业分类的境内股票投资组合" : "报告期末按行业分类的港股通投资股票投资组合";
        List<Map<String, Object>> industryList = ListUtil.list(false);
        try {
            industryList = (List<Map<String, Object>>) industryMap.get(industryKey);
        } catch (Exception ignored) {
        }
        if (CollUtil.isEmpty(industryList)) {
            return;
        }
        for (Map<String, Object> industry : industryList) {
            String industryName = ReportParseUtils.cleaningValue(industry.get("行业类别"));
            if (StrUtil.isBlank(industryName) || !ReportParseUtils.INDUSTRY_COLUMN_NAMES.contains(industryName)) {
                continue;
            }
            ReportInvestmentIndustryDTO dto = new ReportInvestmentIndustryDTO(fileId);
            dto.setInvestType(industryType);
            dto.setIndustryName(industryName);
            dto.setMarketValue(ReportParseUtils.cleaningValue(industry.get("公允价值")));
            dto.setRatio(ReportParseUtils.cleaningValue(industry.get("占基金资产净值比例(%)")));
            dtos.add(dto);
        }
    }
}
