package com.jy.log.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.filter.ValueFilter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jy.framework.model.constants.CommonConstant;
import com.jy.framework.model.event.OperateEvent;
import com.jy.framework.utils.AssertUtil;
import com.jy.framework.utils.ExceptionUtil;
import com.jy.framework.utils.ServletUtil;
import com.jy.log.dao.LogOperateDao;
import com.jy.log.model.dto.LogOperateSelectDto;
import com.jy.log.model.entity.LogOperate;
import com.jy.log.model.vo.LogOperateVo;
import com.jy.log.service.LogOperateService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 操作日志 服务实现类
 * </p>
 *
 * @author
 * @since 2024-09-03
 */
@Service
public class LogOperateServiceImpl implements LogOperateService {

    @Resource
    private HttpServletRequest request;

    @Resource
    private LogOperateDao logOperateDao;

    @Override
    public Page<LogOperateVo> getPage(LogOperateSelectDto dto) {
        return logOperateDao.getPage(dto);
    }

    @Override
    public LogOperateVo getDetail(Long id) {
        LogOperateVo vo = logOperateDao.getDetail(id);
        AssertUtil.notNull(vo, "未知数据");
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> idList) {
        logOperateDao.removeBatchByIds(idList);
    }

    @Override
    public void save(OperateEvent event) {
        String[] excludeFields = event.getExcludeFields();
        Exception exception = event.getException();

        // 获取请求信息
        String method = request.getMethod();
        String bestMatching = ServletUtil.getBestMatching(request);
        String variable = ServletUtil.getVariable(request);
        Map<String, String> paramMap = ServletUtil.getParamMap(request);
        Map<String, Object> bodyMap = ServletUtil.getBodyMap(request);

        // 异步记录异常日志
        String param;
        String body;
        if (ObjectUtil.isEmpty(excludeFields)) {
            param = JSON.toJSONString(paramMap);
            body = JSON.toJSONString(bodyMap);
        } else {
            ValueFilter filter = (object, name, value) -> ArrayUtil.contains(excludeFields, name) ? "***" : value;
            param = JSON.toJSONString(paramMap, filter);
            body = JSON.toJSONString(bodyMap, filter);
        }

        LogOperate logOperate = new LogOperate();
        logOperate.setTitle(event.getTitle());
        logOperate.setBusinessType(event.getBusinessType().getKey());
        logOperate.setCostTime(event.getCostTime());
        logOperate.setMethod(method);
        logOperate.setBestMatching(bestMatching);
        logOperate.setRequestAttribute(variable);
        logOperate.setRequestParam(param);
        logOperate.setRequestBody(body);

        if (exception == null) {
            logOperate.setStatus(CommonConstant.SUCCESS);
            logOperate.setResult(JSONObject.toJSONString(event.getResult()));
        } else {
            logOperate.setStatus(CommonConstant.FAIL);
            logOperate.setErrorMsg(exception.getMessage());
            logOperate.setErrorDetail(ExceptionUtil.getDetailsStr(exception));
        }

        logOperateDao.save(logOperate);
    }

}
