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

import com.fasterxml.jackson.core.type.TypeReference;
import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.base.FileName;
import com.tykj.dev.device.decommissioning.entity.DeviceDecommissioningDetail;
import com.tykj.dev.device.decommissioning.entity.vo.DecommissioningSelectVo;
import com.tykj.dev.device.decommissioning.repository.DeviceDecommissioningDetailDao;
import com.tykj.dev.device.decommissioning.service.DeviceDecommissioningDetailService;
import com.tykj.dev.device.file.entity.FileRet;
import com.tykj.dev.device.file.service.FilesUtil;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.ScriptSaveVo;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.exception.ApiException;
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.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

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

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName DeviceDecommissioningDetailServiceImpl.java
 * @Description TODO
 * @createTime 2021年03月29日 16:18:00
 */
@Service
@Slf4j
@SuppressWarnings("ALL")
public class DeviceDecommissioningDetailServiceImpl implements DeviceDecommissioningDetailService {
    @Autowired
    DeviceDecommissioningDetailDao deviceDecommissioningDetailDao;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Autowired
    BlockChainUtil blockChainUtil;

    @Override
    public DeviceDecommissioningDetail saveDeviceDecommissioningDetail(DeviceDecommissioningDetail deviceDecommissioningDetail) {
//        log.info("[清退] 详情添加成功");
        CompletableFuture.runAsync(()-> {
            if (deviceDecommissioningDetail.getRecordId() == null || deviceDecommissioningDetail.getRecordId().equals("")) {
                deviceDecommissioningDetail.setRecordId(blockChainUtil.sendText(1000, JacksonUtil.toJSon(deviceDecommissioningDetail)).getData().getRecordID());
                deviceDecommissioningDetailDao.save(deviceDecommissioningDetail);
                log.info("[退役]上链数据时间本次");
            } else {
                deviceDecommissioningDetail.setRecordId(blockChainUtil.appendText(JacksonUtil.toJSon(deviceDecommissioningDetail), deviceDecommissioningDetail.getRecordId()).getData().getRecordID());
                deviceDecommissioningDetailDao.save(deviceDecommissioningDetail);
            }
        });
        return deviceDecommissioningDetailDao.save(deviceDecommissioningDetail);
    }

    @Override
    public DeviceDecommissioningDetail findDeviceDecommissioningDetail(Integer decommissioningId) {
        Optional<DeviceDecommissioningDetail> optional = deviceDecommissioningDetailDao.findById(decommissioningId);
        if (optional.isPresent()){
            DeviceDecommissioningDetail deviceDecommissioningDetail=optional.get();
            deviceDecommissioningDetail.setScripts(JacksonUtil.readValue(deviceDecommissioningDetail.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {
            }));
            deviceDecommissioningDetail.setBillFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getBillFile()));
            deviceDecommissioningDetail.setOutboundFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getOutboundFile()));
            deviceDecommissioningDetail.setInFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getInFile()));
            deviceDecommissioningDetail.setReplyFileList(FilesUtil.stringFileToList(deviceDecommissioningDetail.getReplyFiles()));
            deviceDecommissioningDetail.setApplyFileList(FilesUtil.stringFileToList(deviceDecommissioningDetail.getApplyFiles()));
            List<String> seqNumbers=new ArrayList<>();
            JacksonUtil.readValue(deviceDecommissioningDetail.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {}).forEach(
                    scriptSaveVo -> {
                        if (scriptSaveVo.getSeqNumber()!=null){
                            seqNumbers.addAll(DeviceSeqUtil.selectDeviceSeqs(scriptSaveVo.getSeqNumber()));
                        }
                    }
            );
            deviceDecommissioningDetail.setDeviceLibraryEntities(deviceLibraryDao.findAllBySeqNumberIn(seqNumbers).stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList()));
            return deviceDecommissioningDetail;
        }else {
            log.info("[退役] 详情查看错误，id没有找到{}",decommissioningId);
            throw new ApiException(ResponseEntity.status(500).body("退役详情id没有找到:"+decommissioningId));
        }
    }

    @Override
    public DeviceDecommissioningDetail findDeviceDecommissioningDetailNoDev(Integer decommissioningId) {
        Optional<DeviceDecommissioningDetail> optional = deviceDecommissioningDetailDao.findById(decommissioningId);
        if (optional.isPresent()){
            return optional.get();
        }else {
            log.info("[退役] 详情查看错误，id没有找到{}",decommissioningId);
            throw new ApiException(ResponseEntity.status(500).body("退役详情id没有找到:"+decommissioningId));
        }
    }

    @Override
    public List<DeviceDecommissioningDetail> findAll() {
        return deviceDecommissioningDetailDao.findAll();
    }

    @Override
    public DeviceDecommissioningDetail findApplyId(Integer applyId) {
        return deviceDecommissioningDetailDao.findByApplyId(applyId);
    }

    @Override
    public Page<DeviceDecommissioningDetail> findPageDeviceDecommissioningDetail(DecommissioningSelectVo decommissioningSelectVo) {
        return deviceDecommissioningDetailDao.findAll(getFindRetiredSpecification(decommissioningSelectVo),decommissioningSelectVo.getPageable()).map(deviceDecommissioningDetail -> {
            deviceDecommissioningDetail.setScripts(JacksonUtil.readValue(deviceDecommissioningDetail.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {
            }));
            deviceDecommissioningDetail.setBillFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getBillFile()));
            deviceDecommissioningDetail.setOutboundFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getOutboundFile()));
            deviceDecommissioningDetail.setInFiles(FilesUtil.stringFileToList(deviceDecommissioningDetail.getInFile()));
            deviceDecommissioningDetail.setReplyFileList(FilesUtil.stringFileToList(deviceDecommissioningDetail.getReplyFiles()));
            deviceDecommissioningDetail.setApplyFileList(FilesUtil.stringFileToList(deviceDecommissioningDetail.getApplyFiles()));
            return deviceDecommissioningDetail;
        });
    }

    @Override
    public Map<String, List<FileRet>> findByIdToFileMapList(Integer id) {
        Map<String, List<FileRet>> map=new HashMap<>();
        Optional<DeviceDecommissioningDetail> optional = deviceDecommissioningDetailDao.findById(id);
        if (optional.isPresent()){
            DeviceDecommissioningDetail deviceDecommissioningDetail=optional.get();
            map.put(FileName.APPLY.name,FilesUtil.stringFileToList(deviceDecommissioningDetail.getApplyFiles()));
            map.put(FileName.RECEIPT.name,FilesUtil.stringFileToList(deviceDecommissioningDetail.getOutboundFile()));
            map.put(FileName.SIGN.name,FilesUtil.stringFileToList(deviceDecommissioningDetail.getBillFile()));
            map.put(FileName.REPLY.name,FilesUtil.stringFileToList(deviceDecommissioningDetail.getReplyFiles()));
            return map;
        }else {
            log.info("[退役] 详情查看错误，id没有找到{}",id);
            throw new ApiException(ResponseEntity.status(500).body("退役详情id没有找到:"+id));
        }
    }


    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<>();
        }
    }

    private Specification<DeviceDecommissioningDetail> getFindRetiredSpecification(DecommissioningSelectVo decommissioningSelectVo) {
        PredicateBuilder<DeviceDecommissioningDetail> predicateBuilder = Specifications.and();
//        List<Integer> leftStatus=new ArrayList<>();
//        leftStatus.add(com.tykj.dev.config.base.DeviceLifeStatus.RETIRED.id);
        if (decommissioningSelectVo.getStartTime() != null) {
            predicateBuilder.gt("createTime", decommissioningSelectVo.getStartTime());
        }
        if (decommissioningSelectVo.getEndTime() != null) {
            predicateBuilder.lt("createTime", decommissioningSelectVo.getEndTime());
        }
        predicateBuilder.eq("decommissioningStatus", StatusEnum.END.id);

        return predicateBuilder.build();

    }


}
