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

import com.fasterxml.jackson.core.type.TypeReference;
import com.tykj.dev.config.base.DeviceLifeStatus;
import com.tykj.dev.device.apply.service.DeviceApplyBillService;
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.DeviceLibrary;
import com.tykj.dev.device.library.subject.domin.DeviceLog;
import com.tykj.dev.device.library.subject.vo.ScriptSaveVo;
import com.tykj.dev.device.scrap.service.ScrapBusinessService;
import com.tykj.dev.device.scrap.service.ScrapService;
import com.tykj.dev.device.scrap.subject.domin.Scrap;
import com.tykj.dev.device.scrap.subject.vo.ScrapOrderOutData;
import com.tykj.dev.device.scrap.subject.vo.StorageScrap;
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.Units;
import com.tykj.dev.device.user.subject.entity.User;
import com.tykj.dev.device.user.subject.service.UnitsService;
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 com.tykj.dev.misc.utils.StringUtils;
import com.tykj.dev.misc.utils.TaskDisposeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName ScrapBusinessServiceImpl.java
 * @Description TODO
 * @createTime 2021年03月31日 13:16:00
 */
@Service
@SuppressWarnings("ALL")
public class ScrapBusinessServiceImpl implements ScrapBusinessService {
    @Autowired
    UserService userService;

    @Autowired
    DeviceApplyBillService deviceApplyBillService;

    @Autowired
    UnitsService unitsService;

    @Autowired
    ScrapService scrapService;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Autowired
    TaskService taskService;

    @Autowired
    DeviceLibraryService deviceLibraryService;
    @Autowired
    DeviceLogService deviceLogService;

    @Autowired
    MessageService messageService;

    @Override
    public TaskBto saveDeviceScrapDraft(Integer userId, ScrapOrderOutData scrapOrderOutData) {
        User user = userService.findByUser(userId);
        Units units = unitsService.findById(user.getUnitsId());
        Scrap scrap;
        List<ScriptSaveVo> scriptSaveVos = scrapOrderOutData.getScriptSaveVos();
        List<String> seqNumbers = new ArrayList<>();
        TaskBto taskBto;
        scriptSaveVos.forEach(
                scriptSaveVo -> {
                    if (scriptSaveVo.getSeqNumber() != null) {
                        seqNumbers.addAll(DeviceSeqUtil.selectDeviceSeqs(scriptSaveVo.getSeqNumber()));
                    }
                }
        );
        if (scrapOrderOutData.getTaskId()==null) {
            scrap= scrapOrderOutData.toScrap();
            if (scrapOrderOutData.getApplyId() != null){
            Optional<Scrap> scrap1 = scrapService.findApplyId(scrapOrderOutData.getApplyId());
            if (scrap1.isPresent()) {
                scrap.setId(scrap1.get().getId());
            }
            }
            scrapService.saveScrap(scrap);
            scrap.setNum("NO:第" + LocalDateTime.now().getYear() + "QT" + scrap.getId());
            taskBto=sendDraftTask(units.getUnitId(), scrap.getId(), userId);
            scrap.setScrapStatus(taskBto.getBillStatus());
        }else {
            taskBto=taskService.get(scrapOrderOutData.getTaskId());
            scrap= scrapService.findScrap(taskBto.getBillId());
            scrap.setScrapStatus(taskBto.getBillStatus());
            scrap.setSenderUserB(scrapOrderOutData.getSenderUserB());
            scrap.setSendUserbId(scrapOrderOutData.getSendUserbId());

        }

        scrap.setDeviceIds(StringUtils.ListToString(scrapOrderOutData.getDevIds()));
        scrap.setOutboundFile(FilesUtil.stringFileToList(scrapOrderOutData.getOutboundFileList()));
        scrap.setOutboundFile(FilesUtil.stringFileToList(scrapOrderOutData.getOutboundFileList()));
        scrap.setApplyNumber(scrapOrderOutData.getApplyNumber());
        scrap.setReplayNumber(scrapOrderOutData.getReplayNumber());
        scrap.setReplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getReplyFileList()));
        scrap.setApplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getApplyFileList()));
        scrap.setScripts(scrapOrderOutData.getScriptSaveVos());
        scrap.setScriptJson(JacksonUtil.toJSon(scrapOrderOutData.getScriptSaveVos()));
//        scrap.setDeviceLibraryEntities(findInvoleDevice(scrap.getDeviceIds()));
        scrapService.saveScrap(scrap);
        taskBto.setRecordId(scrap.getNum());
        return taskBto;
    }

    @Override
    public Scrap provinceScrap(Integer userId, ScrapOrderOutData scrapOrderOutData) {
        User user = userService.findByUser(userId);
        Units units = unitsService.findById(user.getUnitsId());
        Scrap scrap;
        List<ScriptSaveVo> scriptSaveVos = scrapOrderOutData.getScriptSaveVos();
        List<String> seqNumbers = new ArrayList<>();
        scriptSaveVos.forEach(
                scriptSaveVo -> {
                    if (scriptSaveVo.getSeqNumber() != null) {
                        seqNumbers.addAll(DeviceSeqUtil.selectDeviceSeqs(scriptSaveVo.getSeqNumber()));
                    }
                }
        );
        deviceLibraryService.judgeSeqNumbersInNotEqualLifeStatus(seqNumbers,DeviceLifeStatus.TO_BE_SCRAPPED.id);
        //判断是否为草稿 还是直接发起
        if (scrapOrderOutData.getTaskId()!=null){
            TaskBto taskBto= taskService.get(scrapOrderOutData.getTaskId());
            List<StatusEnum> statusEnums = new ArrayList<>();
            statusEnums.add(StatusEnum.SCRAP_2223);
            statusEnums.add(StatusEnum.SCRAP_2225);
            TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(), statusEnums);
            scrap=scrapService.findScrap(taskBto.getBillId());
            taskService.moveToSpecial(taskBto,StatusEnum.SCRAP_2222,"country");
            addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"发起报废任务,待上传回执单据",gainThisUser(user.getUserId(),user.getUnitsId())));
            scrap.setScrapStatus(taskBto.getBillStatus());
        }else {
            scrap = scrapOrderOutData.toScrap();
            scrapService.saveScrap(scrap);
            scrap.setNum("NO:第" + LocalDateTime.now().getYear() + "QT" + scrap.getId());
            TaskBto taskBto= sendOutSuperior(units.getUnitId(), scrap.getId(),userId);
            addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"发起报废任务,待上传回执单据",gainThisUser(user.getUserId(),user.getUnitsId())));
            scrap.setScrapStatus(taskBto.getBillStatus());
        }
        scrap.setLeftSignatureId(scrapOrderOutData.getLeftSignatureId());
        scrap.setSendUserbId(scrapOrderOutData.getSendUserbId());
        scrap.setSenderUserB(scrapOrderOutData.getSenderUserB());
        scrap.setApplyNumber(scrapOrderOutData.getApplyNumber());
        scrap.setReplayNumber(scrapOrderOutData.getReplayNumber());
        scrap.setDeviceIds(StringUtils.ListToString(scrapOrderOutData.getDevIds()));
        scrap.setOutboundFile(FilesUtil.stringFileToList(scrapOrderOutData.getOutboundFileList()));
        scrap.setReplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getReplyFileList()));
        scrap.setApplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getApplyFileList()));
        scrap.setScripts(scrapOrderOutData.getScriptSaveVos());
        scrap.setScriptJson(JacksonUtil.toJSon(scrapOrderOutData.getScriptSaveVos()));
        scrapService.saveScrap(scrap);
        deviceLibraryDao.upDateSeqNumbersLeftStatus(DeviceLifeStatus.IN_THE_SCRAPPED.id,seqNumbers);
        devLogAdd(seqNumbers,"发了报废任务,状态转化为报废中",userId);
        if (scrapOrderOutData.getApplyId()!=null) {
            Optional<Task> billIdAndBusinessTypeNotBillStatus = taskService.findBillIdAndBusinessTypeNotBillStatus(scrapOrderOutData.getApplyId(), BusinessEnum.APPLY.id);
            taskService.moveToEnd(billIdAndBusinessTypeNotBillStatus.get().parse2Bto());
        }else {
            deviceApplyBillService.updateCompleteNum(3,scriptSaveVos);
        }
        return scrap;
    }


    @Override
    public void receiptSingle(Integer taskId, StorageScrap storageScrap) {
        User user = userService.findByUser(storageScrap.getUserId());
        TaskBto taskBto = taskService.get(taskId);
        TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(),StatusEnum.SCRAP_2222);
        Scrap scrap=scrapService.findScrap(taskBto.getBillId());
        scrap.setBillFile(FilesUtil.stringFileToList(storageScrap.getFileRets()));
        List<String> seqNumbers=new ArrayList<>();
        JacksonUtil.readValue(scrap.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {}).forEach(
                scriptSaveVo -> {
                    if (scriptSaveVo.getSeqNumber()!=null){
                        seqNumbers.addAll(DeviceSeqUtil.selectDeviceSeqs(scriptSaveVo.getSeqNumber()));
                    }
                }
        );
        deviceLibraryService.judgeSeqNumbersInNotEqualLifeStatus(seqNumbers,DeviceLifeStatus.IN_THE_SCRAPPED.id);
        if (storageScrap.getUserBName()!=null) {
            scrap.setReceiveUserB(storageScrap.getUserBName());
        }
        if (storageScrap.getUserB()!=null){
            scrap.setReceiveUserbId(storageScrap.getUserB());

        }
        if (storageScrap.getUserA()!=null){
            scrap.setReceiveUseraId(storageScrap.getUserA());

        }
        if (storageScrap.getUserAName()!=null) {
            scrap.setReceiveUserA(storageScrap.getUserAName());
        }
        if (storageScrap.getSenderId()!=null){
            scrap.setSendUserbId(storageScrap.getSenderId());
        }
        if (storageScrap.getSenderName()!=null){
            scrap.setSenderUserB(storageScrap.getSenderName());
        }
        taskBto = taskService.moveToEnd(taskBto);
        scrap.setScrapStatus(taskBto.getBillStatus());
        scrap.setReceiveTime(new Date());
        deviceLibraryDao.upDateSeqNumbersLeftStatusAndUnitNameAndLockStatus(DeviceLifeStatus.SCRAP_I.id,scrap.getReceiveUnit(),0,seqNumbers);
        scrapService.saveScrap(scrap);
        devLogAdd(seqNumbers,"报废任务完成,状态转化为已报废",user.getUserId());
        addMessage(new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"报废单据上传，任务结束",gainThisUser(user.getUserId(),user.getUnitsId())));
    }

    @Override
    public void sealOfAudit(Integer userId, ScrapOrderOutData scrapOrderOutData) {
        Scrap scrap =new Scrap();
        User user = userService.findByUser(scrapOrderOutData.getSendUserbId());
        Units units=unitsService.findById(user.getUnitsId());
        if (scrapOrderOutData.getTaskId()==null){
            scrap = scrapOrderOutData.toScrap();
            scrapService.saveScrap(scrap);
            scrap.setNum("NO:第" + LocalDateTime.now().getYear() + "QT" + scrap.getId());
            TaskBto taskBto= sealOfAuditTask(units.getUnitId(), scrap.getId(),user.getUserId());
            scrap.setScrapStatus(taskBto.getBillStatus());
        }else {
            TaskBto taskBto = taskService.get(scrapOrderOutData.getTaskId());
            List<StatusEnum> statusEnums = new ArrayList<>();
            statusEnums.add(StatusEnum.SCRAP_2223);
            TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(), statusEnums);
            scrap = scrapService.findScrap(taskBto.getBillId());
            taskBto= taskService.moveToSpecial(taskBto, StatusEnum.SCRAP_2224, user.getUserId());
            scrap.setScrapStatus(taskBto.getBillStatus());
        }
        scrap.setApplyNumber(scrapOrderOutData.getApplyNumber());
        scrap.setReplayNumber(scrapOrderOutData.getReplayNumber());
        scrap.setReplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getReplyFileList()));
        scrap.setApplyFiles(FilesUtil.stringFileToList(scrapOrderOutData.getApplyFileList()));
        scrap.setScriptJson(JacksonUtil.toJSon(scrapOrderOutData.getScriptSaveVos()));
        scrap.setScripts(scrapOrderOutData.getScriptSaveVos());
        scrap.setSenderUserB(user.getName());
        scrap.setSendUserbId(user.getUserId());
        scrapService.saveScrap(scrap);
    }

    @Override
    public void outSealOfAuditEnd(Integer taskId, Integer reviewTheResults) {
        TaskBto taskBto= taskService.get(taskId);
        Scrap scrap=scrapService.findScrap(taskBto.getBillId());

        if (reviewTheResults==0){
           taskBto = taskService.moveToSpecial(taskBto,StatusEnum.SCRAP_2225,0);
           scrap.setScrapStatus(taskBto.getBillStatus());
        }else {
            scrap.setSenderUserB(null);
            scrap.setSendUserbId(null);
            taskBto = taskService.moveToSpecial(taskBto,StatusEnum.SCRAP_2223,scrap.getSendUseraId());
            scrap.setScrapStatus(taskBto.getBillStatus());
        }
        scrapService.saveScrap(scrap);

    }

    @Override
    public void deleteDrafts(Integer taskId) {
     TaskBto taskBto= taskService.get(taskId);
     Scrap scrap=scrapService.findScrap(taskBto.getBillId());
     taskBto=taskService.moveToArchive(taskBto);
     scrap.setScrapStatus(taskBto.getBillStatus());
     scrapService.saveScrap(scrap);
    }

    /**
     * 发起调用电子签章确认任务
     */
    private TaskBto sealOfAuditTask(Integer unitId, Integer repelDetailId,Integer userId){
        List<Integer> list=new ArrayList<>();
        list.add(userId);
        return taskService.start(new TaskBto(StatusEnum.SCRAP_2224.id, "报废设备任务", null, ".", repelDetailId, BusinessEnum.SCRAP.id, unitId, 0, "", list));
    }

    /**
     * 报废省出库中办
     * @param userId 当前用户对象
     * @param unitId 单位id
     * @param repelDetailId 业务id
     * @return
     */
    private TaskBto sendOutSuperior(Integer unitId, Integer repelDetailId,Integer userId){
        List<Integer> userIds = new ArrayList<>();
        userIds.add(userId);
        userIds.add(0);
      return  taskService.start(new TaskBto(StatusEnum.SCRAP_2222.id, "报废设备任务", null, ".", repelDetailId, BusinessEnum.SCRAP.id, unitId, 1, "country", userIds));
    }


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



    /**
     * 异步添加装备日志
     */
    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
     * @param userId
     * @param unitId
     * @return
     */
    private List<Integer> gainThisUser(Integer userId,Integer unitId){
        return userService.findAllByUnite(unitId).stream().filter(user -> user.getUserId()!=userId).map(User::getUserId).collect(Collectors.toList());
    }

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



    private List<DeviceLibrary> findInvoleDevice(String involeDevice){
        if (involeDevice!=null && !involeDevice.equals(",") ) {
            List<String> idStringList = Arrays.asList(involeDevice.split(","));
            List<String> idListString = idStringList.stream().filter(list2->!list2.equals("")).collect(Collectors.toList());
            System.out.println(idListString);
            List<Integer> devIds = idListString.stream().map(Integer::parseInt).collect(Collectors.toList());
            return deviceLibraryDao.getDeviceLibraryEntitiesByIdIn(devIds).stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList());
        }else {
            return new ArrayList<>();
        }
    }
}
