package com.njcn.gather.system.log.service.impl;

import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.db.mybatisplus.constant.UserConstant;
import com.njcn.gather.system.log.mapper.SysLogAuditMapper;
import com.njcn.gather.system.log.pojo.dto.SysLogAuditRecord;
import com.njcn.gather.system.log.pojo.param.SysLogParam;
import com.njcn.gather.system.log.pojo.po.SysLogAudit;
import com.njcn.gather.system.log.service.ISysLogAuditService;
import com.njcn.gather.system.log.util.CSVUtil;
import com.njcn.gather.system.util.ExportFileNameUtil;
import com.njcn.gather.user.user.pojo.po.SysUser;
import com.njcn.gather.user.user.service.ISysUserService;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.HttpServletUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author caozehui
 * @date 2024-11-29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysLogAuditServiceImpl extends ServiceImpl<SysLogAuditMapper, SysLogAudit> implements ISysLogAuditService {

    private final ISysUserService sysUserService;

    @Override
    public Page<SysLogAudit> listSysLogAudit(SysLogParam.QueryParam param) {
        QueryWrapper<SysLogAudit> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(param)) {
            queryWrapper.like(StrUtil.isNotBlank(param.getUserName()), "sys_log_audit.User_name", param.getUserName())
                    .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), "sys_log_audit.Log_time", LocalDateTimeUtil.parse(param.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_FORMATTER))
                    .le(StrUtil.isNotBlank(param.getSearchEndTime()), "sys_log_audit.Log_time", LocalDateTimeUtil.parse(param.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_FORMATTER));
        }
        queryWrapper.orderByDesc("sys_log_audit.Log_time");
        return this.page(new Page<>(PageFactory.getPageNum(param), PageFactory.getPageSize(param)), queryWrapper);
    }

    @Override
    public void exportCSV(SysLogParam.QueryParam param) {
        QueryWrapper<SysLogAudit> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(param)) {
            queryWrapper.like(StrUtil.isNotBlank(param.getUserName()), "sys_log_audit.User_name", param.getUserName())
                    .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), "sys_log_audit.Log_time", LocalDateTimeUtil.parse(param.getSearchBeginTime() + " 00:00:00", DatePattern.NORM_DATETIME_FORMATTER))
                    .le(StrUtil.isNotBlank(param.getSearchEndTime()), "sys_log_audit.Log_time", LocalDateTimeUtil.parse(param.getSearchEndTime() + " 23:59:59", DatePattern.NORM_DATETIME_FORMATTER));
        }
        queryWrapper.orderByDesc("sys_log_audit.Log_time");
        List<SysLogAudit> list = this.list(queryWrapper);
        CsvExportParams params = new CsvExportParams();
        CSVUtil.exportCsv("日志数据.csv", params, SysLogAudit.class, list);
    }

    /**
     * 暂时废弃，有需要再重新写
     *
     * @param param .
     */
    @Override
    @Deprecated
    public void analyse(SysLogParam.QueryParam param) {
        QueryWrapper<SysLogAudit> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(param)) {
            queryWrapper.like(StrUtil.isNotBlank(param.getUserName()), "sys_log_audit.User_name", param.getUserName())
                    .between(StrUtil.isAllNotBlank(param.getSearchBeginTime(), param.getSearchEndTime()), "sys_log_audit.Log_time", param.getSearchBeginTime(), param.getSearchEndTime());
        }
        List<SysLogAudit> list = this.list(queryWrapper);
        Map<String, Long> collect = list.stream().collect(Collectors.groupingBy(SysLogAudit::getLoginName, Collectors.counting()));

        this.exportAnalyseExcel("分析结果", collect);
    }

    @Override
    public void recodeAdviceLog(SysLogAuditRecord logRecord) {
        saveAuditLog(logRecord);
    }

    @Override
    public void recodeBusinessExceptionLog(SysLogAuditRecord logRecord) {
        saveAuditLog(logRecord);
    }

    private void saveAuditLog(SysLogAuditRecord logRecord) {
        if (ObjectUtil.isNull(logRecord)) {
            return;
        }
        SysLogAudit sysLogAudit = new SysLogAudit();
        fillOperator(sysLogAudit, logRecord);
        sysLogAudit.setIp(logRecord.getIp());
        sysLogAudit.setOperate(logRecord.getOperate());
        sysLogAudit.setOperateType(logRecord.getOperateType());
        sysLogAudit.setResult(logRecord.getResult());
        sysLogAudit.setReason(logRecord.getReason());
        sysLogAudit.setType(logRecord.getType() == null ? 1 : logRecord.getType());
        Integer level = logRecord.getLevel() == null ? 0 : logRecord.getLevel();
        sysLogAudit.setLevel(level);
        Integer warn = logRecord.getWarn() == null ? (level == 1 ? 1 : 0) : logRecord.getWarn();
        sysLogAudit.setWarn(warn);
        sysLogAudit.setLogTime(LocalDateTime.now());
        this.save(sysLogAudit);
    }

    private void fillOperator(SysLogAudit sysLogAudit, SysLogAuditRecord logRecord) {
        String userId = logRecord.getUserId();
        String loginName = logRecord.getLoginName();

        if (StrUtil.isNotBlank(userId)) {
            SysUser sysUser = sysUserService.getById(userId);
            if (sysUser != null) {
                sysLogAudit.setUserName(sysUser.getName());
                sysLogAudit.setLoginName(sysUser.getLoginName());
                return;
            }
        }

        if (StrUtil.isNotBlank(loginName) && !LogInfo.UNKNOWN_USER.equalsIgnoreCase(loginName)) {
            sysLogAudit.setUserName(loginName);
            sysLogAudit.setLoginName(loginName);
        } else {
            sysLogAudit.setUserName(UserConstant.UN_LOGIN);
            sysLogAudit.setLoginName(UserConstant.UN_LOGIN);
        }
    }

    private void exportAnalyseExcel(String fileName, Map<String, Long> collect) {
        HttpServletResponse response = HttpServletUtil.getResponse();
        XSSFWorkbook wb = new XSSFWorkbook();

        try (ServletOutputStream outputStream = response.getOutputStream()) {
            fileName = URLEncoder.encode(ExportFileNameUtil.appendToday(fileName), CharsetUtil.UTF_8);
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            response.setContentType("application/octet-stream;charset=UTF-8");

            XSSFSheet sheet = wb.createSheet("sheet1");

            //createPieChart(sheet, collect.keySet().stream().collect(Collectors.toList()), collect.values().stream().collect(Collectors.toList()));

            wb.write(outputStream);
            wb.close();
        } catch (IOException e) {
            log.error(">>> 导出数据异常：{}", e.getMessage());
        }
    }
}
