package com.simuwang.daq.components.report.parser.pdf;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import com.simuwang.base.mapper.EmailFieldMappingMapper;
import com.simuwang.base.pojo.dto.report.*;
import com.simuwang.daq.components.report.parser.ReportParserConstant;
import org.springframework.stereotype.Component;
import technology.tabula.Table;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @author wangzaijun
 * @date 2024/10/10 17:34
 * @description 年报解析逻辑:基本信息被拆分为多个表格，财务报表未解析
 */
@Component(ReportParserConstant.PARSER_PDF_ANNUALLY)
public class PDAnnuallyReportParser extends PDQuarterlyReportParser<AnnuallyReportData> {
    private static final List<String> FINANCIAL_INDICATORS_COLUMN_NAMES = ListUtil.list(false);

    static {
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金净资产");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("报告期期末单位净值");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期利润");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期已实现收益");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配利润");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配基金份额利润");
        FINANCIAL_INDICATORS_COLUMN_NAMES.add("基金份额累计净值增长率");
    }

    private List<Table> fundInfoTables;

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

    @Override
    public String getParser() {
        return ReportParserConstant.PARSER_PDF_ANNUALLY;
    }

    @Override
    protected void initTableInfo(List<Table> tables) {
        // 初始化
        this.fundInfoTables = ListUtil.list(true);
        this.financialIndicatorsTables = ListUtil.list(true);
        this.shareChangeTables = ListUtil.list(true);
        this.assetAllocationTables = ListUtil.list(true);
        this.investmentIndustryTables = ListUtil.list(true);
        for (int i = 0; i < tables.size(); i++) {
            Table table = tables.get(i);
            if (i <= 1) {
                this.fundInfoTables.add(table);
                continue;
            }
            // 用表格的第一列的数据判断是否主要财务指标数据
            List<String> texts = this.getTableColTexts(table, 0);
            if (CollUtil.containsAny(texts, FINANCIAL_INDICATORS_COLUMN_NAMES)) {
                this.financialIndicatorsTables.add(table);
                continue;
            }
            int colCount = table.getColCount();
            if (colCount == 2) {
                // 用表格的第一列的数据判断是否份额变动记录
                if (CollUtil.containsAny(texts, SHARE_CHANGE_COLUMN_NAMES)) {
                    this.shareChangeTables.add(table);
                }
            } else if (colCount == 4) {
                // 用表格的第二列的数据判断是否行业配置数据（内地）
                texts = this.getTableColTexts(table, 1);
                if (CollUtil.containsAny(texts, INDUSTRY_COLUMN_NAMES)) {
                    this.investmentIndustryTables.add(table);
                }
            } else if (colCount == 3) {
                // 用表格的第一列的数据判断是否行业配置数据（港股通）
                if (CollUtil.containsAny(texts, INDUSTRY_COLUMN_NAMES)) {
                    this.investmentIndustryTables.add(table);
                    continue;
                }
                // 资产配置表格识别（兼容跨页的表格）获取表格中第二列的所有文字，判断所有文字中包含"股权投资"等字符串
                texts = this.getTableColTexts(table, 1);
                if (CollUtil.containsAny(texts, ListUtil.of("股权投资", "股票投资", "债券投资", "另类投资", "其他资产", "其他融资总额"))) {
                    this.assetAllocationTables.add(table);
                }
            }
        }
    }

    @Override
    protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
        Map<String, Object> fundInfoMap = MapUtil.newHashMap(32);
        for (Table table : this.fundInfoTables) {
            Map<String, Object> temp = this.parseFundInfo(table);
            fundInfoMap.putAll(temp);
        }
        ReportFundInfoDTO info = new ReportFundInfoDTO(params.getFileId());
        this.buildInfo(fundInfoMap, info);
        return info;
    }

    @Override
    protected AnnuallyReportData buildExtData(ReportBaseInfoDTO reportInfo, ReportFundInfoDTO fundInfo,
                                              List<ReportShareChangeDTO> shareChanges,
                                              List<ReportAssetAllocationDTO> assetAllocations,
                                              List<ReportInvestmentIndustryDTO> investmentIndustries,
                                              Function<Table, Map<String, Object>> function) {
        // 处理财务指标
        List<ReportFinancialIndicatorsDTO> financialIndicators = this.buildFinancialIndicatorsInfo(reportInfo.getFileId());
        // 返回数据构建
        AnnuallyReportData reportData = new AnnuallyReportData(reportInfo, fundInfo);
        reportData.setShareChange(shareChanges);
        reportData.setFinancialIndicators(financialIndicators);
        reportData.setAssetAllocation(assetAllocations);
        reportData.setInvestmentIndustry(investmentIndustries);
        return reportData;
    }

    @Override
    protected void cleaningReportData(AnnuallyReportData reportData) {
        // todo 数据清洗
    }

    private List<ReportFinancialIndicatorsDTO> buildFinancialIndicatorsInfo(Integer fileId) {
        List<ReportFinancialIndicatorsDTO> dtos = ListUtil.list(false);
        // 分级基金
        List<String> levels = this.matchTieredFund(String.join(",", this.textList));
        levels.add(0, "母基金");
        // 假设这里可能存在分级基金，不存在表格跨页
        for (int k = 0; k < this.financialIndicatorsTables.size(); k++) {
            Table table = this.financialIndicatorsTables.get(k);
            int colCount = table.getColCount();
            for (int j = 1; j < colCount; j++) {
                Map<String, Object> infoMap = MapUtil.newHashMap(16);
                String year = this.cleaningValue(table.getCell(0, j).getText());
                infoMap.put("年度", year);
                for (int i = 0; i < table.getRowCount(); i++) {
                    String columnName = this.cleaningValue(table.getCell(i, 0).getText());
                    if (!CollUtil.contains(FINANCIAL_INDICATORS_COLUMN_NAMES, columnName)) {
                        continue;
                    }
                    String value = this.cleaningValue(table.getCell(i, j).getText());
                    infoMap.put(columnName, value);
                }
                ReportFinancialIndicatorsDTO dto = new ReportFinancialIndicatorsDTO(fileId);
                this.buildInfo(infoMap, dto);
                dto.setLevel(levels.get(k));
                dtos.add(dto);
            }
        }
        return dtos;
    }
}
