package com.emergency.avenue.admin.config.aop;

import cn.hutool.json.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.emergency.avenue.admin.api.entity.SysDictItem;
import com.emergency.avenue.admin.api.entity.SysTreeDict;
import com.emergency.avenue.admin.service.SysDictItemService;
import com.emergency.avenue.common.core.constant.FieldParam;
import com.emergency.avenue.common.core.constant.TranslationDict;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Aspect
@Component
@Slf4j
public class TranslateFieldAspect {

	@Resource
	private SysDictItemService sysDictItemService;
	// @TranslationDict({@FieldParam(dictType = "CUSTOMER_SEX", targetField = "sex"),

	/**
	 * 翻译字典值
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(com.emergency.avenue.common.core.constant.TranslationDict)")
	public Object aroundMethodDict(ProceedingJoinPoint joinPoint) throws Throwable {
		//接收到请求时间
		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONUtil.parseObj(result).toString();
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationDict annotation = method.getAnnotation(TranslationDict.class);
		FieldParam[] fieldParams = annotation.value();
		//遍历
		for (FieldParam fieldParam : fieldParams) {
			log.info("开始翻译字典CODE:{},取值字段：{},取值字段值类型：{}.",
					fieldParam.dictType(), fieldParam.targetField(), fieldParam.targetFieldValueClazz());
			Pattern dictPattern = getPattern(fieldParam);
			Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
			StringBuffer sb = new StringBuffer();
			//转义字段
			this.translateDict(fieldParam, dictPattern, dictMatcher, sb);
			dictMatcher.appendTail(sb);
			returnJsonResult = sb.toString();
		}

		result = JSONUtil.toBean(returnJsonResult, returnType);
		//如果这里不返回result，则目标对象实际返回值会被置为null
		//处理完请求时间
		Long endTime = System.currentTimeMillis();
		log.info("The request takes {}ms", endTime - startTime);
		return result;
	}

	/**
	 * 字典值转义为中文
	 *
	 * @param fieldParam
	 * @param fieldPattern
	 * @param fieldMatcher
	 * @param sb
	 */
	private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
		//从缓存中一次性取值
		Map<String, Map<String, String>> sysDictItemList = sysDictItemService.selectDictItem()
				.stream().collect(Collectors.groupingBy(SysDictItem::getDictType,
						Collectors.toMap(SysDictItem::getItemValue, SysDictItem::getLabel, (p1, p2) -> p2)));
		Map<String, String> dictNames = sysDictItemList.get(fieldParam.dictType());
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//""sex":1", ""sex":"1"",""sex":null"
			//属性无值
			if (group.split(":").length <= 1) continue;
			StringBuilder dictName = new StringBuilder();
			//获取字典值
			String dictValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			if (StringUtils.isNotBlank(dictValue) && !dictValue.equalsIgnoreCase("null")) {
				//多值
				if (dictValue.split(",").length > 1) {
					for (String s : dictValue.split(",")) {
						//fieldParam.dictType() + "_" + s 根据自己字典表设置的规则去查询
						dictName.append(dictNames.get(s)).append("/");
					}
				} else {
					dictName = new StringBuilder(dictNames.get(dictValue));
				}
			}
			StringBuilder replacement = new StringBuilder();
			replacement.append("\"").append(fieldParam.targetField())
					.append("Label").append("\":\"").append(dictName)
					.append("\",").append(fieldMatcher.group());
			log.info("拼接后字符串:{}", replacement);
			fieldMatcher.appendReplacement(sb, replacement.toString());
		}
	}

	/**
	 * 获取对应的正则式
	 *
	 * @param fieldParam
	 * @return
	 */
	private Pattern getPattern(FieldParam fieldParam) {
		Pattern fieldPattern;//属性整型 字符型
		if (fieldParam.targetFieldValueClazz().equals(Integer.class)) {
			fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":(\\d+)?");
		} else {
			fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":\"([0-9a-zA-Z_,]+)?\"");
		}
		return fieldPattern;
	}
}
