package com.tykj.dev.device.destroy.service.Impl;

import com.tykj.dev.config.base.DeviceLifeStatus;
import com.tykj.dev.device.apply.service.DeviceApplyBillService;
import com.tykj.dev.device.destroy.entity.domain.DeviceDestroyBill;
import com.tykj.dev.device.destroy.entity.vo.DeviceDestroyBillVo;
import com.tykj.dev.device.destroy.service.DeviceDestroyBillService;
import com.tykj.dev.device.destroy.service.DeviceDestroyBusinessService;
import com.tykj.dev.device.file.service.FilesUtil;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.service.DeviceLibraryService;
import com.tykj.dev.device.library.service.DeviceLogService;
import com.tykj.dev.device.library.subject.Dto.DeviceLogDto;
import com.tykj.dev.device.library.subject.domin.DeviceLog;
import com.tykj.dev.device.library.subject.vo.ScriptSaveVo;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto;
import com.tykj.dev.device.user.subject.entity.SecurityUser;
import com.tykj.dev.device.user.subject.entity.User;
import com.tykj.dev.device.user.subject.service.UserService;
import com.tykj.dev.misc.base.BusinessEnum;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.utils.DeviceSeqUtil;
import com.tykj.dev.misc.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName DeviceDestroyBusinessServiceImpl.java
 * @Description TODO
 * @createTime 2021年04月09日 10:57:00
 */
@Service
@Slf4j
public class DeviceDestroyBusinessServiceImpl implements DeviceDestroyBusinessService {
    @Autowired
    TaskService taskService;

    @Autowired
    DeviceDestroyBillService deviceDestroyBillService;

    @Autowired
    DeviceLibraryService deviceLibraryService;

    @Autowired
    DeviceLogService deviceLogService;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Autowired
    MessageService messageService;

    @Autowired
    UserService userService;

    @Autowired
    DeviceApplyBillService deviceApplyBillService;


    @Override
    public TaskBto saveDeviceDestroyBill(SecurityUser securityUser, DeviceDestroyBillVo deviceDestroyBillVo) {
        TaskBto taskBto;
        DeviceDestroyBill deviceDestroyBill;
        if (deviceDestroyBillVo.getTaskId()==null){
            deviceDestroyBill= deviceDestroyBillVo.toDeviceDestroyBill();
            if (deviceDestroyBillVo.getApplyId()!=null) {
                Optional<DeviceDestroyBill> deviceDestroyBill1 = deviceDestroyBillService.findApplyId(deviceDestroyBillVo.getApplyId());
                deviceDestroyBill1.ifPresent(deviceDestroyBill2 -> deviceDestroyBill.setId(deviceDestroyBill2.getId()));
            }
            deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
            deviceDestroyBill.setNum("NO:第" + LocalDateTime.now().getYear() + "XF" + deviceDestroyBill.getId());
            taskBto= sendDraftTask(securityUser.getCurrentUserInfo().getUnitsId(),deviceDestroyBill.getId(),securityUser.getCurrentUserInfo().getUserId());
            deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
            addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"保存销毁任务草稿",gainThisUser(securityUser.getCurrentUserInfo().getUserId(),securityUser.getCurrentUserInfo().getUnitsId())));
        }else {
            taskBto=taskService.get(deviceDestroyBillVo.getTaskId());
            deviceDestroyBill= deviceDestroyBillService.findDeviceDestroyBill(taskBto.getBillId());
            deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
        }
        deviceDestroyBill.setDestroyTime(deviceDestroyBillVo.getDestroyTime());
        deviceDestroyBill.setApplyNumber(deviceDestroyBillVo.getApplyNumber());
        deviceDestroyBill.setReplayNumber(deviceDestroyBillVo.getReplayNumber());
        deviceDestroyBill.setApplyFiles(FilesUtil.stringFileToList(deviceDestroyBillVo.getApplyFileList()));
        deviceDestroyBill.setReplayFiles(FilesUtil.stringFileToList(deviceDestroyBillVo.getReplayFileList()));
        deviceDestroyBill.setScriptJson(JacksonUtil.toJSon(deviceDestroyBillVo.getScripts()));
        deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
        return taskBto;
    }

    @Override
    public DeviceDestroyBill provinceDeviceDestroyBill(SecurityUser securityUser, DeviceDestroyBillVo deviceDestroyBillVo) {
        DeviceDestroyBill deviceDestroyBill;

        List<String> seqNumbers= scriptListToStringList(deviceDestroyBillVo);
        deviceLibraryService.judgeSeqNumbersInNotEqualLifeStatus(seqNumbers,DeviceLifeStatus.TO_BE_DESTROYED.id);
        if (deviceDestroyBillVo.getTaskId()==null){
            deviceDestroyBill=deviceDestroyBillVo.toDeviceDestroyBill();
            deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
            deviceDestroyBill.setNum("NO:第" + LocalDateTime.now().getYear() + "XF" + deviceDestroyBill.getId());
            TaskBto taskBto= awaitUploadDestructionTask(securityUser.getCurrentUserInfo().getUnitsId(),deviceDestroyBill.getId(),securityUser.getCurrentUserInfo().getUserId());
            deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
            addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"销毁任务等待补充手续",gainThisUser(securityUser.getCurrentUserInfo().getUserId(),securityUser.getCurrentUserInfo().getUnitsId())));
        }else {
           TaskBto taskBto = taskService.get(deviceDestroyBillVo.getTaskId());
           deviceDestroyBill=deviceDestroyBillService.findDeviceDestroyBill(taskBto.getBillId());
           taskBto= taskService.moveToSpecial(taskBto,StatusEnum.DESTROY_2,0);
           deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
           addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"销毁任务等待补充手续",gainThisUser(securityUser.getCurrentUserInfo().getUserId(),securityUser.getCurrentUserInfo().getUnitsId())));

        }
        deviceDestroyBill.setDestroyTime(deviceDestroyBillVo.getDestroyTime());
        deviceDestroyBill.setSupervisor(deviceDestroyBillVo.getSupervisor());
        deviceDestroyBill.setLeader(deviceDestroyBillVo.getLeader());
        deviceDestroyBill.setUndertaker(deviceDestroyBillVo.getUndertaker());
        deviceDestroyBill.setApplyNumber(deviceDestroyBillVo.getApplyNumber());
        deviceDestroyBill.setReplayNumber(deviceDestroyBillVo.getReplayNumber());
        deviceDestroyBill.setApplyFiles(FilesUtil.stringFileToList(deviceDestroyBillVo.getApplyFileList()));
        deviceDestroyBill.setReplayFiles(FilesUtil.stringFileToList(deviceDestroyBillVo.getReplayFileList()));
        deviceDestroyBill.setScriptJson(JacksonUtil.toJSon(deviceDestroyBillVo.getScripts()));
        deviceLibraryDao.upDateSeqNumbersLeftStatus(DeviceLifeStatus.IN_THE_DESTROYED.id,seqNumbers);
        deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
        devLogAdd(seqNumbers,"发了销毁任务,状态转化为销毁中",securityUser.getCurrentUserInfo().getUserId());
        if (deviceDestroyBillVo.getApplyId()!=null) {
            Optional<Task> billIdAndBusinessTypeNotBillStatus = taskService.findBillIdAndBusinessTypeNotBillStatus(deviceDestroyBillVo.getApplyId(), BusinessEnum.APPLY.id);
            taskService.moveToEnd(billIdAndBusinessTypeNotBillStatus.get().parse2Bto());
        }else {
            //2:退役申请，3:报废申请，4:销毁申请
            deviceApplyBillService.updateCompleteNum(4,deviceDestroyBillVo.getScripts());
        }
        return deviceDestroyBill;
    }

    @Override
    public void receiptSingle(Integer taskId,DeviceDestroyBillVo deviceDestroyBillVo,SecurityUser securityUser) {
        TaskBto taskBto= taskService.get(taskId);
        DeviceDestroyBill deviceDestroyBill= deviceDestroyBillService.findDeviceDestroyBill(taskBto.getBillId());
        List<String> seqNumbers= scriptListToStringList(deviceDestroyBillVo);
        deviceLibraryService.judgeSeqNumbersInNotEqualLifeStatus(seqNumbers,DeviceLifeStatus.IN_THE_DESTROYED.id);
        if (deviceDestroyBillVo.getSupervisor()!=null) {
            deviceDestroyBill.setSupervisor(deviceDestroyBillVo.getSupervisor());
        }
        if (deviceDestroyBillVo.getLeader()!=null) {
            deviceDestroyBill.setLeader(deviceDestroyBillVo.getLeader());
        }
        if (deviceDestroyBillVo.getUndertaker()!=null) {
            deviceDestroyBill.setUndertaker(deviceDestroyBillVo.getUndertaker());
        }
        deviceDestroyBill.setDestructionFiles(FilesUtil.stringFileToList(deviceDestroyBillVo.getDestructionFileList()));
        taskBto= taskService.moveToEnd(taskBto);
        deviceDestroyBill.setDestroyTime(new Date());
        deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
        deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
        deviceLibraryDao.upDateSeqNumbersLeftStatus(DeviceLifeStatus.DESTROYED.id,seqNumbers);
        addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"销毁任务补充手续完成",gainThisUser(securityUser.getCurrentUserInfo().getUserId(),securityUser.getCurrentUserInfo().getUnitsId())));
        devLogAdd(seqNumbers,"补充单据信息，状态转化已销毁",deviceDestroyBillVo.getOperationId());

    }

    @Override
    public void moveToArchiveDestroyBill(Integer taskId) {
        TaskBto taskBto= taskService.get(taskId);
        DeviceDestroyBill deviceDestroyBill= deviceDestroyBillService.findDeviceDestroyBill(taskBto.getBillId());
        taskBto = taskService.moveToArchive(taskBto);
        deviceDestroyBill.setDestroyStatus(taskBto.getBillStatus());
        deviceDestroyBillService.saveDeviceDestroyBill(deviceDestroyBill);
    }

    /**
     * 保存为草稿
     */
    private TaskBto sendDraftTask(Integer unitId, Integer repelDetailId, Integer userId){
        List<Integer> list=new ArrayList<>();
        list.add(userId);
        return taskService.start(new TaskBto(StatusEnum.DESTROY_0.id, "销毁设备任务", null, ".", repelDetailId, BusinessEnum.DESTROY.id, unitId, 0, "", list));
    }

    /**
     * 等待上传销毁单据
     * @param userId 当前用户对象
     * @param unitId 单位id
     * @param repelDetailId 业务id
     */
    private TaskBto awaitUploadDestructionTask(Integer unitId, Integer repelDetailId,Integer userId){
        List<Integer> userIds = new ArrayList<>();
        userIds.add(userId);
        userIds.add(0);
        return taskService.start(new TaskBto(StatusEnum.DESTROY_2.id, "销毁设备任务", null, ".", repelDetailId, BusinessEnum.DESTROY.id, unitId, 1, "", userIds));
    }

    private List<String> scriptListToStringList(DeviceDestroyBillVo deviceDestroyBillVo){
        List<ScriptSaveVo> scriptSaveVos = deviceDestroyBillVo.getScripts();
        List<String> seqNumbers = new ArrayList<>();
        scriptSaveVos.forEach(
                scriptSaveVo -> {
                    if (scriptSaveVo.getSeqNumber() != null) {
                        seqNumbers.addAll(DeviceSeqUtil.selectDeviceSeqs(scriptSaveVo.getSeqNumber()));
                    }
                }
        );
        return seqNumbers;
    }

    /**
     * 异步添加装备日志
     */
    private void devLogAdd(List<String> seqNumbers, String remark, Integer userId){

        CompletableFuture.runAsync(() -> {
            List<DeviceLog> logDtos=new ArrayList<>();
            deviceLibraryDao.findAllBySeqNumberIn(seqNumbers).forEach(
                    deviceLibrary -> {
                        logDtos.add(new DeviceLogDto(deviceLibrary.getId(),remark,null,userId).toDo());
                    }
            );
            deviceLogService.saveAllLog(logDtos);
        });

    }

    private void addMessage(MessageBto messageBto){
        messageService.add(messageBto);
    }

    /**
     * 根据单位id查询用户 去除用户id
     */
    private List<Integer> gainThisUser(Integer userId,Integer unitId){
        return userService.findAllByUnite(unitId).stream().filter(user -> !user.getUserId().equals(userId)).map(User::getUserId).collect(Collectors.toList());
    }

    /**
     * 根据单位id查询用户id集合
     */
    private List<Integer> findUnitId(Integer unitId){
        return userService.findAllByUnite(unitId).stream().map(User::getUserId).collect(Collectors.toList());
    }
}
