package com.yiboshi.science.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiboshi.science.base.BaseServiceImpl;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.dao.LogsExceptionDAO;
import com.yiboshi.science.entity.LogsException;
import com.yiboshi.science.param.dto.LogsExceptionDTO;
import com.yiboshi.science.param.query.LogsExceptionQueryVO;
import com.yiboshi.science.service.LogsExceptionService;
import com.yiboshi.science.utils.CustomerIPAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 异常日志 Service 实现类
 *
 * @author lkl
 * @version 2021-08-26
 */
@Service
public class LogsExceptionServiceImpl extends BaseServiceImpl<LogsExceptionDAO, LogsExceptionQueryVO, LogsExceptionDTO, LogsException> implements LogsExceptionService {

    @Autowired
    private LogsExceptionDAO logsExceptionDAO;

    @Autowired
    protected HttpServletRequest request;

    @Override
    protected void setCriteriaForQuery(LogsExceptionQueryVO vo, QueryWrapper<LogsExceptionQueryVO> criteria) {
        if (Objects.nonNull(vo.getLogLevel())) {
            criteria.eq("log_level", vo.getLogLevel());
        }
        if (Objects.nonNull(vo.getShortTitle())) {
            criteria.like("short_title", vo.getShortTitle());
        }
        if (Objects.nonNull(vo.getIpAddress())) {
            criteria.eq("ip_address", vo.getIpAddress());
        }
        if (Objects.nonNull(vo.getCustomerId())) {
            criteria.eq("customer_id", vo.getCustomerId());
        }
        if (Objects.nonNull(vo.getPageUrl())) {
            criteria.eq("page_url", vo.getPageUrl());
        }
        if (Objects.nonNull(vo.getRequestUrl())) {
            criteria.eq("request_url", vo.getRequestUrl());
        }
        if (Objects.nonNull(vo.getMessage())) {
            criteria.eq("message", vo.getMessage());
        }
        if (Objects.nonNull(vo.getStartDate()) && Objects.nonNull(vo.getEndDate())) {
            criteria.between("created", vo.getStartDate(), vo.getEndDate());
        }
    }

    @Override
    public Pagination<LogsExceptionDTO> getListByPage(LogsExceptionQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<LogsExceptionQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<LogsExceptionDTO> dtoList = logsExceptionDAO.getListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    public void logs(HandlerMethod handlerMethod, Exception exception, String msg) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LogsException log = new LogsException();
        if (authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken)) {
            log.setCustomerId(SecurityUserHolder.getPersonId());
        }
        try {
            //获取方法返回类型中，CommonResVo中的泛型对象
            //String typeName = ((ParameterizedType) handlerMethod.getMethod().getGenericReturnType()).getActualTypeArguments()[0].getTypeName();
            //Var data = Class.forName(typeName).newInstance();
            Enumeration names = request.getParameterNames();
            Map<String, String> map = new HashMap<>();
            while (names.hasMoreElements()) {
                String name = (String) names.nextElement();
                String value = request.getParameter(name);
                map.put(name, value);
            }
            String params = JSON.toJSONString(map);

            log.setLogParam(params);
            log.setShortTitle(msg);
            log.setIpAddress(CustomerIPAddress.getIPAddress(request));
            log.setLogLevel(2);
            log.setMessage(exception.getMessage());
            log.setRequestUrl(request.getRequestURI());
            this.insert(log);

        } catch (Exception ex) {
            log.setIpAddress(CustomerIPAddress.getIPAddress(request));
            log.setLogLevel(1);
            log.setMessage(ex.getMessage());
            log.setRequestUrl("");
            log.setShortTitle("全局处理日志异常");
            this.insert(log);
        }
    }
}