package com.app.service.platform.monitor;

import com.app.dto.PageResult;
import com.app.dto.platform.FrontErrorDto;
import com.app.dto.platform.OperationLogDto;
import com.app.dto.platform.SearchLogDto;
import com.app.entity.BaseEntity;
import com.app.entity.platform.monitor.OperationLog;
import com.app.mapper.platform.OperationLogMapper;
import com.app.service.platform.auth.AccountService;
import com.app.util.IpUtil;
import com.app.util.JwtUtil;
import com.app.util.UserAgentUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;

/**
 * 操作日志
 *
 * @Author 梁展鹏
 */
@Service
public class OperationLogService {
    private final String FROM_BACKEND = "1"; // 错误来源：后端
    private final String FROM_FRONTEND = "2"; // 错误来源：前端

    @Autowired
    private OperationLogMapper mapper;

    @Autowired
    private AccountService accountService;

    public PageResult<OperationLogDto> page(SearchLogDto dto) {
        LambdaQueryWrapper<OperationLog> wrapper = new QueryWrapper<OperationLog>().lambda().eq(BaseEntity::getIsDel, dto.getIsDel());
        dto.setType(dto.getType().toUpperCase());
        if (!StringUtils.isEmpty(dto.getUsername())) {
            wrapper.like(OperationLog::getUsername, dto.getUsername());
        }
        if(!StringUtils.isEmpty(dto.getRemarks())){
            wrapper.like(OperationLog::getRemarks,dto.getRemarks());
        }
        wrapper.eq(OperationLog::getType,dto.getType());
        Page<OperationLog> page = mapper.selectPage(new Page<>(dto.getPage(), dto.getSize()), wrapper);
        ArrayList<OperationLogDto> logDtos = new ArrayList<>();
        for (OperationLog record : page.getRecords()) {
            OperationLogDto logDto = new OperationLogDto();
            BeanUtils.copyProperties(record,logDto);
            if(!StringUtils.isEmpty(record.getExceptionDetail())){
                logDto.setExceptionDetail(new String(record.getExceptionDetail(),StandardCharsets.UTF_8));
            }
            logDtos.add(logDto);
        }
        Page<OperationLogDto> p = new Page<>(dto.getPage(),dto.getSize());
        p.setRecords(logDtos);
        return new PageResult<>(dto.getPage(), dto.getSize(), p.getTotal(), p.getRecords());
    }

    // todo 先不要全部删，目前规划用定时器删除定期日志
    public void delAllLogs(String type) {
        mapper.update(null, new UpdateWrapper<OperationLog>().lambda().eq(OperationLog::getType,type.toUpperCase()).set(BaseEntity::getIsDel, Boolean.TRUE));
    }

    public void insertFrontErrorLog(HttpServletRequest request,FrontErrorDto dto) {
        OperationLog _operationLog = new OperationLog();
        _operationLog.setUsername(accountService.findCacheById(JwtUtil.getLocalUser().get().getId()).getNickname());
        _operationLog.setType("ERROR");
        _operationLog.setIp(IpUtil.getIp(request));
        _operationLog.setIpAddress(IpUtil.getIpAddress(request));
        _operationLog.setOs(UserAgentUtil.getOperatingSystem(request));
        _operationLog.setBrowser(UserAgentUtil.getBrowserName(request));
        _operationLog.setBrowserVersion(UserAgentUtil.getBrowserVersion(request));
        _operationLog.setRequestUrl(dto.getRequestUrl());
        if(!StringUtils.isEmpty(dto.getExceptionDetail())){
            _operationLog.setExceptionDetail(dto.getExceptionDetail().getBytes(StandardCharsets.UTF_8));
        }
        _operationLog.setRemarks(dto.getInfo()+" - "+dto.getMessage());
        _operationLog.setLogFrom(FROM_FRONTEND);
        mapper.insert(_operationLog);
    }

    public void insertInfoLog(HttpServletRequest request, String className, String method, String requestParams, Long time, String remarks) {
        OperationLog _operationLog = new OperationLog();
        _operationLog.setUsername(accountService.findCacheById(JwtUtil.getLocalUser().get().getId()).getNickname());
        _operationLog.setType("INFO");
        _operationLog.setIp(IpUtil.getIp(request));
        _operationLog.setIpAddress(IpUtil.getIpAddress(request));
        _operationLog.setOs(UserAgentUtil.getOperatingSystem(request));
        _operationLog.setBrowser(UserAgentUtil.getBrowserName(request));
        _operationLog.setBrowserVersion(UserAgentUtil.getBrowserVersion(request));
        _operationLog.setRequestUrl(request.getRequestURI());
        _operationLog.setClassName(className);
        _operationLog.setMethod(method);
        _operationLog.setRequest(requestParams);
        _operationLog.setTime(time);
        _operationLog.setExceptionDetail("".getBytes(StandardCharsets.UTF_8));
        _operationLog.setRemarks(remarks);
        _operationLog.setLogFrom(FROM_BACKEND);
        mapper.insert(_operationLog);
    }

    public void insertErrorLog(HttpServletRequest request, String className, String method, String requestParams, Long time, byte[] exceptionDetail, String remarks) {
        OperationLog _operationLog = new OperationLog();
        _operationLog.setUsername(accountService.findCacheById(JwtUtil.getLocalUser().get().getId()).getNickname());
        _operationLog.setType("ERROR");
        _operationLog.setIp(IpUtil.getIp(request));
        _operationLog.setIpAddress(IpUtil.getIpAddress(request));
        _operationLog.setOs(UserAgentUtil.getOperatingSystem(request));
        _operationLog.setBrowser(UserAgentUtil.getBrowserName(request));
        _operationLog.setBrowserVersion(UserAgentUtil.getBrowserVersion(request));
        _operationLog.setRequestUrl(request.getRequestURI());
        _operationLog.setClassName(className);
        _operationLog.setMethod(method);
        _operationLog.setRequest(requestParams);
        _operationLog.setTime(time);
        _operationLog.setExceptionDetail(exceptionDetail);
        _operationLog.setRemarks(remarks);
        _operationLog.setLogFrom(FROM_BACKEND);
        mapper.insert(_operationLog);
    }

    public void insertLoginLog(HttpServletRequest request, String nickname, String remarks) {
        OperationLog _operationLog = new OperationLog();
        _operationLog.setUsername(nickname);
        _operationLog.setType("LOGIN");
        _operationLog.setIp(IpUtil.getIp(request));
        _operationLog.setIpAddress(IpUtil.getIpAddress(request));
        _operationLog.setOs(UserAgentUtil.getOperatingSystem(request));
        _operationLog.setBrowser(UserAgentUtil.getBrowserName(request));
        _operationLog.setBrowserVersion(UserAgentUtil.getBrowserVersion(request));
        _operationLog.setRequestUrl(request.getRequestURI());
        _operationLog.setRemarks(remarks);
        _operationLog.setLogFrom(FROM_BACKEND);
        mapper.insert(_operationLog);
    }

}
