package com.storlead.system.util;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.storlead.framework.annotate.AnnBase;
import com.storlead.framework.annotate.Dict;
import com.storlead.system.pojo.entity.SysDictDetailEntity;
import com.storlead.system.pojo.entity.SysDictEntity;
import com.storlead.system.pojo.vo.DictDefinition;
import com.storlead.system.service.SysDictDetailService;
import com.storlead.system.service.SysDictService;
import com.storlead.user.pojo.entity.DeptEntity;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: sp-sales-platform
 * @description:
 * @author: chenkq
 * @create: 2024-04-16 15:44
 */
@Component
@Log4j2
public class DictUtils {

    @Resource
    private  SysDictService dictService;

    @Resource
    private  SysDictDetailService dictDetailService;

//    @Autowired
//    public DictUtils(SysDictService dictService,SysDictDetailService dictDetailService){
//        this.staticDictService = dictService;
//        this.staticDictDetailService = dictDetailService;
//    }

    public void convertDict(Object target) {
        try {
            List<DictDefinition> dictDefinitions = getMetadata(target);
            if (CollectionUtils.isEmpty(dictDefinitions)) return;
            Set<String> dictNames = dictDefinitions.stream().map(d -> d.getDict().dictCode()).collect(Collectors.toSet());
            Map<String, Map<String, String>> dictMapMap = getDictMap(dictNames);
            doConvertDict(target, dictDefinitions, dictMapMap);
        }catch (Exception e) {
            log.error("dictUtils convertDict error =",e);
        }
    }

    public void convertDictls(List<Object> targets) {
        try {
            List<DictDefinition> dictDefinitions = getMetadata(targets.get(0));
            if (CollectionUtils.isEmpty(dictDefinitions)) return;
            Set<String> dictNames = dictDefinitions.stream().map(d -> d.getDict().dictCode()).collect(Collectors.toSet());
            Map<String, Map<String, String>> dictMapMap = getDictMap(dictNames);
            for (Object t : targets) {
                doConvertDict(t, dictDefinitions, dictMapMap);
            }
        }catch (Exception e) {
            log.error("dictUtils convertDict error =",e);
        }
    }


    @SneakyThrows
    public void doConvertDict(Object target, List<DictDefinition> dictDefinitions,
                              Map<String, Map<String, String>> dictMapMap) {

        for (DictDefinition dictDefinition : dictDefinitions) {
            Dict dict = dictDefinition.getDict();
            Field field = dictDefinition.getField();
            // 需要取值的字段
            String getFieldName = field.getName();
            Field getField =field;// FieldUtils.getField(target.getClass(), getFieldName, true);
            if (Objects.isNull(getField)) {
                continue;
            }
            // 需要赋值的字段
            String setFieldName = StrUtil.isNotBlank(dict.valueField()) ? dict.valueField() : dict.keyField();
            if (StrUtil.isBlank(setFieldName)) {
                continue;
            }
            Field setField = FieldUtils.getField(target.getClass(), setFieldName, true);
            if (Objects.isNull(setField)) {
                continue;
            }
            if (dict.multiple()) {
                String fieldValue = String.valueOf(FieldUtils.readField(target,getFieldName, true));
                if (StrUtil.isNotBlank(fieldValue)) {
                    String[] dictValues = fieldValue.split(",");
                    StringBuilder dictValue = new StringBuilder();
                    for (String value : dictValues) {
                        Map<String, String> dictMap = dictMapMap.get(dict.dictCode());
                        Map<String, String> dictKeyMap = StrUtil.isNotBlank(dict.valueField()) ? dictMap : MapUtil.swapKeysAndValues(dictMap);
                        dictValue.append(dictKeyMap.get(value)).append(",");
                    }
                    /**
                     * 不需要最后一个逗号分隔符
                     */
                    if (StrUtil.isNotBlank(dictValue)) {
                        dictValue.deleteCharAt(dictValue.length() - 1);
                    }
                    Class<?> fieldType = setField.getType();
                    Object convertedValue = convertToFieldType(fieldType, dictValue.toString());
                    FieldUtils.writeField(target,setFieldName, convertedValue, true);
                }
            } else {
                Map<String, String> dictMap = dictMapMap.get(dict.dictCode());
                String dictValue = String.valueOf(FieldUtils.readField(target, getFieldName, true));
                Map<String, String> dictKeyMap = StrUtil.isNotBlank(dict.valueField()) ? dictMap : MapUtil.swapKeysAndValues(dictMap);
                if (StrUtil.isNotBlank(dictValue) && Objects.nonNull(dictKeyMap)) {
                    String defaultValue = dictKeyMap.get(dictValue);
                    Class<?> fieldType = setField.getType();
                    Object convertedValue = convertToFieldType(fieldType, defaultValue);
                    FieldUtils.writeField(target,setFieldName,convertedValue, true);
                }
            }
        }
    }
    private static Object convertToFieldType(Class<?> fieldType, Object defaultValue) {
        if (defaultValue == null) {
            return null;  // 如果 defaultValue 为 null，直接返回 null
        }

        // 根据字段的类型进行转换
        if (fieldType == int.class || fieldType == Integer.class) {
            return Integer.parseInt(defaultValue.toString());
        } else if (fieldType == long.class || fieldType == Long.class) {
            return Long.parseLong(defaultValue.toString());
        } else if (fieldType == double.class || fieldType == Double.class) {
            return Double.parseDouble(defaultValue.toString());
        } else if (fieldType == float.class || fieldType == Float.class) {
            return Float.parseFloat(defaultValue.toString());
        } else if (fieldType == boolean.class || fieldType == Boolean.class) {
            return Boolean.parseBoolean(defaultValue.toString());
        } else if (fieldType == String.class) {
            return defaultValue.toString();
        }
        // 其他类型可以根据实际需要继续扩展
        return defaultValue;  // 默认返回原值
    }

    /**
    /**
     * 仅获取一次Dict元数据，降低多次反射造成的性能消耗
     * @param target 目标实体类
     * @return Dict元数据
     */
    private List<DictDefinition> getMetadata(Object target) {
        List<DictDefinition> dictDefinitions = new ArrayList<>();
        if (ClassUtils.isPrimitiveOrWrapper(target.getClass())
                || target instanceof Map || target instanceof String) {
            return dictDefinitions;
        }
        List<Field> fields = FieldUtils.getAllFieldsList(target.getClass());
        for (Field field : fields) {
            Dict dict = AnnotationUtils.getAnnotation(field, Dict.class);
            if (dict != null) {
                DictDefinition dictDefinition = new DictDefinition(dict,field);
                dictDefinitions.add(dictDefinition);
            }
        }
        return dictDefinitions;
    }

    /**
     * 统一获取当前实体类涉及到的字典表数据，避免多次查询数据库造成的性能消耗
     * @param dictCode 字典表Key值
     * @return 字典表数据
     */
    @SneakyThrows
    private Map<String, Map<String, String>> getDictMap(Set<String> dictCode) {
        QueryWrapper<SysDictEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(SysDictEntity::getCode,dictCode);
        List<SysDictEntity> dictList = dictService.list(wrapper);

        QueryWrapper<SysDictDetailEntity> detailWrapper = new QueryWrapper<>();
        List<Long> dIds = dictList.stream().map(SysDictEntity::getDictId).collect(Collectors.toList());
        detailWrapper.lambda().in(SysDictDetailEntity::getDictId,dIds);
        List<SysDictDetailEntity> detailList = dictDetailService.list(detailWrapper);

        Map<String, Map<String, String>> dictMap = new HashMap<>();
        for (SysDictEntity  dict : dictList) {

            List<SysDictDetailEntity>  ds = detailList.stream().filter(d -> d.getDictId().equals(dict.getDictId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(ds)) {
                dictMap.put(dict.getCode(),new HashMap<>());
            } else {
                dictMap.put(dict.getCode(), ds.stream().collect(Collectors.toMap(SysDictDetailEntity::getValue, SysDictDetailEntity::getLabel, (u1,u2) -> u2)));
            }
        }
        return dictMap;
    }

    private Map<String, String> getDictMap(String dictCode) {
        QueryWrapper<SysDictEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SysDictEntity::getCode,dictCode);
        wrapper.last("limit 1");
        SysDictEntity dict = dictService.getOne(wrapper);
        if (Objects.isNull(dict)) {
            return Collections.emptyMap();
        }
        QueryWrapper<SysDictDetailEntity> detailWrapper = new QueryWrapper<>();
        detailWrapper.lambda().eq(SysDictDetailEntity::getDictId,dict.getDictId());
        List<SysDictDetailEntity> detailList = dictDetailService.list(detailWrapper);
        if (CollectionUtils.isEmpty(detailList)) {
            return Collections.emptyMap();
        }
        Map<String, String> dictMap = detailList.stream().collect(Collectors.toMap(SysDictDetailEntity::getValue, SysDictDetailEntity::getLabel, (u1, u2) -> u1));
        return dictMap;
    }

    @Data
    public static class DictDefinition {
        private Dict dict;
        private Field field;

        //构造方法
        public DictDefinition(Dict dict,Field field) {
            this.dict = dict;
            this.field = field;
        }
    }
}
