/*
 * Author: wangjian
 * 生成ServiceImpl
 */
package com.tofly.base.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.base.entity.Log;
import com.tofly.base.service.LogService;
import com.tofly.base.util.DateTimeUtil;
import com.tofly.base.vo.CountLogVo;
import com.tofly.base.vo.OperationRecordsVo;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.ftp.config.FtpUtil;
import com.tofly.common.oauth.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.tofly.base.mapper.LogMapper;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 日志信息表
 *
 * @author admin
 * @date Thu Oct 10 00:00:00 CST 2019
 */
@Service("logService")
public class LogServiceImpl extends ServiceImpl<LogMapper, Log> implements LogService {
    @Value("${user.logFile}")
    private String logFile;

    @Autowired
    private LogMapper logMapper;

    @Override
    public Page<Map> listLogPage(Page page, Map map) {
        return page.setRecords(baseMapper.listLogPage(page, map));
    }

    @Override
    public ResultRespone manuallyAdd(List<MultipartFile> fileList, HttpServletRequest request) {
        //获取ip
        String ip = request.getHeader("X-Real-IP");
        //保存照片
        fileList.forEach(file -> {
            //文件名
            String fileName = file.getOriginalFilename();
            if (!"".equals(fileName)) {
                //文件路径
                assert fileName != null;
                String filePath = logFile + IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf((".")));
                FtpUtil.uploadFile2Ftp(file, filePath);
                Log log = new Log();
                log.setType("0");
                log.setRouteIp(filePath);
                log.setTitle("content:app端日志文件上传");
                log.setRemoteAddr(ip);
                log.setCreateBy(SecurityUtils.getUserName());
                this.save(log);
            }
        });
        return ResultRespone.success();
    }

    @Override
    public List<CountLogVo> countLogType(Map map) {
        return baseMapper.countLogType(map);
    }

    @Override
    public List<OperationRecordsVo> getOperationRecords(String flag, String startTime, String endTime) {
        Date startDate = DateTimeUtil.convertLDTToDate(Objects.requireNonNull(DateTimeUtil.fromString2LocalDateTime(startTime, DateTimeUtil.FULL_FORMAT)));
        Date endDate = DateTimeUtil.convertLDTToDate(Objects.requireNonNull(DateTimeUtil.fromString2LocalDateTime(endTime, DateTimeUtil.FULL_FORMAT)));
        // 获取操作统计分组列表对象
        List<OperationRecordsVo> operationRecords = logMapper.getOperationRecords(startDate, endDate);
        // 按照部门分组
        List<OperationRecordsVo> voList = new ArrayList<>();
        if (StringUtils.isEmpty(flag)) {
            Map<Long, List<OperationRecordsVo>> collect = operationRecords.stream().collect(Collectors.groupingBy(OperationRecordsVo::getDeptId));
            collect.forEach((k, v) -> {
                OperationRecordsVo vo = new OperationRecordsVo();
                if (null != v && v.size() > 0) {
                    OperationRecordsVo vo1 = v.get(0);
                    vo.setServiceId(vo1.getServiceId());
                    vo.setServiceName(vo1.getServiceName());
                    vo.setDeptId(vo1.getDeptId());
                    vo.setDeptName(vo1.getDeptName());
                    BigDecimal reduce = v.stream().map(OperationRecordsVo::getOperatingTime).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                    if (null != reduce && !reduce.equals(BigDecimal.ZERO)) {
                        BigDecimal divide = reduce.divide(BigDecimal.valueOf(3600), 2, BigDecimal.ROUND_HALF_DOWN);
                        vo.setOperatingTime(divide);
                    }

                    vo.setNum(v.stream().filter(i -> null != i.getNum()).mapToInt(OperationRecordsVo::getNum).sum());
                }

                voList.add(vo);

            });

        } else {
            Map<Long, List<OperationRecordsVo>> collect1 = operationRecords.stream().filter(map -> null != map.getUserId()).collect(Collectors.groupingBy(OperationRecordsVo::getUserId));

            collect1.forEach((k, v) -> {
                OperationRecordsVo vo = new OperationRecordsVo();
                OperationRecordsVo vo1 = v.get(0);
                vo.setDeptId(vo1.getDeptId());
                vo.setDeptName(vo1.getDeptName());
                vo.setUserId(vo1.getUserId());
                vo.setRealName(vo1.getRealName());
                AtomicReference<BigDecimal> time = new AtomicReference<>(BigDecimal.ZERO);
                AtomicReference<Integer> num = new AtomicReference<>(0);
                v.forEach(data -> {
                    BigDecimal operatingTime = data.getOperatingTime();
                    if (null != operatingTime && !operatingTime.equals(BigDecimal.ZERO)) {
                        BigDecimal divide = operatingTime.divide(BigDecimal.valueOf(3600), 2, BigDecimal.ROUND_HALF_DOWN);
                        time.set(time.get().add(divide));
                    }
                    num.set(num.get() + (data.getNum() == null ? 0 : data.getNum()));
                });
                vo.setNum(num.get());
                vo.setOperatingTime(time.get());
                voList.add(vo);
            });
        }
        return voList;

    }

    @Override
    public Log getOneLogInfo(Map map) {
        return logMapper.getOneLogInfo(map);
    }

    @Override
    public List<Map<String, Object>> getExportData(String dto, String templateFlag) {
        HashMap hashMap = JSON.parseObject(dto, HashMap.class);
        String startTime = (String) hashMap.get("startTime");
        String endTime = (String) hashMap.get("endTime");
        String flag = (String) hashMap.get("flag");
        String deptId = (String) hashMap.get("deptId");
        List<Map<String, Object>> returnMap = new ArrayList<>();
        Map<String, Object> parentMap = new HashMap<>(12);
        List<OperationRecordsVo> operationRecords = this.getOperationRecords(flag, startTime, endTime);
        if (null != operationRecords) {
            if (!StringUtils.isEmpty(deptId)) {
                List<OperationRecordsVo> collect = operationRecords.stream().filter(info -> Long.valueOf(deptId).equals(info.getDeptId())).collect(Collectors.toList());
                parentMap.put("list", collect);
                parentMap.put("time", startTime + " ~ " + endTime);
                parentMap.put("deptName", collect.get(0).getDeptName());
            } else {
                Map<Long, List<OperationRecordsVo>> collect1 = operationRecords.stream().collect(Collectors.groupingBy(OperationRecordsVo::getDeptId));
                List<OperationRecordsVo> voList = new ArrayList<>();
                collect1.forEach((k, v) -> {
                    OperationRecordsVo vo = new OperationRecordsVo();
                    OperationRecordsVo vo1 = v.get(0);
                    vo.setDeptId(vo1.getDeptId());
                    vo.setDeptName(vo1.getDeptName());
                    AtomicReference<BigDecimal> time = new AtomicReference<>(BigDecimal.ZERO);
                    AtomicReference<Integer> num = new AtomicReference<>(0);
                    v.forEach(data -> {
                        time.set(time.get().add(data.getOperatingTime() == null ? BigDecimal.ZERO : data.getOperatingTime()));
                        num.set(num.get() + (data.getNum() == null ? 0 : data.getNum()));
                    });
                    vo.setNum(num.get());
                    vo.setOperatingTime(time.get());
                    voList.add(vo);
                });
                parentMap.put("list", voList);
                parentMap.put("time", startTime + " ~ " + endTime);
            }
        }


        returnMap.add(parentMap);
        return returnMap;
    }

    @Override
    public Boolean excelDataStorage(List<Object> dataList) {
        return null;
    }
}
