package com.yida.data.log.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.system.Log;
import com.yida.data.common.core.entity.system.enums.OperationLogTypeEnum;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.log.annotation.OperationLog;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 日志service层
 *
 * @author ZYJ
 * @date 2021/1/8
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LogService {

    private final RedisService redisService;

    /**
     * 保存操作日志信息
     *
     * @param joinPoint ProceedingJoinPoint类
     * @param ip        ip地址
     * @param params    请求参数
     * @param result    接口返回结果
     * @author ZYJ
     * @date 2021/1/8 16:30
     */
    @Async
    public void saveOperationLog(JoinPoint joinPoint, String ip, String params, Object result, Long createId, String createName) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperationLog opLog = method.getAnnotation(OperationLog.class);
        //ip地址
        Log systemLogInfo = new Log();
        systemLogInfo.setCreateId(createId);
        systemLogInfo.setCreateName(createName);
        // 创建人
//        if (FebsUtil.isLogin()) {
//            CurrentUser currentUser = FebsUtil.getCurrentUser();
//            if (currentUser != null) {
//                systemLogInfo.setCreateId(currentUser.getUserId());
//                systemLogInfo.setCreateName(currentUser.getUsername());
//            }
//        }
        systemLogInfo.setIp(ip);
        //设置开始时间
        systemLogInfo.setStartTime(LocalDateTime.now());
        systemLogInfo.setCreateDate(LocalDateTime.now());
        try {
            //设置操作模块与操作内容
            OperationLogTypeEnum opType = opLog.type();
            systemLogInfo.setModule(opLog.module().getName());
            systemLogInfo.setMethod(opLog.methods());
            //设置操作方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = method.getName();
            methodName = className + "." + methodName;
            systemLogInfo.setMethodName(methodName);
            //请求参数
            systemLogInfo.setOperateParams(params);
            //返回结果
            systemLogInfo.setResult(JSON.toJSONString(result));
            //将返回值转换为对象
            ResultBean<Object> logResult = JSON.parseObject(JSON.toJSONString(result),
                new TypeReference<ResultBean<Object>>() {
                });
            int successStatus = 200;
            if (logResult != null) {
                if (logResult.getStatus() == successStatus) {
                    //设置操作结果
                    systemLogInfo.setResultStatus(logResult.getStatus());
                    systemLogInfo.setResultMsg("操作成功");
                } else {
                    //设置操作结果
                    systemLogInfo.setResultStatus(logResult.getStatus());
                    systemLogInfo.setResultMsg(logResult.getMessage());
                }
            }
            //日志类型
            systemLogInfo.setLogType(getLogType(opType.getValue(), params));
        } catch (Exception e) {
            log.error("设置操作日志参数失败{}: ", e.getMessage(), e);
            //设置操作结果
            systemLogInfo.setResultMsg(e.getMessage());
        } finally {
            //设置结束时间
            systemLogInfo.setEndTime(LocalDateTime.now());
            //操作时长
            systemLogInfo.setOperationTime(LocalDateTimeUtil.between(systemLogInfo.getStartTime(),
                systemLogInfo.getEndTime(), ChronoUnit.MILLIS));
            //保存数据到redis  list数据
            redisService.lSet(CachePrefixConstant.OPERATION_LOG_LIST, systemLogInfo);
        }
    }

    /**
     * 获取操作日志类型
     *
     * @param value  日志类型枚举值
     * @param params 请求参数
     * @return java.lang.String
     * @author ZYJ
     * @date 2021/1/11 10:52
     */
    private String getLogType(String value, String params) {

        try {
            //当为保存类型时
            if (OperationLogTypeEnum.SAVE.getValue().equals(value)) {
                //当为保存时, 请求参数被封装成了数组
                JSONArray jsonArray = JSON.parseArray(params);
                //获取第一个参数
                JSONObject jsonObject = jsonArray.getJSONObject(0);
                if (jsonObject != null) {
                    String id = jsonObject.getString("id");
                    //判断id值
                    if (StringUtils.isNotBlank(id)) {
                        value = OperationLogTypeEnum.UPDATE.getValue();
                    } else {
                        value = OperationLogTypeEnum.INSERT.getValue();
                    }
                }
            }
            return value;
        } catch (Exception e) {
            log.error("判断日志类型失败{}: ", e.getMessage(), e);
            return value;
        }
    }
}
