package com.jiayue.ssi.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiayue.ssi.annotation.OperateLog;
import com.jiayue.ssi.annotation.PreventReplay;
import com.jiayue.ssi.backenum.AuditType;
import com.jiayue.ssi.backenum.BusinessType;
import com.jiayue.ssi.constant.CustomException;
import com.jiayue.ssi.constant.PermissionCharacter;
import com.jiayue.ssi.entity.SysOperLog;
import com.jiayue.ssi.entity.SysRole;
import com.jiayue.ssi.service.SysOperLogService;
import com.jiayue.ssi.service.SysRoleService;
import com.jiayue.ssi.util.DateUtils;
import com.jiayue.ssi.util.ResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 操作日志记录
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/sysOperlogController")
@Slf4j
public class SysOperlogController {
    @Autowired
    SysOperLogService sysOperLogService;
    @Autowired
    SysRoleService sysRoleService;

    /**
     * 获取审计类型
     */
    @GetMapping(value = "/getAuditType")
    @PreventReplay
    public ResponseVO getAuditType() throws CustomException {
        List<Map> list = new ArrayList<>();
        try {
            // 根据当前用户获取角色
            SysRole sysRole = sysRoleService.selectRoleListByUserId();
            if (PermissionCharacter.P_SJYW.equals(sysRole.getRoleKey())){
                // 业务审计员
                Map<String,String> map = new HashMap<>();
                map.put("value","1");
                map.put("label","业务");
                list.add(map);
            }
            else {
                Map<String,String> map1 = new HashMap<>();
                map1.put("value","0");
                map1.put("label","系统");
                list.add(map1);
                Map<String,String> map2 = new HashMap<>();
                map2.put("value","1");
                map2.put("label","业务");
                list.add(map2);
            }
        } catch (Exception e) {
            throw new CustomException("获取审计类型异常", e);
        }
        return ResponseVO.success(list);
    }

    /**
     * 获取列表分页信息
     *
     * @return 列表信息
     */
    @GetMapping(value = "/getAll")
    @PreAuthorize("@ss.hasPermi('auditManager:operlog:list')")
    @OperateLog(title = "操作日志", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "查询操作日志")
    @PreventReplay
    public ResponseVO getAll(String currentPage, String pageSize, String title, String operName, String auditType,
                             String businessType, String status, String startOperTime, String endOperTime, String sortOrder) throws CustomException {
        try {
            Integer cp;
            if (StringUtils.isNotEmpty(currentPage)) {
                if (NumberUtil.isInteger(currentPage)){
                    cp = Integer.parseInt(currentPage);
                }
                else{
                    return ResponseVO.fail("currentPage不是整数！");
                }
            }
            else{
                return ResponseVO.fail("currentPage不能是空！");
            }

            Integer ps;
            if (StringUtils.isNotEmpty(pageSize)) {
                if (NumberUtil.isInteger(pageSize)){
                    ps = Integer.parseInt(pageSize);
                }
                else{
                    return ResponseVO.fail("pageSize不是整数！");
                }
            }
            else{
                return ResponseVO.fail("pageSize不能是空！");
            }
            if (StringUtils.isNotEmpty(title)) {
                if (title.length() > 50) {
                    return ResponseVO.fail("系统模块长度不能超过50个字符！");
                }
            }
            if (StringUtils.isNotEmpty(operName)) {
                if (operName.length() > 50) {
                    return ResponseVO.fail("操作人员长度不能超过50个字符！");
                }
            }
            QueryWrapper<SysOperLog> wrapper = new QueryWrapper<>();
            if (StringUtils.isNotEmpty(title)) {
                wrapper.like("title", title);
            }
            if (StringUtils.isNotEmpty(operName)) {
                wrapper.like("oper_name", operName);
            }
            if (StringUtils.isNotEmpty(auditType)) {
                wrapper.eq("audit_type", auditType);
            }
            if (StringUtils.isNotEmpty(businessType)) {
                wrapper.eq("business_type", businessType);
            }
            if (StringUtils.isNotEmpty(status)) {
                wrapper.eq("status", status);
            }
            if (StringUtils.isNotEmpty(startOperTime)) {
                wrapper.ge("oper_time", DateUtils.getDayStartTime(DateUtil.parseDate(startOperTime)));
            }
            if (StringUtils.isNotEmpty(endOperTime)) {
                wrapper.le("oper_time", DateUtils.getDayLastTime(DateUtil.parseDate(endOperTime)));
            }
            if (StringUtils.isNotEmpty(sortOrder)) {
                String[] orders = sortOrder.replaceAll("＆","&").split("&");
                String sortDbField = "";
                if ("operTime".equals(orders[0])) {
                    sortDbField = "oper_time";
                } else if ("title".equals(orders[0])) {
                    sortDbField = "title";
                } else if ("operName".equals(orders[0])) {
                    sortDbField = "oper_name";
                }

                if ("asc".equals(orders[1])) {
                    wrapper.orderByAsc(sortDbField);
                } else {
                    wrapper.orderByDesc(sortDbField);
                }
            }
            SysRole sysRole = sysRoleService.selectRoleListByUserId();
            if (PermissionCharacter.P_SJYW.equals(sysRole.getRoleKey())){
                // 业务审计员
                wrapper.eq("audit_type", "1");
            }

            Page<SysOperLog> result = sysOperLogService.page(new Page<>(cp, ps), wrapper);
            return ResponseVO.success(result);
        } catch (Exception e) {
            throw new CustomException("获取操作日志列表异常", e);
        }
    }

    /**
     * 删除登录信息
     */
    @PostMapping(value = "/delOperlog")
    @OperateLog(title = "操作日志", businessType = BusinessType.DELETE, auditType = AuditType.SYS,operdesc = "删除操作日志")
    @PreAuthorize("@ss.hasPermi('auditManager:operlog:remove')")
    public ResponseVO delOperlog(String operId) throws CustomException {
        try {
            if (StringUtils.isEmpty(operId)) {
                return ResponseVO.fail("id不能为空!");
            }
            boolean bo = sysOperLogService.removeOperlogById(Long.parseLong(operId));
            if (bo) {
                return ResponseVO.success("操作日志删除成功");
            } else {
                log.error("操作日志删除失败");
                return ResponseVO.fail("操作日志删除失败");
            }
        } catch (Exception e) {
            throw new CustomException("操作日志删除异常", e);
        }
    }

    /**
     * 操作日志清空
     */
    @PostMapping("/cleanOperLog")
    @OperateLog(title = "操作日志", businessType = BusinessType.CLEAN, auditType = AuditType.SYS,operdesc = "清空操作日志")
    @PreAuthorize("@ss.hasPermi('auditManager:operlog:remove')")
    public ResponseVO cleanOperLog() throws CustomException {
        try {
            boolean bo = sysOperLogService.cleanOperLog();
            if (bo) {
                return ResponseVO.success("操作日志清空成功");
            } else {
                log.error("操作日志清空失败");
                return ResponseVO.fail("操作日志清空失败");
            }
        } catch (Exception e) {
            throw new CustomException("操作日志清空异常", e);
        }
    }

    /**
     * 操作日志统计分析
     *
     * @return 列表信息
     */
    @GetMapping(value = "/sysOperlogTotal")
    @PreAuthorize("@ss.hasPermi('auditManager:sysOperlogTotal:list')")
    @OperateLog(title = "操作日志统计", businessType = BusinessType.QUERY, auditType = AuditType.SYS,operdesc = "查询统计操作日志")
    @PreventReplay
    public ResponseVO sysOperlogTotal(String startLoginTime, String endLoginTime) throws CustomException {
        try {
            QueryWrapper<SysOperLog> wrapper = new QueryWrapper<>();
            if (StringUtils.isNotEmpty(startLoginTime)) {
                wrapper.ge("oper_time", DateUtils.getDayStartTime(DateUtil.parseDate(startLoginTime)));
            }
            if (StringUtils.isNotEmpty(endLoginTime)) {
                wrapper.le("oper_time", DateUtils.getDayLastTime(DateUtil.parseDate(endLoginTime)));
            }
            List<SysOperLog> sysOperLogList = sysOperLogService.list(wrapper);
            Map<String, List<SysOperLog>> map = sysOperLogList.stream().collect(Collectors.groupingBy(item -> DateUtil.format(item.getOperTime(), "yyyy-MM-dd")));
            List<Map<String, String>> resultList = new ArrayList<>();
            map.forEach((key, value) -> {
                List<SysOperLog> list = value;
                Map<String, String> recordMap = new HashMap<>();
                recordMap.put("day", key);
                // 系统类型统计
                List<SysOperLog> sysTypeList = list.stream().filter(sysOperLog -> sysOperLog.getAuditType() == 0).collect(Collectors.toList());
                recordMap.put("syscount", sysTypeList.size() + "");
                // 业务类型统计
                List<SysOperLog> bizTypeList = list.stream().filter(sysOperLog -> sysOperLog.getAuditType() == 1).collect(Collectors.toList());
                recordMap.put("bizcount", bizTypeList.size() + "");
                // 操作成功统计
                List<SysOperLog> successList = list.stream().filter(sysOperLog -> sysOperLog.getStatus() == 0).collect(Collectors.toList());
                recordMap.put("success", successList.size() + "");
                // 操作失败统计
                List<SysOperLog> failList = list.stream().filter(sysOperLog -> sysOperLog.getStatus() == 1).collect(Collectors.toList());
                recordMap.put("fail", failList.size() + "");
                // 操作ip个数统计
                int ips = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getOperIp()))), ArrayList::new)).size();
                recordMap.put("ips", ips + "");
                // 越权访问统计
                List<SysOperLog> yqfwList = list.stream().filter(sysOperLog -> sysOperLog.getBusinessType() == 2).collect(Collectors.toList());
                recordMap.put("yqfw", yqfwList.size() + "");
                // IP地址异常统计
                List<SysOperLog> ipycList = list.stream().filter(sysOperLog -> sysOperLog.getBusinessType() == 17).collect(Collectors.toList());
                recordMap.put("ipyc", ipycList.size() + "");
                resultList.add(recordMap);
            });
            Collections.sort(resultList, new Comparator<Map<String, String>>() {
                @Override
                public int compare(Map<String, String> o1, Map<String, String> o2) {
                    return o1.get("day").compareTo(o2.get("day"));
                }
            });
            return ResponseVO.success(resultList);
        } catch (Exception e) {
            throw new CustomException("获取操作日志统计列表异常", e);
        }
    }
}
