package com.jwipc.log.logic;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import com.jwipc.log.dto.LogDTO;
import com.jwipc.log.dto.LogSettingDTO;
import com.jwipc.log.logic.util.ClassUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.TimerTask;

/**
 * <p>日志解析逻辑控制</p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Slf4j
public class LogAnalysisLogic {
    private final LogSettingLogic logSettingLogic;
    private final LoginUserLogic loginUserLogic;
    private final LogStorageLogic logStorageLogic;

    public LogAnalysisLogic(LogSettingLogic logSettingLogic, LoginUserLogic loginUserLogic,
                            LogStorageLogic logStorageLogic)
    {
        this.logSettingLogic = logSettingLogic;
        this.loginUserLogic = loginUserLogic;
        this.logStorageLogic = logStorageLogic;
    }


    public void analysisThrowException(Class<?> target,
                                       Method method,
                                       Object[] pointArgs,
                                       Throwable subclass,
                                       String url,
                                       final LogDTO logDTO)
    {
        handler(target, method, pointArgs, url, logDTO, subclass);
    }

    public void handler(Class<?> target,
                        Method method, Object[] pointArgs,
                        String url,
                        LogDTO logDTO, Throwable subclass)
    {
        handler(target, method, pointArgs, null, url, logDTO, subclass);
    }

    public void analysis(Class<?> target,
                         Method method,
                         Object[] pointArgs,
                         Object proceed,
                         String url,
                         final LogDTO logDTO)
    {
        handler(target, method, pointArgs, proceed, url, logDTO);
    }

    public void handler(Class<?> target,
                        Method method, Object[] pointArgs,
                        Object proceed,
                        String url,
                        LogDTO logDTO)
    {
        handler(target, method, pointArgs, proceed, url, logDTO, null);
    }

    private void handler(Class<?> targetClass,
                         Method method, Object[] pointArgs,
                         Object proceed,
                         String url,
                         LogDTO logDTO, Throwable subclass)
    {
        String methodName = method.getName();
        //获取拦截方法的参数
        String userId = loginUserLogic.getUserId();
        String userName = loginUserLogic.getUserName();
        TimerTask businessTask = new TimerTask() {
            @Override
            public void run() {
                final String[] fieldsNames;
                String message = "";
                final LogSettingDTO logSettingDTO = logSettingLogic.getByUrl(url);
                if (Objects.isNull(logSettingDTO)) {
                    return;
                }
                String contentFormat = logSettingDTO.getParamTemplate();
                String resultFormat = logSettingDTO.getReturnTemplate();
                final String businessName = logSettingDTO.getBusinessName();
                try {
                    fieldsNames = ClassUtil.getFieldsName(targetClass, methodName);
                    if (ArrayUtil.isNotEmpty(pointArgs)) {
                        Map<String, Object> argsMap = MapUtil.newHashMap();
                        for (int i = 0; i < pointArgs.length; i++) {
                            Object pointArg = pointArgs[i];
                            argsMap.put(fieldsNames[i], pointArg);
                        }
                        message = FreeMarkers.renderString(contentFormat, argsMap);
                    }
                    String result = "";
                    if (!Objects.isNull(proceed)) {
                        Map<String, Object> argsMap = MapUtil.newHashMap();
                        argsMap.put("result", proceed);
                        result = FreeMarkers.renderString(resultFormat, argsMap);
                    } else {
                        if (Objects.nonNull(subclass)) {
                            result = subclass.getMessage();
                        }
                    }
                    LogDTO logDTO1 = new LogDTO(logDTO.getIp(), url, businessName, userId, userName, 0, message, result,
                            logDTO.getUserAgent());
                    logStorageLogic.save(logDTO1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        LogManager.me().executeLog(businessTask);
    }
}
