package com.hzs.common.core.aspect;

import cn.hutool.core.util.ReflectUtil;
import com.hzs.common.core.annotation.Transaction;
import com.hzs.common.core.constant.CountryConstants;
import com.hzs.common.core.context.SecurityContextHolder;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.ELanguages;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.core.web.domain.EnumEntity;
import com.hzs.common.core.web.page.TableDataInfo;
import com.hzs.system.base.ICountryServiceApi;
import com.hzs.system.base.ITransactionServiceApi;
import com.hzs.system.base.dto.CountryDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * Description: 接口返回统一翻译处理
 * Author: jiang chao
 * Time: 2022/8/31 10:19
 * Classname: TransactionAspectAdvice
 * PackageName: com.hzs.common.core.aspect
 */
@Slf4j
@Order(20)
@Aspect
@Component
public class TransactionAspectAdvice {

    @DubboReference
    private ICountryServiceApi iCountryServiceApi;
    @DubboReference
    private ITransactionServiceApi iTransactionServiceApi;

    /**
     * 定义切点Pointcut
     */
    @Pointcut("execution(* com.hzs..controller..*Controller.*(..))")
    public void transactionPointCut() {
    }

    /**
     * 执行返回时进行处理
     *
     * @param joinPoint
     * @param returnValue 返回数据对象
     * @return
     */
    @AfterReturning(value = "transactionPointCut()", returning = "returnValue")
    public Object transactionPointAfter(JoinPoint joinPoint, Object returnValue) {
        // 返回值不为空，则进行处理
        if (null != returnValue) {
            long startTime = System.currentTimeMillis();

            // 默认中国
            int fromCountry = CountryConstants.CHINA_COUNTRY;
            // 从 THREAD_LOCAL 获取用户结算国，获取对应语言
            String countryStr = SecurityContextHolder.getUserCountry();
            if (StringUtils.isNotEmpty(countryStr)) {
                fromCountry = Integer.parseInt(countryStr);
            }

            R<CountryDTO> countryResult = iCountryServiceApi.getCountry(fromCountry);
            if (!countryResult.isSuccess()) {
                // 获取国家失败，则不进行后续处理
                return returnValue;
            }
            CountryDTO countryDTO = countryResult.getData();
            ELanguages language = ELanguages.getLanguagesByValue(countryDTO.getLanguages());
            log.info("language: {}", language.getLocal());

            // 翻译字段map（key：字段， value：字段注解）
            Map<String, Transaction> fieldMap = new HashMap<>();

            if (returnValue instanceof AjaxResult) {
                // 返回为统一 AjaxResult
                AjaxResult ajaxResult = (AjaxResult) returnValue;
                // 返回内容
                Object ajaxResultObj = ajaxResult.get(AjaxResult.DATA_TAG);

                if (null != ajaxResultObj) {
                    // 返回的 data 不为空则进行国际化处理
                    if (ajaxResultObj instanceof String) {
                        // 返回内容为字符串处理
//                        R<String> rStr = iTransactionServiceApi.readTransactionByCache(ajaxResultObj.toString(), toLocal);
//                        if (rStr.isSuccess() && StringUtils.isNotEmpty(rStr.getData())) {
//                            // 处理字符串成功，并且带有返回内容则，则进行替换
//                            ajaxResult.put(AjaxResult.DATA_TAG, rStr.getData());
//                        }
                    } else if (ajaxResultObj instanceof Collection) {
                        // 返回内容为集合处理
                        Collection dataList = (Collection) ajaxResultObj;

                        // 集合数据翻译处理
                        this.handleCollection(dataList, fromCountry, fieldMap);
                    } else if (ajaxResultObj instanceof EnumEntity) {
                        // 返回内容为枚举实体，单独处理
                        EnumEntity enumEntity = (EnumEntity) ajaxResultObj;

                        if (StringUtils.isNotEmpty(enumEntity.getTransactionKey())) {
                            // 当指定翻译前缀才进行处理
                            R<String> rStr = iTransactionServiceApi.readTransactionByCache(enumEntity.getTransactionKey() + enumEntity.getValue(), LocaleContextHolder.getLocale().toLanguageTag());
                            if (rStr.isSuccess() && StringUtils.isNotEmpty(rStr.getData())) {
                                // 处理成功，并且带有返回内容，则进行显示内容赋值
                                enumEntity.setLabel(rStr.getData());
                            }
                        }
                    } else {
                        // 返回内容为单体对象处理
                        this.getFieldMap(ajaxResultObj, fieldMap);

                        // 需要翻译的key列表
                        Set<String> keyList = new HashSet<>();
                        // 需要翻译的内容列表
                        Set<String> contentList = new HashSet<>();

                        // 处理待翻译列表
                        this.handleTransactionList(ajaxResultObj, fieldMap, keyList, contentList);

                        // 获取翻译map
                        Map<String, String> transactionMap = this.getTransactionMap(fromCountry, keyList, contentList);
                        if (null != transactionMap) {
                            // 根据翻译重新赋值
                            this.handleFieldTransaction(ajaxResultObj, fieldMap, transactionMap);
                        }
                    }
                }
            } else if (returnValue instanceof TableDataInfo) {
                // 返回为分页数据
                TableDataInfo tableDataInfo = (TableDataInfo) returnValue;
                Collection dataList = tableDataInfo.getRows();

                // 集合数据翻译处理
                this.handleCollection(dataList, fromCountry, fieldMap);
            }

            log.info("翻译拦截器处理结束，毫秒用时 {}", System.currentTimeMillis() - startTime);
        }
        return returnValue;
    }

    /**
     * 集合数据翻译处理
     *
     * @param dataList    数据集合
     * @param fromCountry 来源国ID
     * @param fieldMap    翻译字段map
     */
    private void handleCollection(Collection dataList, Integer fromCountry, Map<String, Transaction> fieldMap) {
        if (CollectionUtils.isNotEmpty(dataList)) {
            // 数据集合不为空，进行处理

            for (Object obj : dataList.toArray()) {
                if (null != obj) {
                    this.getFieldMap(obj, fieldMap);
                }
            }

            // 需要翻译的缓存key列表
            Set<String> keyList = new HashSet<>();
            // 需要翻译的数据库内容列表
            Set<String> contentList = new HashSet<>();

            // 获取数据集合类型
            Object dataObj = dataList.iterator().next();

            if (dataObj instanceof EnumEntity) {
                // 如果是枚举实体，单独处理
                for (Object obj : dataList) {
                    EnumEntity enumEntity = (EnumEntity) obj;

                    keyList.add(enumEntity.getTransactionKey() + enumEntity.getValue());
                }
            } else {
                // 遍历所有数据，将需要翻译的key集合封装
                if (fieldMap.size() > 0) {
                    for (Object obj : dataList) {
                        // 处理待翻译列表
                        this.handleTransactionList(obj, fieldMap, keyList, contentList);
                    }
                }
            }

            // 获取翻译map
            Map<String, String> transactionMap = this.getTransactionMap(fromCountry, keyList, contentList);
            if (null != transactionMap) {
                if (dataObj instanceof EnumEntity) {
                    // 如果是枚举实体，单独处理
                    for (Object obj : dataList) {
                        EnumEntity enumEntity = (EnumEntity) obj;

                        if (StringUtils.isNotEmpty(enumEntity.getTransactionKey())) {
                            // 当指定翻译前缀才进行处理
                            String str = transactionMap.get(enumEntity.getTransactionKey() + enumEntity.getValue());
                            if (StringUtils.isNotEmpty(str)) {
                                enumEntity.setLabel(transactionMap.get(enumEntity.getTransactionKey() + enumEntity.getValue()));
                            }
                        }
                    }
                } else {
                    // 遍历所有数据，将翻译之后的内容重新赋值
                    for (Object obj : dataList) {
                        // 根据翻译重新赋值
                        this.handleFieldTransaction(obj, fieldMap, transactionMap);
                    }
                }
            }
        }
    }

    /**
     * 根据翻译实体，获取需要翻译的字段map
     *
     * @param obj      数据实体
     * @param fieldMap 翻译字段map
     * @return
     */
    private Map<String, Transaction> getFieldMap(Object obj, Map<String, Transaction> fieldMap) {
        // 获取内容对应实体
        Class dataClass = obj.getClass();
        // 获取实体字段
        Field[] fields = ReflectUtil.getFields(dataClass);

        for (Field field : fields) {
            // 获取带有翻译注解的字段
            Transaction transaction = field.getDeclaredAnnotation(Transaction.class);
            if (null != transaction) {
                // 强制处理时 才进行处理
                if (transaction.isForce()) {
                    // 获取字段值
                    Object fieldObj = ReflectUtil.getFieldValue(obj, field);

                    if (fieldObj instanceof String || fieldObj instanceof Integer || fieldObj instanceof Long) {
                        // 字符串 或 整型 或 长整型
                        fieldMap.put(field.getName(), transaction);
                    } else if (fieldObj instanceof Collection) {
                        // 集合类型
                        fieldMap.put(field.getName(), transaction);

                        Collection dataList = (Collection) fieldObj;
                        if (CollectionUtils.isNotEmpty(dataList)) {
                            // 返回的数据集合不为空
                            Object dataObj = dataList.iterator().next();
                            // 递归调用，生成下级翻译字段，进行合并累加
                            this.getFieldMap(dataObj, fieldMap);
                        }
                    } else {
                        // 当数据为空值时，仍然需要配合取值国际化
                        fieldMap.put(field.getName(), transaction);
                    }
                }
            }
        }
        return fieldMap;
    }

    /**
     * 处理待翻译列表
     *
     * @param obj         数据实体
     * @param fieldMap    翻译字段map
     * @param keyList     需要翻译的缓存key列表
     * @param contentList 需要翻译的数据库内容列表
     */
    private void handleTransactionList(Object obj, Map<String, Transaction> fieldMap, Set<String> keyList, Set<String> contentList) {
        for (String field : fieldMap.keySet()) {
            // 获取字段注解
            Transaction transaction = fieldMap.get(field);
            // 获取字段值
            Object fieldObj = ReflectUtil.getFieldValue(obj, field);

            if (fieldObj instanceof String || fieldObj instanceof Integer || fieldObj instanceof Long) {
                // 字符串 或 整型 或 长整型
                // 翻译枚举前缀
                String transactionKey = transaction.transactionKey();

                if (transaction.isCache()) {
                    // 使用缓存
                    if (transaction.isValue()) {
                        // 第一种情况： 枚举前缀 + 当前字段值
                        keyList.add(transactionKey + fieldObj);
                    } else {
                        // 第二种情况： 枚举前缀 + 固定字段值
                        keyList.add(transactionKey + ReflectUtil.getFieldValue(obj, transaction.valueField()));
                    }
                } else {
                    // 不使用缓存，直接取字段值
                    contentList.add(fieldObj.toString());
//                    // 不使用缓存，直接取字段值
//                    if (transaction.isValue()) {
//                        // 第一种情况： 当前字段值
//                        contentList.add(fieldObj.toString());
//                    } else {
//                        // 第二种情况： 固定字段值
//                        contentList.add(ReflectUtil.getFieldValue(obj, transaction.valueField()));
//                    }
                }
            } else if (fieldObj instanceof Collection) {
                // 集合类型
                Collection dataList = (Collection) fieldObj;
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (Object dataObj : dataList) {
                        // 递归调用，追加下级翻译列表
                        this.handleTransactionList(dataObj, fieldMap, keyList, contentList);
                    }
                }
            }
        }
    }

    /**
     * 获取翻译map
     *
     * @param fromCountry 来源国ID
     * @param keyList     翻译的缓存key列表
     * @param contentList 翻译的数据库内容列表
     * @return
     */
    private Map<String, String> getTransactionMap(int fromCountry, Set<String> keyList, Set<String> contentList) {
        Map<String, String> transactionMap = null;
        // 当需要翻译的两个列表都没值，不进行RPC调用处理
        if (CollectionUtils.isNotEmpty(keyList) || CollectionUtils.isNotEmpty(contentList)) {
            // 调用翻译服务获取最终翻译内容
            R<Map<String, String>> resultR = iTransactionServiceApi.readTransactionAll(fromCountry, contentList, keyList, LocaleContextHolder.getLocale().toLanguageTag());
            if (resultR.isSuccess()) {
                // 翻译后数据map
                transactionMap = resultR.getData();
            }
        }
        return transactionMap;
    }

    /**
     * 根据翻译重新赋值
     *
     * @param obj            数据实体
     * @param fieldMap       翻译字段map
     * @param transactionMap 翻译map
     */
    private void handleFieldTransaction(Object obj, Map<String, Transaction> fieldMap, Map<String, String> transactionMap) {
        for (String fieldName : fieldMap.keySet()) {
            // 获取字段注解
            Transaction transaction = fieldMap.get(fieldName);
            // 获取字段值
            Object fieldObj = ReflectUtil.getFieldValue(obj, fieldName);

            if (fieldObj instanceof String || fieldObj instanceof Integer || fieldObj instanceof Long) {
                // 字符串 或 整型 或 长整型
                // 翻译枚举前缀
                String transactionKey = transaction.transactionKey();

                if (transaction.isCache()) {
                    // 使用缓存
                    String val = "";
                    if (transaction.isValue()) {
                        // 第一种情况： 枚举前缀 + 当前字段值
                        val = transactionMap.get(transactionKey + ReflectUtil.getFieldValue(obj, fieldName));
                    } else {
                        // 第二种情况： 枚举前缀 + 固定字段值
                        val = transactionMap.get(transactionKey + ReflectUtil.getFieldValue(obj, transaction.valueField()));
                    }
                    if (StringUtils.isNotEmpty(val)) {
                        ReflectUtil.setFieldValue(obj, fieldName + "Val", val);
                    }
                } else {
                    // 不使用缓存
                    String val = transactionMap.get(ReflectUtil.getFieldValue(obj, fieldName).toString());
                    if (StringUtils.isNotEmpty(val)) {
                        ReflectUtil.setFieldValue(obj, fieldName, val);
                    }
                }
            } else if (fieldObj instanceof Collection) {
                // 集合类型
                Collection dataList = (Collection) fieldObj;
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (Object dataObj : dataList) {
                        // 递归调用，追加下级翻译重新赋值
                        this.handleFieldTransaction(dataObj, fieldMap, transactionMap);
                    }
                }
            }
        }
    }

}
