package com.sunyard.ssp.modules.monitor.log.controller;

/**
 * @Auther: wp
 * @Date: 2022/2/17 15:34
 * @Description:
 */

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.sunyard.ssp.common.PageVo;
import com.sunyard.ssp.common.Result;
import com.sunyard.ssp.modules.monitor.log.entity.AuditLog;
import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign;
import com.sunyard.ssp.modules.monitor.log.entity.LogSign;
import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService;
import com.sunyard.ssp.modules.monitor.log.service.IAuditLogSignService;
import com.sunyard.ssp.modules.monitor.log.service.ILogSignService;
import com.sunyard.ssp.modules.user.entity.ScUser;
import com.sunyard.ssp.utils.PageUtil;
import com.sunyard.ssp.utils.ResultUtil;
import com.sunyard.ssp.utils.SecurityUtil;
import com.sunyard.ssp.utils.sm3.SM3Digest;
import com.sunyard.ssp.vo.SearchVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RestController
@Slf4j
@Api(description = "审计日志-签名",tags ="审计日志-签名")
@RequestMapping("/monitor/signLog")
@Transactional
public class LogSignController {
    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private IAuditLogSignService auditLogSignService;

    @Autowired
    private ILogSignService logSignService;

    @Autowired
    private IAuditLogService auditLogService;

    @RequestMapping(value = "/getByCondition", method = RequestMethod.GET)
    @ApiOperation(value = "日志签名分页条件查询")
    public Result<org.springframework.data.domain.Page<LogSign>> getByCondition(@ModelAttribute LogSign logSign,
                                                                               @ModelAttribute SearchVo searchVo,
                                                                               @ModelAttribute PageVo pageVo) {
        try {
            org.springframework.data.domain.Page<LogSign> page = logSignService.findByCondition(logSign, searchVo, PageUtil.initPage(pageVo));
            return new ResultUtil<org.springframework.data.domain.Page<LogSign>>().setData(page);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping(value = "/hash",method = RequestMethod.POST)
    @ApiOperation(value = "日志hash")
    public Result<Object> hash(@RequestParam Long[] ids){
        if(ids==null || ids.length<1){
            return new ResultUtil<Object>().setErrorMsg("审计失败，未选择日志");
        }

        ArrayList<Long> list = new ArrayList<>(ids.length);
        Collections.addAll(list, ids);

        List<AuditLog> auditLogList = auditLogService.list(new QueryWrapper<AuditLog>().lambda().in(AuditLog::getId, list).orderByAsc(AuditLog::getId));
        if(CollectionUtil.isEmpty(auditLogList) || list.size()!=auditLogList.size()){
            return new ResultUtil<Object>().setErrorMsg("审计失败，该日志不存在");
        }

        //序列化后hash
        String json = new Gson().toJson(auditLogList);
        String res= SM3Digest.encode(json);
        return new ResultUtil<Object>().setData(res);
    }

    @RequestMapping(value = "/sign",method = RequestMethod.POST)
    @ApiOperation(value = "日志审计签名")
    public Result<Object> sign(@ModelAttribute LogSign logSign, @RequestParam Long[] ids){
        try {
            if(ids==null || ids.length<1){
                return new ResultUtil<Object>().setErrorMsg("审计失败，未选择日志");
            }
            if(null==logSign || StrUtil.isBlank(logSign.getSignValue()) || StrUtil.isBlank(logSign.getPublicKey())){
                return new ResultUtil<Object>().setErrorMsg("审计失败，签名参数不能为空");
            }
            //判断日志是否重复签名
            ArrayList<Long> list = new ArrayList<>(ids.length);
            Collections.addAll(list, ids);
            List<AuditLogSign> logSignList = auditLogSignService.list(new QueryWrapper<AuditLogSign>().lambda().in(AuditLogSign::getLogId, list));
            if(CollectionUtil.isNotEmpty(logSignList)){
                return new ResultUtil<Object>().setErrorMsg("审计失败，该日志已审计过");
            }

            ScUser scUser = securityUtil.getCurrUser();
            logSign.setCreateTime(LocalDateTime.now());
            logSign.setOperatorId(scUser.getId());
            logSign.setOperatorName(scUser.getRealname());
            boolean b = logSignService.save(logSign);
            if(!b){
                return new ResultUtil<Object>().setErrorMsg("审计失败");
            }
            for(Long id:ids){
                AuditLogSign auditLogSign=new AuditLogSign();
                auditLogSign.setLogId(id);
                auditLogSign.setSignId(logSign.getId());
                boolean save = auditLogSignService.save(auditLogSign);
                if(!save){
                    return new ResultUtil<Object>().setErrorMsg("审计失败");
                }
            }
            return new ResultUtil<Object>().setSuccessMsg("审计成功");
        } catch (Exception e){
            e.getStackTrace();
            log.error("错误类名[{}],错误方法名[{}]", this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e.getMessage(), e);
            throw new RuntimeException("审计失败");
        }
    }


}
