package com.simuwang.daq.components;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.simuwang.base.common.enums.ReportType;
import com.simuwang.base.pojo.dos.report.BaseReportDO;
import com.simuwang.base.pojo.dto.report.*;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author wangzaijun
 * @date 2024/9/27 16:06
 * @description 自定义的python报告解析结果转换器，json -> dto
 */
public class PythonReportConverter {
    @SuppressWarnings("unchecked")
    public static <T extends ReportData> ParseResult<T> convert(JSONObject jsonObject, ReportType type) {
        ParseResult<T> result = new ParseResult<>();
        if (jsonObject == null) {
            return result;
        }
        result.setMsg(jsonObject.getStr("msg"));
        result.setStatus(jsonObject.getInt("status"));
        JSONObject data = jsonObject.getJSONObject("data");
        if (data == null || data.isEmpty()) {
            return result;
        }

        T reportData;
        if (Objects.equals(ReportType.ANNUALLY, type) || Objects.equals(ReportType.QUARTERLY, type)) {
            reportData = (T) convertQuarterly(data);
        } else {
            reportData = (T) convertMonthly(data);
        }
        result.setData(reportData);
        return result;
    }

    private static MonthlyReportData convertMonthly(JSONObject jsonObject) {
        ReportBaseInfoDTO baseInfo = convertToObj(jsonObject, "base_info", ReportBaseInfoDTO.class);
        ReportFundInfoDTO fundInfo = convertToObj(jsonObject, "fund_info", ReportFundInfoDTO.class);
        MonthlyReportData reportData = new MonthlyReportData(baseInfo, fundInfo);
        reportData.setNetReport(convertToList(jsonObject, "net_report", ReportNetReportDTO.class));
        return reportData;
    }

    private static QuarterlyReportData convertQuarterly(JSONObject jsonObject) {
        ReportBaseInfoDTO baseInfo = convertToObj(jsonObject, "base_info", ReportBaseInfoDTO.class);
        ReportFundInfoDTO fundInfo = convertToObj(jsonObject, "fund_info", ReportFundInfoDTO.class);
        QuarterlyReportData reportData = new QuarterlyReportData(baseInfo, fundInfo);
        reportData.setAssetAllocation(convertToList(jsonObject, "asset_allocation", ReportAssetAllocationDTO.class));
        reportData.setFinancialIndicators(convertToList(jsonObject, "financial_indicators", ReportFinancialIndicatorsDTO.class));
        reportData.setInvestmentIndustry(convertToList(jsonObject, "investment_industry", ReportInvestmentIndustryDTO.class));
        reportData.setShareChange(convertToList(jsonObject, "share_change", ReportShareChangeDTO.class));
        return reportData;
    }

    /**
     * json转集合后取第一个数据
     *
     * @param jsonObject 待获取的json对象
     * @param key        字段
     * @param clazz      对象类型class
     * @param <T>        泛型
     * @return /
     */
    private static <T extends BaseReportDTO<? extends BaseReportDO>> T convertToObj(JSONObject jsonObject, String key, Class<T> clazz) {
        List<T> dtos = convertToList(jsonObject, key, clazz);
        return CollUtil.isEmpty(dtos) ? null : dtos.get(0);
    }

    /**
     * json转换为集合
     *
     * @param jsonObject 待获取的json对象
     * @param key        字段
     * @param clazz      对象类型class
     * @param <T>        泛型
     * @return /
     */
    private static <T extends BaseReportDTO<? extends BaseReportDO>> List<T> convertToList(JSONObject jsonObject, String key, Class<T> clazz) {
        List<T> dtos = ListUtil.list(false);
        if (jsonObject == null || !jsonObject.containsKey(key)) {
            return dtos;
        }
        JSONArray jsonArray = jsonObject.getJSONArray(key);
        return convertDTOs(jsonArray, clazz);
    }

    /**
     * 通过反射绑定对象
     *
     * @param jsonArray 数据集合
     * @param clazz     对象class对象
     * @param <T>       泛型对象
     * @return /
     */
    private static <T extends BaseReportDTO<? extends BaseReportDO>> List<T> convertDTOs(JSONArray jsonArray, Class<T> clazz) {
        List<T> dtos = ListUtil.list(false);
        if (CollUtil.isEmpty(jsonArray)) {
            return dtos;
        }
        for (Object o : jsonArray) {
            JSONObject obj = JSONUtil.parseObj(o);
            if (obj == null || obj.isEmpty()) {
                continue;
            }
            T dto = setFieldValues(obj, clazz);
            if (dto != null) {
                dtos.add(dto);
            }
        }
        return dtos;
    }

    /**
     * 通过反射设置对象的字段值
     *
     * @param jsonObject json对象
     * @param clazz      对象class类型
     * @param <T>        泛型对象
     * @return 如果构建起初始化报错直接返回null，如果没有字段则跳过该字段的设置
     */
    private static <T extends BaseReportDTO<? extends BaseReportDO>> T setFieldValues(JSONObject jsonObject, Class<T> clazz) {
        T obj = null;
        try {
            obj = clazz.getDeclaredConstructor().newInstance();
        } catch (Exception ignored) {
        }
        if (obj == null) {
            return null;
        }
        Set<String> columns = jsonObject.keySet();
        for (String column : columns) {
            String fieldName = StrUtil.toCamelCase(column);
            try {
                ReflectUtil.setFieldValue(obj, fieldName, jsonObject.get(column));
            } catch (Exception ignored) {
            }
        }
        return obj;
    }
}
