package com.tykj.dev.device.scrap.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.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.device.scrap.repository.ScrapDao;
import com.tykj.dev.device.scrap.service.ScrapService;
import com.tykj.dev.device.scrap.subject.domin.Scrap;
import com.tykj.dev.device.scrap.subject.domin.ScrapBill;
import com.tykj.dev.device.scrap.subject.vo.ScrapSelectVo;
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 javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
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 ScrapServiceImpl.java
 * @Description TODO
 * @createTime 2021年03月31日 10:23:00
 */
@Service
@Slf4j
public class ScrapServiceImpl implements ScrapService {
    @Autowired
    ScrapDao scrapDao;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Autowired
    BlockChainUtil blockChainUtil;

    @Override
    public Scrap saveScrap(Scrap scrap) {
        CompletableFuture.runAsync(()-> {
            if (scrap.getRecordId() == null || scrap.getRecordId().equals("")) {
                scrap.setRecordId(blockChainUtil.sendText(1000, JacksonUtil.toJSon(scrap)).getData().getRecordID());
                scrapDao.save(scrap);
                log.info("[销毁]上链数据时间本次");
            } else {
                scrap.setRecordId(blockChainUtil.appendText(JacksonUtil.toJSon(scrap), scrap.getRecordId()).getData().getRecordID());
                scrapDao.save(scrap);
            }
        });
        return scrapDao.save(scrap);
    }

    @Override
    public Scrap findScrap(Integer scrapId) {
        Optional<Scrap> optional = scrapDao.findById(scrapId);
        if (optional.isPresent()){
            Scrap scrap=optional.get();
//            scrap.setDeviceLibraryEntities(findInvoleDevice(scrap.getDeviceIds()));
            scrap.setScripts(JacksonUtil.readValue(scrap.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {}));
            scrap.setBillFiles(FilesUtil.stringFileToList(scrap.getBillFile()));
            scrap.setOutboundFiles(FilesUtil.stringFileToList(scrap.getOutboundFile()));
            scrap.setReplyFileList(FilesUtil.stringFileToList(scrap.getReplyFiles()));
            scrap.setApplyFileList(FilesUtil.stringFileToList(scrap.getApplyFiles()));
            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()));
                        }
                    }
            );
            scrap.setDeviceLibraryEntities(deviceLibraryDao.findAllBySeqNumberIn(seqNumbers).stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList()));
            return scrap;
        }else {
            log.info("[报废] 详情查看错误，id没有找到{}",scrapId);
            throw new ApiException(ResponseEntity.status(500).body("报废详情id没有找到:"+scrapId));
        }    }

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

    @Override
    public List<Scrap> findAll() {
        return scrapDao.findAll();
    }

    @Override
    public Page<Scrap> findPageScrapList(ScrapSelectVo scrapSelectVo) {
        PredicateBuilder<Scrap> predicateBuilder = Specifications.and();

        if (scrapSelectVo.getStartTime() != null) {
            predicateBuilder.gt("createTime", scrapSelectVo.getStartTime());
        }
        if (scrapSelectVo.getEndTime() != null) {
            predicateBuilder.lt("createTime", scrapSelectVo.getEndTime());
        }
        predicateBuilder.eq("scrapStatus", StatusEnum.END.id);

        return scrapDao.findAll(predicateBuilder.build(), scrapSelectVo.getPageable()).map(
                scrap -> {
                    scrap.setScripts(JacksonUtil.readValue(scrap.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {}));
                    scrap.setBillFiles(FilesUtil.stringFileToList(scrap.getBillFile()));
                    scrap.setOutboundFiles(FilesUtil.stringFileToList(scrap.getOutboundFile()));
                    scrap.setReplyFileList(FilesUtil.stringFileToList(scrap.getReplyFiles()));
                    scrap.setApplyFileList(FilesUtil.stringFileToList(scrap.getApplyFiles()));
                return scrap;
                }

        );
    }

    @Override
    public Optional<Scrap> findApplyId(Integer applyId) {
        return scrapDao.findByApplyId(applyId);
    }


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