package com.tykj.dev.device.task.service.impl;

import com.tykj.dev.blockcha.subject.entity.BcHash;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.TaskBeanConfig;
import com.tykj.dev.device.task.repository.TaskLogDao;
import com.tykj.dev.device.task.service.TaskLogService;
import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.task.subject.domin.TaskLog;
import com.tykj.dev.device.task.subject.vo.TaskLogSelectVo;
import com.tykj.dev.device.task.subject.vo.TaskLogUserVo;
import com.tykj.dev.device.task.utils.TaskUtils;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.JacksonUtil;
import com.tykj.dev.misc.utils.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * @author dengdiyi
 */
@Service
@Slf4j
public class TaskLogServiceImpl implements TaskLogService {

    @Autowired
    private TaskLogDao taskLogDao;

    @Autowired
    private TaskUtils taskUtils;

    @Autowired
    private BlockChainUtil blockChainUtil;

    @Override
    public void addLog(TaskLogBto taskLogBto) {
        TaskLog taskLog = taskLogDao.save(taskLogBto.toDo());
        CompletableFuture.runAsync(() ->{
            TaskLog taskLog1 = taskLogDao.findById(taskLog.getId()).get();
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(taskLog1));
            String recordId = bcText.getData().getRecordID();
            taskLog1.setRecordId(recordId);
            taskLogDao.save(taskLog1);
        }, TaskBeanConfig.getThreadPoolTaskScheduler());
    }

    @Async("taskScheduler")
    public void sendHash(TaskLog taskLog) {
        CompletableFuture.runAsync(() ->{
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(taskLog));
            String recordId = bcText.getData().getRecordID();
            taskLog.setRecordId(recordId);
            taskLogDao.save(taskLog);
        });
    }

    @Override
    public TaskLogBto getOne(Integer id) {
        Optional<TaskLog> taskLog = taskLogDao.findById(id);
        if (taskLog.isPresent()) {
            return taskLog.get().parse2bto();
        } else {
            throw new ApiException(ResultUtil.failed("查询的id不存在"));
        }
    }

    /**
     * @param taskId 业务id
     *               获取业务日志
     */
    @Override
    public List<TaskLogUserVo> getByTaskId(Integer taskId) {
        List<TaskLog> taskLogs = taskUtils.orderByCreateTimeDesc(taskLogDao.getAllByTaskId(taskId));
        return taskLogs.stream().map(TaskLog::parse2bto).map(TaskLogBto::toVo).collect(Collectors.toList());
    }

    /**
     * @param taskLogSelectVo 查询vo
     *                        获取所有业务操作日志
     */
    @Override
    public List<TaskLogUserVo> getAllByTime(TaskLogSelectVo taskLogSelectVo) {
        List<TaskLogUserVo> taskLogUserVos = taskLogDao.findAll().stream().map(TaskLog::parse2bto).map(TaskLogBto::toVo).collect(Collectors.toList());
        if (taskLogSelectVo!=null&&taskLogSelectVo.getStartTime()!=null&&taskLogSelectVo.getEndTime()!=null){
            return taskLogUserVos.stream()
                    .filter(taskLogUserVo -> taskLogUserVo.getCreateTime().after(taskLogSelectVo.getStartTime())&&taskLogUserVo.getCreateTime().before(taskLogSelectVo.getEndTime()))
                    .sorted(Comparator.comparing(TaskLogUserVo::getCreateTime,Comparator.nullsLast(Date::compareTo)).reversed())
                    .collect(Collectors.toList());
        }
        else {
            return taskLogUserVos.stream()
                    .sorted(Comparator.comparing(TaskLogUserVo::getCreateTime,Comparator.nullsLast(Date::compareTo)).reversed())
                    .collect(Collectors.toList());
        }
    }

}
