package com.youchain.utils;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.youchain.basicdata.service.dto.TableConfigDto;
import com.youchain.basicdata.service.dto.TableConfigQueryCriteria;
import com.youchain.basicdata.service.impl.TableConfigServiceImpl;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.system.domain.DictDetail;
import com.youchain.modules.system.service.impl.DictDetailServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;

import java.lang.reflect.Field;
import java.util.*;
@Slf4j
public  class ExcelDownUtils {
    public static   List<Map<String, Object>> CreateMap(List  all,String tableType) throws Exception{
        Long stTime=System.currentTimeMillis();

        //查询配置表
        TableConfigServiceImpl tableConfigService = SpringContextHolder.getBean(TableConfigServiceImpl.class);
        TableConfigQueryCriteria tbble_criteria =new TableConfigQueryCriteria();
        tbble_criteria.setTableType(tableType.trim());
        List<TableConfigDto> tableConfigDtoList=tableConfigService.queryAll(tbble_criteria);
        if(tableConfigDtoList.size()<=0){
            throw new BadRequestException("请先保存配置");
        }
        TableConfigDto tableConfigDto=tableConfigDtoList.get(0);
        //解析配置内容
        List<FanShe> tableConfigList;
        try{
            tableConfigList= JSONUtil.toList(tableConfigDto.getValue(),FanShe.class);
        }catch (Exception e){
            throw new BadRequestException("请保存配置");
        }
        log.error("导出配置数据："+tableConfigList+"");

        //创建空的字典集合
        Map<String, Map<String, DictDetail>> dictDetailMaps =new HashMap<>();
        //加载字典表
        DictDetailServiceImpl dictDetailService = SpringContextHolder.getBean(DictDetailServiceImpl.class);
        //查找所需要用到的字典
        tableConfigList.forEach(fanShe->{
            //遍历配置属性

            String property=fanShe.property;
            if(property.indexOf("#")>-1){
                //如果带# 代表调用了字典
                try{
                    String  dictStr=property.split("#")[0];
                    Map<String, DictDetail> dictDetailMap=dictDetailService.getDictDetailByNameForValue(dictStr);
                    dictDetailMaps.put(dictStr,dictDetailMap);
                }catch (Exception e){
                    log.error(e.toString());
                    log.error("获取字典配置"+property+"异常");
                }

            }
        });

        List<Map<String, Object>> list = new ArrayList<>();

        for (Object obj : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            tableConfigList.forEach(fanShe->{
                if(fanShe.visible){
                    //获取属性名
                    String property=fanShe.property;

                    if(property.indexOf("#")>-1){
                        try{
                            String  dictStr=property.split("#")[0];
                            String  propertyStr=property.split("#")[1];

                            Map<String, DictDetail> dictDetailMap=dictDetailMaps.get(dictStr);
                            //log.info("dictDetailMap："+dictDetailMap.size());
                            //for (String key: dictDetailMap.keySet()) {
                            //log.info("dictDetailMap："+key);
                            //}
                            //log.info(dictStr+"获取value："+json.getByPath(propertyStr)+"");

                            DictDetail dictDetail=dictDetailMap.get(getNestedFieldValue(obj,propertyStr));

                            //log.info(jsonObject.getStr("label")+"--"+dictDetail.getLabel()+"");
                            String value=dictDetail.getLabel()+"";
                            map.put(fanShe.label, value.trim()+"");
                        }catch (Exception e){
                            log.error(e.toString());
                            log.error("匹配字典："+property+"异常");
                        }


                    }else{
                        try{
                            Object value= getNestedFieldValue(obj,property);
                            if(value!=null){
                                if(value instanceof String){
                                    value=((String) value).trim();
                                }
                                map.put(fanShe.label,value);
                            }else{
                                map.put(fanShe.label,"");
                            }
                        }catch (Exception e){
                            //log.error(e.toString());
                            //log.error("匹配数据"+property+"异常");
                        }

                    }

                }

            });


            list.add(map);


            //Object value2 = jsonObj.eval("$.address.city");

        }
        return  list;
    }
    private static Field getFieldRecursively(Class<?> clazz, String fieldName) {
        while (clazz != null) {
            try {
                return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            }
        }
        return null;
    }

    public static Object getNestedFieldValue(Object obj, String nestedFieldName) throws Exception {
        String[] fields = nestedFieldName.split("\\.");
        try {
            Object result = obj;
            for (String field : fields) {
                if (result == null) {
                    throw new IllegalArgumentException("尝试在 null 对象上访问字段: " + field);
                }

                Field f = getFieldRecursively(result.getClass(), field);
                if (f == null) {
                    throw new NoSuchFieldException("字段 " + field + " 在类 " +
                            result.getClass().getName() + " 中不存在");
                }

                f.setAccessible(true);
                result = f.get(result);
            }
            return result;
        } catch (Exception e) {
            log.error("获取字段值失败: " + e.getMessage());

            return null;
        }
    }
}
