package com.ruoyi.common.filepathsplicing;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.FilePathSplicingType;
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.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @author Lion Li
 */
@Slf4j
@Aspect
@Component
public class FilePathSplicingAspect {

    @Resource
    private FilePathSplicingUtil filePathSplicingUtil;

    @Value("${oss.richReplaceValue}")
    private String richReplaceValue;

    /**
     * 环绕
     */
    @Pointcut("@annotation(com.ruoyi.common.filepathsplicing.FilePathSplicing)")
    public void aspectPoint() {
    }

    @Around("aspectPoint()")
    public Object processAuthority(ProceedingJoinPoint point) throws Throwable {
        // 获取注解
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        FilePathSplicing annotation = method.getAnnotation(FilePathSplicing.class);

        // 获取注解上的类型
        FilePathSplicingType[] type = annotation.type();
        List<FilePathSplicingType> filePathSplicingTypes = Arrays.asList(type);

        //处理请求参数
        if (filePathSplicingTypes.contains(FilePathSplicingType.REQUEST)) {
            //请求参数
            Object[] args = point.getArgs();
            if (args.length > 0) {
                //处理参数
                for (Object obj : args) {
                    this.disposeRequestParam(obj);
                }
            }
        }

        //响应参数
        Object proceed = point.proceed();
        //处理响应参数
        if (filePathSplicingTypes.contains(FilePathSplicingType.RESPONSE)) {
            return this.disposeResponseParam(proceed);
        }

        return proceed;
    }

    /**
     * 处理请求参数
     *
     * @param obj
     */
    private Object disposeRequestParam(Object obj) throws IllegalAccessException {
        if (ObjectUtil.isEmpty(obj)) {
            return obj;
        }
        if (obj instanceof String) {
            //拼接
            return this.disposeRequestFieldValue(String.valueOf(obj));
        } else if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            if (CollectionUtil.isEmpty(collection)) {
                return obj;
            }
            List<Object> newList = new ArrayList<>();
            for (Object o : collection) {
                if (o instanceof String) {
                    newList.add(this.disposeRequestFieldValue(String.valueOf(o)));
                } else {
                    newList.add(this.disposeRequestParam(o));
                }
            }
            return newList;
        } else {
            //如果是实体
            Class<?> aClass = obj.getClass();
            //获取字段
            Field[] declaredFields = aClass.getDeclaredFields();
            //遍历所有字段
            for (Field field : declaredFields) {
                FilePathValue filePathValue = field.getAnnotation(FilePathValue.class);
                if (ObjectUtil.isNotNull(filePathValue)) {
                    //需要处理的文件路径
                    field.setAccessible(true);
                    //获取值
                    Object value = field.get(obj);
                    if (ObjectUtil.isEmpty(value)) {
                        continue;
                    }
                    if (value instanceof String) {
                        //拼接
                        field.set(obj, this.disposeRequestFieldValue(String.valueOf(value)));
                    } else {
                        field.set(obj, this.disposeRequestParam(value));
                    }
                }

                //富文本
                FilePathRich filePathRich = field.getAnnotation(FilePathRich.class);
                if (ObjectUtil.isNotNull(filePathRich)) {
                    field.setAccessible(true);
                    //获取值
                    Object value = field.get(obj);
                    if (ObjectUtil.isEmpty(value)) {
                        continue;
                    }
                    //富文本只考虑字符串
                    if (value instanceof String) {
                        //拼接
                        field.set(obj, this.disposeRequestFieldRich(String.valueOf(value)));
                    }
                }
            }

            return obj;
        }
    }

    /**
     * 处理响应参数
     *
     * @param obj
     */
    private Object disposeResponseParam(Object obj) throws IllegalAccessException {
        //结果
        if (obj instanceof TableDataInfo) {
            //分页
            // 获取TableDataInfo中的值
            TableDataInfo responseData = (TableDataInfo) obj;
            List rows = responseData.getRows();
            // 将page中所有records都包装一遍
            for (Object row : rows) {
                disposeResponseObject(row);
            }
            return responseData;
        } else if (obj instanceof R) {
            //实体
            R r = (R) obj;
            Object data = r.getData();
            r.setData(this.disposeResponseObject(data));
            return r;
        }
        return obj;
    }

    /**
     * 处理响应的值
     *
     * @param obj
     * @throws IllegalAccessException
     */
    private Object disposeResponseObject(Object obj) throws IllegalAccessException {
        if (ObjectUtil.isEmpty(obj)) {
            return obj;
        }
        if (obj instanceof String) {
            //拼接
            return this.disposeResponseFieldValue(String.valueOf(obj));
        } else if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            if (CollectionUtil.isEmpty(collection)) {
                return obj;
            }
            List<Object> newList = new ArrayList<>();
            for (Object o : collection) {
                if (o instanceof String) {
                    newList.add(this.disposeResponseFieldValue(String.valueOf(o)));
                } else {
                    newList.add(this.disposeResponseObject(o));
                }
            }
            return newList;
        }
        // 如果是Array类型
        else if (ArrayUtil.isArray(obj)) {
            //obj转数组
            Object[] result = new Object[Array.getLength(obj)];
            for (int i = 0; i < result.length; i++) {
                result[i] = Array.get(obj, i);
            }
            List<Object> newList = new ArrayList<>();
            for (Object o : result) {
                if (o instanceof String) {
                    newList.add(this.disposeResponseFieldValue(String.valueOf(o)));
                } else {
                    newList.add(this.disposeResponseObject(o));
                }
            }
            return newList;
        } else {
            //如果是实体
            Class<?> aClass = obj.getClass();
            //获取字段
            Field[] declaredFields = aClass.getDeclaredFields();
            //遍历所有字段
            for (Field field : declaredFields) {
                FilePathValue filePathValue = field.getAnnotation(FilePathValue.class);
                if (ObjectUtil.isNotNull(filePathValue)) {
                    //需要处理的文件路径
                    field.setAccessible(true);
                    //获取值
                    Object value = field.get(obj);
                    if (ObjectUtil.isEmpty(value)) {
                        continue;
                    }
                    if (value instanceof String) {
                        //拼接
                        field.set(obj, this.disposeResponseFieldValue(String.valueOf(value)));
                    } else {
                        field.set(obj, this.disposeResponseObject(value));
                    }
                }

                //富文本
                FilePathRich filePathRich = field.getAnnotation(FilePathRich.class);
                if (ObjectUtil.isNotNull(filePathRich)) {
                    field.setAccessible(true);
                    //获取值
                    Object value = field.get(obj);
                    if (ObjectUtil.isEmpty(value)) {
                        continue;
                    }
                    //富文本只处理字符串
                    if (value instanceof String) {
                        //拼接
                        field.set(obj, this.disposeResponseFieldRich(String.valueOf(value)));
                    }
                }
            }
        }

        return obj;
    }


    /**
     * 处理请求的值
     *
     * @param value
     */
    private String disposeRequestFieldValue(String value) {
        String prefix = filePathSplicingUtil.getPrefix();
        if (ObjectUtil.isEmpty(value) || !value.startsWith(prefix)) {
            return value;
        }
        if (value.contains(",")) {
            String[] split = value.split(",");
            List<String> list = new ArrayList<>();
            for (String v : split) {
                list.add(v.replaceFirst(prefix, ""));
            }
            return String.join(",", list);
        } else {
            return value.replaceFirst(prefix, "");
        }
    }

    /**
     * 处理响应的值
     *
     * @param value
     */
    private String disposeResponseFieldValue(String value) {
        if (ObjectUtil.isEmpty(value) || value.startsWith("http")) {
            return value;
        }
        String prefix = filePathSplicingUtil.getPrefix();

        if (value.contains(",")) {
            String[] split = value.split(",");
            List<String> list = new ArrayList<>();
            for (String v : split) {
                list.add(prefix + v);
            }
            return String.join(",", list);
        } else {
            return prefix + value;
        }
    }

    /**
     * 处理请求的富文本值
     *
     * @param value
     */
    private String disposeRequestFieldRich(String value) {
        String prefix = filePathSplicingUtil.getPrefix();
        if (ObjectUtil.isEmpty(value) || !value.contains(prefix)) {
            return value;
        }

        return value.replaceAll(prefix, richReplaceValue);
    }

    /**
     * 处理响应的富文本值
     *
     * @param value
     */
    private String disposeResponseFieldRich(String value) {
        if (ObjectUtil.isEmpty(value) || !value.contains(richReplaceValue)) {
            return value;
        }

        String prefix = filePathSplicingUtil.getPrefix();
        return value.replaceAll(richReplaceValue, prefix);
    }

}
